Changeset 3e01316f in mainline for uspace/lib/posix


Ignore:
Timestamp:
2011-08-17T18:04:50Z (15 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0cf27ee
Parents:
e898296d (diff), e6165be (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge libposix.

Location:
uspace/lib/posix
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/errno.h

    re898296d r3e01316f  
    135135        POSIX_ENOTTY = __TOP_ERRNO + 37,
    136136        POSIX_ENXIO = __TOP_ERRNO + 38,
    137         POSIX_EOPNOTSUPP = POSIX_ENOTSUP,
     137        POSIX_EOPNOTSUPP = __TOP_ERRNO + 39,
    138138        POSIX_EOVERFLOW = -EOVERFLOW,
    139         POSIX_EOWNERDEAD = __TOP_ERRNO + 39,
     139        POSIX_EOWNERDEAD = __TOP_ERRNO + 40,
    140140        POSIX_EPERM = -EPERM,
    141         POSIX_EPIPE = __TOP_ERRNO + 40,
    142         POSIX_EPROTO = __TOP_ERRNO + 41,
     141        POSIX_EPIPE = __TOP_ERRNO + 41,
     142        POSIX_EPROTO = __TOP_ERRNO + 42,
    143143        POSIX_EPROTONOSUPPORT = -EPROTONOSUPPORT,
    144         POSIX_EPROTOTYPE = __TOP_ERRNO + 42,
     144        POSIX_EPROTOTYPE = __TOP_ERRNO + 43,
    145145        POSIX_ERANGE = -ERANGE,
    146         POSIX_EROFS = __TOP_ERRNO + 43,
    147         POSIX_ESPIPE = __TOP_ERRNO + 44,
    148         POSIX_ESRCH = __TOP_ERRNO + 45,
    149         POSIX_ESTALE = __TOP_ERRNO + 46,
    150         POSIX_ETIME = __TOP_ERRNO + 47,
    151         POSIX_ETIMEDOUT = __TOP_ERRNO + 48,
    152         POSIX_ETXTBSY = __TOP_ERRNO + 49,
    153         POSIX_EWOULDBLOCK = POSIX_EAGAIN,
     146        POSIX_EROFS = __TOP_ERRNO + 44,
     147        POSIX_ESPIPE = __TOP_ERRNO + 45,
     148        POSIX_ESRCH = __TOP_ERRNO + 46,
     149        POSIX_ESTALE = __TOP_ERRNO + 47,
     150        POSIX_ETIME = __TOP_ERRNO + 48,
     151        POSIX_ETIMEDOUT = __TOP_ERRNO + 49,
     152        POSIX_ETXTBSY = __TOP_ERRNO + 50,
     153        POSIX_EWOULDBLOCK = __TOP_ERRNO + 51,
    154154        POSIX_EXDEV = -EXDEV,
    155155};
  • uspace/lib/posix/fnmatch.c

    re898296d r3e01316f  
    3333 */
    3434
    35 // TODO: clean this up a bit
     35/* This file contains an implementation of the fnmatch() pattern matching
     36 * function. There is more code than necessary to account for the possibility
     37 * of adding POSIX-like locale support to the system in the future. Functions
     38 * that are only necessary for locale support currently simply use single
     39 * characters for "collation elements".
     40 * When (or if) locales are properly implemented, extending this implementation
     41 * will be fairly straightforward.
     42 */
    3643
    3744#include "stdbool.h"
     
    4653#include "fnmatch.h"
    4754
    48 // TODO: documentation
    49 
     55/* Returned by _match... functions. */
    5056#define INVALID_PATTERN -1
    5157
     
    5359 * but may be extended for better locale support.
    5460 */
    55 typedef int _coll_elm_t;
    56 
     61typedef int coll_elm_t;
     62
     63/** Return value indicating that the element in question
     64 * is not valid in the current locale. (That is, if locales are supported.)
     65 */
    5766#define COLL_ELM_INVALID -1
    5867
     
    6069 *
    6170 * @param str
    62  * @return
    63  */
    64 static _coll_elm_t _coll_elm_get(const char* str)
     71 * @return Matching collating element or COLL_ELM_INVALID.
     72 */
     73static coll_elm_t _coll_elm_get(const char* str)
    6574{
    6675        if (str[0] == '\0' || str[1] != '\0') {
     
    7584 * @return
    7685 */
    77 static _coll_elm_t _coll_elm_char(int c)
     86static coll_elm_t _coll_elm_char(int c)
    7887{
    7988        return c;
     
    8695 * @return 0 if the element doesn't match, or the number of characters matched.
    8796 */
    88 static int _coll_elm_match(_coll_elm_t elm, const char *str)
     97static int _coll_elm_match(coll_elm_t elm, const char *str)
    8998{
    9099        return elm == *str;
    91100}
    92101
    93 static int _coll_elm_between(_coll_elm_t first, _coll_elm_t second,
     102/** Checks whether a string begins with a collating element in the given range.
     103 *  Ordering depends on the locale (if locales are supported).
     104 *
     105 * @param first First element of the range.
     106 * @param second Last element of the range.
     107 * @param str String to match.
     108 * @return 0 if there is no match, or the number of characters matched.
     109 */
     110static int _coll_elm_between(coll_elm_t first, coll_elm_t second,
    94111    const char *str)
    95112{
     
    105122 * @param buf_sz Read buffer's size. If the buffer is not large enough for
    106123 *    the entire string, the string is cut with no error indication.
    107  * @return
     124 * @param flags Flags modifying the behavior.
     125 * @return True on success, false if the pattern is invalid.
    108126 */
    109127static bool _get_delimited(
     
    171189};
    172190
    173 /**
     191/** Compare function for binary search in the _char_classes array.
    174192 *
    175193 * @param key
     
    183201}
    184202
    185 /**
     203/** Returns whether the given character belongs to the specified character class.
    186204 *
    187  * @param cname
    188  * @param c
    189  * @return
     205 * @param cname Name of the character class.
     206 * @param c Character.
     207 * @return True if the character belongs to the class, false otherwise.
    190208 */
    191209static bool _is_in_class (const char *cname, int c)
     
    205223}
    206224
    207 /**
     225/** Tries to parse an initial part of the pattern as a character class pattern,
     226 *  and if successful, matches the beginning of the given string against the class.
    208227 *
    209  * @param pattern
    210  * @param str
    211  * @param flags
    212  * @return
     228 * @param pattern Pointer to the pattern to match. Must begin with a class
     229 *    specifier and is repositioned to the first character after the specifier
     230 *    if successful.
     231 * @param str String to match.
     232 * @param flags Flags modifying the behavior (see fnmatch()).
     233 * @return INVALID_PATTERN if the pattern doesn't start with a valid class
     234 *    specifier, 0 if the beginning of the matched string doesn't belong
     235 *    to the class, or positive number of characters matched.
    213236 */
    214237static int _match_char_class(const char **pattern, const char *str, int flags)
     
    225248/************** END CHARACTER CLASSES ****************/
    226249
    227 /**
     250/** Reads the next collating element in the pattern, taking into account
     251 *  locale (if supported) and flags (see fnmatch()).
    228252 *
    229  * @param pattern
    230  * @param flags
    231  * @return
    232  */
    233 static _coll_elm_t _next_coll_elm(const char **pattern, int flags)
    234 {
     253 * @param pattern Pattern.
     254 * @param flags Flags given to fnmatch().
     255 * @return Collating element on success,
     256 *     or COLL_ELM_INVALID if the pattern is invalid.
     257 */
     258static coll_elm_t _next_coll_elm(const char **pattern, int flags)
     259{
     260        assert(pattern != NULL);
     261        assert(*pattern != NULL);
     262        assert(**pattern != '\0');
     263
    235264        const char *p = *pattern;
    236265        const bool noescape = (flags & FNM_NOESCAPE) != 0;
     
    257286        if (!noescape && *p == '\\') {
    258287                p++;
     288                if (*p == '\0') {
     289                        *pattern = p;
     290                        return COLL_ELM_INVALID;
     291                }
    259292        }
    260293        if (pathname && *p == '/') {
    261294                return COLL_ELM_INVALID;
    262295        }
    263 
     296       
    264297        *pattern = p + 1;
    265298        return _coll_elm_char(*p);
    266299}
    267300
    268 /**
     301/** Matches the beginning of the given string against a bracket expression
     302 *  the pattern begins with.
    269303 *
    270  * @param pattern
    271  * @param str
    272  * @param flags
    273  * @return
     304 * @param pattern Pointer to the beginning of a bracket expression in a pattern.
     305 *     On success, the pointer is moved to the first character after the
     306 *     bracket expression.
     307 * @param str Unmatched part of the string.
     308 * @param flags Flags given to fnmatch().
     309 * @return INVALID_PATTERN if the pattern is invalid, 0 if there is no match
     310 *     or the number of matched characters on success.
    274311 */
    275312static int _match_bracket_expr(const char **pattern, const char *str, int flags)
     
    315352        }
    316353       
    317         _coll_elm_t current_elm = COLL_ELM_INVALID;
     354        coll_elm_t current_elm = COLL_ELM_INVALID;
    318355       
    319356        while (*p != ']') {
     
    322359                        /* Range expression. */
    323360                        p++;
    324                         _coll_elm_t end_elm = _next_coll_elm(&p, flags);
     361                        coll_elm_t end_elm = _next_coll_elm(&p, flags);
    325362                        if (end_elm == COLL_ELM_INVALID) {
    326363                                return INVALID_PATTERN;
     
    357394}
    358395
    359 /**
     396/** Matches a portion of the pattern containing no asterisks (*) against
     397 *  the given string.
    360398 *
    361  * @param pattern
    362  * @param string
    363  * @param flags
    364  * @return
     399 * @param pattern Pointer to the unmatched portion of the pattern.
     400 *     On success, the pointer is moved to the first asterisk, or to the
     401 *     terminating nul character, whichever occurs first.
     402 * @param string Pointer to the input string. On success, the pointer is moved
     403 *     to the first character that wasn't explicitly matched.
     404 * @param flags Flags given to fnmatch().
     405 * @return True if the entire subpattern matched. False otherwise.
    365406 */
    366407static bool _partial_match(const char **pattern, const char **string, int flags)
     
    456497}
    457498
    458 /**
     499/** Match string against a pattern.
    459500 *
    460  * @param pattern
    461  * @param string
    462  * @param flags
    463  * @return
     501 * @param pattern Pattern.
     502 * @param string String to match.
     503 * @param flags Flags given to fnmatch().
     504 * @return True if the string matched the pattern, false otherwise.
    464505 */
    465506static bool _full_match(const char *pattern, const char *string, int flags)
     
    496537                        end = string;
    497538                } else {
    498                         end= strchrnul(string, pathname ? '/' : '\0');
     539                        end = strchrnul(string, pathname ? '/' : '\0');
    499540                }
    500541
     
    518559}
    519560
    520 /**
     561/** Transform the entire string to lowercase.
    521562 *
    522  * @param s
    523  * @return
     563 * @param s Input string.
     564 * @return Newly allocated copy of the input string with all uppercase
     565 *     characters folded to their lowercase variants.
    524566 */
    525567static char *_casefold(const char *s)
  • uspace/lib/posix/locale.c

    re898296d r3e01316f  
    4242#include "string.h"
    4343
    44 // TODO: documentation
     44/* Just a very basic dummy implementation.
     45 * This should allow code using locales to work properly, but doesn't provide
     46 * any localization functionality.
     47 * Should be extended/rewritten when or if HelenOS supports locales natively.
     48 */
    4549
    4650struct __posix_locale {
     
    7579};
    7680
    77 /**
     81/** Set program locale.
    7882 *
    79  * @param category
    80  * @param locale
    81  * @return
     83 * @param category What category to set.
     84 * @param locale Locale name.
     85 * @return Original locale name on success, NULL on failure.
    8286 */
    8387char *posix_setlocale(int category, const char *locale)
     
    9195}
    9296
    93 /**
     97/** Return locale-specific information.
    9498 *
    95  * @return
     99 * @return Information about the current locale.
    96100 */
    97101struct posix_lconv *posix_localeconv(void)
     
    101105}
    102106
    103 /**
     107/** Duplicate locale object.
    104108 *
    105  * @param locobj
    106  * @return
     109 * @param locobj Object to duplicate.
     110 * @return Duplicated object.
    107111 */
    108112posix_locale_t posix_duplocale(posix_locale_t locobj)
     
    121125}
    122126
    123 /**
     127/** Free locale object.
    124128 *
    125  * @param locobj
     129 * @param locobj Object to free.
    126130 */
    127131void posix_freelocale(posix_locale_t locobj)
     
    132136}
    133137
    134 /**
     138/** Create or modify a locale object.
    135139 *
    136  * @param category_mask
    137  * @param locale
    138  * @param base
    139  * @return
     140 * @param category_mask Mask of categories to be set or modified.
     141 * @param locale Locale to be used.
     142 * @param base Object to modify. 0 if new object is to be created.
     143 * @return The new/modified locale object.
    140144 */
    141145posix_locale_t posix_newlocale(int category_mask, const char *locale,
     
    159163}
    160164
    161 /**
     165/** Set locale for the current thread.
    162166 *
    163  * @param newloc
    164  * @return
     167 * @param newloc Locale to use.
     168 * @return The previously set locale or LC_GLOBAL_LOCALE
    165169 */
    166170posix_locale_t posix_uselocale(posix_locale_t newloc)
    167171{
    168172        // TODO
    169         return NULL;
     173        return LC_GLOBAL_LOCALE;
    170174}
    171175
  • uspace/lib/posix/locale.h

    re898296d r3e01316f  
    3535#ifndef POSIX_LOCALE_H_
    3636#define POSIX_LOCALE_H_
    37 
    38 // TODO: documentation
    3937
    4038#ifndef NULL
  • uspace/lib/posix/signal.c

    re898296d r3e01316f  
    4545#include "libc/task.h"
    4646
    47 // TODO: documentation
     47/* This file implements a fairly dumb and incomplete "simulation" of
     48 * POSIX signals. Since HelenOS doesn't support signals and mostly doesn't
     49 * have any equivalent functionality, most of the signals are useless. The
     50 * main purpose of this implementation is thus to help port applications using
     51 * signals with minimal modification, but if the application uses signals for
     52 * anything non-trivial, it's quite probable it won't work properly even if
     53 * it builds without problems.
     54 */
    4855
    4956/* Used to serialize signal handling. */
    5057static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
    5158
     59static LIST_INITIALIZE(_signal_queue);
     60
    5261static posix_sigset_t _signal_mask = 0;
    5362
     
    5564    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
    5665
     66/* Actions associated with each signal number. */
    5767static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
    5868        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     
    126136}
    127137
    128 /**
     138/** Just an empty function to get an unique pointer value for comparison.
    129139 *
    130140 * @param signo
     
    135145}
    136146
    137 /**
     147/** Empty function to be used as ignoring handler.
    138148 *
    139149 * @param signo
     
    144154}
    145155
    146 /**
    147  *
    148  * @param set
    149  * @return
     156/** Clear the signal set.
     157 *
     158 * @param set Pointer to the signal set.
     159 * @return Always returns zero.
    150160 */
    151161int posix_sigemptyset(posix_sigset_t *set)
     
    157167}
    158168
    159 /**
    160  *
    161  * @param set
    162  * @return
     169/** Fill the signal set (i.e. add all signals).
     170 *
     171 * @param set Pointer to the signal set.
     172 * @return Always returns zero.
    163173 */
    164174int posix_sigfillset(posix_sigset_t *set)
     
    170180}
    171181
    172 /**
    173  *
    174  * @param set
    175  * @param signo
    176  * @return
     182/** Add a signal to the set.
     183 *
     184 * @param set Pointer to the signal set.
     185 * @param signo Signal number to add.
     186 * @return Always returns zero.
    177187 */
    178188int posix_sigaddset(posix_sigset_t *set, int signo)
     
    184194}
    185195
    186 /**
    187  *
    188  * @param set
    189  * @param signo
    190  * @return
     196/** Delete a signal from the set.
     197 *
     198 * @param set Pointer to the signal set.
     199 * @param signo Signal number to remove.
     200 * @return Always returns zero.
    191201 */
    192202int posix_sigdelset(posix_sigset_t *set, int signo)
     
    198208}
    199209
    200 /**
    201  *
    202  * @param set
    203  * @param signo
    204  * @return
     210/** Inclusion test for a signal set.
     211 *
     212 * @param set Pointer to the signal set.
     213 * @param signo Signal number to query.
     214 * @return 1 if the signal is in the set, 0 otherwise.
    205215 */
    206216int posix_sigismember(const posix_sigset_t *set, int signo)
     
    211221}
    212222
    213 /**
     223/** Unsafe variant of the sigaction() function.
     224 *  Doesn't do any checking of its arguments and
     225 *  does not deal with thread-safety.
    214226 *
    215227 * @param sig
     
    231243}
    232244
    233 /**
    234  *
    235  * @param sig
    236  * @param act
    237  * @param oact
    238  * @return
     245/** Sets a new action for the given signal number.
     246 *
     247 * @param sig Signal number to set action for.
     248 * @param act If not NULL, contents of this structure are
     249 *     used as the new action for the signal.
     250 * @param oact If not NULL, the original action associated with the signal
     251 *     is stored in the structure pointer to.
     252 * @return -1 with errno set on failure, 0 on success.
    239253 */
    240254int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
     
    252266                    " or fully unsupported signal. This handler may only be"
    253267                    " invoked by the raise() function, which may not be what"
    254                     " the application developer intended.\nSignal name");
     268                    " the application developer intended");
    255269        }
    256270
     
    262276}
    263277
    264 /**
    265  *
    266  * @param sig
    267  * @param func
    268  * @return
     278/** Sets a new handler for the given signal number.
     279 *
     280 * @param sig Signal number to set handler for.
     281 * @param func Handler function.
     282 * @return SIG_ERR on failure, original handler on success.
    269283 */
    270284void (*posix_signal(int sig, void (*func)(int)))(int)
     
    284298}
    285299
    286 /**
    287  *
    288  * @param signo
    289  * @param siginfo
    290  * @return
    291  */
    292 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     300typedef struct {
     301        link_t link;
     302        int signo;
     303        posix_siginfo_t siginfo;
     304} signal_queue_item;
     305
     306/** Queue blocked signal.
     307 *
     308 * @param signo Signal number.
     309 * @param siginfo Additional information about the signal.
     310 */
     311static void _queue_signal(int signo, posix_siginfo_t *siginfo)
    293312{
    294313        assert(signo >= 0 && signo <= _TOP_SIGNAL);
    295314        assert(siginfo != NULL);
     315       
     316        signal_queue_item *item = malloc(sizeof(signal_queue_item));
     317        link_initialize(&(item->link));
     318        item->signo = signo;
     319        memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t));
     320        list_append(&(item->link), &_signal_queue);
     321}
     322
     323
     324/** Executes an action associated with the given signal.
     325 *
     326 * @param signo Signal number.
     327 * @param siginfo Additional information about the circumstances of this raise.
     328 * @return 0 if the action has been successfully executed. -1 if the signal is
     329 *     blocked.
     330 */
     331static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     332{
     333        assert(signo >= 0 && signo <= _TOP_SIGNAL);
     334        assert(siginfo != NULL);
    296335
    297336        fibril_mutex_lock(&_signal_mutex);
     
    301340        if (posix_sigismember(&_signal_mask, signo) ||
    302341            action.sa_handler == SIG_HOLD) {
    303                 // TODO: queue signal
     342                _queue_signal(signo, siginfo);
    304343                fibril_mutex_unlock(&_signal_mutex);
    305344                return -1;
     
    312351        if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
    313352                _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
    314         };
     353        }
    315354
    316355        if (action.sa_flags & SA_SIGINFO) {
     
    327366}
    328367
    329 /**
    330  *
    331  * @param sig
    332  * @return
     368/** Raise all unblocked previously queued signals.
     369 */
     370static void _dequeue_unblocked_signals()
     371{
     372        link_t *iterator = _signal_queue.head.next;
     373        link_t *next;
     374       
     375        while (iterator != &(_signal_queue).head) {
     376                next = iterator->next;
     377               
     378                signal_queue_item *item =
     379                    list_get_instance(iterator, signal_queue_item, link);
     380               
     381                if (!posix_sigismember(&_signal_mask, item->signo) &&
     382                    _signal_actions[item->signo].sa_handler != SIG_HOLD) {
     383                        list_remove(&(item->link));
     384                        _raise_sigaction(item->signo, &(item->siginfo));
     385                        free(item);
     386                }
     387               
     388                iterator = next;
     389        }
     390}
     391
     392/** Raise a signal for the calling process.
     393 *
     394 * @param sig Signal number.
     395 * @return -1 with errno set on failure, 0 on success.
    333396 */
    334397int posix_raise(int sig)
     
    346409}
    347410
    348 /**
    349  *
    350  * @param pid
    351  * @param signo
    352  * @return
     411/** Raises a signal for a selected process.
     412 *
     413 * @param pid PID of the process for which the signal shall be raised.
     414 * @param signo Signal to raise.
     415 * @return -1 with errno set on failure (possible errors include unsupported
     416 *     action, invalid signal number, lack of permissions, etc.), 0 on success.
    353417 */
    354418int posix_kill(posix_pid_t pid, int signo)
     
    360424        }
    361425
     426        if (signo > _TOP_SIGNAL) {
     427                errno = EINVAL;
     428                return -1;
     429        }
     430
    362431        if (pid == (posix_pid_t) task_get_id()) {
    363432                return posix_raise(signo);
    364         }
    365 
    366         if (pid > _TOP_SIGNAL) {
    367                 errno = EINVAL;
    368                 return -1;
    369433        }
    370434
     
    382446}
    383447
    384 /**
    385  *
    386  * @param pid
    387  * @param sig
    388  * @return
     448/** Send a signal to a process group. Always fails at the moment because of
     449 *  lack of this functionality in HelenOS.
     450 *
     451 * @param pid PID of the process group.
     452 * @param sig Signal number.
     453 * @return -1 on failure, 0 on success (see kill()).
    389454 */
    390455int posix_killpg(posix_pid_t pid, int sig)
     
    394459}
    395460
    396 /**
    397  *
    398  * @param pinfo
    399  * @param message
     461/** Outputs information about the signal to the standard error stream.
     462 *
     463 * @param pinfo SigInfo struct to write.
     464 * @param message String to output alongside human-readable signal description.
    400465 */
    401466void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
     
    406471}
    407472
    408 /**
    409  *
    410  * @param signum
    411  * @param message
     473/** Outputs information about the signal to the standard error stream.
     474 *
     475 * @param signum Signal number.
     476 * @param message String to output alongside human-readable signal description.
    412477 */
    413478void posix_psignal(int signum, const char *message)
     
    421486}
    422487
    423 /**
    424  *
    425  * @param how
    426  * @param set
    427  * @param oset
    428  * @return
     488/** Manipulate the signal mask of the calling thread.
     489 *
     490 * @param how What to do with the mask.
     491 * @param set Signal set to work with.
     492 * @param oset If not NULL, the original signal mask is coppied here.
     493 * @return 0 success, errorcode on failure.
    429494 */
    430495int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
     
    452517                }
    453518        }
    454 
    455         // TODO: queued signal handling
     519       
     520        _dequeue_unblocked_signals();
    456521
    457522        fibril_mutex_unlock(&_signal_mutex);
     
    460525}
    461526
    462 /**
    463  *
    464  * @param how
    465  * @param set
    466  * @param oset
    467  * @return
     527/** Manipulate the signal mask of the process.
     528 *
     529 * @param how What to do with the mask.
     530 * @param set Signal set to work with.
     531 * @param oset If not NULL, the original signal mask is coppied here.
     532 * @return 0 on success, -1 with errno set on failure.
    468533 */
    469534int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
  • uspace/lib/posix/signal.h

    re898296d r3e01316f  
    3636#define POSIX_SIGNAL_H_
    3737
    38 // TODO: documentation
    39 
    4038#include "libc/errno.h"
    4139#include "sys/types.h"
     
    5755typedef uint32_t posix_sigset_t;
    5856typedef struct posix_mcontext {
    59         // FIXME: should not be empty to avoid compiler warnings (-pedantic)
     57        /* must not be empty to avoid compiler warnings (-pedantic) */
    6058        int dummy;
    6159} posix_mcontext_t;
  • uspace/lib/posix/stdio.c

    re898296d r3e01316f  
    4444#include "assert.h"
    4545#include "errno.h"
     46#include "stdlib.h"
    4647#include "string.h"
    4748#include "sys/types.h"
     49#include "unistd.h"
    4850
    4951#include "libc/io/printf_core.h"
     
    255257        assert(stream != NULL);
    256258       
    257         /* Retieve the node. */
     259        /* Retrieve the node. */
    258260        struct stat st;
    259261        int rc;
     
    263265        } else {
    264266                rc = stat(filename, &st);
     267                if (-rc == ENOENT) {
     268                        /* file does not exist, create new file */
     269                        FILE* tmp = fopen(filename, mode);
     270                        if (tmp != NULL) {
     271                                fclose(tmp);
     272                                /* try again */
     273                                rc = stat(filename, &st);
     274                        }
     275                }
    265276        }
    266277       
     
    273284        fdi_node_t node = {
    274285                .fs_handle = st.fs_handle,
    275                 .devmap_handle = st.devmap_handle,
     286                .service_id = st.service_id,
    276287                .index = st.index
    277288        };
     
    306317       
    307318        return stream;
    308 }
    309 
    310 /**
    311  *
    312  * @param buf
    313  * @param size
    314  * @param mode
    315  * @return
    316  */
    317 FILE *posix_fmemopen(void *restrict buf, size_t size,
    318     const char *restrict mode)
    319 {
    320         // TODO
    321         not_implemented();
    322 }
    323 
    324 /**
    325  *
    326  * @param bufp
    327  * @param sizep
    328  * @return
    329  */
    330 FILE *posix_open_memstream(char **bufp, size_t *sizep)
    331 {
    332         // TODO
    333         not_implemented();
    334319}
    335320
     
    724709 * Rename a file or directory.
    725710 *
    726  * @param old
    727  * @param new
     711 * @param old Old pathname.
     712 * @param new New pathname.
    728713 * @return Zero on success, -1 (with errno set) otherwise.
    729714 */
     
    734719
    735720/**
    736  *
    737  * @param s
    738  * @return
     721 * Get a unique temporary file name (obsolete).
     722 *
     723 * @param s Buffer for the file name. Must be at least L_tmpnam bytes long.
     724 * @return The value of s on success, NULL on failure.
    739725 */
    740726char *posix_tmpnam(char *s)
    741727{
    742         // TODO: low priority, just a compile-time dependency of binutils
    743         not_implemented();
     728        assert(L_tmpnam >= posix_strlen("/tmp/tnXXXXXX"));
     729       
     730        static char buffer[L_tmpnam + 1];
     731        if (s == NULL) {
     732                s = buffer;
     733        }
     734       
     735        posix_strcpy(s, "/tmp/tnXXXXXX");
     736        posix_mktemp(s);
     737       
     738        if (*s == '\0') {
     739                /* Errno set by mktemp(). */
     740                return NULL;
     741        }
     742       
     743        return s;
     744}
     745
     746/**
     747 * Get an unique temporary file name with additional constraints (obsolete).
     748 *
     749 * @param dir Path to directory, where the file should be created.
     750 * @param pfx Optional prefix up to 5 characters long.
     751 * @return Newly allocated unique path for temporary file. NULL on failure.
     752 */
     753char *posix_tempnam(const char *dir, const char *pfx)
     754{
     755        /* Sequence number of the filename. */
     756        static int seq = 0;
     757       
     758        size_t dir_len = posix_strlen(dir);
     759        if (dir[dir_len - 1] == '/') {
     760                dir_len--;
     761        }
     762       
     763        size_t pfx_len = posix_strlen(pfx);
     764        if (pfx_len > 5) {
     765                pfx_len = 5;
     766        }
     767       
     768        char *result = malloc(dir_len + /* slash*/ 1 +
     769            pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1);
     770       
     771        if (result == NULL) {
     772                errno = ENOMEM;
     773                return NULL;
     774        }
     775       
     776        char *res_ptr = result;
     777        posix_strncpy(res_ptr, dir, dir_len);
     778        res_ptr += dir_len;
     779        posix_strncpy(res_ptr, pfx, pfx_len);
     780        res_ptr += pfx_len;
     781       
     782        for (; seq < 1000; ++seq) {
     783                snprintf(res_ptr, 8, "%03d.tmp", seq);
     784               
     785                int orig_errno = errno;
     786                errno = 0;
     787                /* Check if the file exists. */
     788                if (posix_access(result, F_OK) == -1) {
     789                        if (errno == ENOENT) {
     790                                errno = orig_errno;
     791                                break;
     792                        } else {
     793                                /* errno set by access() */
     794                                return NULL;
     795                        }
     796                }
     797        }
     798       
     799        if (seq == 1000) {
     800                free(result);
     801                errno = EINVAL;
     802                return NULL;
     803        }
     804       
     805        return result;
     806}
     807
     808/**
     809 * Create and open an unique temporary file.
     810 * The file is automatically removed when the stream is closed.
     811 *
     812 * @param dir Path to directory, where the file should be created.
     813 * @param pfx Optional prefix up to 5 characters long.
     814 * @return Newly allocated unique path for temporary file. NULL on failure.
     815 */
     816FILE *posix_tmpfile(void)
     817{
     818        char filename[] = "/tmp/tfXXXXXX";
     819        int fd = posix_mkstemp(filename);
     820        if (fd == -1) {
     821                /* errno set by mkstemp(). */
     822                return NULL;
     823        }
     824       
     825        /* Unlink the created file, so that it's removed on close(). */
     826        posix_unlink(filename);
     827        return fdopen(fd, "w+");
    744828}
    745829
  • uspace/lib/posix/stdio.h

    re898296d r3e01316f  
    6565extern FILE *posix_freopen(const char *restrict filename,
    6666    const char *restrict mode, FILE *restrict stream);
    67 extern FILE *posix_fmemopen(void *restrict buf, size_t size,
    68     const char *restrict mode);
    69 extern FILE *posix_open_memstream(char **bufp, size_t *sizep);
    7067
    7168/* Error Messages */
     
    123120#define L_tmpnam PATH_MAX
    124121extern char *posix_tmpnam(char *s);
     122extern char *posix_tempnam(const char *dir, const char *pfx);
     123extern FILE *posix_tmpfile(void);
    125124
    126125#ifndef LIBPOSIX_INTERNAL
     126        /* DEBUG macro does not belong to POSIX stdio.h. Its unconditional
     127         * definition in the native stdio.h causes unexpected behaviour of
     128         * applications which uses their own DEBUG macro (e.g. debugging
     129         * output is printed even if not desirable). */
     130        #undef DEBUG
     131
    127132        #define ctermid posix_ctermid
    128133
     
    176181
    177182        #define tmpnam posix_tmpnam
     183        #define tempnam posix_tempnam
     184        #define tmpfile posix_tmpfile
    178185#endif
    179186
  • uspace/lib/posix/stdlib.c

    re898296d r3e01316f  
    4040
    4141#include "errno.h"
     42#include "fcntl.h"
    4243#include "limits.h"
     44#include "string.h"
     45#include "sys/stat.h"
     46#include "unistd.h"
    4347
    4448#include "libc/sort.h"
    4549#include "libc/str.h"
    4650#include "libc/vfs/vfs.h"
     51#include "libc/stats.h"
    4752
    4853/**
     
    385390
    386391/**
    387  *
    388  * @param tmpl
    389  * @return
     392 * Creates and opens an unique temporary file from template.
     393 *
     394 * @param tmpl Template. Last six characters must be XXXXXX.
     395 * @return The opened file descriptor or -1 on error.
     396 */
     397int posix_mkstemp(char *tmpl)
     398{
     399        int fd = -1;
     400       
     401        char *tptr = tmpl + posix_strlen(tmpl) - 6;
     402       
     403        while (fd < 0) {
     404                if (*posix_mktemp(tmpl) == '\0') {
     405                        /* Errno set by mktemp(). */
     406                        return -1;
     407                }
     408               
     409                fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
     410               
     411                if (fd == -1) {
     412                        /* Restore template to it's original state. */
     413                        snprintf(tptr, 7, "XXXXXX");
     414                }
     415        }
     416       
     417        return fd;
     418}
     419
     420/**
     421 * Creates an unique temporary file name from template.
     422 *
     423 * @param tmpl Template. Last six characters must be XXXXXX.
     424 * @return The value of tmpl. The template is modified in place.
     425 *    If no temporary file name can be created, template is
     426 *    reduced to an empty string.
    390427 */
    391428char *posix_mktemp(char *tmpl)
    392429{
    393         // TODO: low priority, just a compile-time dependency of binutils
    394         not_implemented();
     430        int tmpl_len = posix_strlen(tmpl);
     431        if (tmpl_len < 6) {
     432                errno = EINVAL;
     433                *tmpl = '\0';
     434                return tmpl;
     435        }
     436       
     437        char *tptr = tmpl + tmpl_len - 6;
     438        if (posix_strcmp(tptr, "XXXXXX") != 0) {
     439                errno = EINVAL;
     440                *tmpl = '\0';
     441                return tmpl;
     442        }
     443       
     444        static int seq = 0;
     445       
     446        for (; seq < 1000000; ++seq) {
     447                snprintf(tptr, 7, "%06d", seq);
     448               
     449                int orig_errno = errno;
     450                errno = 0;
     451                /* Check if the file exists. */
     452                if (posix_access(tmpl, F_OK) == -1) {
     453                        if (errno == ENOENT) {
     454                                errno = orig_errno;
     455                                break;
     456                        } else {
     457                                /* errno set by access() */
     458                                *tmpl = '\0';
     459                                return tmpl;
     460                        }
     461                }
     462        }
     463       
     464        if (seq == 10000000) {
     465                errno = EEXIST;
     466                *tmpl = '\0';
     467                return tmpl;
     468        }
     469       
     470        return tmpl;
    395471}
    396472
    397473/**
    398474 * Get system load average statistics.
    399  *
    400  * Not supported. Always returns -1.
    401475 *
    402476 * @param loadavg Array where the load averages shall be placed.
     
    406480int bsd_getloadavg(double loadavg[], int nelem)
    407481{
    408         return -1;
     482        assert(nelem > 0);
     483       
     484        size_t count;
     485        load_t *loads = stats_get_load(&count);
     486       
     487        if (loads == NULL) {
     488                return -1;
     489        }
     490       
     491        if (((size_t) nelem) < count) {
     492                count = nelem;
     493        }
     494       
     495        for (size_t i = 0; i < count; ++i) {
     496                loadavg[i] = (double) loads[i];
     497        }
     498       
     499        free(loads);
     500        return count;
    409501}
    410502
  • uspace/lib/posix/stdlib.h

    re898296d r3e01316f  
    113113extern void posix_free(void *ptr);
    114114
     115/* Temporary Files */
     116extern int posix_mkstemp(char *tmpl);
     117
    115118/* Legacy Declarations */
    116119extern char *posix_mktemp(char *tmpl);
     
    158161        #define free posix_free
    159162
     163        #define mkstemp posix_mkstemp
     164
    160165        #define mktemp posix_mktemp
    161166        #define getloadavg bsd_getloadavg
  • uspace/lib/posix/stdlib/strtold.c

    re898296d r3e01316f  
    4848#include "../limits.h"
    4949
    50 // FIXME: #include <float.h>
     50#include "../float.h"
    5151
    5252#ifndef HUGE_VALL
  • uspace/lib/posix/string.c

    re898296d r3e01316f  
    553553char *posix_strerror(int errnum)
    554554{
    555         /* Uses function from libc, we just have to negate errno
    556          * (POSIX uses positive errorcodes, HelenOS has negative).
    557          */
    558         // FIXME: not all POSIX error codes are in libc
    559         return (char *) str_error(-posix_abs(errnum));
     555        static const char *error_msgs[] = {
     556                [E2BIG] = "[E2BIG] Argument list too long",
     557                [EACCES] = "[EACCES] Permission denied",
     558                [EADDRINUSE] = "[EADDRINUSE] Address in use",
     559                [EADDRNOTAVAIL] = "[EADDRNOTAVAIL] Address not available",
     560                [EAFNOSUPPORT] = "[EAFNOSUPPORT] Address family not supported",
     561                [EAGAIN] = "[EAGAIN] Resource unavailable, try again",
     562                [EALREADY] = "[EALREADY] Connection already in progress",
     563                [EBADF] = "[EBADF] Bad file descriptor",
     564                [EBADMSG] = "[EBADMSG] Bad message",
     565                [EBUSY] = "[EBUSY] Device or resource busy",
     566                [ECANCELED] = "[ECANCELED] Operation canceled",
     567                [ECHILD] = "[ECHILD] No child processes",
     568                [ECONNABORTED] = "[ECONNABORTED] Connection aborted",
     569                [ECONNREFUSED] = "[ECONNREFUSED] Connection refused",
     570                [ECONNRESET] = "[ECONNRESET] Connection reset",
     571                [EDEADLK] = "[EDEADLK] Resource deadlock would occur",
     572                [EDESTADDRREQ] = "[EDESTADDRREQ] Destination address required",
     573                [EDOM] = "[EDOM] Mathematics argument out of domain of function",
     574                [EDQUOT] = "[EDQUOT] Reserved",
     575                [EEXIST] = "[EEXIST] File exists",
     576                [EFAULT] = "[EFAULT] Bad address",
     577                [EFBIG] = "[EFBIG] File too large",
     578                [EHOSTUNREACH] = "[EHOSTUNREACH] Host is unreachable",
     579                [EIDRM] = "[EIDRM] Identifier removed",
     580                [EILSEQ] = "[EILSEQ] Illegal byte sequence",
     581                [EINPROGRESS] = "[EINPROGRESS] Operation in progress",
     582                [EINTR] = "[EINTR] Interrupted function",
     583                [EINVAL] = "[EINVAL] Invalid argument",
     584                [EIO] = "[EIO] I/O error",
     585                [EISCONN] = "[EISCONN] Socket is connected",
     586                [EISDIR] = "[EISDIR] Is a directory",
     587                [ELOOP] = "[ELOOP] Too many levels of symbolic links",
     588                [EMFILE] = "[EMFILE] File descriptor value too large",
     589                [EMLINK] = "[EMLINK] Too many links",
     590                [EMSGSIZE] = "[EMSGSIZE] Message too large",
     591                [EMULTIHOP] = "[EMULTIHOP] Reserved",
     592                [ENAMETOOLONG] = "[ENAMETOOLONG] Filename too long",
     593                [ENETDOWN] = "[ENETDOWN] Network is down",
     594                [ENETRESET] = "[ENETRESET] Connection aborted by network",
     595                [ENETUNREACH] = "[ENETUNREACH] Network unreachable",
     596                [ENFILE] = "[ENFILE] Too many files open in system",
     597                [ENOBUFS] = "[ENOBUFS] No buffer space available",
     598                [ENODATA] = "[ENODATA] No message is available on the STREAM head read queue",
     599                [ENODEV] = "[ENODEV] No such device",
     600                [ENOENT] = "[ENOENT] No such file or directory",
     601                [ENOEXEC] = "[ENOEXEC] Executable file format error",
     602                [ENOLCK] = "[ENOLCK] No locks available",
     603                [ENOLINK] = "[ENOLINK] Reserved",
     604                [ENOMEM] = "[ENOMEM] Not enough space",
     605                [ENOMSG] = "[ENOMSG] No message of the desired type",
     606                [ENOPROTOOPT] = "[ENOPROTOOPT] Protocol not available",
     607                [ENOSPC] = "[ENOSPC] No space left on device",
     608                [ENOSR] = "[ENOSR] No STREAM resources.",
     609                [ENOSTR] = "[ENOSTR] Not a STREAM",
     610                [ENOSYS] = "[ENOSYS] Function not supported",
     611                [ENOTCONN] = "[ENOTCONN] The socket is not connected",
     612                [ENOTDIR] = "[ENOTDIR] Not a directory",
     613                [ENOTEMPTY] = "[ENOTEMPTY] Directory not empty",
     614                [ENOTRECOVERABLE] = "[ENOTRECOVERABLE] State not recoverable",
     615                [ENOTSOCK] = "[ENOTSOCK] Not a socket",
     616                [ENOTSUP] = "[ENOTSUP] Not supported",
     617                [ENOTTY] = "[ENOTTY] Inappropriate I/O control operation",
     618                [ENXIO] = "[ENXIO] No such device or address",
     619                [EOPNOTSUPP] = "[EOPNOTSUPP] Operation not supported",
     620                [EOVERFLOW] = "[EOVERFLOW] Value too large to be stored in data type",
     621                [EOWNERDEAD] = "[EOWNERDEAD] Previous owned died",
     622                [EPERM] = "[EPERM] Operation not permitted",
     623                [EPIPE] = "[EPIPE] Broken pipe",
     624                [EPROTO] = "[EPROTO] Protocol error",
     625                [EPROTONOSUPPORT] = "[EPROTONOSUPPORT] Protocol not supported",
     626                [EPROTOTYPE] = "[EPROTOTYPE] Protocol wrong type for socket",
     627                [ERANGE] = "[ERANGE] Result too large",
     628                [EROFS] = "[EROFS] Read-only file system",
     629                [ESPIPE] = "[ESPIPE] Invalid seek",
     630                [ESRCH] = "[ESRCH] No such process",
     631                [ESTALE] = "[ESTALE] Reserved",
     632                [ETIME] = "[ETIME] Stream ioctl() timeout",
     633                [ETIMEDOUT] = "[ETIMEDOUT] Connection timed out",
     634                [ETXTBSY] = "[ETXTBSY] Text file busy",
     635                [EWOULDBLOCK] = "[EWOULDBLOCK] Operation would block",
     636                [EXDEV] = "[EXDEV] Cross-device link",
     637        };
     638
     639        return (char *) error_msgs[posix_abs(errnum)];
    560640}
    561641
     
    573653       
    574654        char *errstr = posix_strerror(errnum);
    575         /* HelenOS str_error can't fail */
    576655       
    577656        if (posix_strlen(errstr) + 1 > bufsz) {
    578                 return -ERANGE;
     657                return ERANGE;
    579658        } else {
    580659                posix_strcpy(buf, errstr);
  • uspace/lib/posix/sys/stat.c

    re898296d r3e01316f  
    5252        memset(dest, 0, sizeof(struct posix_stat));
    5353       
    54         dest->st_dev = src->device;
     54        dest->st_dev = src->service;
    5555        dest->st_ino = src->index;
    5656       
  • uspace/lib/posix/sys/wait.c

    re898296d r3e01316f  
    6767
    6868/**
     69 * Wait for any child process to stop or terminate.
    6970 *
    70  * @param stat_ptr
    71  * @return
     71 * @param stat_ptr Location of the final status code of the child process.
     72 * @return ID of the child process for which status is reported,
     73 *     -1 on signal interrupt, (pid_t)-1 otherwise.
    7274 */
    7375posix_pid_t posix_wait(int *stat_ptr)
     
    7981
    8082/**
     83 * Wait for a child process to stop or terminate.
    8184 *
    82  * @param pid
    83  * @param stat_ptr
    84  * @param options
    85  * @return
     85 * @param pid What child process shall the caller wait for. See POSIX manual
     86 *     for details.
     87 * @param stat_ptr Location of the final status code of the child process.
     88 * @param options Constraints of the waiting. See POSIX manual for details.
     89 * @return ID of the child process for which status is reported,
     90 *     -1 on signal interrupt, 0 if non-blocking wait is requested but there is
     91 *     no child process whose status can be reported, (pid_t)-1 otherwise.
    8692 */
    8793posix_pid_t posix_waitpid(posix_pid_t pid, int *stat_ptr, int options)
  • uspace/lib/posix/time.c

    re898296d r3e01316f  
    5454// TODO: test everything in this file
    5555
     56/* In some places in this file, phrase "normalized broken-down time" is used.
     57 * This means time broken down to components (year, month, day, hour, min, sec),
     58 * in which every component is in its proper bounds. Non-normalized time could
     59 * e.g. be 2011-54-5 29:13:-5, which would semantically mean start of year 2011
     60 * + 53 months + 4 days + 29 hours + 13 minutes - 5 seconds.
     61 */
     62
     63
     64
    5665/* Helper functions ***********************************************************/
    5766
     
    6372#define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
    6473
    65 /**
    66  *
    67  * @param year
    68  * @return
     74/** Checks whether the year is a leap year.
     75 *
     76 * @param year Year since 1900 (e.g. for 1970, the value is 70).
     77 * @return true if year is a leap year, false otherwise
    6978 */
    7079static bool _is_leap_year(time_t year)
     
    8190}
    8291
    83 /**
    84  *
    85  * @param year
    86  * @param mon
    87  * @return
     92/** Returns how many days there are in the given month of the given year.
     93 *  Note that year is only taken into account if month is February.
     94 *
     95 * @param year Year since 1900 (can be negative).
     96 * @param mon Month of the year. 0 for January, 11 for December.
     97 * @return Number of days in the specified month.
    8898 */
    8999static int _days_in_month(time_t year, time_t mon)
    90100{
    91101        assert(mon >= 0 && mon <= 11);
    92         year += 1900;
    93102
    94103        static int month_days[] =
     
    96105
    97106        if (mon == 1) {
     107                year += 1900;
    98108                /* february */
    99109                return _is_leap_year(year) ? 29 : 28;
     
    103113}
    104114
    105 /**
    106  *
    107  * @param year
    108  * @param mon
    109  * @param mday
    110  * @return
     115/** For specified year, month and day of month, returns which day of that year
     116 *  it is.
     117 *
     118 * For example, given date 2011-01-03, the corresponding expression is:
     119 *     _day_of_year(111, 0, 3) == 2
     120 *
     121 * @param year Year (year 1900 = 0, can be negative).
     122 * @param mon Month (January = 0).
     123 * @param mday Day of month (First day is 1).
     124 * @return Day of year (First day is 0).
    111125 */
    112126static int _day_of_year(time_t year, time_t mon, time_t mday)
     
    120134}
    121135
    122 /**
    123  * Integer division that rounds to negative infinity.
     136/** Integer division that rounds to negative infinity.
     137 *  Used by some functions in this file.
    124138 *
    125139 * @param op1
     
    136150}
    137151
    138 /**
    139  * Modulo that rounds to negative infinity.
     152/** Modulo that rounds to negative infinity.
     153 *  Used by some functions in this file.
    140154 *
    141155 * @param op1
     
    160174}
    161175
    162 /**
    163  *
    164  * @param year
    165  * @param mon
    166  * @param mday
    167  * @return
     176/** Number of days since the Epoch.
     177 *  Epoch is 1970-01-01, which is also equal to day 0.
     178 *
     179 * @param year Year (year 1900 = 0, may be negative).
     180 * @param mon Month (January = 0).
     181 * @param mday Day of month (first day = 1).
     182 * @return Number of days since the Epoch.
    168183 */
    169184static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
     
    174189}
    175190
    176 /**
    177  * Assumes normalized broken-down time.
    178  *
    179  * @param tm
    180  * @return
     191/** Seconds since the Epoch. see also _days_since_epoch().
     192 *
     193 * @param tm Normalized broken-down time.
     194 * @return Number of seconds since the epoch, not counting leap seconds.
    181195 */
    182196static time_t _secs_since_epoch(const struct posix_tm *tm)
     
    187201}
    188202
    189 /**
    190  *
    191  * @param year
    192  * @param mon
    193  * @param mday
    194  * @return
     203/** Which day of week the specified date is.
     204 *
     205 * @param year Year (year 1900 = 0).
     206 * @param mon Month (January = 0).
     207 * @param mday Day of month (first = 1).
     208 * @return Day of week (Sunday = 0).
    195209 */
    196210static int _day_of_week(time_t year, time_t mon, time_t mday)
    197211{
    198212        /* 1970-01-01 is Thursday */
    199         return (_days_since_epoch(year, mon, mday) + 4) % 7;
    200 }
    201 
    202 struct _long_tm {
    203         time_t tm_sec;
    204         time_t tm_min;
    205         time_t tm_hour;
    206         time_t tm_mday;
    207         time_t tm_mon;
    208         time_t tm_year;
    209         int tm_wday;
    210         int tm_yday;
    211         int tm_isdst;
    212 };
    213 
    214 /**
    215  *
    216  * @param ltm
    217  * @param ptm
    218  */
    219 static void _posix_to_long_tm(struct _long_tm *ltm, struct posix_tm *ptm)
    220 {
    221         assert(ltm != NULL && ptm != NULL);
    222         ltm->tm_sec = ptm->tm_sec;
    223         ltm->tm_min = ptm->tm_min;
    224         ltm->tm_hour = ptm->tm_hour;
    225         ltm->tm_mday = ptm->tm_mday;
    226         ltm->tm_mon = ptm->tm_mon;
    227         ltm->tm_year = ptm->tm_year;
    228         ltm->tm_wday = ptm->tm_wday;
    229         ltm->tm_yday = ptm->tm_yday;
    230         ltm->tm_isdst = ptm->tm_isdst;
    231 }
    232 
    233 /**
    234  *
    235  * @param ptm
    236  * @param ltm
    237  */
    238 static void _long_to_posix_tm(struct posix_tm *ptm, struct _long_tm *ltm)
    239 {
    240         assert(ltm != NULL && ptm != NULL);
    241         // FIXME: the cast should be unnecessary, libarch/common.h brain-damage
    242         assert((ltm->tm_year >= (int) INT_MIN) && (ltm->tm_year <= (int) INT_MAX));
    243 
    244         ptm->tm_sec = ltm->tm_sec;
    245         ptm->tm_min = ltm->tm_min;
    246         ptm->tm_hour = ltm->tm_hour;
    247         ptm->tm_mday = ltm->tm_mday;
    248         ptm->tm_mon = ltm->tm_mon;
    249         ptm->tm_year = ltm->tm_year;
    250         ptm->tm_wday = ltm->tm_wday;
    251         ptm->tm_yday = ltm->tm_yday;
    252         ptm->tm_isdst = ltm->tm_isdst;
    253 }
    254 
    255 /**
    256  *
    257  * @param tm
    258  */
    259 static void _normalize_time(struct _long_tm *tm)
     213        return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
     214}
     215
     216/** Normalizes the broken-down time and optionally adds specified amount of
     217 *  seconds.
     218 *
     219 * @param tm Broken-down time to normalize.
     220 * @param sec_add Seconds to add.
     221 * @return 0 on success, -1 on overflow
     222 */
     223static int _normalize_time(struct posix_tm *tm, time_t sec_add)
    260224{
    261225        // TODO: DST correction
    262226
     227        /* Set initial values. */
     228        time_t sec = tm->tm_sec + sec_add;
     229        time_t min = tm->tm_min;
     230        time_t hour = tm->tm_hour;
     231        time_t day = tm->tm_mday - 1;
     232        time_t mon = tm->tm_mon;
     233        time_t year = tm->tm_year;
     234
    263235        /* Adjust time. */
    264         tm->tm_min += _floor_div(tm->tm_sec, SECS_PER_MIN);
    265         tm->tm_sec = _floor_mod(tm->tm_sec, SECS_PER_MIN);
    266         tm->tm_hour += _floor_div(tm->tm_min, MINS_PER_HOUR);
    267         tm->tm_min = _floor_mod(tm->tm_min, MINS_PER_HOUR);
    268         tm->tm_mday += _floor_div(tm->tm_hour, HOURS_PER_DAY);
    269         tm->tm_hour = _floor_mod(tm->tm_hour, HOURS_PER_DAY);
     236        min += _floor_div(sec, SECS_PER_MIN);
     237        sec = _floor_mod(sec, SECS_PER_MIN);
     238        hour += _floor_div(min, MINS_PER_HOUR);
     239        min = _floor_mod(min, MINS_PER_HOUR);
     240        day += _floor_div(hour, HOURS_PER_DAY);
     241        hour = _floor_mod(hour, HOURS_PER_DAY);
    270242
    271243        /* Adjust month. */
    272         tm->tm_year += _floor_div(tm->tm_mon, 12);
    273         tm->tm_mon = _floor_mod(tm->tm_mon, 12);
     244        year += _floor_div(mon, 12);
     245        mon = _floor_mod(mon, 12);
    274246
    275247        /* Now the difficult part - days of month. */
    276         /* Slow, but simple. */
    277         // FIXME: do this faster
    278 
    279         while (tm->tm_mday < 1) {
    280                 tm->tm_mon--;
    281                 if (tm->tm_mon == -1) {
    282                         tm->tm_mon = 11;
    283                         tm->tm_year--;
     248       
     249        /* First, deal with whole cycles of 400 years = 146097 days. */
     250        year += _floor_div(day, 146097) * 400;
     251        day = _floor_mod(day, 146097);
     252       
     253        /* Then, go in one year steps. */
     254        if (mon <= 1) {
     255                /* January and February. */
     256                while (day > 365) {
     257                        day -= _is_leap_year(year) ? 366 : 365;
     258                        year++;
    284259                }
    285                
    286                 tm->tm_mday += _days_in_month(tm->tm_year, tm->tm_mon);
    287         }
    288 
    289         while (tm->tm_mday > _days_in_month(tm->tm_year, tm->tm_mon)) {
    290                 tm->tm_mday -= _days_in_month(tm->tm_year, tm->tm_mon);
    291                
    292                 tm->tm_mon++;
    293                 if (tm->tm_mon == 12) {
    294                         tm->tm_mon = 0;
    295                         tm->tm_year++;
     260        } else {
     261                /* Rest of the year. */
     262                while (day > 365) {
     263                        day -= _is_leap_year(year + 1) ? 366 : 365;
     264                        year++;
    296265                }
    297266        }
    298 
     267       
     268        /* Finally, finish it off month per month. */
     269        while (day >= _days_in_month(year, mon)) {
     270                day -= _days_in_month(year, mon);
     271                mon++;
     272                if (mon >= 12) {
     273                        mon -= 12;
     274                        year++;
     275                }
     276        }
     277       
    299278        /* Calculate the remaining two fields. */
    300         tm->tm_yday = _day_of_year(tm->tm_year, tm->tm_mon, tm->tm_mday);
    301         tm->tm_wday = _day_of_week(tm->tm_year, tm->tm_mon, tm->tm_mday);
    302 }
    303 
    304 /**
    305  * Which day the week-based year starts on relative to the first calendar day.
    306  * E.g. if the year starts on December 31st, the return value is -1.
    307  *
    308  * @param year
    309  * @return
     279        tm->tm_yday = _day_of_year(year, mon, day + 1);
     280        tm->tm_wday = _day_of_week(year, mon, day + 1);
     281       
     282        /* And put the values back to the struct. */
     283        tm->tm_sec = (int) sec;
     284        tm->tm_min = (int) min;
     285        tm->tm_hour = (int) hour;
     286        tm->tm_mday = (int) day + 1;
     287        tm->tm_mon = (int) mon;
     288       
     289        /* Casts to work around libc brain-damage. */
     290        if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
     291                tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
     292                return -1;
     293        }
     294       
     295        tm->tm_year = (int) year;
     296        return 0;
     297}
     298
     299/** Which day the week-based year starts on, relative to the first calendar day.
     300 *  E.g. if the year starts on December 31st, the return value is -1.
     301 *
     302 * @param Year since 1900.
     303 * @return Offset of week-based year relative to calendar year.
    310304 */
    311305static int _wbyear_offset(int year)
     
    315309}
    316310
    317 /**
    318  * Returns week-based year of the specified time.
    319  * Assumes normalized broken-down time.
    320  *
    321  * @param tm
    322  * @return
     311/** Returns week-based year of the specified time.
     312 *
     313 * @param tm Normalized broken-down time.
     314 * @return Week-based year.
    323315 */
    324316static int _wbyear(const struct posix_tm *tm)
     
    329321                return tm->tm_year - 1;
    330322        }
    331         if (day > 364 + _is_leap_year(tm->tm_year)){
     323        if (day > 364 + _is_leap_year(tm->tm_year)) {
    332324                /* First week of next year. */
    333325                return tm->tm_year + 1;
     
    337329}
    338330
    339 /**
    340  * Week number of the year, assuming weeks start on sunday.
    341  * The first Sunday of January is the first day of week 1;
    342  * days in the new year before this are in week 0.
     331/** Week number of the year, assuming weeks start on sunday.
     332 *  The first Sunday of January is the first day of week 1;
     333 *  days in the new year before this are in week 0.
    343334 *
    344335 * @param tm Normalized broken-down time.
     
    351342}
    352343
    353 /**
    354  * Week number of the year, assuming weeks start on monday.
    355  * If the week containing January 1st has four or more days in the new year,
    356  * then it is considered week 1. Otherwise, it is the last week of the previous
    357  * year, and the next week is week 1. Both January 4th and the first Thursday
    358  * of January are always in week 1.
     344/** Week number of the year, assuming weeks start on monday.
     345 *  If the week containing January 1st has four or more days in the new year,
     346 *  then it is considered week 1. Otherwise, it is the last week of the previous
     347 *  year, and the next week is week 1. Both January 4th and the first Thursday
     348 *  of January are always in week 1.
    359349 *
    360350 * @param tm Normalized broken-down time.
     
    368358                return 53;
    369359        }
    370         if (day > 364 + _is_leap_year(tm->tm_year)){
     360        if (day > 364 + _is_leap_year(tm->tm_year)) {
    371361                /* First week of next year. */
    372362                return 1;
     
    376366}
    377367
    378 /**
    379  * Week number of the year, assuming weeks start on monday.
    380  * The first Monday of January is the first day of week 1;
    381  * days in the new year before this are in week 0.
     368/** Week number of the year, assuming weeks start on monday.
     369 *  The first Monday of January is the first day of week 1;
     370 *  days in the new year before this are in week 0.
    382371 *
    383372 * @param tm Normalized broken-down time.
     
    396385char *posix_tzname[2];
    397386
    398 /**
     387/** Set timezone conversion information.
    399388 *
    400389 */
     
    408397}
    409398
    410 /**
     399/** Calculate the difference between two times, in seconds.
    411400 *
    412401 * @param time1
    413402 * @param time0
    414  * @return
     403 * @return Time in seconds.
    415404 */
    416405double posix_difftime(time_t time1, time_t time0)
     
    419408}
    420409
    421 /**
    422  * This function first normalizes the provided broken-down time
    423  * (moves all values to their proper bounds) and then tries to
    424  * calculate the appropriate time_t representation.
     410/** This function first normalizes the provided broken-down time
     411 *  (moves all values to their proper bounds) and then tries to
     412 *  calculate the appropriate time_t representation.
    425413 *
    426414 * @param tm Broken-down time.
     
    432420        // TODO: detect overflow
    433421
    434         struct _long_tm ltm;
    435         _posix_to_long_tm(&ltm, tm);
    436         _normalize_time(&ltm);
    437         _long_to_posix_tm(tm, &ltm);
    438 
     422        _normalize_time(tm, 0);
    439423        return _secs_since_epoch(tm);
    440424}
    441425
    442 /**
    443  *
    444  * @param timer
    445  * @return
     426/** Converts a time value to a broken-down UTC time.
     427 *
     428 * @param timer Time to convert.
     429 * @return Normalized broken-down time in UTC, NULL on overflow.
    446430 */
    447431struct posix_tm *posix_gmtime(const time_t *timer)
    448432{
     433        assert(timer != NULL);
     434
    449435        static struct posix_tm result;
    450436        return posix_gmtime_r(timer, &result);
    451437}
    452438
    453 /**
    454  *
    455  * @param timer
    456  * @param result
    457  * @return
     439/** Converts a time value to a broken-down UTC time.
     440 *
     441 * @param timer Time to convert.
     442 * @param result Structure to store the result to.
     443 * @return Value of result on success, NULL on overflow.
    458444 */
    459445struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
     
    463449        assert(result != NULL);
    464450
    465         /* Set epoch and seconds to _long_tm struct and normalize to get
    466          * correct values.
    467          */
    468         struct _long_tm ltm = {
    469                 .tm_sec = *timer,
    470                 .tm_min = 0,
    471                 .tm_hour = 0, /* 00:00:xx */
    472                 .tm_mday = 1,
    473                 .tm_mon = 0, /* January 1st */
    474                 .tm_year = 70, /* 1970 */
    475         };
    476         _normalize_time(&ltm);
    477 
    478         if (ltm.tm_year < (int) INT_MIN || ltm.tm_year > (int) INT_MAX) {
     451        /* Set result to epoch. */
     452        result->tm_sec = 0;
     453        result->tm_min = 0;
     454        result->tm_hour = 0;
     455        result->tm_mday = 1;
     456        result->tm_mon = 0;
     457        result->tm_year = 70; /* 1970 */
     458
     459        if (_normalize_time(result, *timer) == -1) {
    479460                errno = EOVERFLOW;
    480461                return NULL;
    481462        }
    482463
    483         _long_to_posix_tm(result, &ltm);
    484464        return result;
    485465}
    486466
    487 /**
    488  *
    489  * @param timer
    490  * @return
     467/** Converts a time value to a broken-down local time.
     468 *
     469 * @param timer Time to convert.
     470 * @return Normalized broken-down time in local timezone, NULL on overflow.
    491471 */
    492472struct posix_tm *posix_localtime(const time_t *timer)
     
    496476}
    497477
    498 /**
    499  *
    500  * @param timer
    501  * @param result
    502  * @return
     478/** Converts a time value to a broken-down local time.
     479 *
     480 * @param timer Time to convert.
     481 * @param result Structure to store the result to.
     482 * @return Value of result on success, NULL on overflow.
    503483 */
    504484struct posix_tm *posix_localtime_r(const time_t *restrict timer,
     
    510490}
    511491
    512 /**
    513  *
    514  * @param timeptr
    515  * @return
     492/** Converts broken-down time to a string in format
     493 *  "Sun Jan 1 00:00:00 1970\n". (Obsolete)
     494 *
     495 * @param timeptr Broken-down time structure.
     496 * @return Pointer to a statically allocated string.
    516497 */
    517498char *posix_asctime(const struct posix_tm *timeptr)
     
    521502}
    522503
    523 /**
    524  *
    525  * @param timeptr
    526  * @param buf
    527  * @return
     504/** Converts broken-down time to a string in format
     505 *  "Sun Jan 1 00:00:00 1970\n". (Obsolete)
     506 *
     507 * @param timeptr Broken-down time structure.
     508 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN
     509 *     bytes long.
     510 * @return Value of buf.
    528511 */
    529512char *posix_asctime_r(const struct posix_tm *restrict timeptr,
     
    551534}
    552535
    553 /**
    554  *
    555  * @param timer
    556  * @return
     536/** Equivalent to asctime(localtime(clock)).
     537 *
     538 * @param timer Time to convert.
     539 * @return Pointer to a statically allocated string holding the date.
    557540 */
    558541char *posix_ctime(const time_t *timer)
     
    565548}
    566549
    567 /**
    568  *
    569  * @param timer
    570  * @param buf
    571  * @return
     550/** Reentrant variant of ctime().
     551 *
     552 * @param timer Time to convert.
     553 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN
     554 *     bytes long.
     555 * @return Pointer to buf on success, NULL on falure.
    572556 */
    573557char *posix_ctime_r(const time_t *timer, char *buf)
     
    580564}
    581565
    582 /**
    583  *
    584  * @param s
    585  * @param maxsize
    586  * @param format
    587  * @param tm
    588  * @return
     566/** Convert time and date to a string, based on a specified format and
     567 *  current locale.
     568 *
     569 * @param s Buffer to write string to.
     570 * @param maxsize Size of the buffer.
     571 * @param format Format of the output.
     572 * @param tm Broken-down time to format.
     573 * @return Number of bytes written.
    589574 */
    590575size_t posix_strftime(char *restrict s, size_t maxsize,
    591576    const char *restrict format, const struct posix_tm *restrict tm)
    592577{
     578        assert(s != NULL);
     579        assert(format != NULL);
     580        assert(tm != NULL);
     581
    593582        // TODO: use locale
    594583        static const char *wday_abbr[] = {
     
    766755}
    767756
    768 /**
    769  *
    770  * @param s
    771  * @param maxsize
    772  * @param format
    773  * @param tm
    774  * @param loc
    775  * @return
    776  */
    777 extern size_t posix_strftime_l(char *restrict s, size_t maxsize,
    778     const char *restrict format, const struct posix_tm *restrict tm,
    779     posix_locale_t loc)
    780 {
    781         // TODO
    782         not_implemented();
    783 }
    784 
    785 /**
    786  *
    787  * @param clock_id
    788  * @param res
    789  * @return
     757/** Get clock resolution. Only CLOCK_REALTIME is supported.
     758 *
     759 * @param clock_id Clock ID.
     760 * @param res Pointer to the variable where the resolution is to be written.
     761 * @return 0 on success, -1 with errno set on failure.
    790762 */
    791763int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res)
     
    804776}
    805777
    806 /**
    807  *
    808  * @param clock_id
    809  * @param tp
     778/** Get time. Only CLOCK_REALTIME is supported.
     779 *
     780 * @param clock_id ID of the clock to query.
     781 * @param tp Pointer to the variable where the time is to be written.
    810782 * @return
    811783 */
     
    828800}
    829801
    830 /**
    831  *
    832  * @param clock_id
    833  * @param tp
    834  * @return
     802/** Set time on a specified clock. As HelenOS doesn't support this yet,
     803 *  this function always fails.
     804 *
     805 * @param clock_id ID of the clock to set.
     806 * @param tp Time to set.
     807 * @return 0 on success, -1 with errno on failure.
    835808 */
    836809int posix_clock_settime(posix_clockid_t clock_id,
     
    852825}
    853826
    854 /**
    855  *
    856  * @param clock_id
    857  * @param flags
    858  * @param rqtp
    859  * @param rmtp
    860  * @return
     827/** Sleep on a specified clock.
     828 *
     829 * @param clock_id ID of the clock to sleep on (only CLOCK_REALTIME supported).
     830 * @param flags Flags (none supported).
     831 * @param rqtp Sleep time.
     832 * @param rmtp Remaining time is written here if sleep is interrupted.
     833 * @return 0 on success, -1 with errno set on failure.
    861834 */
    862835int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
     
    882855}
    883856
    884 #if 0
    885 
    886 struct __posix_timer {
    887         posix_clockid_t clockid;
    888         struct posix_sigevent evp;
    889 };
    890 
    891 /**
    892  *
    893  * @param clockid
    894  * @param evp
    895  * @param timerid
    896  * @return
    897  */
    898 int posix_timer_create(posix_clockid_t clockid,
    899     struct posix_sigevent *restrict evp,
    900     posix_timer_t *restrict timerid)
    901 {
    902         // TODO
    903         not_implemented();
    904 }
    905 
    906 /**
    907  *
    908  * @param timerid
    909  * @return
    910  */
    911 int posix_timer_delete(posix_timer_t timerid)
    912 {
    913         // TODO
    914         not_implemented();
    915 }
    916 
    917 /**
    918  *
    919  * @param timerid
    920  * @return
    921  */
    922 int posix_timer_getoverrun(posix_timer_t timerid)
    923 {
    924         // TODO
    925         not_implemented();
    926 }
    927 
    928 /**
    929  *
    930  * @param timerid
    931  * @param value
    932  * @return
    933  */
    934 int posix_timer_gettime(posix_timer_t timerid,
    935     struct posix_itimerspec *value)
    936 {
    937         // TODO
    938         not_implemented();
    939 }
    940 
    941 /**
    942  *
    943  * @param timerid
    944  * @param flags
    945  * @param value
    946  * @param ovalue
    947  * @return
    948  */
    949 int posix_timer_settime(posix_timer_t timerid, int flags,
    950     const struct posix_itimerspec *restrict value,
    951     struct posix_itimerspec *restrict ovalue)
    952 {
    953         // TODO
    954         not_implemented();
    955 }
    956 
    957 #endif
    958 
    959 /**
    960  * Get CPU time used since the process invocation.
     857/** Get CPU time used since the process invocation.
    961858 *
    962859 * @return Consumed CPU cycles by this process or -1 if not available.
  • uspace/lib/posix/time.h

    re898296d r3e01316f  
    119119extern size_t posix_strftime(char *restrict s, size_t maxsize,
    120120    const char *restrict format, const struct posix_tm *restrict tm);
    121 extern size_t posix_strftime_l(char *restrict s, size_t maxsize,
    122     const char *restrict format, const struct posix_tm *restrict tm,
    123     posix_locale_t loc);
    124121
    125122/* Clocks */
     
    132129extern int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
    133130    const struct posix_timespec *rqtp, struct posix_timespec *rmtp);
    134 
    135 #if 0
    136 
    137 /* Timers */
    138 extern int posix_timer_create(posix_clockid_t clockid,
    139     struct posix_sigevent *restrict evp,
    140     posix_timer_t *restrict timerid);
    141 extern int posix_timer_delete(posix_timer_t timerid);
    142 extern int posix_timer_getoverrun(posix_timer_t timerid);
    143 extern int posix_timer_gettime(posix_timer_t timerid,
    144     struct posix_itimerspec *value);
    145 extern int posix_timer_settime(posix_timer_t timerid, int flags,
    146     const struct posix_itimerspec *restrict value,
    147     struct posix_itimerspec *restrict ovalue);
    148 
    149 #endif
    150131
    151132/* CPU Time */
     
    176157        #define ctime_r posix_ctime_r
    177158        #define strftime posix_strftime
    178         #define strftime_l posix_strftime_l
    179159
    180160        #define clock_getres posix_clock_getres
  • uspace/lib/posix/unistd.c

    re898296d r3e01316f  
    8888int posix_isatty(int fd)
    8989{
     90        // TODO
    9091        /* Always returns false, because there is no easy way to find
    9192         * out under HelenOS. */
     
    186187 * Close a file.
    187188 *
    188  * @param fildes
     189 * @param fildes File descriptor of the opened file.
    189190 * @return 0 on success, -1 on error.
    190191 */
     
    223224 * Requests outstanding data to be written to the underlying storage device.
    224225 *
    225  * @param fildes
     226 * @param fildes File descriptor of the opened file.
     227 * @return Zero on success, -1 otherwise.
    226228 */
    227229int posix_fsync(int fildes)
     
    230232}
    231233
     234/**
     235 * Truncate a file to a specified length.
     236 *
     237 * @param fildes File descriptor of the opened file.
     238 * @param length New length of the file.
     239 * @return Zero on success, -1 otherwise.
     240 */
    232241int posix_ftruncate(int fildes, posix_off_t length)
    233242{
     
    257266}
    258267
     268/**
     269 * Duplicate an open file descriptor.
     270 *
     271 * @param fildes File descriptor to be duplicated.
     272 * @return On success, new file descriptor for the same file, otherwise -1.
     273 */
    259274int posix_dup(int fildes)
    260275{
     
    262277}
    263278
     279/**
     280 * Duplicate an open file descriptor.
     281 *
     282 * @param fildes File descriptor to be duplicated.
     283 * @param fildes2 File descriptor to be paired with the same file description
     284 *     as is paired fildes.
     285 * @return fildes2 on success, -1 otherwise.
     286 */
    264287int posix_dup2(int fildes, int fildes2)
    265288{
  • uspace/lib/posix/unistd.h

    re898296d r3e01316f  
    7272/* File Manipulation */
    7373extern int posix_close(int fildes);
    74 
    7574extern ssize_t posix_read(int fildes, void *buf, size_t nbyte);
    7675extern ssize_t posix_write(int fildes, const void *buf, size_t nbyte);
    77 
    7876extern int posix_fsync(int fildes);
    7977extern int posix_ftruncate(int fildes, posix_off_t length);
    80 
    8178extern int posix_rmdir(const char *path);
    8279extern int posix_unlink(const char *path);
    83 
    8480extern int posix_dup(int fildes);
    8581extern int posix_dup2(int fildes, int fildes2);
Note: See TracChangeset for help on using the changeset viewer.