Changes in / [8cd8bf6:f5b2522] in mainline


Ignore:
Location:
uspace/lib/posix
Files:
8 deleted
26 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/Makefile

    r8cd8bf6 rf5b2522  
    4040SOURCES = \
    4141        ctype.c \
    42         errno.c \
    4342        fcntl.c \
    4443        fnmatch.c \
    45         locale.c \
    4644        math.c \
    4745        pwd.c \
    48         signal.c \
    4946        stdio.c \
    50         stdio/scanf.c \
    5147        stdlib.c \
    5248        stdlib/strtol.c \
  • uspace/lib/posix/ctype.c

    r8cd8bf6 rf5b2522  
    108108}
    109109
    110 /**
    111  * Checks whether character is ASCII. (obsolete)
    112  *
    113  * @param c
    114  * @return
    115  */
    116 extern int posix_isascii(int c)
    117 {
    118         return c >= 0 && c < 128;
    119 }
    120 
    121 /**
    122  * Converts argument to a 7-bit ASCII character. (obsolete)
    123  *
    124  * @param c
    125  * @return
    126  */
    127 extern int posix_toascii(int c)
    128 {
    129         return c & 0x7F;
    130 }
    131 
    132110/** @}
    133111 */
  • uspace/lib/posix/ctype.h

    r8cd8bf6 rf5b2522  
    4747extern int posix_ispunct(int c);
    4848
    49 /* Obsolete Functions and Macros */
    50 extern int posix_isascii(int c);
    51 extern int posix_toascii(int c);
    52 #undef _tolower
    53 #define _tolower(c) ((c) - 'A' + 'a')
    54 #undef _toupper
    55 #define _toupper(c) ((c) - 'a' + 'A')
    56 
    57 
    5849#ifndef LIBPOSIX_INTERNAL
    5950        #define isxdigit posix_isxdigit
     
    6354        #define isprint posix_isprint
    6455        #define ispunct posix_ispunct
    65        
    66         #define isascii posix_isascii
    67         #define toascii posix_toascii
    6856#endif
    6957
  • uspace/lib/posix/fcntl.c

    r8cd8bf6 rf5b2522  
    3838#include "fcntl.h"
    3939
    40 #include "libc/unistd.h"
    41 #include "libc/vfs/vfs.h"
    42 #include "errno.h"
    43 
    4440/**
    45  * Performs set of operations on the opened files.
    46  *
    47  * @param fd File descriptor of the opened file.
    48  * @param cmd Operation to carry out.
    49  * @return Non-negative on success. Might have special meaning corresponding
    50  *     to the requested operation.
     41 *
     42 * @param fd
     43 * @param cmd
     44 * @param ...
     45 * @return
    5146 */
    5247int posix_fcntl(int fd, int cmd, ...)
    5348{
    54         int rc;
    55         int flags;
    56 
    57         switch (cmd) {
    58         case F_DUPFD:
    59         case F_DUPFD_CLOEXEC: /* FD_CLOEXEC is not supported. */
    60                 /* VFS does not provide means to express constraints on the new
    61                  * file descriptor so the third argument is ignored. */
    62 
    63                 /* Retrieve node triplet corresponding to the file descriptor. */
    64                 /* Empty statement after label. */;
    65                 fdi_node_t node;
    66                 rc = fd_node(fd, &node);
    67                 if (rc != EOK) {
    68                         errno = -rc;
    69                         return -1;
    70                 }
    71 
    72                 /* Reopen the node so the fresh file descriptor is generated. */
    73                 int newfd = open_node(&node, 0);
    74                 if (newfd < 0) {
    75                         errno = -newfd;
    76                         return -1;
    77                 }
    78 
    79                 /* Associate the newly generated descriptor to the file description
    80                  * of the old file descriptor. Just reopened node will be automatically
    81                  * closed. */
    82                 rc = dup2(fd, newfd);
    83                 if (rc != EOK) {
    84                         errno = -rc;
    85                         return -1;
    86                 }
    87 
    88                 return newfd;
    89         case F_GETFD:
    90                 /* FD_CLOEXEC is not supported. There are no other flags. */
    91                 return 0;
    92         case F_SETFD:
    93                 /* FD_CLOEXEC is not supported. Ignore arguments and report success. */
    94                 return 0;
    95         case F_GETFL:
    96                 /* File status flags (i.e. O_APPEND) are currently private to the
    97                  * VFS server so it cannot be easily retrieved. */
    98                 flags = 0;
    99                 /* File access flags are currently not supported for file descriptors.
    100                  * Provide full access. */
    101                 flags |= O_RDWR;
    102                 return flags;
    103         case F_SETFL:
    104                 /* File access flags are currently not supported for file descriptors.
    105                  * Ignore arguments and report success. */
    106                 return 0;
    107         case F_GETOWN:
    108         case F_SETOWN:
    109         case F_GETLK:
    110         case F_SETLK:
    111         case F_SETLKW:
    112                 /* Signals (SIGURG) and file locks are not supported. */
    113                 errno = ENOTSUP;
    114                 return -1;
    115         default:
    116                 /* Unknown command */
    117                 errno = EINVAL;
    118                 return -1;
    119         }
     49        // TODO
     50        not_implemented();
    12051}
    12152
  • uspace/lib/posix/fcntl.h

    r8cd8bf6 rf5b2522  
    3636#define POSIX_FCNTL_H_
    3737
    38 #include "sys/types.h"
    3938#include "libc/fcntl.h"
    40 
    41 /* Mask for file access modes. */
    42 #undef O_ACCMODE
    43 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
    4439
    4540/* fcntl commands */
    4641#undef F_DUPFD
    47 #undef F_DUPFD_CLOEXEC
    4842#undef F_GETFD
    4943#undef F_SETFD
     
    5246#undef F_GETOWN
    5347#undef F_SETOWN
    54 #undef F_GETLK
    55 #undef F_SETLK
    56 #undef F_SETLKW
    57 #define F_DUPFD            0 /* Duplicate file descriptor. */
    58 #define F_DUPFD_CLOEXEC    1 /* Same as F_DUPFD but with FD_CLOEXEC flag set. */
    59 #define F_GETFD            2 /* Get file descriptor flags. */
    60 #define F_SETFD            3 /* Set file descriptor flags. */
    61 #define F_GETFL            4 /* Get file status and access flags. */
    62 #define F_SETFL            5 /* Set file status flags. */
    63 #define F_GETOWN           6 /* Get socket owner. */
    64 #define F_SETOWN           7 /* Set socket owner. */
    65 #define F_GETLK            8 /* Get locking information. */
    66 #define F_SETLK            9 /* Set locking information. */
    67 #define F_SETLKW          10 /* Set locking information; wait if blocked. */
     48#define F_DUPFD         0       /* Duplicate file descriptor. */
     49#define F_GETFD         1       /* Get file descriptor flags. */
     50#define F_SETFD         2       /* Set file descriptor flags. */
     51#define F_GETFL         3       /* Get file status flags. */
     52#define F_SETFL         4       /* Set file status flags. */
     53#define F_GETOWN        5       /* Get owner. */
     54#define F_SETOWN        6       /* Set owner. */
    6855
    6956/* File descriptor flags used with F_GETFD and F_SETFD. */
    7057#undef FD_CLOEXEC
    71 #define FD_CLOEXEC         1 /* Close on exec. */
     58#define FD_CLOEXEC      1       /* Close on exec. */
    7259
    7360extern int posix_fcntl(int fd, int cmd, ...);
  • uspace/lib/posix/fnmatch.c

    r8cd8bf6 rf5b2522  
    3333 */
    3434
    35 // TODO: clean this up a bit
    36 
    37 #include "stdbool.h"
    38 #include "ctype.h"
    39 #include "string.h"
    40 #include "stdlib.h"
    41 #include "assert.h"
    42 
    4335#define LIBPOSIX_INTERNAL
    4436
    4537#include "internal/common.h"
    4638#include "fnmatch.h"
    47 
    48 #define INVALID_PATTERN -1
    49 
    50 /* Type for collating element, simple identity with characters now,
    51  * but may be extended for better locale support.
    52  */
    53 typedef int _coll_elm_t;
    54 
    55 #define COLL_ELM_INVALID -1
    56 
    57 /** Get collating element matching a string.
    58  *
    59  * @param str
    60  * @return
    61  */
    62 static _coll_elm_t _coll_elm_get(const char* str)
    63 {
    64         if (str[0] == '\0' || str[1] != '\0') {
    65                 return COLL_ELM_INVALID;
    66         }
    67         return str[0];
    68 }
    69 
    70 /** Get collating element matching a single character.
    71  *
    72  * @param c
    73  * @return
    74  */
    75 static _coll_elm_t _coll_elm_char(int c)
    76 {
    77         return c;
    78 }
    79 
    80 /** Match collating element with a beginning of a string.
    81  *
    82  * @param elm
    83  * @param str
    84  * @return 0 if the element doesn't match, or the number of characters matched.
    85  */
    86 static int _coll_elm_match(_coll_elm_t elm, const char *str)
    87 {
    88         return elm == *str;
    89 }
    90 
    91 static int _coll_elm_between(_coll_elm_t first, _coll_elm_t second,
    92     const char *str)
    93 {
    94         return *str >= first && *str <= second;
    95 }
    96 
    97 /** Read a string delimited by [? and ?].
    98  *
    99  * @param pattern Pointer to the string to read from. Its position is moved
    100  *    to the first character after the closing ].
    101  * @param seq The character on the inside of brackets.
    102  * @param buf Read buffer.
    103  * @param buf_sz Read buffer's size. If the buffer is not large enough for
    104  *    the entire string, the string is cut with no error indication.
    105  * @return
    106  */
    107 static bool _get_delimited(
    108     const char **pattern, int seq,
    109     char *buf, size_t buf_sz, int flags)
    110 {
    111         const bool noescape = (flags & FNM_NOESCAPE) != 0;
    112         const bool pathname = (flags & FNM_PATHNAME) != 0;
    113 
    114         const char *p = *pattern;
    115         assert(p[0] == '[' && p[1] == seq /* Caller should ensure this. */);
    116         p += 2;
    117 
    118         while (true) {
    119                 if (*p == seq && *(p + 1) == ']') {
    120                         /* String properly ended, return. */
    121                         *pattern = p + 2;
    122                         *buf = '\0';
    123                         return true;
    124                 }
    125                 if (!noescape && *p == '\\') {
    126                         p++;
    127                 }
    128                 if (*p == '\0') {
    129                         /* String not ended properly, invalid pattern. */
    130                         return false;
    131                 }
    132                 if (pathname && *p == '/') {
    133                         /* Slash in a pathname pattern is invalid. */
    134                         return false;
    135                 }
    136                 if (buf_sz > 1) {
    137                         /* Only add to the buffer if there is space. */
    138                         *buf = *p;
    139                         buf++;
    140                         buf_sz--;
    141                 }
    142                 p++;
    143         }
    144 }
    145 
    146 /************** CHARACTER CLASSES ****************/
    147 
    148 #define MAX_CLASS_OR_COLL_LEN 6
    149 
    150 struct _char_class {
    151         const char *name;
    152         int (*func) (int);
    153 };
    154 
    155 /* List of supported character classes. */
    156 static const struct _char_class _char_classes[] = {
    157         { "alnum", isalnum },
    158         { "alpha", isalpha },
    159         { "blank", isblank },
    160         { "cntrl", iscntrl },
    161         { "digit", isdigit },
    162         { "graph", isgraph },
    163         { "lower", islower },
    164         { "print", isprint },
    165         { "punct", ispunct },
    166         { "space", isspace },
    167         { "upper", isupper },
    168         { "xdigit", isxdigit }
    169 };
    170 
    171 static int _class_compare(const void *key, const void *elem)
    172 {
    173         const struct _char_class *class = elem;
    174         return strcmp((const char *) key, class->name);
    175 }
    176 
    177 static bool _is_in_class (const char *cname, int c)
    178 {
    179         /* Search for class in the array of supported character classes. */
    180         const struct _char_class *class = bsearch(cname, _char_classes,
    181             sizeof(_char_classes) / sizeof(struct _char_class),
    182             sizeof(struct _char_class), _class_compare);
    183 
    184         if (class == NULL) {
    185                 /* No such class supported - treat as an empty class. */
    186                 return false;
    187         } else {
    188                 /* Class matched. */
    189                 return class->func(c);
    190         }
    191 }
    192 
    193 static int _match_char_class(const char **pattern, const char *str, int flags)
    194 {
    195         char class[MAX_CLASS_OR_COLL_LEN + 1];
    196 
    197         if (!_get_delimited(pattern, ':', class, sizeof(class), flags)) {
    198                 return INVALID_PATTERN;
    199         }
    200 
    201         return _is_in_class(class, *str);
    202 }
    203 
    204 /************** END CHARACTER CLASSES ****************/
    205 
    206 static _coll_elm_t _next_coll_elm(const char **pattern, int flags)
    207 {
    208         const char *p = *pattern;
    209         const bool noescape = (flags & FNM_NOESCAPE) != 0;
    210         const bool pathname = (flags & FNM_PATHNAME) != 0;
    211 
    212         if (*p == '[') {
    213                 if (*(p + 1) == '.') {
    214                         char buf[MAX_CLASS_OR_COLL_LEN + 1];
    215                         if (!_get_delimited(pattern, '.', buf, sizeof(buf), flags)) {
    216                                 return COLL_ELM_INVALID;
    217                         }
    218                         return _coll_elm_get(buf);
    219                 }
    220 
    221                 if (*(p + 1) == '=') {
    222                         char buf[MAX_CLASS_OR_COLL_LEN + 1];
    223                         if (!_get_delimited(pattern, '=', buf, sizeof(buf), flags)) {
    224                                 return COLL_ELM_INVALID;
    225                         }
    226                         return _coll_elm_get(buf);
    227                 }
    228         }
    229 
    230         if (!noescape && *p == '\\') {
    231                 p++;
    232         }
    233         if (pathname && *p == '/') {
    234                 return COLL_ELM_INVALID;
    235         }
    236 
    237         *pattern = p + 1;
    238         return _coll_elm_char(*p);
    239 }
    240 
    241 /**
    242  *
    243  */
    244 static int _match_bracket_expr(const char **pattern, const char *str, int flags)
    245 {
    246         const bool pathname = (flags & FNM_PATHNAME) != 0;
    247         const bool special_period = (flags & FNM_PERIOD) != 0;
    248         const char *p = *pattern;
    249         bool negative = false;
    250         int matched = 0;
    251 
    252         #define _matched(match) { \
    253                 int _match = match; \
    254                 if (_match < 0) { \
    255                         /* Invalid pattern */ \
    256                         return _match; \
    257                 } else if (matched == 0 && _match > 0) { \
    258                         /* First match */ \
    259                         matched = _match; \
    260                 } \
    261         }
    262 
    263         assert(*p == '[');  /* calling code should ensure this */
    264         p++;
    265 
    266         if (*str == '\0' || (pathname && *str == '/') ||
    267             (pathname && special_period && *str == '.' && *(str - 1) == '/')) {
    268                 /* No bracket expression matches end of string,
    269                  * slash in pathname match or initial period with FNM_PERIOD
    270                  * option.
    271                  */
    272                 return 0;
    273         }
    274 
    275         if (*p == '^' || *p == '!') {
    276                 negative = true;
    277                 p++;
    278         }
    279 
    280         if (*p == ']') {
    281                 /* When ']' is first, treat it as a normal character. */
    282                 _matched(*str == ']');
    283                 p++;
    284         }
    285        
    286         _coll_elm_t current_elm = COLL_ELM_INVALID;
    287        
    288         while (*p != ']') {
    289                 if (*p == '-' && *(p + 1) != ']' &&
    290                     current_elm != COLL_ELM_INVALID) {
    291                         /* Range expression. */
    292                         p++;
    293                         _coll_elm_t end_elm = _next_coll_elm(&p, flags);
    294                         if (end_elm == COLL_ELM_INVALID) {
    295                                 return INVALID_PATTERN;
    296                         }
    297                         _matched(_coll_elm_between(current_elm, end_elm, str));
    298                         continue;
    299                 }
    300        
    301                 if (*p == '[' && *(p + 1) == ':') {
    302                         current_elm = COLL_ELM_INVALID;
    303                         _matched(_match_char_class(&p, str, flags));
    304                         continue;
    305                 }
    306                
    307                 current_elm = _next_coll_elm(&p, flags);
    308                 if (current_elm == COLL_ELM_INVALID) {
    309                         return INVALID_PATTERN;
    310                 }
    311                 _matched(_coll_elm_match(current_elm, str));
    312         }
    313 
    314         /* No error occured - update pattern pointer. */
    315         *pattern = p + 1;
    316 
    317         if (matched == 0) {
    318                 /* No match found */
    319                 return negative;
    320         } else {
    321                 /* Matched 'match' characters. */
    322                 return negative ? 0 : matched;
    323         }
    324 
    325         #undef _matched
    326 }
    327 
    328 /**
    329  *
    330  */
    331 static bool _partial_match(const char **pattern, const char **string, int flags)
    332 {
    333         /* Only a single *-delimited subpattern is matched here.
    334          * So in this function, '*' is understood as the end of pattern.
    335          */
    336 
    337         const bool pathname = (flags & FNM_PATHNAME) != 0;
    338         const bool special_period = (flags & FNM_PERIOD) != 0;
    339         const bool noescape = (flags & FNM_NOESCAPE) != 0;
    340         const bool leading_dir = (flags & FNM_LEADING_DIR) != 0;
    341 
    342         const char *s = *string;
    343         const char *p = *pattern;
    344 
    345         while (*p != '*') {
    346                 /* Bracket expression. */
    347                 if (*p == '[') {
    348                         int matched = _match_bracket_expr(&p, s, flags);
    349                         if (matched == 0) {
    350                                 /* Doesn't match. */
    351                                 return false;
    352                         }
    353                         if (matched != INVALID_PATTERN) {
    354                                 s += matched;
    355                                 continue;
    356                         }
    357 
    358                         assert(matched == INVALID_PATTERN);
    359                         /* Fall through to match [ as an ordinary character. */
    360                 }
    361 
    362                 /* Wildcard match. */
    363                 if (*p == '?') {
    364                         if (*s == '\0') {
    365                                 /* No character to match. */
    366                                 return false;
    367                         }
    368                         if (pathname && *s == '/') {
    369                                 /* Slash must be matched explicitly. */
    370                                 return false;
    371                         }
    372                         if (special_period && pathname &&
    373                             *s == '.' && *(s - 1) == '/') {
    374                                 /* Initial period must be matched explicitly. */
    375                                 return false;
    376                         }
    377                        
    378                         /* None of the above, match anything else. */
    379                         p++;
    380                         s++;
    381                         continue;
    382                 }
    383 
    384                 if (!noescape && *p == '\\') {
    385                         /* Escaped character. */
    386                         p++;
    387                 }
    388 
    389                 if (*p == '\0') {
    390                         /* End of pattern, must match end of string or
    391                          * an end of subdirectory name (optional).
    392                          */
    393 
    394                         if (*s == '\0' || (leading_dir && *s == '/')) {
    395                                 break;
    396                         }
    397 
    398                         return false;
    399                 }
    400 
    401                 if (*p == *s) {
    402                         /* Exact match. */
    403                         p++;
    404                         s++;
    405                         continue;
    406                 }
    407 
    408                 /* Nothing matched. */
    409                 return false;
    410         }
    411 
    412         /* Entire sub-pattern matched. */
    413        
    414         /* postconditions */
    415         assert(*p == '\0' || *p == '*');
    416         assert(*p != '\0' || *s == '\0' || (leading_dir && *s == '/'));
    417        
    418         *pattern = p;
    419         *string = s;
    420         return true;
    421 }
    422 
    423 static bool _full_match(const char *pattern, const char *string, int flags)
    424 {
    425         const bool pathname = (flags & FNM_PATHNAME) != 0;
    426         const bool special_period = (flags & FNM_PERIOD) != 0;
    427         const bool leading_dir = (flags & FNM_LEADING_DIR) != 0;
    428 
    429         if (special_period && *string == '.') {
    430                 /* Initial dot must be matched by an explicit dot in pattern. */
    431                 if (*pattern != '.') {
    432                         return false;
    433                 }
    434                 pattern++;
    435                 string++;
    436         }
    437 
    438         if (*pattern != '*') {
    439                 if (!_partial_match(&pattern, &string, flags)) {
    440                         /* The initial match must succeed. */
    441                         return false;
    442                 }
    443         }
    444 
    445         while (*pattern != '\0') {
    446                 assert(*pattern == '*');
    447                 pattern++;
    448 
    449                 bool matched = false;
    450 
    451                 const char *end;
    452                 if (pathname && special_period &&
    453                     *string == '.' && *(string - 1) == '/') {
    454                         end = string;
    455                 } else {
    456                         end= strchrnul(string, pathname ? '/' : '\0');
    457                 }
    458 
    459                 /* Try to match every possible offset. */
    460                 while (string <= end) {
    461                         if (_partial_match(&pattern, &string, flags)) {
    462                                 matched = true;
    463                                 break;
    464                         }
    465                         string++;
    466                 }
    467 
    468                 if (matched) {
    469                         continue;
    470                 }
    471 
    472                 return false;
    473         }
    474 
    475         return *string == '\0' || (leading_dir && *string == '/');
    476 }
    477 
    478 static char *_casefold(const char *s)
    479 {
    480         char *result = strdup(s);
    481         for (char *i = result; *i != '\0'; ++i) {
    482                 *i = tolower(*i);
    483         }
    484         return result;
    485 }
    48639
    48740/**
     
    49548int posix_fnmatch(const char *pattern, const char *string, int flags)
    49649{
    497         // TODO: don't fold everything in advance, but only when needed
    498 
    499         if ((flags & FNM_CASEFOLD) != 0) {
    500                 /* Just fold the entire pattern and string. */
    501                 pattern = _casefold(pattern);
    502                 string = _casefold(string);
    503         }
    504 
    505         bool result = _full_match(pattern, string, flags);
    506 
    507         if ((flags & FNM_CASEFOLD) != 0) {
    508                 free((char *) pattern);
    509                 free((char *) string);
    510         }
    511 
    512         return result ? 0 : FNM_NOMATCH;
     50        // TODO
     51        not_implemented();
    51352}
    514 
    515 // FIXME: put the testcases somewhere else
    516 
    517 #if 0
    518 
    519 #include <stdio.h>
    520 
    521 void __posix_fnmatch_test()
    522 {
    523         int fail = 0;
    524 
    525         #undef assert
    526         #define assert(x) { if (x) printf("SUCCESS: "#x"\n"); else { printf("FAILED: "#x"\n"); fail++; } }
    527         #define match(s1, s2, flags) assert(posix_fnmatch(s1, s2, flags) == 0)
    528         #define nomatch(s1, s2, flags) assert(posix_fnmatch(s1, s2, flags) == FNM_NOMATCH)
    529 
    530         assert(FNM_PATHNAME == FNM_FILE_NAME);
    531         match("", "", 0);
    532         match("*", "hello", 0);
    533         match("hello", "hello", 0);
    534         match("hello*", "hello", 0);
    535         nomatch("hello?", "hello", 0);
    536         match("*hello", "prdel hello", 0);
    537         match("he[sl]lo", "hello", 0);
    538         match("he[sl]lo", "heslo", 0);
    539         nomatch("he[sl]lo", "heblo", 0);
    540         nomatch("he[^sl]lo", "hello", 0);
    541         nomatch("he[^sl]lo", "heslo", 0);
    542         match("he[^sl]lo", "heblo", 0);
    543         nomatch("he[!sl]lo", "hello", 0);
    544         nomatch("he[!sl]lo", "heslo", 0);
    545         match("he[!sl]lo", "heblo", 0);
    546         match("al*[c-t]a*vis*ta", "alheimer talir jehovista", 0);
    547         match("al*[c-t]a*vis*ta", "alfons had jehovista", 0);
    548         match("[a-ce-z]", "a", 0);
    549         match("[a-ce-z]", "c", 0);
    550         nomatch("[a-ce-z]", "d", 0);
    551         match("[a-ce-z]", "e", 0);
    552         match("[a-ce-z]", "z", 0);
    553         nomatch("[^a-ce-z]", "a", 0);
    554         nomatch("[^a-ce-z]", "c", 0);
    555         match("[^a-ce-z]", "d", 0);
    556         nomatch("[^a-ce-z]", "e", 0);
    557         nomatch("[^a-ce-z]", "z", 0);
    558         match("helen??", "helenos", 0);
    559         match("****booo****", "booo", 0);
    560        
    561         match("hello[[:space:]]world", "hello world", 0);
    562         nomatch("hello[[:alpha:]]world", "hello world", 0);
    563        
    564         match("/hoooo*", "/hooooooo/hooo", 0);
    565         nomatch("/hoooo*", "/hooooooo/hooo", FNM_PATHNAME);
    566         nomatch("/hoooo*/", "/hooooooo/hooo", FNM_PATHNAME);
    567         match("/hoooo*/*", "/hooooooo/hooo", FNM_PATHNAME);
    568         match("/hoooo*/hooo", "/hooooooo/hooo", FNM_PATHNAME);
    569         match("/hoooo*", "/hooooooo/hooo", FNM_PATHNAME | FNM_LEADING_DIR);
    570         nomatch("/hoooo*/", "/hooooooo/hooo", FNM_PATHNAME | FNM_LEADING_DIR);
    571         nomatch("/hoooo", "/hooooooo/hooo", FNM_LEADING_DIR);
    572         match("/hooooooo", "/hooooooo/hooo", FNM_LEADING_DIR);
    573        
    574         match("*", "hell", 0);
    575         match("*?", "hell", 0);
    576         match("?*?", "hell", 0);
    577         match("?*??", "hell", 0);
    578         match("??*??", "hell", 0);
    579         nomatch("???*??", "hell", 0);
    580        
    581         nomatch("", "hell", 0);
    582         nomatch("?", "hell", 0);
    583         nomatch("??", "hell", 0);
    584         nomatch("???", "hell", 0);
    585         match("????", "hell", 0);
    586        
    587         match("*", "h.ello", FNM_PERIOD);
    588         match("*", "h.ello", FNM_PATHNAME | FNM_PERIOD);
    589         nomatch("*", ".hello", FNM_PERIOD);
    590         match("h?ello", "h.ello", FNM_PERIOD);
    591         nomatch("?hello", ".hello", FNM_PERIOD);
    592         match("/home/user/.*", "/home/user/.hello", FNM_PATHNAME | FNM_PERIOD);
    593         match("/home/user/*", "/home/user/.hello", FNM_PERIOD);
    594         nomatch("/home/user/*", "/home/user/.hello", FNM_PATHNAME | FNM_PERIOD);
    595 
    596         nomatch("HeLlO", "hello", 0);
    597         match("HeLlO", "hello", FNM_CASEFOLD);
    598 
    599         printf("Failed: %d\n", fail);
    600 }
    601 
    602 #endif
    60353
    60454/** @}
  • uspace/lib/posix/fnmatch.h

    r8cd8bf6 rf5b2522  
    4848#define FNM_NOESCAPE 4
    4949
    50 /* GNU Extensions */
    51 #undef FNM_FILE_NAME
    52 #undef FNM_LEADING_DIR
    53 #undef FNM_CASEFOLD
    54 #define FNM_FILE_NAME FNM_PATHNAME
    55 #define FNM_LEADING_DIR 8
    56 #define FNM_CASEFOLD 16
    57 
    5850extern int posix_fnmatch(const char *pattern, const char *string, int flags);
    5951
  • uspace/lib/posix/pwd.c

    r8cd8bf6 rf5b2522  
    4747        .pw_gid = 1,
    4848        .pw_dir = (char *) "/",
    49         .pw_shell = (char *) "/app/bdsh"
     49        .pw_shell = (char *) "bdsh"
    5050};
    5151
  • uspace/lib/posix/signal.h

    r8cd8bf6 rf5b2522  
    3939#include "sys/types.h"
    4040
    41 extern void __posix_default_signal_handler(int signo);
    42 extern void __posix_hold_signal_handler(int signo);
    43 extern void __posix_ignore_signal_handler(int signo);
     41/* HelenOS doesn't have signals, so calls to functions of this header
     42 * are just replaced with their respective failure return value.
     43 *
     44 * Other macros and constants are here just to satisfy the symbol resolver
     45 * and have no practical value whatsoever, until HelenOS implements some
     46 * equivalent of signals. Maybe something neat based on IPC will be devised
     47 * in the future?
     48 */
    4449
    4550#undef SIG_DFL
    46 #define SIG_DFL ((void (*)(int)) __posix_default_signal_handler)
     51#define SIG_DFL ((void (*)(int)) 0)
    4752#undef SIG_ERR
    48 #define SIG_ERR ((void (*)(int)) NULL)
     53#define SIG_ERR ((void (*)(int)) 0)
    4954#undef SIG_HOLD
    50 #define SIG_HOLD ((void (*)(int)) __posix_hold_signal_handler)
     55#define SIG_HOLD ((void (*)(int)) 0)
    5156#undef SIG_IGN
    52 #define SIG_IGN ((void (*)(int)) __posix_ignore_signal_handler)
     57#define SIG_IGN ((void (*)(int)) 0)
     58
     59#define signal(sig,func) (errno = ENOTSUP, SIG_ERR)
     60#define raise(sig) ((int) -1)
     61#define kill(pid,sig) (errno = ENOTSUP, (int) -1)
    5362
    5463typedef int posix_sig_atomic_t;
    55 typedef uint32_t posix_sigset_t;
     64typedef int posix_sigset_t;
    5665typedef struct posix_mcontext {
    5766        // FIXME: should not be empty to avoid compiler warnings (-pedantic)
     
    7887        int si_errno;
    7988
    80         posix_pid_t si_pid;
    81         posix_uid_t si_uid;
     89        pid_t si_pid;
     90        uid_t si_uid;
    8291        void *si_addr;
    8392        int si_status;
     
    111120/* Values of posix_sigevent::sigev_notify */
    112121#undef SIGEV_NONE
     122#define SIGEV_NONE 0
    113123#undef SIGEV_SIGNAL
     124#define SIGEV_SIGNAL 0
    114125#undef SIGEV_THREAD
    115 #define SIGEV_NONE 0
    116 #define SIGEV_SIGNAL 0
    117126#define SIGEV_THREAD 0
    118127
    119128#undef SIGRT_MIN
     129#define SIGRT_MIN 0
    120130#undef SIGRT_MAX
    121 #define SIGRT_MIN 0
    122131#define SIGRT_MAX 0
    123132
    124133#undef SIG_BLOCK
     134#define SIG_BLOCK 0
    125135#undef SIG_UNBLOCK
     136#define SIG_UNBLOCK 0
    126137#undef SIG_SETMASK
    127 #define SIG_BLOCK 0
    128 #define SIG_UNBLOCK 1
    129 #define SIG_SETMASK 2
     138#define SIG_SETMASK 0
    130139
    131140#undef SA_NOCLDSTOP
     141#define SA_NOCLDSTOP 0
    132142#undef SA_ONSTACK
     143#define SA_ONSTACK 0
    133144#undef SA_RESETHAND
     145#define SA_RESETHAND 0
    134146#undef SA_RESTART
     147#define SA_RESTART 0
    135148#undef SA_SIGINFO
     149#define SA_SIGINFO 0
    136150#undef SA_NOCLDWAIT
     151#define SA_NOCLDWAIT 0
    137152#undef SA_NODEFER
    138 #define SA_NOCLDSTOP (1 << 0)
    139 #define SA_ONSTACK (1 << 1)
    140 #define SA_RESETHAND (1 << 2)
    141 #define SA_RESTART (1 << 3)
    142 #define SA_SIGINFO (1 << 4)
    143 #define SA_NOCLDWAIT (1 << 5)
    144 #define SA_NODEFER (1 << 6)
     153#define SA_NODEFER 0
    145154
    146155#undef SS_ONSTACK
     156#define SS_ONSTACK 0
    147157#undef SS_DISABLE
    148 #define SS_ONSTACK 0
    149158#define SS_DISABLE 0
    150159
    151160#undef MINSIGSTKSZ
     161#define MINSIGSTKSZ 0
    152162#undef SIGSTKSZ
    153 #define MINSIGSTKSZ 0
    154163#define SIGSTKSZ 0
    155164
    156165/* full POSIX set */
    157166enum {
    158         /* Termination Signals */
    159167        SIGABRT,
     168        SIGALRM,
     169        SIGBUS,
     170        SIGCHLD,
     171        SIGCONT,
     172        SIGFPE,
     173        SIGHUP,
     174        SIGILL,
     175        SIGINT,
     176        SIGKILL,
     177        SIGPIPE,
    160178        SIGQUIT,
    161         SIGINT,
     179        SIGSEGV,
     180        SIGSTOP,
    162181        SIGTERM,
    163        
    164         /* Child Signal */
    165         SIGCHLD,
    166        
    167         /* User signals */
    168         SIGUSR1,
    169         SIGUSR2,
    170 
    171         /* Timer */
    172         SIGALRM,
    173         SIGVTALRM,
    174         SIGPROF, /* obsolete */
    175 
    176         _TOP_CATCHABLE_SIGNAL = SIGPROF,
    177 
    178         /* Process Scheduler Interaction - not supported */
    179         SIGSTOP,
    180         SIGCONT,
    181 
    182         /* Process Termination - can't be caught */
    183         SIGKILL,
    184 
    185         _TOP_SENDABLE_SIGNAL = SIGKILL,
    186 
    187         /* Hardware Exceptions - can't be caught or sent */
    188         SIGFPE,
    189         SIGBUS,
    190         SIGILL,
    191         SIGSEGV,
    192 
    193         /* Other Exceptions - not supported */
    194         SIGSYS,
    195         SIGXCPU,
    196         SIGXFSZ,
    197 
    198         /* Debugging - not supported */
    199         SIGTRAP,
    200 
    201         /* Communication Signals - not supported */
    202         SIGHUP,
    203         SIGPIPE,
    204         SIGPOLL, /* obsolete */
    205         SIGURG,
    206 
    207         /* Terminal Signals - not supported */
    208182        SIGTSTP,
    209183        SIGTTIN,
    210184        SIGTTOU,
    211        
    212         _TOP_SIGNAL = SIGTTOU
    213 };
    214 
    215 /* Values for sigaction field si_code. */
    216 
    217 enum {
    218         SI_USER,
    219         SI_QUEUE,
    220         SI_TIMER,
    221         SI_ASYNCIO,
    222         SI_MESGQ,
    223         ILL_ILLOPC,
    224         ILL_ILLOPN,
    225         ILL_ILLADR,
    226         ILL_ILLTRP,
    227         ILL_PRVOPC,
    228         ILL_PRVREG,
    229         ILL_COPROC,
    230         ILL_BADSTK,
    231         FPE_INTDIV,
    232         FPE_INTOVF,
    233         FPE_FLTDIV,
    234         FPE_FLTOVF,
    235         FPE_FLTUND,
    236         FPE_FLTRES,
    237         FPE_FLTINV,
    238         FPE_FLTSUB,
    239         SEGV_MAPERR,
    240         SEGV_ACCERR,
    241         BUS_ADRALN,
    242         BUS_ADRERR,
    243         BUS_OBJERR,
    244         TRAP_BRKPT,
    245         TRAP_TRACE,
    246         CLD_EXITED,
    247         CLD_KILLED,
    248         CLD_DUMPED,
    249         CLD_TRAPPED,
    250         CLD_STOPPED,
    251         CLD_CONTINUED,
    252         POLL_IN,
    253         POLL_OUT,
    254         POLL_MSG,
    255         POLL_ERR,
    256         POLL_PRI,
    257         POLL_HUP
    258 };
    259 
    260 extern int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
    261     struct posix_sigaction *restrict oact);
    262 
    263 extern void (*posix_signal(int sig, void (*func)(int)))(int);
    264 extern int posix_raise(int sig);
    265 extern int posix_kill(posix_pid_t pid, int sig);
    266 extern int posix_killpg(posix_pid_t pid, int sig);
    267 
    268 extern void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message);
    269 extern void posix_psignal(int signum, const char *message);
    270 
     185        SIGUSR1,
     186        SIGUSR2,
     187        SIGPOLL,
     188        SIGPROF,
     189        SIGSYS,
     190        SIGTRAP,
     191        SIGURG,
     192        SIGVTALRM,
     193        SIGXCPU,
     194        SIGXFSZ
     195};
     196
     197/* Just declared to avoid compiler warnings. */
    271198extern int posix_sigemptyset(posix_sigset_t *set);
    272 extern int posix_sigfillset(posix_sigset_t *set);
    273 extern int posix_sigaddset(posix_sigset_t *set, int signo);
    274 extern int posix_sigdelset(posix_sigset_t *set, int signo);
    275 extern int posix_sigismember(const posix_sigset_t *set, int signo);
    276 
    277 extern int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
    278     posix_sigset_t *restrict oset);
    279199extern int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
    280200    posix_sigset_t *restrict oset);
     
    284204        #define sigset_t posix_sigset_t
    285205        #define sigval posix_sigval
    286         #ifndef sigevent
    287                 #define sigevent posix_sigevent
    288         #endif
     206        #define sigevent posix_sigevent
    289207        #define sigaction posix_sigaction
    290208        #define mcontext_t posix_mcontext_t
     
    292210        #define stack_t posix_stack_t
    293211        #define siginfo_t posix_siginfo_t
    294 
    295         #define signal posix_signal
    296         #define raise posix_raise
    297         #define kill posix_kill
    298         #define killpg posix_killpg
    299 
    300         #define psiginfo posix_psiginfo
    301         #define psignal posix_psignal
    302 
    303212        #define sigemptyset posix_sigemptyset
    304         #define sigfillset posix_sigfillset
    305         #define sigaddset posix_sigaddset
    306         #define sigdelset posix_sigdelset
    307         #define sigismember posix_sigismember
    308 
    309         #define pthread_sigmask posix_thread_sigmask
    310213        #define sigprocmask posix_sigprocmask
    311214#endif
  • uspace/lib/posix/stdbool.h

    r8cd8bf6 rf5b2522  
    4040
    4141#ifdef LIBC_BOOL_H_
    42         #error "You can't include bool.h and stdbool.h at the same time."
     42        #error You can't include bool.h and stdbool.h at the same time.
    4343#endif
    4444#define LIBC_BOOL_H_
  • uspace/lib/posix/stdint.h

    r8cd8bf6 rf5b2522  
    3535#ifndef POSIX_STDINT_H_
    3636#define POSIX_STDINT_H_
    37 
    38 #include "libc/stdint.h"
    3937
    4038#undef INT8_MAX
  • uspace/lib/posix/stdio.c

    r8cd8bf6 rf5b2522  
    3636#define LIBPOSIX_INTERNAL
    3737
    38 /* Has to be first. */
    39 #include "stdbool.h"
     38#include <assert.h>
     39#include <errno.h>
    4040
    4141#include "internal/common.h"
    4242#include "stdio.h"
    43 
    44 #include "assert.h"
    45 #include "errno.h"
    4643#include "string.h"
    47 #include "sys/types.h"
    48 
    49 #include "libc/io/printf_core.h"
    50 #include "libc/str.h"
    51 #include "libc/malloc.h"
    52 
    53 
    54 /* not the best of solutions, but freopen and ungetc will eventually
     44
     45/* not the best of solutions, but freopen will eventually
    5546 * need to be implemented in libc anyway
    5647 */
    5748#include "../c/generic/private/stdio.h"
    5849
    59 /** Clears the stream's error and end-of-file indicators.
    60  *
    61  * @param stream Stream whose indicators shall be cleared.
    62  */
    63 void posix_clearerr(FILE *stream)
    64 {
    65         stream->error = 0;
    66         stream->eof = 0;
    67 }
    68 
    69 /**
    70  * Generate a pathname for the controlling terminal.
    71  *
    72  * @param s Allocated buffer to which the pathname shall be put.
    73  * @return Either s or static location filled with the requested pathname.
    74  */
    75 char *posix_ctermid(char *s)
    76 {
    77         /* Currently always returns an error value (empty string). */
    78         // TODO: return a real terminal path
    79 
    80         static char dummy_path[L_ctermid] = {'\0'};
    81 
    82         if (s == NULL) {
    83                 return dummy_path;
    84         }
    85 
    86         s[0] = '\0';
    87         return s;
    88 }
    89 
    90 /**
    91  * Push byte back into input stream.
    92  *
    93  * @param c Byte to be pushed back.
    94  * @param stream Stream to where the byte shall be pushed.
    95  * @return Provided byte on success or EOF if not possible.
     50/**
     51 *
     52 * @param c
     53 * @param stream
     54 * @return
    9655 */
    9756int posix_ungetc(int c, FILE *stream)
    9857{
    99         uint8_t b = (uint8_t) c;
    100 
    101         bool can_unget =
    102                 /* Provided character is legal. */
    103             c != EOF &&
    104                 /* Stream is consistent. */
    105             !stream->error &&
    106                 /* Stream is buffered. */
    107             stream->btype != _IONBF &&
    108                 /* Last operation on the stream was a read operation. */
    109             stream->buf_state == _bs_read &&
    110                 /* Stream buffer is already allocated (i.e. there was already carried
    111                  * out either write or read operation on the stream). This is probably
    112                  * redundant check but let's be safe. */
    113             stream->buf != NULL &&
    114                 /* There is still space in the stream to retreat. POSIX demands the
    115                  * possibility to unget at least 1 character. It should be always
    116                  * possible, assuming the last operation on the stream read at least 1
    117                  * character, because the buffer is refilled in the lazily manner. */
    118             stream->buf_tail > stream->buf;
    119 
    120         if (can_unget) {
    121                 --stream->buf_tail;
    122                 stream->buf_tail[0] = b;
    123                 stream->eof = false;
    124                 return (int) b;
    125         } else {
    126                 return EOF;
    127         }
    128 }
    129 
    130 /**
    131  * Read a stream until the delimiter (or EOF) is encountered.
    132  *
    133  * @param lineptr Pointer to the output buffer in which there will be stored
    134  *     nul-terminated string together with the delimiter (if encountered).
    135  *     Will be resized if necessary.
    136  * @param n Pointer to the size of the output buffer. Will be increased if
    137  *     necessary.
    138  * @param delimiter Delimiter on which to finish reading the stream.
    139  * @param stream Input stream.
    140  * @return Number of fetched characters (including delimiter if encountered)
    141  *     or -1 on error (set in errno).
    142  */
    143 ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
    144     int delimiter, FILE *restrict stream)
    145 {
    146         /* Check arguments for sanity. */
    147         if (!lineptr || !n) {
    148                 errno = EINVAL;
    149                 return -1;
    150         }
    151 
    152         size_t alloc_step = 80; /* Buffer size gain during reallocation. */
    153         char *pos = *lineptr; /* Next free byte of the output buffer. */
    154         size_t cnt = 0; /* Number of fetched characters. */
    155         int c = fgetc(stream); /* Current input character. Might be EOF. */
    156 
    157         do {
    158                 /* Mask EOF as NUL to terminate string. */
    159                 if (c == EOF) {
    160                         c = '\0';
    161                 }
    162 
    163                 /* Ensure there is still space left in the buffer. */
    164                 if (pos == *lineptr + *n) {
    165                         *lineptr = realloc(*lineptr, *n + alloc_step);
    166                         if (*lineptr) {
    167                                 pos = *lineptr + *n;
    168                                 *n += alloc_step;
    169                         } else {
    170                                 errno = ENOMEM;
    171                                 return -1;
    172                         }
    173                 }
    174 
    175                 /* Store the fetched character. */
    176                 *pos = c;
    177 
    178                 /* Fetch the next character according to the current character. */
    179                 if (c != '\0') {
    180                         ++pos;
    181                         ++cnt;
    182                         if (c == delimiter) {
    183                                 /* Delimiter was just stored. Provide EOF as the next
    184                                  * character - it will be masked as NUL and output string
    185                                  * will be properly terminated. */
    186                                 c = EOF;
    187                         } else {
    188                                 /* Neither delimiter nor EOF were encountered. Just fetch
    189                                  * the next character from the stream. */
    190                                 c = fgetc(stream);
    191                         }
    192                 }
    193         } while (c != '\0');
    194 
    195         if (errno == EOK && cnt > 0) {
    196                 return cnt;
    197         } else {
    198                 /* Either some error occured or the stream was already at EOF. */
    199                 return -1;
    200         }
    201 }
    202 
    203 /**
    204  * Read a stream until the newline (or EOF) is encountered.
    205  *
    206  * @param lineptr Pointer to the output buffer in which there will be stored
    207  *     nul-terminated string together with the delimiter (if encountered).
    208  *     Will be resized if necessary.
    209  * @param n Pointer to the size of the output buffer. Will be increased if
    210  *     necessary.
    211  * @param stream Input stream.
    212  * @return Number of fetched characters (including newline if encountered)
    213  *     or -1 on error (set in errno).
    214  */
    215 ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
    216     FILE *restrict stream)
    217 {
    218         return posix_getdelim(lineptr, n, '\n', stream);
    219 }
    220 
    221 /**
    222  * Reopen a file stream.
    223  *
    224  * @param filename Pathname of a file to be reopened or NULL for changing
    225  *     the mode of the stream.
    226  * @param mode Mode to be used for reopening the file or changing current
    227  *     mode of the stream.
    228  * @param stream Current stream associated with the opened file.
    229  * @return On success, either a stream of the reopened file or the provided
    230  *     stream with a changed mode. NULL otherwise.
     58        // TODO
     59        not_implemented();
     60}
     61
     62/**
     63 *
     64 * @param filename
     65 * @param mode
     66 * @param stream
     67 * @return
    23168 */
    23269FILE *posix_freopen(
     
    278115/**
    279116 *
    280  * @param buf
    281  * @param size
    282  * @param mode
    283  * @return
    284  */
    285 FILE *posix_fmemopen(void *restrict buf, size_t size,
    286     const char *restrict mode)
    287 {
    288         // TODO
    289         not_implemented();
    290 }
    291 
    292 /**
    293  *
    294  * @param bufp
    295  * @param sizep
    296  * @return
    297  */
    298 FILE *posix_open_memstream(char **bufp, size_t *sizep)
    299 {
    300         // TODO
    301         not_implemented();
    302 }
    303 
    304 /**
    305  * Write error messages to standard error.
    306  *
    307  * @param s Error message.
     117 * @param s
    308118 */
    309119void posix_perror(const char *s)
    310120{
    311         if (s == NULL || s[0] == '\0') {
    312                 fprintf(stderr, "%s\n", posix_strerror(errno));
    313         } else {
    314                 fprintf(stderr, "%s: %s\n", s, posix_strerror(errno));
    315         }
    316 }
    317 
    318 struct _posix_fpos {
    319         off64_t offset;
    320 };
    321 
    322 /** Restores stream a to position previously saved with fgetpos().
    323  *
    324  * @param stream Stream to restore
    325  * @param pos Position to restore
    326  * @return Zero on success, non-zero (with errno set) on failure
    327  */
    328 int posix_fsetpos(FILE *stream, const posix_fpos_t *pos)
    329 {
    330         return fseek(stream, pos->offset, SEEK_SET);
    331 }
    332 
    333 /** Saves the stream's position for later use by fsetpos().
    334  *
    335  * @param stream Stream to save
    336  * @param pos Place to store the position
    337  * @return Zero on success, non-zero (with errno set) on failure
    338  */
    339 int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos)
    340 {
    341         off64_t ret = ftell(stream);
    342         if (ret == -1) {
    343                 return errno;
    344         }
    345         pos->offset = ret;
    346         return 0;
    347 }
    348 
    349 /**
    350  * Reposition a file-position indicator in a stream.
    351  *
    352  * @param stream Stream to seek in.
    353  * @param offset Direction and amount of bytes to seek.
    354  * @param whence From where to seek.
    355  * @return Zero on success, -1 otherwise.
    356  */
    357 int posix_fseek(FILE *stream, long offset, int whence)
    358 {
    359         return fseek(stream, (off64_t) offset, whence);
    360 }
    361 
    362 /**
    363  * Reposition a file-position indicator in a stream.
    364  *
    365  * @param stream Stream to seek in.
    366  * @param offset Direction and amount of bytes to seek.
    367  * @param whence From where to seek.
    368  * @return Zero on success, -1 otherwise.
     121        // TODO
     122        not_implemented();
     123}
     124
     125/**
     126 *
     127 * @param stream
     128 * @param offset
     129 * @param whence
     130 * @return
    369131 */
    370132int posix_fseeko(FILE *stream, posix_off_t offset, int whence)
    371133{
    372         return fseek(stream, (off64_t) offset, whence);
    373 }
    374 
    375 /**
    376  * Discover current file offset in a stream.
    377  *
    378  * @param stream Stream for which the offset shall be retrieved.
    379  * @return Current offset or -1 if not possible.
    380  */
    381 long posix_ftell(FILE *stream)
    382 {
    383         return (long) ftell(stream);
    384 }
    385 
    386 /**
    387  * Discover current file offset in a stream.
    388  *
    389  * @param stream Stream for which the offset shall be retrieved.
    390  * @return Current offset or -1 if not possible.
     134        // TODO
     135        not_implemented();
     136}
     137
     138/**
     139 *
     140 * @param stream
     141 * @return
    391142 */
    392143posix_off_t posix_ftello(FILE *stream)
    393144{
    394         return (posix_off_t) ftell(stream);
    395 }
    396 
    397 /**
    398  * Print formatted output to the opened file.
    399  *
    400  * @param fildes File descriptor of the opened file.
    401  * @param format Format description.
    402  * @return Either the number of printed characters or negative value on error.
    403  */
    404 int posix_dprintf(int fildes, const char *restrict format, ...)
    405 {
    406         va_list list;
    407         va_start(list, format);
    408         int result = posix_vdprintf(fildes, format, list);
    409         va_end(list);
    410         return result;
    411 }
    412 
    413 /**
    414  * Write ordinary string to the opened file.
    415  *
    416  * @param str String to be written.
    417  * @param size Size of the string (in bytes)..
    418  * @param fd File descriptor of the opened file.
    419  * @return The number of written characters.
    420  */
    421 static int _dprintf_str_write(const char *str, size_t size, void *fd)
    422 {
    423         ssize_t wr = write(*(int *) fd, str, size);
    424         return str_nlength(str, wr);
    425 }
    426 
    427 /**
    428  * Write wide string to the opened file.
    429  *
    430  * @param str String to be written.
    431  * @param size Size of the string (in bytes).
    432  * @param fd File descriptor of the opened file.
    433  * @return The number of written characters.
    434  */
    435 static int _dprintf_wstr_write(const wchar_t *str, size_t size, void *fd)
    436 {
    437         size_t offset = 0;
    438         size_t chars = 0;
    439         size_t sz;
    440         char buf[4];
    441        
    442         while (offset < size) {
    443                 sz = 0;
    444                 if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) {
    445                         break;
    446                 }
    447                
    448                 if (write(*(int *) fd, buf, sz) != (ssize_t) sz) {
    449                         break;
    450                 }
    451                
    452                 chars++;
    453                 offset += sizeof(wchar_t);
    454         }
    455        
    456         return chars;
    457 }
    458 
    459 /**
    460  * Print formatted output to the opened file.
    461  *
    462  * @param fildes File descriptor of the opened file.
    463  * @param format Format description.
    464  * @param ap Print arguments.
    465  * @return Either the number of printed characters or negative value on error.
    466  */
    467 int posix_vdprintf(int fildes, const char *restrict format, va_list ap)
    468 {
    469         printf_spec_t spec = {
    470                 .str_write = _dprintf_str_write,
    471                 .wstr_write = _dprintf_wstr_write,
    472                 .data = &fildes
    473         };
    474        
    475         return printf_core(format, &spec, ap);
    476 }
    477 
    478 /**
    479  * Print formatted output to the string.
    480  *
    481  * @param s Output string.
    482  * @param format Format description.
    483  * @return Either the number of printed characters (excluding null byte) or
    484  *     negative value on error.
    485  */
    486 int posix_sprintf(char *s, const char *restrict format, ...)
    487 {
    488         va_list list;
    489         va_start(list, format);
    490         int result = posix_vsprintf(s, format, list);
    491         va_end(list);
    492         return result;
    493 }
    494 
    495 /**
    496  * Print formatted output to the string.
    497  *
    498  * @param s Output string.
    499  * @param format Format description.
    500  * @param ap Print arguments.
    501  * @return Either the number of printed characters (excluding null byte) or
    502  *     negative value on error.
    503  */
    504 int posix_vsprintf(char *s, const char *restrict format, va_list ap)
    505 {
    506         return vsnprintf(s, STR_NO_LIMIT, format, ap);
    507 }
    508 
    509 /**
    510  * Convert formatted input from the stream.
    511  *
    512  * @param stream Input stream.
    513  * @param format Format description.
    514  * @return The number of converted output items or EOF on failure.
    515  */
    516 int posix_fscanf(FILE *restrict stream, const char *restrict format, ...)
    517 {
    518         va_list list;
    519         va_start(list, format);
    520         int result = posix_vfscanf(stream, format, list);
    521         va_end(list);
    522         return result;
    523 }
    524 
    525 /**
    526  * Convert formatted input from the standard input.
    527  *
    528  * @param format Format description.
    529  * @return The number of converted output items or EOF on failure.
    530  */
    531 int posix_scanf(const char *restrict format, ...)
    532 {
    533         va_list list;
    534         va_start(list, format);
    535         int result = posix_vscanf(format, list);
    536         va_end(list);
    537         return result;
    538 }
    539 
    540 /**
    541  * Convert formatted input from the standard input.
    542  *
    543  * @param format Format description.
    544  * @param arg Output items.
    545  * @return The number of converted output items or EOF on failure.
    546  */
    547 int posix_vscanf(const char *restrict format, va_list arg)
    548 {
    549         return posix_vfscanf(stdin, format, arg);
    550 }
    551 
    552 /**
    553  * Convert formatted input from the string.
    554  *
    555  * @param s Input string.
    556  * @param format Format description.
    557  * @return The number of converted output items or EOF on failure.
    558  */
    559 int posix_sscanf(const char *restrict s, const char *restrict format, ...)
    560 {
    561         va_list list;
    562         va_start(list, format);
    563         int result = posix_vsscanf(s, format, list);
    564         va_end(list);
    565         return result;
    566 }
    567 
    568 /**
    569  * Acquire file stream for the thread.
    570  *
    571  * @param file File stream to lock.
    572  */
    573 void posix_flockfile(FILE *file)
    574 {
    575         /* dummy */
    576 }
    577 
    578 /**
    579  * Acquire file stream for the thread (non-blocking).
    580  *
    581  * @param file File stream to lock.
    582  * @return Zero for success and non-zero if the lock cannot be acquired.
    583  */
    584 int posix_ftrylockfile(FILE *file)
    585 {
    586         /* dummy */
    587         return 0;
    588 }
    589 
    590 /**
    591  * Relinquish the ownership of the locked file stream.
    592  *
    593  * @param file File stream to unlock.
    594  */
    595 void posix_funlockfile(FILE *file)
    596 {
    597         /* dummy */
    598 }
    599 
    600 /**
    601  * Get a byte from a stream (thread-unsafe).
    602  *
    603  * @param stream Input file stream.
    604  * @return Either read byte or EOF.
    605  */
    606 int posix_getc_unlocked(FILE *stream)
    607 {
    608         return getc(stream);
    609 }
    610 
    611 /**
    612  * Get a byte from the standard input stream (thread-unsafe).
    613  *
    614  * @return Either read byte or EOF.
    615  */
    616 int posix_getchar_unlocked(void)
    617 {
    618         return getchar();
    619 }
    620 
    621 /**
    622  * Put a byte on a stream (thread-unsafe).
    623  *
    624  * @param c Byte to output.
    625  * @param stream Output file stream.
    626  * @return Either written byte or EOF.
    627  */
    628 int posix_putc_unlocked(int c, FILE *stream)
    629 {
    630         return putc(c, stream);
    631 }
    632 
    633 /**
    634  * Put a byte on the standard output stream (thread-unsafe).
    635  *
    636  * @param c Byte to output.
    637  * @return Either written byte or EOF.
    638  */
    639 int posix_putchar_unlocked(int c)
    640 {
    641         return putchar(c);
    642 }
    643 
    644 /**
    645  * Remove a file.
    646  *
    647  * @param path Pathname of the file that shall be removed.
    648  * @return Zero on success, -1 otherwise.
     145        // TODO
     146        not_implemented();
     147}
     148
     149/**
     150 *
     151 * @param s
     152 * @param format
     153 * @param ...
     154 * @return
     155 */
     156int posix_sprintf(char *s, const char *format, ...)
     157{
     158        // TODO
     159        not_implemented();
     160}
     161
     162/**
     163 *
     164 * @param s
     165 * @param format
     166 * @param ...
     167 * @return
     168 */
     169int posix_vsprintf(char *s, const char *format, va_list ap)
     170{
     171        // TODO: low priority, just a compile-time dependency of binutils
     172        not_implemented();
     173}
     174
     175/**
     176 *
     177 * @param s
     178 * @param format
     179 * @param ...
     180 * @return
     181 */
     182int posix_sscanf(const char *s, const char *format, ...)
     183{
     184        // TODO
     185        not_implemented();
     186}
     187
     188/**
     189 *
     190 * @param path
     191 * @return
    649192 */
    650193int posix_remove(const char *path)
    651194{
    652         // FIXME: unlink() and rmdir() seem to be equivalent at the moment,
    653         //        but that does not have to be true forever
    654         return unlink(path);
     195        // TODO: low priority, just a compile-time dependency of binutils
     196        not_implemented();
    655197}
    656198
  • uspace/lib/posix/stdio.h

    r8cd8bf6 rf5b2522  
    4040#include "sys/types.h"
    4141#include "libc/stdarg.h"
    42 #include "limits.h"
    4342
    44 #undef L_ctermid
    45 #define L_ctermid PATH_MAX
    46 
    47 extern void posix_clearerr(FILE *stream);
    48 extern char *posix_ctermid(char *s);
    49 
    50 /* Input/Output */
     43/* Character Input/Output */
    5144#undef putc
    5245#define putc fputc
     
    5447#define getc fgetc
    5548extern int posix_ungetc(int c, FILE *stream);
    56 
    57 extern ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
    58     int delimiter, FILE *restrict stream);
    59 extern ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
    60     FILE *restrict stream);
    6149
    6250/* Opening Streams */
     
    6654   FILE *restrict stream);
    6755
    68 /* Memory Streams */
    69 
    70 extern FILE *posix_fmemopen(void *restrict buf, size_t size,
    71     const char *restrict mode);
    72 extern FILE *posix_open_memstream(char **bufp, size_t *sizep);
    73 
    7456/* Error Messages */
    7557extern void posix_perror(const char *s);
    7658
    7759/* File Positioning */
    78 
    79 typedef struct _posix_fpos posix_fpos_t;
    80 extern int posix_fsetpos(FILE *stream, const posix_fpos_t *pos);
    81 extern int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos);
    82 extern int posix_fseek(FILE *stream, long offset, int whence);
    8360extern int posix_fseeko(FILE *stream, posix_off_t offset, int whence);
    84 extern long posix_ftell(FILE *stream);
    8561extern posix_off_t posix_ftello(FILE *stream);
    8662
    8763/* Formatted Input/Output */
    88 extern int posix_dprintf(int fildes, const char *restrict format, ...)
    89     PRINTF_ATTRIBUTE(2, 3);
    90 extern int posix_vdprintf(int fildes, const char *restrict format, va_list ap);
    91 extern int posix_sprintf(char *restrict s, const char *restrict format, ...)
    92     PRINTF_ATTRIBUTE(2, 3);
     64extern int posix_sprintf(char *restrict s, const char *restrict format, ...);
    9365extern int posix_vsprintf(char *restrict s, const char *restrict format, va_list ap);
    94 
    95 extern int posix_fscanf(
    96     FILE *restrict stream, const char *restrict format, ...);
    97 extern int posix_vfscanf(
    98     FILE *restrict stream, const char *restrict format, va_list arg);
    99 extern int posix_scanf(const char *restrict format, ...);
    100 extern int posix_vscanf(const char *restrict format, va_list arg);
    101 extern int posix_sscanf(
    102     const char *restrict s, const char *restrict format, ...);
    103 extern int posix_vsscanf(
    104     const char *restrict s, const char *restrict format, va_list arg);
    105 
    106 /* File Locking */
    107 
    108 extern void posix_flockfile(FILE *file);
    109 extern int posix_ftrylockfile(FILE *file);
    110 extern void posix_funlockfile(FILE *file);
    111 
    112 extern int posix_getc_unlocked(FILE *stream);
    113 extern int posix_getchar_unlocked(void);
    114 extern int posix_putc_unlocked(int c, FILE *stream);
    115 extern int posix_putchar_unlocked(int c);
     66extern int posix_sscanf(const char *restrict s, const char *restrict format, ...);
    11667
    11768/* Deleting Files */
     
    12576
    12677#ifndef LIBPOSIX_INTERNAL
    127         #define clearerr posix_clearerr
    128         #define ctermid posix_ctermid
    129 
    13078        #define ungetc posix_ungetc
    131 
    132         #define getdelim posix_getdelim
    133         #define getline posix_getline
    13479
    13580        #define freopen posix_freopen
    13681
    137         #define fmemopen posix_fmemopen
    138         #define open_memstream posix_open_memstream
    139 
    14082        #define perror posix_perror
    14183
    142         #define fpos_t posix_fpos_t
    143         #define fsetpos posix_fsetpos
    144         #define fgetpos posix_fgetpos
    145         #define fseek posix_fseek
    14684        #define fseeko posix_fseeko
    147         #define ftell posix_ftell
    14885        #define ftello posix_ftello
    14986
    150         #define dprintf posix_dprintf
    151         #define vdprintf posix_vdprintf
    15287        #define sprintf posix_sprintf
    15388        #define vsprintf posix_vsprintf
    154 
    155         #define fscanf posix_fscanf
    156         #define vfscanf posix_vfscanf
    157         #define vscanf posix_vscanf
    158         #define scanf posix_scanf
    15989        #define sscanf posix_sscanf
    160         #define vsscanf posix_vsscanf
    161 
    162         #define flockfile posix_flockfile
    163         #define ftrylockfile posix_ftrylockfile
    164         #define funlockfile posix_funlockfile
    165 
    166         #define getc_unlocked posix_getc_unlocked
    167         #define getchar_unlocked posix_getchar_unlocked
    168         #define putc_unlocked posix_putc_unlocked
    169         #define putchar_unlocked posix_putchar_unlocked
    17090
    17191        #define remove posix_remove
  • uspace/lib/posix/stdlib.c

    r8cd8bf6 rf5b2522  
    3636#define LIBPOSIX_INTERNAL
    3737
    38 #include "internal/common.h"
    3938#include "stdlib.h"
    40 
    41 #include "errno.h"
    42 
    4339#include "libc/sort.h"
    4440#include "libc/str.h"
    4541#include "libc/vfs/vfs.h"
     42#include "internal/common.h"
     43#include <errno.h>  // FIXME: use POSIX errno
    4644
    4745/**
     
    340338}
    341339
    342 /**
    343  * Should read system load statistics. Not supported. Always returns -1.
    344  *
    345  * @param loadavg
    346  * @param nelem
    347  * @return
    348  */
    349 int bsd_getloadavg(double loadavg[], int nelem)
    350 {
    351         return -1;
    352 }
    353 
    354340/** @}
    355341 */
  • uspace/lib/posix/stdlib.h

    r8cd8bf6 rf5b2522  
    120120/* Legacy Declarations */
    121121extern char *posix_mktemp(char *tmpl);
    122 extern int bsd_getloadavg(double loadavg[], int nelem);
    123122
    124123#ifndef LIBPOSIX_INTERNAL
     
    164163
    165164        #define mktemp posix_mktemp
    166         #define getloadavg bsd_getloadavg
    167165#endif
    168166
  • uspace/lib/posix/stdlib/strtol.c

    r8cd8bf6 rf5b2522  
    3737#include "../internal/common.h"
    3838#include "../stdlib.h"
    39 
     39#include <errno.h>  // FIXME: use POSIX errno
    4040#include "../limits.h"
    4141#include "../ctype.h"
    42 #include "../errno.h"
    4342
    4443// TODO: documentation
  • uspace/lib/posix/stdlib/strtold.c

    r8cd8bf6 rf5b2522  
    3535#define LIBPOSIX_INTERNAL
    3636
    37 /* Must be first. */
    38 #include "../stdbool.h"
    39 
    4037#include "../internal/common.h"
     38
     39#include "../libc/assert.h"
     40#include "../ctype.h"
     41#include <errno.h> // TODO: use POSIX errno
     42#include "../libc/bool.h"
     43#include "../stdint.h"
    4144#include "../stdlib.h"
    42 
    43 #include "../assert.h"
    44 #include "../ctype.h"
    45 #include "../stdint.h"
    4645#include "../strings.h"
    47 #include "../errno.h"
    4846
    4947#ifndef HUGE_VALL
  • uspace/lib/posix/string.c

    r8cd8bf6 rf5b2522  
    3636#define LIBPOSIX_INTERNAL
    3737
    38 #include "internal/common.h"
    3938#include "string.h"
    4039
    41 #include "assert.h"
    42 #include "errno.h"
    43 #include "limits.h"
    44 #include "stdlib.h"
    45 #include "signal.h"
    46 
    47 #include "libc/str_error.h"
     40#include <assert.h>
     41#include <str_error.h>
     42#include <stdlib.h>
     43#include <errno.h>
     44
     45/**
     46 * Defined for convenience. Returns pointer to the terminating nul character.
     47 *
     48 * @param s
     49 * @return
     50 */
     51static char *strzero(const char *s)
     52{
     53        while (*s != '\0') {
     54                s++;
     55        }
     56
     57        return (char *) s;
     58}
    4859
    4960/**
     
    172183        assert(src != NULL);
    173184
    174         posix_strcpy(posix_strchr(dest, '\0'), src);
     185        posix_strcpy(strzero(dest), src);
    175186        return dest;
    176187}
     
    188199        assert(src != NULL);
    189200
    190         char *zeroptr = posix_strncpy(posix_strchr(dest, '\0'), src, n);
     201        char *zeroptr = posix_strncpy(strzero(dest), src, n);
    191202        /* strncpy doesn't append the nul terminator, so we do it here */
    192203        zeroptr[n] = '\0';
     
    229240char *posix_strdup(const char *s)
    230241{
    231         return posix_strndup(s, SIZE_MAX);
     242        // FIXME: SIZE_MAX doesn't work
     243        return posix_strndup(s, STR_NO_LIMIT);
    232244}
    233245
     
    348360        assert(s != NULL);
    349361       
    350         char *res = gnu_strchrnul(s, c);
    351         return (*res == c) ? res : NULL;
     362        /* special handling for the case that zero is searched for */
     363        if (c == '\0') {
     364                return strzero(s);
     365        }
     366       
     367        /* otherwise just loop through the string until found */
     368        while (*s != (char) c) {
     369                if (*s == '\0') {
     370                        return NULL;
     371                }
     372
     373                s++;
     374        }
     375       
     376        return (char *) s;
    352377}
    353378
     
    362387        assert(s != NULL);
    363388       
    364         const char *ptr = posix_strchr(s, '\0');
     389        const char *ptr = strzero(s);
    365390       
    366391        /* the same as in strchr, except it loops in reverse direction */
     
    374399
    375400        return (char *) ptr;
    376 }
    377 
    378 char *gnu_strchrnul(const char *s, int c)
    379 {
    380         assert(s != NULL);
    381        
    382         while (*s != c && *s != '\0') {
    383                 s++;
    384         }
    385        
    386         return (char *) s;
    387401}
    388402
     
    510524char *posix_strerror(int errnum)
    511525{
    512         /* Uses function from libc, we just have to negate errno
    513          * (POSIX uses positive errorcodes, HelenOS has negative).
     526        /* uses function from libc, we just have to negate errno
     527         * (POSIX uses positive errorcodes, HelenOS has negative)
    514528         */
    515         // FIXME: not all POSIX error codes are in libc
    516         return (char *) str_error(-posix_abs(errnum));
     529        return (char *) str_error(-errnum);
    517530}
    518531
     
    549562        assert(s != NULL);
    550563       
    551         return (size_t) (posix_strchr(s, '\0') - s);
     564        return (size_t) (strzero(s) - s);
    552565}
    553566
     
    572585}
    573586
    574 /**
    575  *
    576  * @param signum
    577  * @return
    578  */
    579 char *posix_strsignal(int signum)
    580 {
    581         static const char *const sigstrings[] = {
    582                 [SIGABRT] = "SIGABRT (Process abort signal)",
    583                 [SIGALRM] = "SIGALRM (Alarm clock)",
    584                 [SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
    585                 [SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
    586                 [SIGCONT] = "SIGCONT (Continue executing, if stopped)",
    587                 [SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
    588                 [SIGHUP] = "SIGHUP (Hangup)",
    589                 [SIGILL] = "SIGILL (Illegal instruction)",
    590                 [SIGINT] = "SIGINT (Terminal interrupt signal)",
    591                 [SIGKILL] = "SIGKILL (Kill process)",
    592                 [SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
    593                 [SIGQUIT] = "SIGQUIT (Terminal quit signal)",
    594                 [SIGSEGV] = "SIGSEGV (Invalid memory reference)",
    595                 [SIGSTOP] = "SIGSTOP (Stop executing)",
    596                 [SIGTERM] = "SIGTERM (Termination signal)",
    597                 [SIGTSTP] = "SIGTSTP (Terminal stop signal)",
    598                 [SIGTTIN] = "SIGTTIN (Background process attempting read)",
    599                 [SIGTTOU] = "SIGTTOU (Background process attempting write)",
    600                 [SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
    601                 [SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
    602                 [SIGPOLL] = "SIGPOLL (Pollable event)",
    603                 [SIGPROF] = "SIGPROF (Profiling timer expired)",
    604                 [SIGSYS] = "SIGSYS (Bad system call)",
    605                 [SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
    606                 [SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
    607                 [SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
    608                 [SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
    609                 [SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
    610         };
    611 
    612         if (signum <= _TOP_SIGNAL) {
    613                 return (char *) sigstrings[signum];
    614         }
    615 
    616         return (char *) "ERROR, Invalid signal number";
    617 }
    618 
    619587/** @}
    620588 */
  • uspace/lib/posix/string.h

    r8cd8bf6 rf5b2522  
    8585extern char *posix_strchr(const char *s, int c);
    8686extern char *posix_strrchr(const char *s, int c);
    87 extern char *gnu_strchrnul(const char *s, int c);
    8887extern char *posix_strpbrk(const char *s1, const char *s2);
    8988extern size_t posix_strcspn(const char *s1, const char *s2);
     
    102101extern size_t posix_strlen(const char *s);
    103102extern size_t posix_strnlen(const char *s, size_t n);
    104 
    105 /* Signal messages */
    106 extern char *posix_strsignal(int signum);
    107103
    108104/* Legacy declarations */
     
    131127        #define strchr posix_strchr
    132128        #define strrchr posix_strrchr
    133         #define strchrnul gnu_strchrnul
    134129        #define strpbrk posix_strpbrk
    135130        #define strcspn posix_strcspn
     
    146141        #define strnlen posix_strnlen
    147142
    148         #define strsignal posix_strsignal
    149 
    150143        #define ffs posix_ffs
    151144        #define strcasecmp posix_strcasecmp
  • uspace/lib/posix/strings.c

    r8cd8bf6 rf5b2522  
    3838#include "internal/common.h"
    3939#include "strings.h"
    40 
    4140#include "string.h"
    4241#include "ctype.h"
  • uspace/lib/posix/sys/stat.c

    r8cd8bf6 rf5b2522  
    3636#define LIBPOSIX_INTERNAL
    3737
     38#include "stat.h"
    3839#include "../internal/common.h"
    39 #include "stat.h"
    40 
    41 #include "../errno.h"
    42 #include "../libc/mem.h"
     40#include <mem.h>
    4341
    4442/**
    45  * Convert HelenOS stat struct into POSIX stat struct (if possible).
     43 * Convert HelenOS stat struct into POSIX stat struct (if possible)
    4644 *
    47  * @param dest POSIX stat struct.
    48  * @param src HelenOS stat struct.
     45 * @param dest
     46 * @param src
    4947 */
    5048static void stat_to_posix(struct posix_stat *dest, struct stat *src)
     
    6866
    6967/**
    70  * Retrieve file status for file associated with file descriptor.
    7168 *
    72  * @param fd File descriptor of the opened file.
    73  * @param st Status structure to be filled with information.
    74  * @return Zero on success, -1 otherwise.
     69 * @param fd
     70 * @param st
     71 * @return
    7572 */
    7673int posix_fstat(int fd, struct posix_stat *st)
    7774{
    7875        struct stat hst;
    79         int rc = fstat(fd, &hst);
    80         if (rc < 0) {
    81                 /* fstat() returns negative error code instead of using errno.
    82                  */
    83                 errno = -rc;
     76        if (fstat(fd, &hst) == -1) {
     77                // TODO: propagate a POSIX compatible errno
    8478                return -1;
    8579        }
     
    8983
    9084/**
    91  * Retrieve file status for symbolic link.
    9285 *
    93  * @param path Path to the symbolic link.
    94  * @param st Status structure to be filled with information.
    95  * @return Zero on success, -1 otherwise.
     86 * @param path
     87 * @param st
     88 * @return
    9689 */
    97 int posix_lstat(const char *path, struct posix_stat *st)
     90int posix_lstat(const char *restrict path, struct posix_stat *restrict st)
    9891{
    99         /* There are currently no symbolic links in HelenOS. */
    100         return posix_stat(path, st);
     92        // TODO
     93        not_implemented();
    10194}
    10295
    10396/**
    104  * Retrieve file status for regular file (or symbolic link target).
    10597 *
    106  * @param path Path to the file/link.
    107  * @param st Status structure to be filled with information.
    108  * @return Zero on success, -1 otherwise.
     98 * @param path
     99 * @param st
     100 * @return
    109101 */
    110102int posix_stat(const char *path, struct posix_stat *st)
    111103{
    112104        struct stat hst;
    113         int rc = stat(path, &hst);
    114         if (rc < 0) {
    115                 /* stat() returns negative error code instead of using errno.
    116                  */
    117                 errno = -rc;
     105        if (stat(path, &hst) == -1) {
     106                // TODO: propagate a POSIX compatible errno
    118107                return -1;
    119108        }
     
    123112
    124113/**
    125  * Change permission bits for the file if possible.
    126114 *
    127  * @param path Path to the file.
    128  * @param mode Permission bits to be set.
    129  * @return Zero on success, -1 otherwise.
     115 * @param path
     116 * @param mode
     117 * @return
    130118 */
    131119int posix_chmod(const char *path, mode_t mode)
    132120{
    133         /* HelenOS doesn't support permissions, return success. */
    134         return 0;
     121        // TODO
     122        not_implemented();
    135123}
    136124
    137125/**
    138  * Set the file mode creation mask of the process.
    139126 *
    140  * @param mask Set permission bits are cleared in the related creation
    141  *     functions. Non-permission bits are ignored.
    142  * @return Previous file mode creation mask.
     127 * @param mask
     128 * @return
    143129 */
    144130mode_t posix_umask(mode_t mask)
    145131{
    146         /* HelenOS doesn't support permissions, return empty mask. */
    147         return 0;
     132        // TODO
     133        not_implemented();
    148134}
    149135
  • uspace/lib/posix/sys/types.h

    r8cd8bf6 rf5b2522  
    5252typedef struct posix_thread_attr posix_thread_attr_t;
    5353
    54 /* Clock types */
    55 typedef long posix_clock_t;
    56 typedef int posix_clockid_t;
    57 
    5854#ifndef LIBPOSIX_INTERNAL
    5955        #define ino_t posix_ino_t
     
    6864       
    6965        #define pthread_attr_t posix_thread_attr_t
    70        
    71         #define clock_t posix_clock_t
    72         #define clockid_t posix_clockid_t
    7366#endif
    7467
  • uspace/lib/posix/time.c

    r8cd8bf6 rf5b2522  
    3636#define LIBPOSIX_INTERNAL
    3737
    38 /* Must be first. */
    39 #include "stdbool.h"
    40 
    4138#include "internal/common.h"
    4239#include "time.h"
    43 
    44 #include "ctype.h"
    45 #include "errno.h"
    46 #include "signal.h"
    47 
    48 #include "libc/malloc.h"
    49 #include "libc/task.h"
    50 #include "libc/stats.h"
    51 #include "libc/sys/time.h"
    52 
    53 // TODO: documentation
    54 // TODO: test everything in this file
    55 
    56 /* Helper functions ***********************************************************/
    57 
    58 #define HOURS_PER_DAY (24)
    59 #define MINS_PER_HOUR (60)
    60 #define SECS_PER_MIN (60)
    61 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY)
    62 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
    63 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY)
    64 
    65 static bool _is_leap_year(time_t year)
    66 {
    67         year += 1900;
    68 
    69         if (year % 400 == 0)
    70                 return true;
    71         if (year % 100 == 0)
    72                 return false;
    73         if (year % 4 == 0)
    74                 return true;
    75         return false;
    76 }
    77 
    78 static int _days_in_month(time_t year, time_t mon)
    79 {
    80         assert(mon >= 0 && mon <= 11);
    81         year += 1900;
    82 
    83         static int month_days[] =
    84                 { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    85 
    86         if (mon == 1) {
    87                 /* february */
    88                 return _is_leap_year(year) ? 29 : 28;
    89         } else {
    90                 return month_days[mon];
    91         }
    92 }
    93 
    94 static int _day_of_year(time_t year, time_t mon, time_t mday)
    95 {
    96         static int mdays[] =
    97             { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
    98         static int leap_mdays[] =
    99             { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
    100 
    101         return (_is_leap_year(year) ? leap_mdays[mon] : mdays[mon]) + mday - 1;
    102 }
    103 
    104 /* Integer division that rounds to negative infinity.
    105  */
    106 static time_t _floor_div(time_t op1, time_t op2)
    107 {
    108         if (op1 >= 0 || op1 % op2 == 0) {
    109                 return op1 / op2;
    110         } else {
    111                 return op1 / op2 - 1;
    112         }
    113 }
    114 
    115 /* Modulo that rounds to negative infinity.
    116  */
    117 static time_t _floor_mod(time_t op1, time_t op2)
    118 {
    119         int div = _floor_div(op1, op2);
    120 
    121         /* (a / b) * b + a % b == a */
    122         /* thus, a % b == a - (a / b) * b */
    123 
    124         int result = op1 - div * op2;
    125        
    126         /* Some paranoid checking to ensure I didn't make a mistake here. */
    127         assert(result >= 0);
    128         assert(result < op2);
    129         assert(div * op2 + result == op1);
    130        
    131         return result;
    132 }
    133 
    134 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday)
    135 {
    136         return (year - 70) * 365 + _floor_div(year - 69, 4) -
    137             _floor_div(year - 1, 100) + _floor_div(year + 299, 400) +
    138             _day_of_year(year, mon, mday);
    139 }
    140 
    141 /* Assumes normalized broken-down time. */
    142 static time_t _secs_since_epoch(const struct posix_tm *tm)
    143 {
    144         return _days_since_epoch(tm->tm_year, tm->tm_mon, tm->tm_mday) *
    145             SECS_PER_DAY + tm->tm_hour * SECS_PER_HOUR +
    146             tm->tm_min * SECS_PER_MIN + tm->tm_sec;
    147 }
    148 
    149 static int _day_of_week(time_t year, time_t mon, time_t mday)
    150 {
    151         /* 1970-01-01 is Thursday */
    152         return (_days_since_epoch(year, mon, mday) + 4) % 7;
    153 }
    154 
    155 struct _long_tm {
    156         time_t tm_sec;
    157         time_t tm_min;
    158         time_t tm_hour;
    159         time_t tm_mday;
    160         time_t tm_mon;
    161         time_t tm_year;
    162         int tm_wday;
    163         int tm_yday;
    164         int tm_isdst;
    165 };
    166 
    167 static void _posix_to_long_tm(struct _long_tm *ltm, struct posix_tm *ptm)
    168 {
    169         assert(ltm != NULL && ptm != NULL);
    170         ltm->tm_sec = ptm->tm_sec;
    171         ltm->tm_min = ptm->tm_min;
    172         ltm->tm_hour = ptm->tm_hour;
    173         ltm->tm_mday = ptm->tm_mday;
    174         ltm->tm_mon = ptm->tm_mon;
    175         ltm->tm_year = ptm->tm_year;
    176         ltm->tm_wday = ptm->tm_wday;
    177         ltm->tm_yday = ptm->tm_yday;
    178         ltm->tm_isdst = ptm->tm_isdst;
    179 }
    180 
    181 static void _long_to_posix_tm(struct posix_tm *ptm, struct _long_tm *ltm)
    182 {
    183         assert(ltm != NULL && ptm != NULL);
    184         // FIXME: the cast should be unnecessary, libarch/common.h brain-damage
    185         assert((ltm->tm_year >= (int) INT_MIN) && (ltm->tm_year <= (int) INT_MAX));
    186 
    187         ptm->tm_sec = ltm->tm_sec;
    188         ptm->tm_min = ltm->tm_min;
    189         ptm->tm_hour = ltm->tm_hour;
    190         ptm->tm_mday = ltm->tm_mday;
    191         ptm->tm_mon = ltm->tm_mon;
    192         ptm->tm_year = ltm->tm_year;
    193         ptm->tm_wday = ltm->tm_wday;
    194         ptm->tm_yday = ltm->tm_yday;
    195         ptm->tm_isdst = ltm->tm_isdst;
    196 }
    197 
    198 static void _normalize_time(struct _long_tm *tm)
    199 {
    200         // TODO: DST correction
    201 
    202         /* Adjust time. */
    203         tm->tm_min += _floor_div(tm->tm_sec, SECS_PER_MIN);
    204         tm->tm_sec = _floor_mod(tm->tm_sec, SECS_PER_MIN);
    205         tm->tm_hour += _floor_div(tm->tm_min, MINS_PER_HOUR);
    206         tm->tm_min = _floor_mod(tm->tm_min, MINS_PER_HOUR);
    207         tm->tm_mday += _floor_div(tm->tm_hour, HOURS_PER_DAY);
    208         tm->tm_hour = _floor_mod(tm->tm_hour, HOURS_PER_DAY);
    209 
    210         /* Adjust month. */
    211         tm->tm_year += _floor_div(tm->tm_mon, 12);
    212         tm->tm_mon = _floor_mod(tm->tm_mon, 12);
    213 
    214         /* Now the difficult part - days of month. */
    215         /* Slow, but simple. */
    216         // FIXME: do this faster
    217 
    218         while (tm->tm_mday < 1) {
    219                 tm->tm_mon--;
    220                 if (tm->tm_mon == -1) {
    221                         tm->tm_mon = 11;
    222                         tm->tm_year--;
    223                 }
    224                
    225                 tm->tm_mday += _days_in_month(tm->tm_year, tm->tm_mon);
    226         }
    227 
    228         while (tm->tm_mday > _days_in_month(tm->tm_year, tm->tm_mon)) {
    229                 tm->tm_mday -= _days_in_month(tm->tm_year, tm->tm_mon);
    230                
    231                 tm->tm_mon++;
    232                 if (tm->tm_mon == 12) {
    233                         tm->tm_mon = 0;
    234                         tm->tm_year++;
    235                 }
    236         }
    237 
    238         /* Calculate the remaining two fields. */
    239         tm->tm_yday = _day_of_year(tm->tm_year, tm->tm_mon, tm->tm_mday);
    240         tm->tm_wday = _day_of_week(tm->tm_year, tm->tm_mon, tm->tm_mday);
    241 }
    242 
    243 /* Which day the week-based year starts on relative to the first calendar day.
    244  * E.g. if the year starts on December 31st, the return value is -1.
    245  */
    246 static int _wbyear_offset(int year)
    247 {
    248         int start_wday = _day_of_week(year, 0, 1);
    249         return _floor_mod(4 - start_wday, 7) - 3;
    250 }
    251 
    252 /* Returns week-based year of the specified time.
    253  * Assumes normalized broken-down time.
    254  */
    255 static int _wbyear(const struct posix_tm *tm)
    256 {
    257         int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
    258         if (day < 0) {
    259                 /* Last week of previous year. */
    260                 return tm->tm_year - 1;
    261         }
    262         if (day > 364 + _is_leap_year(tm->tm_year)){
    263                 /* First week of next year. */
    264                 return tm->tm_year + 1;
    265         }
    266         /* All the other days are in the calendar year. */
    267         return tm->tm_year;
    268 }
    269 
    270 /** Week number of the year, assuming weeks start on sunday.
    271  *  The first Sunday of January is the first day of week 1;
    272  *  days in the new year before this are in week 0.
    273  *
    274  * @param tm Normalized broken-down time.
    275  * @return The week number (0 - 53).
    276  */
    277 static int _sun_week_number(const struct posix_tm *tm)
    278 {
    279         int first_day = (7 - _day_of_week(tm->tm_year, 0, 1)) % 7;
    280         return (tm->tm_yday - first_day + 7) / 7;
    281 }
    282 
    283 /** Week number of the year, assuming weeks start on monday.
    284  *  If the week containing January 1st has four or more days in the new year,
    285  *  then it is considered week 1. Otherwise, it is the last week of the previous
    286  *  year, and the next week is week 1. Both January 4th and the first Thursday
    287  *  of January are always in week 1.
    288  *
    289  * @param tm Normalized broken-down time.
    290  * @return The week number (1 - 53).
    291  */
    292 static int _iso_week_number(const struct posix_tm *tm)
    293 {
    294         int day = tm->tm_yday - _wbyear_offset(tm->tm_year);
    295         if (day < 0) {
    296                 /* Last week of previous year. */
    297                 return 53;
    298         }
    299         if (day > 364 + _is_leap_year(tm->tm_year)){
    300                 /* First week of next year. */
    301                 return 1;
    302         }
    303         /* All the other days give correct answer. */
    304         return (day / 7 + 1);
    305 }
    306 
    307 /** Week number of the year, assuming weeks start on monday.
    308  *  The first Monday of January is the first day of week 1;
    309  *  days in the new year before this are in week 0.
    310  *
    311  * @param tm Normalized broken-down time.
    312  * @return The week number (0 - 53).
    313  */
    314 static int _mon_week_number(const struct posix_tm *tm)
    315 {
    316         int first_day = (1 - _day_of_week(tm->tm_year, 0, 1)) % 7;
    317         return (tm->tm_yday - first_day + 7) / 7;
    318 }
    319 
    320 /******************************************************************************/
    321 
    322 int posix_daylight;
    323 long posix_timezone;
    324 char *posix_tzname[2];
    325 
    326 void posix_tzset(void)
    327 {
    328         // TODO: read environment
    329         posix_tzname[0] = (char *) "GMT";
    330         posix_tzname[1] = (char *) "GMT";
    331         posix_daylight = 0;
    332         posix_timezone = 0;
    333 }
    334 
    335 double posix_difftime(time_t time1, time_t time0)
    336 {
    337         return (double) (time1 - time0);
    338 }
    339 
    340 /** This function first normalizes the provided broken-down time
    341  *  (moves all values to their proper bounds) and then tries to
    342  *  calculate the appropriate time_t representation.
    343  *
    344  * @param timeptr Broken-down time.
    345  * @return time_t representation of the time, undefined value on overflow
    346  */
    347 time_t posix_mktime(struct posix_tm *tm)
    348 {
    349         // TODO: take DST flag into account
    350         // TODO: detect overflow
    351 
    352         struct _long_tm ltm;
    353         _posix_to_long_tm(&ltm, tm);
    354         _normalize_time(&ltm);
    355         _long_to_posix_tm(tm, &ltm);
    356 
    357         return _secs_since_epoch(tm);
    358 }
    359 
    360 struct posix_tm *posix_gmtime(const time_t *timer)
    361 {
    362         static struct posix_tm result;
    363         return posix_gmtime_r(timer, &result);
    364 }
    365 
    366 struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
    367     struct posix_tm *restrict result)
    368 {
    369         assert(timer != NULL);
    370         assert(result != NULL);
    371 
    372         /* Set epoch and seconds to _long_tm struct and normalize to get
    373          * correct values.
    374          */
    375         struct _long_tm ltm = {
    376                 .tm_sec = *timer,
    377                 .tm_min = 0,
    378                 .tm_hour = 0, /* 00:00:xx */
    379                 .tm_mday = 1,
    380                 .tm_mon = 0, /* January 1st */
    381                 .tm_year = 70, /* 1970 */
    382         };
    383         _normalize_time(&ltm);
    384 
    385         if (ltm.tm_year < (int) INT_MIN || ltm.tm_year > (int) INT_MAX) {
    386                 errno = EOVERFLOW;
    387                 return NULL;
    388         }
    389 
    390         _long_to_posix_tm(result, &ltm);
    391         return result;
    392 }
    39340
    39441/**
     
    39744 * @return
    39845 */
    399 struct posix_tm *posix_localtime(const time_t *timer)
     46struct posix_tm *posix_localtime(const time_t *timep)
    40047{
    401         static struct posix_tm result;
    402         return posix_localtime_r(timer, &result);
    403 }
    404 
    405 struct posix_tm *posix_localtime_r(const time_t *restrict timer,
    406     struct posix_tm *restrict result)
    407 {
    408         // TODO: deal with timezone
    409         // currently assumes system and all times are in GMT
    410         return posix_gmtime_r(timer, result);
     48        // TODO
     49        static struct posix_tm result = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     50        return &result;
    41151}
    41252
     
    41656 * @return
    41757 */
    418 char *posix_asctime(const struct posix_tm *timeptr)
     58char *posix_asctime(const struct posix_tm *tm)
    41959{
    420         static char buf[ASCTIME_BUF_LEN];
    421         return posix_asctime_r(timeptr, buf);
    422 }
    423 
    424 char *posix_asctime_r(const struct posix_tm *restrict timeptr,
    425     char *restrict buf)
    426 {
    427         assert(timeptr != NULL);
    428         assert(buf != NULL);
    429 
    430         static const char *wday[] = {
    431                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    432         };
    433         static const char *mon[] = {
    434                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    435                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    436         };
    437 
    438         snprintf(buf, ASCTIME_BUF_LEN, "%s %s %2d %02d:%02d:%02d %d\n",
    439             wday[timeptr->tm_wday],
    440             mon[timeptr->tm_mon],
    441             timeptr->tm_mday, timeptr->tm_hour,
    442             timeptr->tm_min, timeptr->tm_sec,
    443             1900 + timeptr->tm_year);
    444 
    445         return buf;
     60        // TODO
     61        static char result[] = "Sun Jan 01 00:00:00 1900\n";
     62        return result;
    44663}
    44764
     
    45168 * @return
    45269 */
    453 char *posix_ctime(const time_t *timer)
     70char *posix_ctime(const time_t *timep)
    45471{
    455         struct posix_tm *loctime = posix_localtime(timer);
    456         if (loctime == NULL) {
    457                 return NULL;
    458         }
    459         return posix_asctime(loctime);
    460 }
    461 
    462 char *posix_ctime_r(const time_t *timer, char *buf)
    463 {
    464         struct posix_tm loctime;
    465         if (posix_localtime_r(timer, &loctime) == NULL) {
    466                 return NULL;
    467         }
    468         return posix_asctime_r(&loctime, buf);
     72        return posix_asctime(posix_localtime(timep));
    46973}
    47074
     
    47781 * @return
    47882 */
    479 size_t posix_strftime(char *s, size_t maxsize,
    480     const char *format, const struct posix_tm *tm)
    481 {
    482         // TODO: use locale
    483         static const char *wday_abbr[] = {
    484                 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    485         };
    486         static const char *wday[] = {
    487                 "Sunday", "Monday", "Tuesday", "Wednesday",
    488                 "Thursday", "Friday", "Saturday"
    489         };
    490         static const char *mon_abbr[] = {
    491                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    492                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    493         };
    494         static const char *mon[] = {
    495                 "January", "February", "March", "April", "May", "June", "July",
    496                 "August", "September", "October", "November", "December"
    497         };
    498        
    499         if (maxsize < 1) {
    500                 return 0;
    501         }
    502        
    503         char *ptr = s;
    504         size_t consumed;
    505         size_t remaining = maxsize;
    506        
    507         #define append(...) { \
    508                 /* FIXME: this requires POSIX-correct snprintf */ \
    509                 /*        otherwise it won't work with non-ascii chars */ \
    510                 consumed = snprintf(ptr, remaining, __VA_ARGS__); \
    511                 if (consumed >= remaining) { \
    512                         return 0; \
    513                 } \
    514                 ptr += consumed; \
    515                 remaining -= consumed; \
    516         }
    517        
    518         #define recurse(fmt) { \
    519                 consumed = posix_strftime(ptr, remaining, fmt, tm); \
    520                 if (consumed == 0) { \
    521                         return 0; \
    522                 } \
    523                 ptr += consumed; \
    524                 remaining -= consumed; \
    525         }
    526        
    527         #define TO_12H(hour) (((hour) > 12) ? ((hour) - 12) : \
    528             (((hour) == 0) ? 12 : (hour)))
    529        
    530         while (*format != '\0') {
    531                 if (*format != '%') {
    532                         append("%c", *format);
    533                         format++;
    534                         continue;
    535                 }
    536                
    537                 format++;
    538                 if (*format == '0' || *format == '+') {
    539                         // TODO: padding
    540                         format++;
    541                 }
    542                 while (isdigit(*format)) {
    543                         // TODO: padding
    544                         format++;
    545                 }
    546                 if (*format == 'O' || *format == 'E') {
    547                         // TODO: locale's alternative format
    548                         format++;
    549                 }
    550                
    551                 switch (*format) {
    552                 case 'a':
    553                         append("%s", wday_abbr[tm->tm_wday]); break;
    554                 case 'A':
    555                         append("%s", wday[tm->tm_wday]); break;
    556                 case 'b':
    557                         append("%s", mon_abbr[tm->tm_mon]); break;
    558                 case 'B':
    559                         append("%s", mon[tm->tm_mon]); break;
    560                 case 'c':
    561                         // TODO: locale-specific datetime format
    562                         recurse("%Y-%m-%d %H:%M:%S"); break;
    563                 case 'C':
    564                         append("%02d", (1900 + tm->tm_year) / 100); break;
    565                 case 'd':
    566                         append("%02d", tm->tm_mday); break;
    567                 case 'D':
    568                         recurse("%m/%d/%y"); break;
    569                 case 'e':
    570                         append("%2d", tm->tm_mday); break;
    571                 case 'F':
    572                         recurse("%+4Y-%m-%d"); break;
    573                 case 'g':
    574                         append("%02d", _wbyear(tm) % 100); break;
    575                 case 'G':
    576                         append("%d", _wbyear(tm)); break;
    577                 case 'h':
    578                         recurse("%b"); break;
    579                 case 'H':
    580                         append("%02d", tm->tm_hour); break;
    581                 case 'I':
    582                         append("%02d", TO_12H(tm->tm_hour)); break;
    583                 case 'j':
    584                         append("%03d", tm->tm_yday); break;
    585                 case 'k':
    586                         append("%2d", tm->tm_hour); break;
    587                 case 'l':
    588                         append("%2d", TO_12H(tm->tm_hour)); break;
    589                 case 'm':
    590                         append("%02d", tm->tm_mon); break;
    591                 case 'M':
    592                         append("%02d", tm->tm_min); break;
    593                 case 'n':
    594                         append("\n"); break;
    595                 case 'p':
    596                         append("%s", tm->tm_hour < 12 ? "AM" : "PM"); break;
    597                 case 'P':
    598                         append("%s", tm->tm_hour < 12 ? "am" : "PM"); break;
    599                 case 'r':
    600                         recurse("%I:%M:%S %p"); break;
    601                 case 'R':
    602                         recurse("%H:%M"); break;
    603                 case 's':
    604                         append("%ld", _secs_since_epoch(tm)); break;
    605                 case 'S':
    606                         append("%02d", tm->tm_sec); break;
    607                 case 't':
    608                         append("\t"); break;
    609                 case 'T':
    610                         recurse("%H:%M:%S"); break;
    611                 case 'u':
    612                         append("%d", (tm->tm_wday == 0) ? 7 : tm->tm_wday); break;
    613                 case 'U':
    614                         append("%02d", _sun_week_number(tm)); break;
    615                 case 'V':
    616                         append("%02d", _iso_week_number(tm)); break;
    617                 case 'w':
    618                         append("%d", tm->tm_wday); break;
    619                 case 'W':
    620                         append("%02d", _mon_week_number(tm)); break;
    621                 case 'x':
    622                         // TODO: locale-specific date format
    623                         recurse("%Y-%m-%d"); break;
    624                 case 'X':
    625                         // TODO: locale-specific time format
    626                         recurse("%H:%M:%S"); break;
    627                 case 'y':
    628                         append("%02d", tm->tm_year % 100); break;
    629                 case 'Y':
    630                         append("%d", 1900 + tm->tm_year); break;
    631                 case 'z':
    632                         // TODO: timezone
    633                         break;
    634                 case 'Z':
    635                         // TODO: timezone
    636                         break;
    637                 case '%':
    638                         append("%%");
    639                         break;
    640                 default:
    641                         /* Invalid specifier, print verbatim. */
    642                         while (*format != '%') {
    643                                 format--;
    644                         }
    645                         append("%%");
    646                         break;
    647                 }
    648                 format++;
    649         }
    650        
    651         #undef append
    652         #undef recurse
    653        
    654         return maxsize - remaining;
    655 }
    656 
    657 int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res)
    658 {
    659         assert(res != NULL);
    660 
    661         switch (clock_id) {
    662                 case CLOCK_REALTIME:
    663                         res->tv_sec = 0;
    664                         res->tv_nsec = 1000; /* Microsecond resolution. */
    665                         return 0;
    666                 default:
    667                         errno = EINVAL;
    668                         return -1;
    669         }
    670 }
    671 
    672 int posix_clock_gettime(posix_clockid_t clock_id, struct posix_timespec *tp)
    673 {
    674         assert(tp != NULL);
    675 
    676         switch (clock_id) {
    677                 case CLOCK_REALTIME:
    678                         ;
    679                         struct timeval tv;
    680                         gettimeofday(&tv, NULL);
    681                         tp->tv_sec = tv.tv_sec;
    682                         tp->tv_nsec = tv.tv_usec * 1000;
    683                         return 0;
    684                 default:
    685                         errno = EINVAL;
    686                         return -1;
    687         }
    688 }
    689 
    690 int posix_clock_settime(posix_clockid_t clock_id,
    691     const struct posix_timespec *tp)
    692 {
    693         assert(tp != NULL);
    694 
    695         switch (clock_id) {
    696                 case CLOCK_REALTIME:
    697                         // TODO: setting clock
    698                         // FIXME: HelenOS doesn't actually support hardware
    699                         //        clock yet
    700                         errno = EPERM;
    701                         return -1;
    702                 default:
    703                         errno = EINVAL;
    704                         return -1;
    705         }
    706 }
    707 
    708 int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
    709     const struct posix_timespec *rqtp, struct posix_timespec *rmtp)
    710 {
    711         assert(rqtp != NULL);
    712         assert(rmtp != NULL);
    713 
    714         switch (clock_id) {
    715                 case CLOCK_REALTIME:
    716                         // TODO: interruptible sleep
    717                         if (rqtp->tv_sec != 0) {
    718                                 sleep(rqtp->tv_sec);
    719                         }
    720                         if (rqtp->tv_nsec != 0) {
    721                                 usleep(rqtp->tv_nsec / 1000);
    722                         }
    723                         return 0;
    724                 default:
    725                         errno = EINVAL;
    726                         return -1;
    727         }
    728 }
    729 
    730 #if 0
    731 
    732 struct __posix_timer {
    733         posix_clockid_t clockid;
    734         struct posix_sigevent evp;
    735 };
    736 
    737 int posix_timer_create(posix_clockid_t clockid,
    738     struct posix_sigevent *restrict evp,
    739     posix_timer_t *restrict timerid)
     83size_t posix_strftime(char *s, size_t maxsize, const char *format, const struct posix_tm *tm)
    74084{
    74185        // TODO
     
    74387}
    74488
    745 int posix_timer_delete(posix_timer_t timerid)
     89/**
     90 *
     91 * @return
     92 */
     93posix_clock_t posix_clock(void)
    74694{
    74795        // TODO
     
    74997}
    75098
    751 int posix_timer_getoverrun(posix_timer_t timerid)
    752 {
    753         // TODO
    754         not_implemented();
    755 }
    756 
    757 int posix_timer_gettime(posix_timer_t timerid,
    758     struct posix_itimerspec *value)
    759 {
    760         // TODO
    761         not_implemented();
    762 }
    763 
    764 int posix_timer_settime(posix_timer_t timerid, int flags,
    765     const struct posix_itimerspec *restrict value,
    766     struct posix_itimerspec *restrict ovalue)
    767 {
    768         // TODO
    769         not_implemented();
    770 }
    771 
    772 #endif
    773 
    774 /**
    775  * Get CPU time used since the process invocation.
    776  *
    777  * @return Consumed CPU cycles by this process or -1 if not available.
    778  */
    779 posix_clock_t posix_clock(void)
    780 {
    781         posix_clock_t total_cycles = -1;
    782         stats_task_t *task_stats = stats_get_task(task_get_id());
    783         if (task_stats) {
    784                 total_cycles = (posix_clock_t) (task_stats->kcycles + task_stats->ucycles);
    785         }
    786         free(task_stats);
    787         task_stats = 0;
    788 
    789         return total_cycles;
    790 }
    791 
    79299/** @}
    793100 */
  • uspace/lib/posix/time.h

    r8cd8bf6 rf5b2522  
    3838
    3939#include "libc/time.h"
    40 #include "sys/types.h"
    4140
    4241#ifndef NULL
    4342        #define NULL  ((void *) 0)
    4443#endif
    45 
    46 #ifndef CLOCKS_PER_SEC
    47         #define CLOCKS_PER_SEC (1000000L)
    48 #endif
    49 
    50 #ifndef __locale_t_defined
    51         #define __locale_t_defined
    52         typedef struct __posix_locale *posix_locale_t;
    53         #ifndef LIBPOSIX_INTERNAL
    54                 #define locale_t posix_locale_t
    55         #endif
    56 #endif
    57 
    58 #ifndef POSIX_SIGNAL_H_
    59         struct posix_sigevent;
    60         #ifndef LIBPOSIX_INTERNAL
    61                 #define sigevent posix_sigevent
    62         #endif
    63 #endif
    64 
    65 #undef ASCTIME_BUF_LEN
    66 #define ASCTIME_BUF_LEN 26
    67 
    68 #undef CLOCK_REALTIME
    69 #define CLOCK_REALTIME ((posix_clockid_t) 0)
    7044
    7145struct posix_tm {
     
    8155};
    8256
    83 struct posix_timespec {
    84         time_t tv_sec; /* Seconds. */
    85         long tv_nsec; /* Nanoseconds. */
    86 };
    87 
    88 struct posix_itimerspec {
    89         struct posix_timespec it_interval; /* Timer period. */
    90         struct posix_timespec it_value; /* Timer expiration. */
    91 };
    92 
    93 typedef struct __posix_timer *posix_timer_t;
    94 
    95 /* Timezones */
    96 
    97 extern int posix_daylight;
    98 extern long posix_timezone;
    99 extern char *posix_tzname[2];
    100 
    101 extern void posix_tzset(void);
    102 
    103 /* time_t */
    104 
    105 extern double posix_difftime(time_t time1, time_t time0);
     57typedef long posix_clock_t;
    10658
    10759/* Broken-down Time */
    108 extern time_t posix_mktime(struct posix_tm *timeptr);
    109 extern struct posix_tm *posix_gmtime(const time_t *timer);
    110 extern struct posix_tm *posix_gmtime_r(const time_t *restrict timer,
    111     struct posix_tm *restrict result);
    112 extern struct posix_tm *posix_localtime(const time_t *timer);
    113 extern struct posix_tm *posix_localtime_r(const time_t *restrict timer,
    114     struct posix_tm *restrict result);
     60extern struct posix_tm *posix_localtime(const time_t *timep);
    11561
    11662/* Formatting Calendar Time */
    117 extern char *posix_asctime(const struct posix_tm *timeptr);
    118 extern char *posix_asctime_r(const struct posix_tm *restrict timeptr,
    119     char *restrict buf);
    120 extern char *posix_ctime(const time_t *timer);
    121 extern char *posix_ctime_r(const time_t *timer, char *buf);
    122 
    123 extern size_t posix_strftime(char *restrict s, size_t maxsize,
    124     const char *restrict format, const struct posix_tm *restrict tm);
    125 
    126 extern size_t posix_strftime_l(char *restrict s, size_t maxsize,
    127     const char *restrict format, const struct posix_tm *restrict tm,
    128     posix_locale_t loc);
    129 
    130 /* Clocks. */
    131 
    132 extern int posix_clock_getres(posix_clockid_t clock_id,
    133     struct posix_timespec *res);
    134 extern int posix_clock_gettime(posix_clockid_t clock_id,
    135     struct posix_timespec *tp);
    136 extern int posix_clock_settime(posix_clockid_t clock_id,
    137     const struct posix_timespec *tp);
    138 extern int posix_clock_nanosleep(posix_clockid_t clock_id, int flags,
    139     const struct posix_timespec *rqtp, struct posix_timespec *rmtp);
    140 
    141 /* Timers. */
    142 
    143 #if 0
    144 
    145 extern int posix_timer_create(posix_clockid_t clockid,
    146     struct posix_sigevent *restrict evp,
    147     posix_timer_t *restrict timerid);
    148 extern int posix_timer_delete(posix_timer_t timerid);
    149 extern int posix_timer_getoverrun(posix_timer_t timerid);
    150 extern int posix_timer_gettime(posix_timer_t timerid,
    151     struct posix_itimerspec *value);
    152 extern int posix_timer_settime(posix_timer_t timerid, int flags,
    153     const struct posix_itimerspec *restrict value,
    154     struct posix_itimerspec *restrict ovalue);
    155 
    156 #endif
     63extern char *posix_asctime(const struct posix_tm *tm);
     64extern char *posix_ctime(const time_t *timep);
     65extern size_t posix_strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct posix_tm *restrict tm);
    15766
    15867/* CPU Time */
    15968extern posix_clock_t posix_clock(void);
    16069
    161 
    16270#ifndef LIBPOSIX_INTERNAL
    16371        #define tm posix_tm
    16472
    165         #define timespec posix_timespec
    166         #define itimerspec posix_itimerspec
    167         #define timer_t posix_timer_t
     73        #define clock_t posix_clock_t
    16874
    169         #define difftime posix_difftime
    170         #define mktime posix_mktime
    171         #define gmtime posix_gmtime
    172         #define gmtime_r posix_gmtime_r
    17375        #define localtime posix_localtime
    174         #define localtime_r posix_localtime_r
    175 
    176         #define daylight posix_daylight
    177         #define timezone posix_timezone
    178         #define tzname posix_tzname
    179         #define tzset posix_tzset
    18076
    18177        #define asctime posix_asctime
    182         #define asctime_r posix_asctime_r
    18378        #define ctime posix_ctime
    184         #define ctime_r posix_ctime_r
    18579        #define strftime posix_strftime
    18680
    187         #define clock_getres posix_clock_getres
    188         #define clock_gettime posix_clock_gettime
    189         #define clock_settime posix_clock_settime
    190         #define clock_nanosleep posix_clock_nanosleep
    191        
    192         #define timer_create posix_timer_create
    193         #define timer_delete posix_timer_delete
    194         #define timer_getoverrun posix_timer_getoverrun
    195         #define timer_gettime posix_timer_gettime
    196         #define timer_settime posix_timer_settime
    197        
    19881        #define clock posix_clock
    19982#endif
  • uspace/lib/posix/unistd.c

    r8cd8bf6 rf5b2522  
    3838#include "internal/common.h"
    3939#include "unistd.h"
    40 
    41 #include "errno.h"
    42 #include "string.h"
    43 #include "fcntl.h"
    44 
    45 #include "libc/task.h"
    46 #include "libc/stats.h"
    47 #include "libc/malloc.h"
     40#include <task.h>
    4841
    4942/* Array of environment variable strings (NAME=VALUE). */
    50 char **posix_environ = NULL;
     43char **environ = NULL;
    5144
    5245/**
    53  * Get current user name.
     46 * Dummy function. Always returns false, because there is no easy way to find
     47 * out under HelenOS.
    5448 *
    55  * @return User name (static) string or NULL if not found.
    56  */
    57 char *posix_getlogin(void)
    58 {
    59         /* There is currently no support for user accounts in HelenOS. */
    60         return (char *) "user";
    61 }
    62 
    63 /**
    64  * Get current user name.
    65  *
    66  * @param name Pointer to a user supplied buffer.
    67  * @param namesize Length of the buffer.
    68  * @return Zero on success, error code otherwise.
    69  */
    70 int posix_getlogin_r(char *name, size_t namesize)
    71 {
    72         /* There is currently no support for user accounts in HelenOS. */
    73         if (namesize >= 5) {
    74                 posix_strcpy(name, (char *) "user");
    75                 return 0;
    76         } else {
    77                 errno = ERANGE;
    78                 return -1;
    79         }
    80 }
    81 
    82 /**
    83  * Test whether open file descriptor is associated with a terminal.
    84  *
    85  * @param fd Open file descriptor to test.
    86  * @return Boolean result of the test.
     49 * @param fd
     50 * @return Always false.
    8751 */
    8852int posix_isatty(int fd)
    8953{
    90         /* Always returns false, because there is no easy way to find
    91      * out under HelenOS. */
    9254        return false;
    9355}
    9456
    9557/**
    96  * Determine the page size of the current run of the process.
    97  *
    98  * @return Page size of the process.
     58 *
     59 * @return
    9960 */
    10061int posix_getpagesize(void)
     
    10465
    10566/**
    106  * Get the process ID of the calling process.
    107  *
    108  * @return Process ID.
     67 *
     68 * @return
    10969 */
    11070posix_pid_t posix_getpid(void)
     
    11474
    11575/**
    116  * Get the real user ID of the calling process.
    11776 *
    118  * @return User ID.
     77 * @return
    11978 */
    12079posix_uid_t posix_getuid(void)
    12180{
    122         /* There is currently no support for user accounts in HelenOS. */
    123         return 0;
     81        // TODO
     82        not_implemented();
    12483}
    12584
    12685/**
    127  * Get the real group ID of the calling process.
    12886 *
    129  * @return Group ID.
     87 * @return
    13088 */
    13189posix_gid_t posix_getgid(void)
    13290{
    133         /* There is currently no support for user accounts in HelenOS. */
    134         return 0;
     91        // TODO
     92        not_implemented();
    13593}
    13694
    13795/**
    138  * Determine accessibility of a file.
    139  *
    140  * @param path File to check accessibility for.
    141  * @param amode Either check for existence or intended access mode.
    142  * @return Zero on success, -1 otherwise.
     96 *
     97 * @param path
     98 * @param amode
     99 * @return
    143100 */
    144101int posix_access(const char *path, int amode)
    145102{
    146         if (amode == F_OK) {
    147                 /* Check file existence by attempt to open it. */
    148                 int fd = open(path, O_RDONLY);
    149                 if (fd < 0) {
    150                         /* FIXME: open() returns error code as negative retval. */
    151                         errno = -fd;
    152                         fd = -1;
    153                 } else {
    154                         close(fd);
    155                 }
    156                 return fd;
    157         } else if (amode & (X_OK | W_OK | R_OK)) {
    158                 /* HelenOS doesn't support permissions, return success. */
    159                 return 0;
    160         } else {
    161                 /* Invalid amode argument. */
    162                 errno = EINVAL;
    163                 return -1;
    164         }
     103        // TODO
     104        not_implemented();
    165105}
    166106
    167107/**
    168  * Get configurable system variables.
    169108 *
    170  * @param name Variable name.
    171  * @return Variable value.
     109 * @param name
     110 * @return
    172111 */
    173112long posix_sysconf(int name)
    174113{
    175         long clk_tck = 0;
    176         size_t cpu_count = 0;
    177         stats_cpu_t *cpu_stats = stats_get_cpus(&cpu_count);
    178         if (cpu_stats && cpu_count > 0) {
    179                 clk_tck = ((long) cpu_stats[0].frequency_mhz) * 1000000L;
    180         }
    181         free(cpu_stats);
    182         cpu_stats = 0;
    183 
    184         long phys_pages = 0;
    185         long avphys_pages = 0;
    186         stats_physmem_t *mem_stats = stats_get_physmem();
    187         if (mem_stats) {
    188                 phys_pages = (long) (mem_stats->total / getpagesize());
    189                 avphys_pages = (long) (mem_stats->free / getpagesize());
    190         }
    191         free(mem_stats);
    192         mem_stats = 0;
    193 
    194         switch (name) {
    195         case _SC_PHYS_PAGES:
    196                 return phys_pages;
    197         case _SC_AVPHYS_PAGES:
    198                 return avphys_pages;
    199         case _SC_PAGESIZE:
    200                 return getpagesize();
    201         case _SC_CLK_TCK:
    202                 return clk_tck;
    203         default:
    204                 errno = EINVAL;
    205                 return -1;
    206         }
     114        // TODO
     115        not_implemented();
    207116}
    208117
  • uspace/lib/posix/unistd.h

    r8cd8bf6 rf5b2522  
    4848extern int getopt(int, char * const [], const char *);
    4949
    50 /* Environment */
     50/* Environmental Variables */
    5151extern char **posix_environ;
    52 
    53 extern char *posix_getlogin(void);
    54 extern int posix_getlogin_r(char *name, size_t namesize);
    5552
    5653/* Identifying Terminals */
     
    129126#ifndef LIBPOSIX_INTERNAL
    130127        #define environ posix_environ
    131         #define getlogin posix_getlogin
    132         #define getlogin_r posix_getlogin_r
    133128
    134129        #define isatty posix_isatty
Note: See TracChangeset for help on using the changeset viewer.