Changes in / [8cd8bf6:f5b2522] in mainline
- Location:
- uspace/lib/posix
- Files:
-
- 8 deleted
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/Makefile
r8cd8bf6 rf5b2522 40 40 SOURCES = \ 41 41 ctype.c \ 42 errno.c \43 42 fcntl.c \ 44 43 fnmatch.c \ 45 locale.c \46 44 math.c \ 47 45 pwd.c \ 48 signal.c \49 46 stdio.c \ 50 stdio/scanf.c \51 47 stdlib.c \ 52 48 stdlib/strtol.c \ -
uspace/lib/posix/ctype.c
r8cd8bf6 rf5b2522 108 108 } 109 109 110 /**111 * Checks whether character is ASCII. (obsolete)112 *113 * @param c114 * @return115 */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 c125 * @return126 */127 extern int posix_toascii(int c)128 {129 return c & 0x7F;130 }131 132 110 /** @} 133 111 */ -
uspace/lib/posix/ctype.h
r8cd8bf6 rf5b2522 47 47 extern int posix_ispunct(int c); 48 48 49 /* Obsolete Functions and Macros */50 extern int posix_isascii(int c);51 extern int posix_toascii(int c);52 #undef _tolower53 #define _tolower(c) ((c) - 'A' + 'a')54 #undef _toupper55 #define _toupper(c) ((c) - 'a' + 'A')56 57 58 49 #ifndef LIBPOSIX_INTERNAL 59 50 #define isxdigit posix_isxdigit … … 63 54 #define isprint posix_isprint 64 55 #define ispunct posix_ispunct 65 66 #define isascii posix_isascii67 #define toascii posix_toascii68 56 #endif 69 57 -
uspace/lib/posix/fcntl.c
r8cd8bf6 rf5b2522 38 38 #include "fcntl.h" 39 39 40 #include "libc/unistd.h"41 #include "libc/vfs/vfs.h"42 #include "errno.h"43 44 40 /** 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 51 46 */ 52 47 int posix_fcntl(int fd, int cmd, ...) 53 48 { 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(); 120 51 } 121 52 -
uspace/lib/posix/fcntl.h
r8cd8bf6 rf5b2522 36 36 #define POSIX_FCNTL_H_ 37 37 38 #include "sys/types.h"39 38 #include "libc/fcntl.h" 40 41 /* Mask for file access modes. */42 #undef O_ACCMODE43 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)44 39 45 40 /* fcntl commands */ 46 41 #undef F_DUPFD 47 #undef F_DUPFD_CLOEXEC48 42 #undef F_GETFD 49 43 #undef F_SETFD … … 52 46 #undef F_GETOWN 53 47 #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. */ 68 55 69 56 /* File descriptor flags used with F_GETFD and F_SETFD. */ 70 57 #undef FD_CLOEXEC 71 #define FD_CLOEXEC 1/* Close on exec. */58 #define FD_CLOEXEC 1 /* Close on exec. */ 72 59 73 60 extern int posix_fcntl(int fd, int cmd, ...); -
uspace/lib/posix/fnmatch.c
r8cd8bf6 rf5b2522 33 33 */ 34 34 35 // TODO: clean this up a bit36 37 #include "stdbool.h"38 #include "ctype.h"39 #include "string.h"40 #include "stdlib.h"41 #include "assert.h"42 43 35 #define LIBPOSIX_INTERNAL 44 36 45 37 #include "internal/common.h" 46 38 #include "fnmatch.h" 47 48 #define INVALID_PATTERN -149 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 -156 57 /** Get collating element matching a string.58 *59 * @param str60 * @return61 */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 c73 * @return74 */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 elm83 * @param str84 * @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 moved100 * 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 for104 * the entire string, the string is cut with no error indication.105 * @return106 */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 6149 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_PERIOD270 * 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 _matched326 }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 or391 * 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 }486 39 487 40 /** … … 495 48 int posix_fnmatch(const char *pattern, const char *string, int flags) 496 49 { 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(); 513 52 } 514 515 // FIXME: put the testcases somewhere else516 517 #if 0518 519 #include <stdio.h>520 521 void __posix_fnmatch_test()522 {523 int fail = 0;524 525 #undef assert526 #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 #endif603 53 604 54 /** @} -
uspace/lib/posix/fnmatch.h
r8cd8bf6 rf5b2522 48 48 #define FNM_NOESCAPE 4 49 49 50 /* GNU Extensions */51 #undef FNM_FILE_NAME52 #undef FNM_LEADING_DIR53 #undef FNM_CASEFOLD54 #define FNM_FILE_NAME FNM_PATHNAME55 #define FNM_LEADING_DIR 856 #define FNM_CASEFOLD 1657 58 50 extern int posix_fnmatch(const char *pattern, const char *string, int flags); 59 51 -
uspace/lib/posix/pwd.c
r8cd8bf6 rf5b2522 47 47 .pw_gid = 1, 48 48 .pw_dir = (char *) "/", 49 .pw_shell = (char *) " /app/bdsh"49 .pw_shell = (char *) "bdsh" 50 50 }; 51 51 -
uspace/lib/posix/signal.h
r8cd8bf6 rf5b2522 39 39 #include "sys/types.h" 40 40 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 */ 44 49 45 50 #undef SIG_DFL 46 #define SIG_DFL ((void (*)(int)) __posix_default_signal_handler)51 #define SIG_DFL ((void (*)(int)) 0) 47 52 #undef SIG_ERR 48 #define SIG_ERR ((void (*)(int)) NULL)53 #define SIG_ERR ((void (*)(int)) 0) 49 54 #undef SIG_HOLD 50 #define SIG_HOLD ((void (*)(int)) __posix_hold_signal_handler)55 #define SIG_HOLD ((void (*)(int)) 0) 51 56 #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) 53 62 54 63 typedef int posix_sig_atomic_t; 55 typedef uint32_t posix_sigset_t;64 typedef int posix_sigset_t; 56 65 typedef struct posix_mcontext { 57 66 // FIXME: should not be empty to avoid compiler warnings (-pedantic) … … 78 87 int si_errno; 79 88 80 p osix_pid_t si_pid;81 posix_uid_t si_uid;89 pid_t si_pid; 90 uid_t si_uid; 82 91 void *si_addr; 83 92 int si_status; … … 111 120 /* Values of posix_sigevent::sigev_notify */ 112 121 #undef SIGEV_NONE 122 #define SIGEV_NONE 0 113 123 #undef SIGEV_SIGNAL 124 #define SIGEV_SIGNAL 0 114 125 #undef SIGEV_THREAD 115 #define SIGEV_NONE 0116 #define SIGEV_SIGNAL 0117 126 #define SIGEV_THREAD 0 118 127 119 128 #undef SIGRT_MIN 129 #define SIGRT_MIN 0 120 130 #undef SIGRT_MAX 121 #define SIGRT_MIN 0122 131 #define SIGRT_MAX 0 123 132 124 133 #undef SIG_BLOCK 134 #define SIG_BLOCK 0 125 135 #undef SIG_UNBLOCK 136 #define SIG_UNBLOCK 0 126 137 #undef SIG_SETMASK 127 #define SIG_BLOCK 0 128 #define SIG_UNBLOCK 1 129 #define SIG_SETMASK 2 138 #define SIG_SETMASK 0 130 139 131 140 #undef SA_NOCLDSTOP 141 #define SA_NOCLDSTOP 0 132 142 #undef SA_ONSTACK 143 #define SA_ONSTACK 0 133 144 #undef SA_RESETHAND 145 #define SA_RESETHAND 0 134 146 #undef SA_RESTART 147 #define SA_RESTART 0 135 148 #undef SA_SIGINFO 149 #define SA_SIGINFO 0 136 150 #undef SA_NOCLDWAIT 151 #define SA_NOCLDWAIT 0 137 152 #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 145 154 146 155 #undef SS_ONSTACK 156 #define SS_ONSTACK 0 147 157 #undef SS_DISABLE 148 #define SS_ONSTACK 0149 158 #define SS_DISABLE 0 150 159 151 160 #undef MINSIGSTKSZ 161 #define MINSIGSTKSZ 0 152 162 #undef SIGSTKSZ 153 #define MINSIGSTKSZ 0154 163 #define SIGSTKSZ 0 155 164 156 165 /* full POSIX set */ 157 166 enum { 158 /* Termination Signals */159 167 SIGABRT, 168 SIGALRM, 169 SIGBUS, 170 SIGCHLD, 171 SIGCONT, 172 SIGFPE, 173 SIGHUP, 174 SIGILL, 175 SIGINT, 176 SIGKILL, 177 SIGPIPE, 160 178 SIGQUIT, 161 SIGINT, 179 SIGSEGV, 180 SIGSTOP, 162 181 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 */208 182 SIGTSTP, 209 183 SIGTTIN, 210 184 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. */ 271 198 extern 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);279 199 extern int posix_sigprocmask(int how, const posix_sigset_t *restrict set, 280 200 posix_sigset_t *restrict oset); … … 284 204 #define sigset_t posix_sigset_t 285 205 #define sigval posix_sigval 286 #ifndef sigevent 287 #define sigevent posix_sigevent 288 #endif 206 #define sigevent posix_sigevent 289 207 #define sigaction posix_sigaction 290 208 #define mcontext_t posix_mcontext_t … … 292 210 #define stack_t posix_stack_t 293 211 #define siginfo_t posix_siginfo_t 294 295 #define signal posix_signal296 #define raise posix_raise297 #define kill posix_kill298 #define killpg posix_killpg299 300 #define psiginfo posix_psiginfo301 #define psignal posix_psignal302 303 212 #define sigemptyset posix_sigemptyset 304 #define sigfillset posix_sigfillset305 #define sigaddset posix_sigaddset306 #define sigdelset posix_sigdelset307 #define sigismember posix_sigismember308 309 #define pthread_sigmask posix_thread_sigmask310 213 #define sigprocmask posix_sigprocmask 311 214 #endif -
uspace/lib/posix/stdbool.h
r8cd8bf6 rf5b2522 40 40 41 41 #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. 43 43 #endif 44 44 #define LIBC_BOOL_H_ -
uspace/lib/posix/stdint.h
r8cd8bf6 rf5b2522 35 35 #ifndef POSIX_STDINT_H_ 36 36 #define POSIX_STDINT_H_ 37 38 #include "libc/stdint.h"39 37 40 38 #undef INT8_MAX -
uspace/lib/posix/stdio.c
r8cd8bf6 rf5b2522 36 36 #define LIBPOSIX_INTERNAL 37 37 38 /* Has to be first. */ 39 #include "stdbool.h"38 #include <assert.h> 39 #include <errno.h> 40 40 41 41 #include "internal/common.h" 42 42 #include "stdio.h" 43 44 #include "assert.h"45 #include "errno.h"46 43 #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 55 46 * need to be implemented in libc anyway 56 47 */ 57 48 #include "../c/generic/private/stdio.h" 58 49 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 96 55 */ 97 56 int posix_ungetc(int c, FILE *stream) 98 57 { 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 231 68 */ 232 69 FILE *posix_freopen( … … 278 115 /** 279 116 * 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 308 118 */ 309 119 void posix_perror(const char *s) 310 120 { 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 369 131 */ 370 132 int posix_fseeko(FILE *stream, posix_off_t offset, int whence) 371 133 { 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 391 142 */ 392 143 posix_off_t posix_ftello(FILE *stream) 393 144 { 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 */ 156 int 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 */ 169 int 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 */ 182 int posix_sscanf(const char *s, const char *format, ...) 183 { 184 // TODO 185 not_implemented(); 186 } 187 188 /** 189 * 190 * @param path 191 * @return 649 192 */ 650 193 int posix_remove(const char *path) 651 194 { 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(); 655 197 } 656 198 -
uspace/lib/posix/stdio.h
r8cd8bf6 rf5b2522 40 40 #include "sys/types.h" 41 41 #include "libc/stdarg.h" 42 #include "limits.h"43 42 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 */ 51 44 #undef putc 52 45 #define putc fputc … … 54 47 #define getc fgetc 55 48 extern 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);61 49 62 50 /* Opening Streams */ … … 66 54 FILE *restrict stream); 67 55 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 74 56 /* Error Messages */ 75 57 extern void posix_perror(const char *s); 76 58 77 59 /* 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);83 60 extern int posix_fseeko(FILE *stream, posix_off_t offset, int whence); 84 extern long posix_ftell(FILE *stream);85 61 extern posix_off_t posix_ftello(FILE *stream); 86 62 87 63 /* 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); 64 extern int posix_sprintf(char *restrict s, const char *restrict format, ...); 93 65 extern 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); 66 extern int posix_sscanf(const char *restrict s, const char *restrict format, ...); 116 67 117 68 /* Deleting Files */ … … 125 76 126 77 #ifndef LIBPOSIX_INTERNAL 127 #define clearerr posix_clearerr128 #define ctermid posix_ctermid129 130 78 #define ungetc posix_ungetc 131 132 #define getdelim posix_getdelim133 #define getline posix_getline134 79 135 80 #define freopen posix_freopen 136 81 137 #define fmemopen posix_fmemopen138 #define open_memstream posix_open_memstream139 140 82 #define perror posix_perror 141 83 142 #define fpos_t posix_fpos_t143 #define fsetpos posix_fsetpos144 #define fgetpos posix_fgetpos145 #define fseek posix_fseek146 84 #define fseeko posix_fseeko 147 #define ftell posix_ftell148 85 #define ftello posix_ftello 149 86 150 #define dprintf posix_dprintf151 #define vdprintf posix_vdprintf152 87 #define sprintf posix_sprintf 153 88 #define vsprintf posix_vsprintf 154 155 #define fscanf posix_fscanf156 #define vfscanf posix_vfscanf157 #define vscanf posix_vscanf158 #define scanf posix_scanf159 89 #define sscanf posix_sscanf 160 #define vsscanf posix_vsscanf161 162 #define flockfile posix_flockfile163 #define ftrylockfile posix_ftrylockfile164 #define funlockfile posix_funlockfile165 166 #define getc_unlocked posix_getc_unlocked167 #define getchar_unlocked posix_getchar_unlocked168 #define putc_unlocked posix_putc_unlocked169 #define putchar_unlocked posix_putchar_unlocked170 90 171 91 #define remove posix_remove -
uspace/lib/posix/stdlib.c
r8cd8bf6 rf5b2522 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include "internal/common.h"39 38 #include "stdlib.h" 40 41 #include "errno.h"42 43 39 #include "libc/sort.h" 44 40 #include "libc/str.h" 45 41 #include "libc/vfs/vfs.h" 42 #include "internal/common.h" 43 #include <errno.h> // FIXME: use POSIX errno 46 44 47 45 /** … … 340 338 } 341 339 342 /**343 * Should read system load statistics. Not supported. Always returns -1.344 *345 * @param loadavg346 * @param nelem347 * @return348 */349 int bsd_getloadavg(double loadavg[], int nelem)350 {351 return -1;352 }353 354 340 /** @} 355 341 */ -
uspace/lib/posix/stdlib.h
r8cd8bf6 rf5b2522 120 120 /* Legacy Declarations */ 121 121 extern char *posix_mktemp(char *tmpl); 122 extern int bsd_getloadavg(double loadavg[], int nelem);123 122 124 123 #ifndef LIBPOSIX_INTERNAL … … 164 163 165 164 #define mktemp posix_mktemp 166 #define getloadavg bsd_getloadavg167 165 #endif 168 166 -
uspace/lib/posix/stdlib/strtol.c
r8cd8bf6 rf5b2522 37 37 #include "../internal/common.h" 38 38 #include "../stdlib.h" 39 39 #include <errno.h> // FIXME: use POSIX errno 40 40 #include "../limits.h" 41 41 #include "../ctype.h" 42 #include "../errno.h"43 42 44 43 // TODO: documentation -
uspace/lib/posix/stdlib/strtold.c
r8cd8bf6 rf5b2522 35 35 #define LIBPOSIX_INTERNAL 36 36 37 /* Must be first. */38 #include "../stdbool.h"39 40 37 #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" 41 44 #include "../stdlib.h" 42 43 #include "../assert.h"44 #include "../ctype.h"45 #include "../stdint.h"46 45 #include "../strings.h" 47 #include "../errno.h"48 46 49 47 #ifndef HUGE_VALL -
uspace/lib/posix/string.c
r8cd8bf6 rf5b2522 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include "internal/common.h"39 38 #include "string.h" 40 39 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 */ 51 static char *strzero(const char *s) 52 { 53 while (*s != '\0') { 54 s++; 55 } 56 57 return (char *) s; 58 } 48 59 49 60 /** … … 172 183 assert(src != NULL); 173 184 174 posix_strcpy( posix_strchr(dest, '\0'), src);185 posix_strcpy(strzero(dest), src); 175 186 return dest; 176 187 } … … 188 199 assert(src != NULL); 189 200 190 char *zeroptr = posix_strncpy( posix_strchr(dest, '\0'), src, n);201 char *zeroptr = posix_strncpy(strzero(dest), src, n); 191 202 /* strncpy doesn't append the nul terminator, so we do it here */ 192 203 zeroptr[n] = '\0'; … … 229 240 char *posix_strdup(const char *s) 230 241 { 231 return posix_strndup(s, SIZE_MAX); 242 // FIXME: SIZE_MAX doesn't work 243 return posix_strndup(s, STR_NO_LIMIT); 232 244 } 233 245 … … 348 360 assert(s != NULL); 349 361 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; 352 377 } 353 378 … … 362 387 assert(s != NULL); 363 388 364 const char *ptr = posix_strchr(s, '\0');389 const char *ptr = strzero(s); 365 390 366 391 /* the same as in strchr, except it loops in reverse direction */ … … 374 399 375 400 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;387 401 } 388 402 … … 510 524 char *posix_strerror(int errnum) 511 525 { 512 /* Uses function from libc, we just have to negate errno513 * (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) 514 528 */ 515 // FIXME: not all POSIX error codes are in libc 516 return (char *) str_error(-posix_abs(errnum)); 529 return (char *) str_error(-errnum); 517 530 } 518 531 … … 549 562 assert(s != NULL); 550 563 551 return (size_t) ( posix_strchr(s, '\0') - s);564 return (size_t) (strzero(s) - s); 552 565 } 553 566 … … 572 585 } 573 586 574 /**575 *576 * @param signum577 * @return578 */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 619 587 /** @} 620 588 */ -
uspace/lib/posix/string.h
r8cd8bf6 rf5b2522 85 85 extern char *posix_strchr(const char *s, int c); 86 86 extern char *posix_strrchr(const char *s, int c); 87 extern char *gnu_strchrnul(const char *s, int c);88 87 extern char *posix_strpbrk(const char *s1, const char *s2); 89 88 extern size_t posix_strcspn(const char *s1, const char *s2); … … 102 101 extern size_t posix_strlen(const char *s); 103 102 extern size_t posix_strnlen(const char *s, size_t n); 104 105 /* Signal messages */106 extern char *posix_strsignal(int signum);107 103 108 104 /* Legacy declarations */ … … 131 127 #define strchr posix_strchr 132 128 #define strrchr posix_strrchr 133 #define strchrnul gnu_strchrnul134 129 #define strpbrk posix_strpbrk 135 130 #define strcspn posix_strcspn … … 146 141 #define strnlen posix_strnlen 147 142 148 #define strsignal posix_strsignal149 150 143 #define ffs posix_ffs 151 144 #define strcasecmp posix_strcasecmp -
uspace/lib/posix/strings.c
r8cd8bf6 rf5b2522 38 38 #include "internal/common.h" 39 39 #include "strings.h" 40 41 40 #include "string.h" 42 41 #include "ctype.h" -
uspace/lib/posix/sys/stat.c
r8cd8bf6 rf5b2522 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include "stat.h" 38 39 #include "../internal/common.h" 39 #include "stat.h" 40 41 #include "../errno.h" 42 #include "../libc/mem.h" 40 #include <mem.h> 43 41 44 42 /** 45 * Convert HelenOS stat struct into POSIX stat struct (if possible) .43 * Convert HelenOS stat struct into POSIX stat struct (if possible) 46 44 * 47 * @param dest POSIX stat struct.48 * @param src HelenOS stat struct.45 * @param dest 46 * @param src 49 47 */ 50 48 static void stat_to_posix(struct posix_stat *dest, struct stat *src) … … 68 66 69 67 /** 70 * Retrieve file status for file associated with file descriptor.71 68 * 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 75 72 */ 76 73 int posix_fstat(int fd, struct posix_stat *st) 77 74 { 78 75 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 84 78 return -1; 85 79 } … … 89 83 90 84 /** 91 * Retrieve file status for symbolic link.92 85 * 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 96 89 */ 97 int posix_lstat(const char * path, struct posix_stat *st)90 int posix_lstat(const char *restrict path, struct posix_stat *restrict st) 98 91 { 99 / * There are currently no symbolic links in HelenOS. */100 return posix_stat(path, st);92 // TODO 93 not_implemented(); 101 94 } 102 95 103 96 /** 104 * Retrieve file status for regular file (or symbolic link target).105 97 * 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 109 101 */ 110 102 int posix_stat(const char *path, struct posix_stat *st) 111 103 { 112 104 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 118 107 return -1; 119 108 } … … 123 112 124 113 /** 125 * Change permission bits for the file if possible.126 114 * 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 130 118 */ 131 119 int posix_chmod(const char *path, mode_t mode) 132 120 { 133 / * HelenOS doesn't support permissions, return success. */134 return 0;121 // TODO 122 not_implemented(); 135 123 } 136 124 137 125 /** 138 * Set the file mode creation mask of the process.139 126 * 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 143 129 */ 144 130 mode_t posix_umask(mode_t mask) 145 131 { 146 / * HelenOS doesn't support permissions, return empty mask. */147 return 0;132 // TODO 133 not_implemented(); 148 134 } 149 135 -
uspace/lib/posix/sys/types.h
r8cd8bf6 rf5b2522 52 52 typedef struct posix_thread_attr posix_thread_attr_t; 53 53 54 /* Clock types */55 typedef long posix_clock_t;56 typedef int posix_clockid_t;57 58 54 #ifndef LIBPOSIX_INTERNAL 59 55 #define ino_t posix_ino_t … … 68 64 69 65 #define pthread_attr_t posix_thread_attr_t 70 71 #define clock_t posix_clock_t72 #define clockid_t posix_clockid_t73 66 #endif 74 67 -
uspace/lib/posix/time.c
r8cd8bf6 rf5b2522 36 36 #define LIBPOSIX_INTERNAL 37 37 38 /* Must be first. */39 #include "stdbool.h"40 41 38 #include "internal/common.h" 42 39 #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: documentation54 // TODO: test everything in this file55 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-damage185 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 correction201 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 faster217 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 previous286 * year, and the next week is week 1. Both January 4th and the first Thursday287 * 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 environment329 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 time341 * (moves all values to their proper bounds) and then tries to342 * calculate the appropriate time_t representation.343 *344 * @param timeptr Broken-down time.345 * @return time_t representation of the time, undefined value on overflow346 */347 time_t posix_mktime(struct posix_tm *tm)348 {349 // TODO: take DST flag into account350 // TODO: detect overflow351 352 struct _long_tm ltm;353 _posix_to_long_tm(<m, tm);354 _normalize_time(<m);355 _long_to_posix_tm(tm, <m);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 get373 * 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(<m);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, <m);391 return result;392 }393 40 394 41 /** … … 397 44 * @return 398 45 */ 399 struct posix_tm *posix_localtime(const time_t *time r)46 struct posix_tm *posix_localtime(const time_t *timep) 400 47 { 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; 411 51 } 412 52 … … 416 56 * @return 417 57 */ 418 char *posix_asctime(const struct posix_tm *t imeptr)58 char *posix_asctime(const struct posix_tm *tm) 419 59 { 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; 446 63 } 447 64 … … 451 68 * @return 452 69 */ 453 char *posix_ctime(const time_t *time r)70 char *posix_ctime(const time_t *timep) 454 71 { 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)); 469 73 } 470 74 … … 477 81 * @return 478 82 */ 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) 83 size_t posix_strftime(char *s, size_t maxsize, const char *format, const struct posix_tm *tm) 740 84 { 741 85 // TODO … … 743 87 } 744 88 745 int posix_timer_delete(posix_timer_t timerid) 89 /** 90 * 91 * @return 92 */ 93 posix_clock_t posix_clock(void) 746 94 { 747 95 // TODO … … 749 97 } 750 98 751 int posix_timer_getoverrun(posix_timer_t timerid)752 {753 // TODO754 not_implemented();755 }756 757 int posix_timer_gettime(posix_timer_t timerid,758 struct posix_itimerspec *value)759 {760 // TODO761 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 // TODO769 not_implemented();770 }771 772 #endif773 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 792 99 /** @} 793 100 */ -
uspace/lib/posix/time.h
r8cd8bf6 rf5b2522 38 38 39 39 #include "libc/time.h" 40 #include "sys/types.h"41 40 42 41 #ifndef NULL 43 42 #define NULL ((void *) 0) 44 43 #endif 45 46 #ifndef CLOCKS_PER_SEC47 #define CLOCKS_PER_SEC (1000000L)48 #endif49 50 #ifndef __locale_t_defined51 #define __locale_t_defined52 typedef struct __posix_locale *posix_locale_t;53 #ifndef LIBPOSIX_INTERNAL54 #define locale_t posix_locale_t55 #endif56 #endif57 58 #ifndef POSIX_SIGNAL_H_59 struct posix_sigevent;60 #ifndef LIBPOSIX_INTERNAL61 #define sigevent posix_sigevent62 #endif63 #endif64 65 #undef ASCTIME_BUF_LEN66 #define ASCTIME_BUF_LEN 2667 68 #undef CLOCK_REALTIME69 #define CLOCK_REALTIME ((posix_clockid_t) 0)70 44 71 45 struct posix_tm { … … 81 55 }; 82 56 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); 57 typedef long posix_clock_t; 106 58 107 59 /* 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); 60 extern struct posix_tm *posix_localtime(const time_t *timep); 115 61 116 62 /* 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 63 extern char *posix_asctime(const struct posix_tm *tm); 64 extern char *posix_ctime(const time_t *timep); 65 extern size_t posix_strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct posix_tm *restrict tm); 157 66 158 67 /* CPU Time */ 159 68 extern posix_clock_t posix_clock(void); 160 69 161 162 70 #ifndef LIBPOSIX_INTERNAL 163 71 #define tm posix_tm 164 72 165 #define timespec posix_timespec 166 #define itimerspec posix_itimerspec 167 #define timer_t posix_timer_t 73 #define clock_t posix_clock_t 168 74 169 #define difftime posix_difftime170 #define mktime posix_mktime171 #define gmtime posix_gmtime172 #define gmtime_r posix_gmtime_r173 75 #define localtime posix_localtime 174 #define localtime_r posix_localtime_r175 176 #define daylight posix_daylight177 #define timezone posix_timezone178 #define tzname posix_tzname179 #define tzset posix_tzset180 76 181 77 #define asctime posix_asctime 182 #define asctime_r posix_asctime_r183 78 #define ctime posix_ctime 184 #define ctime_r posix_ctime_r185 79 #define strftime posix_strftime 186 80 187 #define clock_getres posix_clock_getres188 #define clock_gettime posix_clock_gettime189 #define clock_settime posix_clock_settime190 #define clock_nanosleep posix_clock_nanosleep191 192 #define timer_create posix_timer_create193 #define timer_delete posix_timer_delete194 #define timer_getoverrun posix_timer_getoverrun195 #define timer_gettime posix_timer_gettime196 #define timer_settime posix_timer_settime197 198 81 #define clock posix_clock 199 82 #endif -
uspace/lib/posix/unistd.c
r8cd8bf6 rf5b2522 38 38 #include "internal/common.h" 39 39 #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> 48 41 49 42 /* Array of environment variable strings (NAME=VALUE). */ 50 char ** posix_environ = NULL;43 char **environ = NULL; 51 44 52 45 /** 53 * Get current user name. 46 * Dummy function. Always returns false, because there is no easy way to find 47 * out under HelenOS. 54 48 * 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. 87 51 */ 88 52 int posix_isatty(int fd) 89 53 { 90 /* Always returns false, because there is no easy way to find91 * out under HelenOS. */92 54 return false; 93 55 } 94 56 95 57 /** 96 * Determine the page size of the current run of the process. 97 * 98 * @return Page size of the process. 58 * 59 * @return 99 60 */ 100 61 int posix_getpagesize(void) … … 104 65 105 66 /** 106 * Get the process ID of the calling process. 107 * 108 * @return Process ID. 67 * 68 * @return 109 69 */ 110 70 posix_pid_t posix_getpid(void) … … 114 74 115 75 /** 116 * Get the real user ID of the calling process.117 76 * 118 * @return User ID.77 * @return 119 78 */ 120 79 posix_uid_t posix_getuid(void) 121 80 { 122 / * There is currently no support for user accounts in HelenOS. */123 return 0;81 // TODO 82 not_implemented(); 124 83 } 125 84 126 85 /** 127 * Get the real group ID of the calling process.128 86 * 129 * @return Group ID.87 * @return 130 88 */ 131 89 posix_gid_t posix_getgid(void) 132 90 { 133 / * There is currently no support for user accounts in HelenOS. */134 return 0;91 // TODO 92 not_implemented(); 135 93 } 136 94 137 95 /** 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 143 100 */ 144 101 int posix_access(const char *path, int amode) 145 102 { 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(); 165 105 } 166 106 167 107 /** 168 * Get configurable system variables.169 108 * 170 * @param name Variable name.171 * @return Variable value.109 * @param name 110 * @return 172 111 */ 173 112 long posix_sysconf(int name) 174 113 { 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(); 207 116 } 208 117 -
uspace/lib/posix/unistd.h
r8cd8bf6 rf5b2522 48 48 extern int getopt(int, char * const [], const char *); 49 49 50 /* Environment */50 /* Environmental Variables */ 51 51 extern char **posix_environ; 52 53 extern char *posix_getlogin(void);54 extern int posix_getlogin_r(char *name, size_t namesize);55 52 56 53 /* Identifying Terminals */ … … 129 126 #ifndef LIBPOSIX_INTERNAL 130 127 #define environ posix_environ 131 #define getlogin posix_getlogin132 #define getlogin_r posix_getlogin_r133 128 134 129 #define isatty posix_isatty
Note:
See TracChangeset
for help on using the changeset viewer.