Changeset ee24574 in mainline for uspace/lib/posix


Ignore:
Timestamp:
2011-08-18T08:00:42Z (15 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a92cf94f
Parents:
0f963cb (diff), c53a705 (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 changes.

Location:
uspace/lib/posix
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/ctype.c

    r0f963cb ree24574  
    3737
    3838#include "ctype.h"
    39 
    40 // TODO: propose for inclusion in libc
    4139
    4240/**
  • uspace/lib/posix/errno.h

    r0f963cb ree24574  
    5757 * redefinition for such error codes.
    5858 *
    59  * FIXME: maybe all HOS error codes should be redefined
     59 * XXX: maybe all HOS error codes should be redefined
    6060 *
    6161 * NOTE: This redefinition is slightly POSIX incompatible, since the
     
    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

    r0f963cb ree24574  
    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
    59 /** Get collating element matching a string.
    60  *
    61  * @param str
    62  * @return
    63  */
    64 static _coll_elm_t _coll_elm_get(const char* str)
     68/**
     69 * Get collating element matching a string.
     70 *
     71 * @param str String representation of the element.
     72 * @return Matching collating element or COLL_ELM_INVALID.
     73 */
     74static coll_elm_t _coll_elm_get(const char* str)
    6575{
    6676        if (str[0] == '\0' || str[1] != '\0') {
     
    7080}
    7181
    72 /** Get collating element matching a single character.
    73  *
    74  * @param c
    75  * @return
    76  */
    77 static _coll_elm_t _coll_elm_char(int c)
     82/**
     83 * Get collating element matching a single character.
     84 *
     85 * @param c Character representation of the element.
     86 * @return Matching collating element.
     87 */
     88static coll_elm_t _coll_elm_char(int c)
    7889{
    7990        return c;
    8091}
    8192
    82 /** Match collating element with a beginning of a string.
    83  *
    84  * @param elm
    85  * @param str
     93/**
     94 * Match collating element with a beginning of a string.
     95 *
     96 * @param elm Collating element to match.
     97 * @param str String which beginning should match the element.
    8698 * @return 0 if the element doesn't match, or the number of characters matched.
    8799 */
    88 static int _coll_elm_match(_coll_elm_t elm, const char *str)
     100static int _coll_elm_match(coll_elm_t elm, const char *str)
    89101{
    90102        return elm == *str;
    91103}
    92104
    93 static int _coll_elm_between(_coll_elm_t first, _coll_elm_t second,
     105/**
     106 * Checks whether a string begins with a collating element in the given range.
     107 * Ordering depends on the locale (if locales are supported).
     108 *
     109 * @param first First element of the range.
     110 * @param second Last element of the range.
     111 * @param str String to match.
     112 * @return 0 if there is no match, or the number of characters matched.
     113 */
     114static int _coll_elm_between(coll_elm_t first, coll_elm_t second,
    94115    const char *str)
    95116{
     
    97118}
    98119
    99 /** Read a string delimited by [? and ?].
     120/**
     121 * Read a string delimited by [? and ?].
    100122 *
    101123 * @param pattern Pointer to the string to read from. Its position is moved
     
    105127 * @param buf_sz Read buffer's size. If the buffer is not large enough for
    106128 *    the entire string, the string is cut with no error indication.
    107  * @return
     129 * @param flags Flags modifying the behavior.
     130 * @return True on success, false if the pattern is invalid.
    108131 */
    109132static bool _get_delimited(
     
    172195
    173196/**
     197 * Compare function for binary search in the _char_classes array.
    174198 *
    175  * @param key
    176  * @param elem
    177  * @return
     199 * @param key Key of the searched element.
     200 * @param elem Element of _char_classes array.
     201 * @return Ordering indicator (-1 less than, 0 equal, 1 greater than).
    178202 */
    179203static int _class_compare(const void *key, const void *elem)
     
    184208
    185209/**
     210 * Returns whether the given character belongs to the specified character class.
    186211 *
    187  * @param cname
    188  * @param c
    189  * @return
     212 * @param cname Name of the character class.
     213 * @param c Character.
     214 * @return True if the character belongs to the class, false otherwise.
    190215 */
    191216static bool _is_in_class (const char *cname, int c)
     
    206231
    207232/**
     233 * Tries to parse an initial part of the pattern as a character class pattern,
     234 * and if successful, matches the beginning of the given string against the class.
    208235 *
    209  * @param pattern
    210  * @param str
    211  * @param flags
    212  * @return
     236 * @param pattern Pointer to the pattern to match. Must begin with a class
     237 *    specifier and is repositioned to the first character after the specifier
     238 *    if successful.
     239 * @param str String to match.
     240 * @param flags Flags modifying the behavior (see fnmatch()).
     241 * @return INVALID_PATTERN if the pattern doesn't start with a valid class
     242 *    specifier, 0 if the beginning of the matched string doesn't belong
     243 *    to the class, or positive number of characters matched.
    213244 */
    214245static int _match_char_class(const char **pattern, const char *str, int flags)
     
    226257
    227258/**
     259 * Reads the next collating element in the pattern, taking into account
     260 * locale (if supported) and flags (see fnmatch()).
    228261 *
    229  * @param pattern
    230  * @param flags
    231  * @return
    232  */
    233 static _coll_elm_t _next_coll_elm(const char **pattern, int flags)
    234 {
     262 * @param pattern Pattern.
     263 * @param flags Flags given to fnmatch().
     264 * @return Collating element on success,
     265 *     or COLL_ELM_INVALID if the pattern is invalid.
     266 */
     267static coll_elm_t _next_coll_elm(const char **pattern, int flags)
     268{
     269        assert(pattern != NULL);
     270        assert(*pattern != NULL);
     271        assert(**pattern != '\0');
     272
    235273        const char *p = *pattern;
    236274        const bool noescape = (flags & FNM_NOESCAPE) != 0;
     
    257295        if (!noescape && *p == '\\') {
    258296                p++;
     297                if (*p == '\0') {
     298                        *pattern = p;
     299                        return COLL_ELM_INVALID;
     300                }
    259301        }
    260302        if (pathname && *p == '/') {
    261303                return COLL_ELM_INVALID;
    262304        }
    263 
     305       
    264306        *pattern = p + 1;
    265307        return _coll_elm_char(*p);
     
    267309
    268310/**
     311 * Matches the beginning of the given string against a bracket expression
     312 * the pattern begins with.
    269313 *
    270  * @param pattern
    271  * @param str
    272  * @param flags
    273  * @return
     314 * @param pattern Pointer to the beginning of a bracket expression in a pattern.
     315 *     On success, the pointer is moved to the first character after the
     316 *     bracket expression.
     317 * @param str Unmatched part of the string.
     318 * @param flags Flags given to fnmatch().
     319 * @return INVALID_PATTERN if the pattern is invalid, 0 if there is no match
     320 *     or the number of matched characters on success.
    274321 */
    275322static int _match_bracket_expr(const char **pattern, const char *str, int flags)
     
    315362        }
    316363       
    317         _coll_elm_t current_elm = COLL_ELM_INVALID;
     364        coll_elm_t current_elm = COLL_ELM_INVALID;
    318365       
    319366        while (*p != ']') {
     
    322369                        /* Range expression. */
    323370                        p++;
    324                         _coll_elm_t end_elm = _next_coll_elm(&p, flags);
     371                        coll_elm_t end_elm = _next_coll_elm(&p, flags);
    325372                        if (end_elm == COLL_ELM_INVALID) {
    326373                                return INVALID_PATTERN;
     
    358405
    359406/**
     407 * Matches a portion of the pattern containing no asterisks (*) against
     408 * the given string.
    360409 *
    361  * @param pattern
    362  * @param string
    363  * @param flags
    364  * @return
     410 * @param pattern Pointer to the unmatched portion of the pattern.
     411 *     On success, the pointer is moved to the first asterisk, or to the
     412 *     terminating nul character, whichever occurs first.
     413 * @param string Pointer to the input string. On success, the pointer is moved
     414 *     to the first character that wasn't explicitly matched.
     415 * @param flags Flags given to fnmatch().
     416 * @return True if the entire subpattern matched. False otherwise.
    365417 */
    366418static bool _partial_match(const char **pattern, const char **string, int flags)
     
    457509
    458510/**
     511 * Match string against a pattern.
    459512 *
    460  * @param pattern
    461  * @param string
    462  * @param flags
    463  * @return
     513 * @param pattern Pattern.
     514 * @param string String to match.
     515 * @param flags Flags given to fnmatch().
     516 * @return True if the string matched the pattern, false otherwise.
    464517 */
    465518static bool _full_match(const char *pattern, const char *string, int flags)
     
    496549                        end = string;
    497550                } else {
    498                         end= strchrnul(string, pathname ? '/' : '\0');
     551                        end = strchrnul(string, pathname ? '/' : '\0');
    499552                }
    500553
     
    519572
    520573/**
     574 * Transform the entire string to lowercase.
    521575 *
    522  * @param s
    523  * @return
     576 * @param s Input string.
     577 * @return Newly allocated copy of the input string with all uppercase
     578 *     characters folded to their lowercase variants.
    524579 */
    525580static char *_casefold(const char *s)
     
    536591 * Filename pattern matching.
    537592 *
    538  * @param pattern
    539  * @param string
    540  * @param flags
    541  * @return
     593 * @param pattern Pattern to match the string against.
     594 * @param string Matched string.
     595 * @param flags Flags altering the matching of special characters
     596 *     (mainly for dot and slash).
     597 * @return Zero if the string matches the pattern, FNM_NOMATCH otherwise.
    542598 */
    543599int posix_fnmatch(const char *pattern, const char *string, int flags)
     
    568624}
    569625
    570 // FIXME: put the testcases somewhere else
     626// FIXME: put the testcases to the app/tester after fnmatch is included into libc
    571627
    572628#if 0
  • uspace/lib/posix/locale.c

    r0f963cb ree24574  
    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 {
     
    7680
    7781/**
     82 * Set program locale.
    7883 *
    79  * @param category
    80  * @param locale
    81  * @return
     84 * @param category What category to set.
     85 * @param locale Locale name.
     86 * @return Original locale name on success, NULL on failure.
    8287 */
    8388char *posix_setlocale(int category, const char *locale)
     
    9297
    9398/**
     99 * Return locale-specific information.
    94100 *
    95  * @return
     101 * @return Information about the current locale.
    96102 */
    97103struct posix_lconv *posix_localeconv(void)
     
    102108
    103109/**
     110 * Duplicate locale object.
    104111 *
    105  * @param locobj
    106  * @return
     112 * @param locobj Object to duplicate.
     113 * @return Duplicated object.
    107114 */
    108115posix_locale_t posix_duplocale(posix_locale_t locobj)
     
    122129
    123130/**
     131 * Free locale object.
    124132 *
    125  * @param locobj
     133 * @param locobj Object to free.
    126134 */
    127135void posix_freelocale(posix_locale_t locobj)
     
    133141
    134142/**
     143 * Create or modify a locale object.
    135144 *
    136  * @param category_mask
    137  * @param locale
    138  * @param base
    139  * @return
     145 * @param category_mask Mask of categories to be set or modified.
     146 * @param locale Locale to be used.
     147 * @param base Object to modify. 0 if new object is to be created.
     148 * @return The new/modified locale object.
    140149 */
    141150posix_locale_t posix_newlocale(int category_mask, const char *locale,
     
    160169
    161170/**
     171 * Set locale for the current thread.
    162172 *
    163  * @param newloc
    164  * @return
     173 * @param newloc Locale to use.
     174 * @return The previously set locale or LC_GLOBAL_LOCALE
    165175 */
    166176posix_locale_t posix_uselocale(posix_locale_t newloc)
    167177{
    168178        // TODO
    169         return NULL;
     179        return LC_GLOBAL_LOCALE;
    170180}
    171181
  • uspace/lib/posix/locale.h

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

    r0f963cb ree24574  
    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,
     
    127137
    128138/**
    129  *
    130  * @param signo
     139 * Just an empty function to get an unique pointer value for comparison.
     140 *
     141 * @param signo Signal number.
    131142 */
    132143void __posix_hold_signal_handler(int signo)
     
    136147
    137148/**
    138  *
    139  * @param signo
     149 * Empty function to be used as ignoring handler.
     150 *
     151 * @param signo Signal number.
    140152 */
    141153void __posix_ignore_signal_handler(int signo)
     
    145157
    146158/**
    147  *
    148  * @param set
    149  * @return
     159 * Clear the signal set.
     160 *
     161 * @param set Pointer to the signal set.
     162 * @return Always returns zero.
    150163 */
    151164int posix_sigemptyset(posix_sigset_t *set)
     
    158171
    159172/**
    160  *
    161  * @param set
    162  * @return
     173 * Fill the signal set (i.e. add all signals).
     174 *
     175 * @param set Pointer to the signal set.
     176 * @return Always returns zero.
    163177 */
    164178int posix_sigfillset(posix_sigset_t *set)
     
    171185
    172186/**
    173  *
    174  * @param set
    175  * @param signo
    176  * @return
     187 * Add a signal to the set.
     188 *
     189 * @param set Pointer to the signal set.
     190 * @param signo Signal number to add.
     191 * @return Always returns zero.
    177192 */
    178193int posix_sigaddset(posix_sigset_t *set, int signo)
     
    185200
    186201/**
    187  *
    188  * @param set
    189  * @param signo
    190  * @return
     202 * Delete a signal from the set.
     203 *
     204 * @param set Pointer to the signal set.
     205 * @param signo Signal number to remove.
     206 * @return Always returns zero.
    191207 */
    192208int posix_sigdelset(posix_sigset_t *set, int signo)
     
    199215
    200216/**
    201  *
    202  * @param set
    203  * @param signo
    204  * @return
     217 * Inclusion test for a signal set.
     218 *
     219 * @param set Pointer to the signal set.
     220 * @param signo Signal number to query.
     221 * @return 1 if the signal is in the set, 0 otherwise.
    205222 */
    206223int posix_sigismember(const posix_sigset_t *set, int signo)
     
    212229
    213230/**
     231 * Unsafe variant of the sigaction() function.
     232 * Doesn't do any checking of its arguments and
     233 * does not deal with thread-safety.
    214234 *
    215235 * @param sig
     
    232252
    233253/**
    234  *
    235  * @param sig
    236  * @param act
    237  * @param oact
    238  * @return
     254 * Sets a new action for the given signal number.
     255 *
     256 * @param sig Signal number to set action for.
     257 * @param act If not NULL, contents of this structure are
     258 *     used as the new action for the signal.
     259 * @param oact If not NULL, the original action associated with the signal
     260 *     is stored in the structure pointer to.
     261 * @return -1 with errno set on failure, 0 on success.
    239262 */
    240263int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
     
    263286
    264287/**
    265  *
    266  * @param sig
    267  * @param func
    268  * @return
     288 * Sets a new handler for the given signal number.
     289 *
     290 * @param sig Signal number to set handler for.
     291 * @param func Handler function.
     292 * @return SIG_ERR on failure, original handler on success.
    269293 */
    270294void (*posix_signal(int sig, void (*func)(int)))(int)
     
    284308}
    285309
    286 /**
    287  *
    288  * @param signo
    289  * @param siginfo
    290  * @return
    291  */
    292 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     310typedef struct {
     311        link_t link;
     312        int signo;
     313        posix_siginfo_t siginfo;
     314} signal_queue_item;
     315
     316/**
     317 * Queue blocked signal.
     318 *
     319 * @param signo Signal number.
     320 * @param siginfo Additional information about the signal.
     321 */
     322static void _queue_signal(int signo, posix_siginfo_t *siginfo)
    293323{
    294324        assert(signo >= 0 && signo <= _TOP_SIGNAL);
    295325        assert(siginfo != NULL);
     326       
     327        signal_queue_item *item = malloc(sizeof(signal_queue_item));
     328        link_initialize(&(item->link));
     329        item->signo = signo;
     330        memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t));
     331        list_append(&(item->link), &_signal_queue);
     332}
     333
     334
     335/**
     336 * Executes an action associated with the given signal.
     337 *
     338 * @param signo Signal number.
     339 * @param siginfo Additional information about the circumstances of this raise.
     340 * @return 0 if the action has been successfully executed. -1 if the signal is
     341 *     blocked.
     342 */
     343static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     344{
     345        assert(signo >= 0 && signo <= _TOP_SIGNAL);
     346        assert(siginfo != NULL);
    296347
    297348        fibril_mutex_lock(&_signal_mutex);
     
    301352        if (posix_sigismember(&_signal_mask, signo) ||
    302353            action.sa_handler == SIG_HOLD) {
    303                 // TODO: queue signal
     354                _queue_signal(signo, siginfo);
    304355                fibril_mutex_unlock(&_signal_mutex);
    305356                return -1;
     
    312363        if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
    313364                _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
    314         };
     365        }
    315366
    316367        if (action.sa_flags & SA_SIGINFO) {
     
    328379
    329380/**
    330  *
    331  * @param sig
    332  * @return
     381 * Raise all unblocked previously queued signals.
     382 */
     383static void _dequeue_unblocked_signals()
     384{
     385        link_t *iterator = _signal_queue.head.next;
     386        link_t *next;
     387       
     388        while (iterator != &(_signal_queue).head) {
     389                next = iterator->next;
     390               
     391                signal_queue_item *item =
     392                    list_get_instance(iterator, signal_queue_item, link);
     393               
     394                if (!posix_sigismember(&_signal_mask, item->signo) &&
     395                    _signal_actions[item->signo].sa_handler != SIG_HOLD) {
     396                        list_remove(&(item->link));
     397                        _raise_sigaction(item->signo, &(item->siginfo));
     398                        free(item);
     399                }
     400               
     401                iterator = next;
     402        }
     403}
     404
     405/**
     406 * Raise a signal for the calling process.
     407 *
     408 * @param sig Signal number.
     409 * @return -1 with errno set on failure, 0 on success.
    333410 */
    334411int posix_raise(int sig)
     
    347424
    348425/**
    349  *
    350  * @param pid
    351  * @param signo
    352  * @return
     426 * Raises a signal for a selected process.
     427 *
     428 * @param pid PID of the process for which the signal shall be raised.
     429 * @param signo Signal to raise.
     430 * @return -1 with errno set on failure (possible errors include unsupported
     431 *     action, invalid signal number, lack of permissions, etc.), 0 on success.
    353432 */
    354433int posix_kill(posix_pid_t pid, int signo)
     
    383462
    384463/**
    385  *
    386  * @param pid
    387  * @param sig
    388  * @return
     464 * Send a signal to a process group. Always fails at the moment because of
     465 * lack of this functionality in HelenOS.
     466 *
     467 * @param pid PID of the process group.
     468 * @param sig Signal number.
     469 * @return -1 on failure, 0 on success (see kill()).
    389470 */
    390471int posix_killpg(posix_pid_t pid, int sig)
     
    395476
    396477/**
    397  *
    398  * @param pinfo
    399  * @param message
     478 * Outputs information about the signal to the standard error stream.
     479 *
     480 * @param pinfo SigInfo struct to write.
     481 * @param message String to output alongside human-readable signal description.
    400482 */
    401483void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
     
    407489
    408490/**
    409  *
    410  * @param signum
    411  * @param message
     491 * Outputs information about the signal to the standard error stream.
     492 *
     493 * @param signum Signal number.
     494 * @param message String to output alongside human-readable signal description.
    412495 */
    413496void posix_psignal(int signum, const char *message)
     
    422505
    423506/**
    424  *
    425  * @param how
    426  * @param set
    427  * @param oset
    428  * @return
     507 * Manipulate the signal mask of the calling thread.
     508 *
     509 * @param how What to do with the mask.
     510 * @param set Signal set to work with.
     511 * @param oset If not NULL, the original signal mask is coppied here.
     512 * @return 0 success, errorcode on failure.
    429513 */
    430514int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
     
    452536                }
    453537        }
    454 
    455         // TODO: queued signal handling
     538       
     539        _dequeue_unblocked_signals();
    456540
    457541        fibril_mutex_unlock(&_signal_mutex);
     
    461545
    462546/**
    463  *
    464  * @param how
    465  * @param set
    466  * @param oset
    467  * @return
     547 * Manipulate the signal mask of the process.
     548 *
     549 * @param how What to do with the mask.
     550 * @param set Signal set to work with.
     551 * @param oset If not NULL, the original signal mask is coppied here.
     552 * @return 0 on success, -1 with errno set on failure.
    468553 */
    469554int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
  • uspace/lib/posix/signal.h

    r0f963cb ree24574  
    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/stdbool.h

    r0f963cb ree24574  
    3636#define POSIX_STDBOOL_H_
    3737
    38 // TODO: propose for inclusion in libc and drop bool.h,
    39 //       it's a very silly incompatibility with standard C
    40 
    4138#ifdef LIBC_BOOL_H_
    4239        #error "You can't include bool.h and stdbool.h at the same time."
  • uspace/lib/posix/stdint.h

    r0f963cb ree24574  
    103103typedef uint64_t posix_uintmax_t;
    104104
    105 // FIXME: should be integrated into build process similarly to uintptr_t
    106 typedef ssize_t posix_intptr_t;
    107 
    108105#ifndef LIBPOSIX_INTERNAL
    109106        #define intmax_t posix_intmax_t
    110107        #define uintmax_t posix_uintmax_t
    111 
    112         #define intptr_t posix_intptr_t
    113108#endif
    114109
  • uspace/lib/posix/stdio.c

    r0f963cb ree24574  
    284284        fdi_node_t node = {
    285285                .fs_handle = st.fs_handle,
    286                 .devmap_handle = st.devmap_handle,
     286                .service_id = st.service_id,
    287287                .index = st.index
    288288        };
     
    317317       
    318318        return stream;
    319 }
    320 
    321 /**
    322  *
    323  * @param buf
    324  * @param size
    325  * @param mode
    326  * @return
    327  */
    328 FILE *posix_fmemopen(void *restrict buf, size_t size,
    329     const char *restrict mode)
    330 {
    331         // TODO
    332         not_implemented();
    333 }
    334 
    335 /**
    336  *
    337  * @param bufp
    338  * @param sizep
    339  * @return
    340  */
    341 FILE *posix_open_memstream(char **bufp, size_t *sizep)
    342 {
    343         // TODO
    344         not_implemented();
    345319}
    346320
  • uspace/lib/posix/stdio.h

    r0f963cb ree24574  
    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 */
     
    143140
    144141        #define freopen posix_freopen
    145         #define fmemopen posix_fmemopen
    146         #define open_memstream posix_open_memstream
    147142
    148143        #define perror posix_perror
  • uspace/lib/posix/stdio/scanf.c

    r0f963cb ree24574  
    707707                                                        break;
    708708                                                case LMOD_t: ;
    709                                                         // FIXME: What is unsigned counterpart of the ptrdiff_t?
     709                                                        // XXX: What is unsigned counterpart of the ptrdiff_t?
    710710                                                        size_t *pt = va_arg(arg, size_t *);
    711711                                                        *pt = (size_t) ures;
     
    12211221}
    12221222
    1223 // FIXME: put the testcases somewhere else
     1223// FIXME: put the testcases to the app/tester after scanf is included into libc
    12241224
    12251225#if 0
  • uspace/lib/posix/stdlib.c

    r0f963cb ree24574  
    4949#include "libc/str.h"
    5050#include "libc/vfs/vfs.h"
     51#include "libc/stats.h"
    5152
    5253/**
     
    473474 * Get system load average statistics.
    474475 *
    475  * Not supported. Always returns -1.
    476  *
    477476 * @param loadavg Array where the load averages shall be placed.
    478477 * @param nelem Maximum number of elements to be placed into the array.
     
    481480int bsd_getloadavg(double loadavg[], int nelem)
    482481{
    483         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;
    484501}
    485502
  • uspace/lib/posix/stdlib/strtold.c

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

    r0f963cb ree24574  
    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/string.h

    r0f963cb ree24574  
    5151 * void *memmove(void *, const void *, size_t);
    5252 *
    53  * unimplemented due to missing locales
     53 * TODO: not implemented due to missing locale support
    5454 *
    5555 * int      strcoll_l(const char *, const char *, locale_t);
    5656 * char    *strerror_l(int, locale_t);
    5757 * size_t   strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
    58  *
    5958 */
    60 
    61 // TODO: provide *_l once there is locale.h
    6259
    6360#ifndef NULL
  • uspace/lib/posix/strings.h

    r0f963cb ree24574  
    4848#endif
    4949
    50 /* TODO: not implemented due to missing locale.h
     50/* TODO: not implemented due to missing locale support
    5151 *
    5252 * int strcasecmp_l(const char *, const char *, locale_t);
  • uspace/lib/posix/sys/stat.c

    r0f963cb ree24574  
    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/time.c

    r0f963cb ree24574  
    5151#include "libc/sys/time.h"
    5252
    53 // TODO: documentation
    5453// TODO: test everything in this file
     54
     55/* In some places in this file, phrase "normalized broken-down time" is used.
     56 * This means time broken down to components (year, month, day, hour, min, sec),
     57 * in which every component is in its proper bounds. Non-normalized time could
     58 * e.g. be 2011-54-5 29:13:-5, which would semantically mean start of year 2011
     59 * + 53 months + 4 days + 29 hours + 13 minutes - 5 seconds.
     60 */
     61
     62
    5563
    5664/* Helper functions ***********************************************************/
     
    6472
    6573/**
    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)
     
    8291
    8392/**
    84  *
    85  * @param year
    86  * @param mon
    87  * @return
     93 * Returns how many days there are in the given month of the given year.
     94 * Note that year is only taken into account if month is February.
     95 *
     96 * @param year Year since 1900 (can be negative).
     97 * @param mon Month of the year. 0 for January, 11 for December.
     98 * @return Number of days in the specified month.
    8899 */
    89100static int _days_in_month(time_t year, time_t mon)
    90101{
    91102        assert(mon >= 0 && mon <= 11);
    92         year += 1900;
    93103
    94104        static int month_days[] =
     
    96106
    97107        if (mon == 1) {
     108                year += 1900;
    98109                /* february */
    99110                return _is_leap_year(year) ? 29 : 28;
     
    104115
    105116/**
    106  *
    107  * @param year
    108  * @param mon
    109  * @param mday
    110  * @return
     117 * For specified year, month and day of month, returns which day of that year
     118 * it is.
     119 *
     120 * For example, given date 2011-01-03, the corresponding expression is:
     121 *     _day_of_year(111, 0, 3) == 2
     122 *
     123 * @param year Year (year 1900 = 0, can be negative).
     124 * @param mon Month (January = 0).
     125 * @param mday Day of month (First day is 1).
     126 * @return Day of year (First day is 0).
    111127 */
    112128static int _day_of_year(time_t year, time_t mon, time_t mday)
     
    122138/**
    123139 * Integer division that rounds to negative infinity.
    124  *
    125  * @param op1
    126  * @param op2
    127  * @return
     140 * Used by some functions in this file.
     141 *
     142 * @param op1 Divident.
     143 * @param op2 Divisor.
     144 * @return Rounded quotient.
    128145 */
    129146static time_t _floor_div(time_t op1, time_t op2)
     
    138155/**
    139156 * Modulo that rounds to negative infinity.
    140  *
    141  * @param op1
    142  * @param op2
    143  * @return
     157 * Used by some functions in this file.
     158 *
     159 * @param op1 Divident.
     160 * @param op2 Divisor.
     161 * @return Remainder.
    144162 */
    145163static time_t _floor_mod(time_t op1, time_t op2)
     
    161179
    162180/**
    163  *
    164  * @param year
    165  * @param mon
    166  * @param mday
    167  * @return
     181 * Number of days since the Epoch.
     182 * Epoch is 1970-01-01, which is also equal to day 0.
     183 *
     184 * @param year Year (year 1900 = 0, may be negative).
     185 * @param mon Month (January = 0).
     186 * @param mday Day of month (first day = 1).
     187 * @return Number of days since the Epoch.
    168188 */
    169189static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
     
    175195
    176196/**
    177  * Assumes normalized broken-down time.
    178  *
    179  * @param tm
    180  * @return
     197 * Seconds since the Epoch. see also _days_since_epoch().
     198 * 
     199 * @param tm Normalized broken-down time.
     200 * @return Number of seconds since the epoch, not counting leap seconds.
    181201 */
    182202static time_t _secs_since_epoch(const struct posix_tm *tm)
     
    188208
    189209/**
    190  *
    191  * @param year
    192  * @param mon
    193  * @param mday
    194  * @return
     210 * Which day of week the specified date is.
     211 *
     212 * @param year Year (year 1900 = 0).
     213 * @param mon Month (January = 0).
     214 * @param mday Day of month (first = 1).
     215 * @return Day of week (Sunday = 0).
    195216 */
    196217static int _day_of_week(time_t year, time_t mon, time_t mday)
    197218{
    198219        /* 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)
     220        return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7);
     221}
     222
     223/**
     224 * Normalizes the broken-down time and optionally adds specified amount of
     225 * seconds.
     226 *
     227 * @param tm Broken-down time to normalize.
     228 * @param sec_add Seconds to add.
     229 * @return 0 on success, -1 on overflow
     230 */
     231static int _normalize_time(struct posix_tm *tm, time_t sec_add)
    260232{
    261233        // TODO: DST correction
    262234
     235        /* Set initial values. */
     236        time_t sec = tm->tm_sec + sec_add;
     237        time_t min = tm->tm_min;
     238        time_t hour = tm->tm_hour;
     239        time_t day = tm->tm_mday - 1;
     240        time_t mon = tm->tm_mon;
     241        time_t year = tm->tm_year;
     242
    263243        /* 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);
     244        min += _floor_div(sec, SECS_PER_MIN);
     245        sec = _floor_mod(sec, SECS_PER_MIN);
     246        hour += _floor_div(min, MINS_PER_HOUR);
     247        min = _floor_mod(min, MINS_PER_HOUR);
     248        day += _floor_div(hour, HOURS_PER_DAY);
     249        hour = _floor_mod(hour, HOURS_PER_DAY);
    270250
    271251        /* Adjust month. */
    272         tm->tm_year += _floor_div(tm->tm_mon, 12);
    273         tm->tm_mon = _floor_mod(tm->tm_mon, 12);
     252        year += _floor_div(mon, 12);
     253        mon = _floor_mod(mon, 12);
    274254
    275255        /* 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--;
     256       
     257        /* First, deal with whole cycles of 400 years = 146097 days. */
     258        year += _floor_div(day, 146097) * 400;
     259        day = _floor_mod(day, 146097);
     260       
     261        /* Then, go in one year steps. */
     262        if (mon <= 1) {
     263                /* January and February. */
     264                while (day > 365) {
     265                        day -= _is_leap_year(year) ? 366 : 365;
     266                        year++;
    284267                }
    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++;
     268        } else {
     269                /* Rest of the year. */
     270                while (day > 365) {
     271                        day -= _is_leap_year(year + 1) ? 366 : 365;
     272                        year++;
    296273                }
    297274        }
    298 
     275       
     276        /* Finally, finish it off month per month. */
     277        while (day >= _days_in_month(year, mon)) {
     278                day -= _days_in_month(year, mon);
     279                mon++;
     280                if (mon >= 12) {
     281                        mon -= 12;
     282                        year++;
     283                }
     284        }
     285       
    299286        /* 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.
     287        tm->tm_yday = _day_of_year(year, mon, day + 1);
     288        tm->tm_wday = _day_of_week(year, mon, day + 1);
     289       
     290        /* And put the values back to the struct. */
     291        tm->tm_sec = (int) sec;
     292        tm->tm_min = (int) min;
     293        tm->tm_hour = (int) hour;
     294        tm->tm_mday = (int) day + 1;
     295        tm->tm_mon = (int) mon;
     296       
     297        /* Casts to work around libc brain-damage. */
     298        if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) {
     299                tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX);
     300                return -1;
     301        }
     302       
     303        tm->tm_year = (int) year;
     304        return 0;
     305}
     306
     307/**
     308 * Which day the week-based year starts on, relative to the first calendar day.
    306309 * E.g. if the year starts on December 31st, the return value is -1.
    307310 *
    308  * @param year
    309  * @return
     311 * @param Year since 1900.
     312 * @return Offset of week-based year relative to calendar year.
    310313 */
    311314static int _wbyear_offset(int year)
     
    317320/**
    318321 * Returns week-based year of the specified time.
    319  * Assumes normalized broken-down time.
    320  *
    321  * @param tm
    322  * @return
     322 *
     323 * @param tm Normalized broken-down time.
     324 * @return Week-based year.
    323325 */
    324326static int _wbyear(const struct posix_tm *tm)
     
    329331                return tm->tm_year - 1;
    330332        }
    331         if (day > 364 + _is_leap_year(tm->tm_year)){
     333        if (day > 364 + _is_leap_year(tm->tm_year)) {
    332334                /* First week of next year. */
    333335                return tm->tm_year + 1;
     
    368370                return 53;
    369371        }
    370         if (day > 364 + _is_leap_year(tm->tm_year)){
     372        if (day > 364 + _is_leap_year(tm->tm_year)) {
    371373                /* First week of next year. */
    372374                return 1;
     
    397399
    398400/**
    399  *
     401 * Set timezone conversion information.
    400402 */
    401403void posix_tzset(void)
     
    409411
    410412/**
    411  *
    412  * @param time1
    413  * @param time0
    414  * @return
     413 * Calculate the difference between two times, in seconds.
     414 *
     415 * @param time1 First time.
     416 * @param time0 Second time.
     417 * @return Time in seconds.
    415418 */
    416419double posix_difftime(time_t time1, time_t time0)
     
    425428 *
    426429 * @param tm Broken-down time.
    427  * @return time_t representation of the time, undefined value on overflow
     430 * @return time_t representation of the time, undefined value on overflow.
    428431 */
    429432time_t posix_mktime(struct posix_tm *tm)
     
    432435        // TODO: detect overflow
    433436
    434         struct _long_tm ltm;
    435         _posix_to_long_tm(&ltm, tm);
    436         _normalize_time(&ltm);
    437         _long_to_posix_tm(tm, &ltm);
    438 
     437        _normalize_time(tm, 0);
    439438        return _secs_since_epoch(tm);
    440439}
    441440
    442441/**
    443  *
    444  * @param timer
    445  * @return
     442 * Converts a time value to a broken-down UTC time.
     443 *
     444 * @param timer Time to convert.
     445 * @return Normalized broken-down time in UTC, NULL on overflow.
    446446 */
    447447struct posix_tm *posix_gmtime(const time_t *timer)
    448448{
     449        assert(timer != NULL);
     450
    449451        static struct posix_tm result;
    450452        return posix_gmtime_r(timer, &result);
     
    452454
    453455/**
    454  *
    455  * @param timer
    456  * @param result
    457  * @return
     456 * Converts a time value to a broken-down UTC time.
     457 *
     458 * @param timer Time to convert.
     459 * @param result Structure to store the result to.
     460 * @return Value of result on success, NULL on overflow.
    458461 */
    459462struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
     
    463466        assert(result != NULL);
    464467
    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) {
     468        /* Set result to epoch. */
     469        result->tm_sec = 0;
     470        result->tm_min = 0;
     471        result->tm_hour = 0;
     472        result->tm_mday = 1;
     473        result->tm_mon = 0;
     474        result->tm_year = 70; /* 1970 */
     475
     476        if (_normalize_time(result, *timer) == -1) {
    479477                errno = EOVERFLOW;
    480478                return NULL;
    481479        }
    482480
    483         _long_to_posix_tm(result, &ltm);
    484481        return result;
    485482}
    486483
    487484/**
    488  *
    489  * @param timer
    490  * @return
     485 * Converts a time value to a broken-down local time.
     486 *
     487 * @param timer Time to convert.
     488 * @return Normalized broken-down time in local timezone, NULL on overflow.
    491489 */
    492490struct posix_tm *posix_localtime(const time_t *timer)
     
    497495
    498496/**
    499  *
    500  * @param timer
    501  * @param result
    502  * @return
     497 * Converts a time value to a broken-down local time.
     498 *
     499 * @param timer Time to convert.
     500 * @param result Structure to store the result to.
     501 * @return Value of result on success, NULL on overflow.
    503502 */
    504503struct posix_tm *posix_localtime_r(const time_t *restrict timer,
     
    511510
    512511/**
    513  *
    514  * @param timeptr
    515  * @return
     512 * Converts broken-down time to a string in format
     513 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
     514 *
     515 * @param timeptr Broken-down time structure.
     516 * @return Pointer to a statically allocated string.
    516517 */
    517518char *posix_asctime(const struct posix_tm *timeptr)
     
    522523
    523524/**
    524  *
    525  * @param timeptr
    526  * @param buf
    527  * @return
     525 * Converts broken-down time to a string in format
     526 * "Sun Jan 1 00:00:00 1970\n". (Obsolete)
     527 *
     528 * @param timeptr Broken-down time structure.
     529 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN
     530 *     bytes long.
     531 * @return Value of buf.
    528532 */
    529533char *posix_asctime_r(const struct posix_tm *restrict timeptr,
     
    552556
    553557/**
    554  *
    555  * @param timer
    556  * @return
     558 * Equivalent to asctime(localtime(clock)).
     559 *
     560 * @param timer Time to convert.
     561 * @return Pointer to a statically allocated string holding the date.
    557562 */
    558563char *posix_ctime(const time_t *timer)
     
    566571
    567572/**
    568  *
    569  * @param timer
    570  * @param buf
    571  * @return
     573 * Reentrant variant of ctime().
     574 *
     575 * @param timer Time to convert.
     576 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN
     577 *     bytes long.
     578 * @return Pointer to buf on success, NULL on falure.
    572579 */
    573580char *posix_ctime_r(const time_t *timer, char *buf)
     
    581588
    582589/**
    583  *
    584  * @param s
    585  * @param maxsize
    586  * @param format
    587  * @param tm
    588  * @return
     590 * Convert time and date to a string, based on a specified format and
     591 * current locale.
     592 *
     593 * @param s Buffer to write string to.
     594 * @param maxsize Size of the buffer.
     595 * @param format Format of the output.
     596 * @param tm Broken-down time to format.
     597 * @return Number of bytes written.
    589598 */
    590599size_t posix_strftime(char *restrict s, size_t maxsize,
    591600    const char *restrict format, const struct posix_tm *restrict tm)
    592601{
     602        assert(s != NULL);
     603        assert(format != NULL);
     604        assert(tm != NULL);
     605
    593606        // TODO: use locale
    594607        static const char *wday_abbr[] = {
     
    767780
    768781/**
    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
     782 * Get clock resolution. Only CLOCK_REALTIME is supported.
     783 *
     784 * @param clock_id Clock ID.
     785 * @param res Pointer to the variable where the resolution is to be written.
     786 * @return 0 on success, -1 with errno set on failure.
    790787 */
    791788int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res)
     
    805802
    806803/**
    807  *
    808  * @param clock_id
    809  * @param tp
    810  * @return
     804 * Get time. Only CLOCK_REALTIME is supported.
     805 *
     806 * @param clock_id ID of the clock to query.
     807 * @param tp Pointer to the variable where the time is to be written.
     808 * @return 0 on success, -1 with errno on failure.
    811809 */
    812810int posix_clock_gettime(posix_clockid_t clock_id, struct posix_timespec *tp)
     
    829827
    830828/**
    831  *
    832  * @param clock_id
    833  * @param tp
    834  * @return
     829 * Set time on a specified clock. As HelenOS doesn't support this yet,
     830 * this function always fails.
     831 *
     832 * @param clock_id ID of the clock to set.
     833 * @param tp Time to set.
     834 * @return 0 on success, -1 with errno on failure.
    835835 */
    836836int posix_clock_settime(posix_clockid_t clock_id,
     
    853853
    854854/**
    855  *
    856  * @param clock_id
    857  * @param flags
    858  * @param rqtp
    859  * @param rmtp
    860  * @return
     855 * Sleep on a specified clock.
     856 *
     857 * @param clock_id ID of the clock to sleep on (only CLOCK_REALTIME supported).
     858 * @param flags Flags (none supported).
     859 * @param rqtp Sleep time.
     860 * @param rmtp Remaining time is written here if sleep is interrupted.
     861 * @return 0 on success, -1 with errno set on failure.
    861862 */
    862863int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
     
    882883}
    883884
    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 
    959885/**
    960886 * Get CPU time used since the process invocation.
  • uspace/lib/posix/time.h

    r0f963cb ree24574  
    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
     
    182162        #define clock_settime posix_clock_settime
    183163        #define clock_nanosleep posix_clock_nanosleep
    184        
    185         #define timer_create posix_timer_create
    186         #define timer_delete posix_timer_delete
    187         #define timer_getoverrun posix_timer_getoverrun
    188         #define timer_gettime posix_timer_gettime
    189         #define timer_settime posix_timer_settime
    190        
     164
    191165        #define clock posix_clock
    192166#endif
  • uspace/lib/posix/unistd.c

    r0f963cb ree24574  
    8888int posix_isatty(int fd)
    8989{
     90        // TODO
    9091        /* Always returns false, because there is no easy way to find
    9192         * out under HelenOS. */
Note: See TracChangeset for help on using the changeset viewer.