Changeset 8cd8bf6 in mainline
- Timestamp:
- 2011-07-08T17:25:53Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 11809eab
- Parents:
- f5b2522 (diff), ddc63fd (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- uspace/lib/posix
- Files:
-
- 8 added
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/Makefile
rf5b2522 r8cd8bf6 40 40 SOURCES = \ 41 41 ctype.c \ 42 errno.c \ 42 43 fcntl.c \ 43 44 fnmatch.c \ 45 locale.c \ 44 46 math.c \ 45 47 pwd.c \ 48 signal.c \ 46 49 stdio.c \ 50 stdio/scanf.c \ 47 51 stdlib.c \ 48 52 stdlib/strtol.c \ -
uspace/lib/posix/ctype.c
rf5b2522 r8cd8bf6 108 108 } 109 109 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 110 132 /** @} 111 133 */ -
uspace/lib/posix/ctype.h
rf5b2522 r8cd8bf6 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 _tolower 53 #define _tolower(c) ((c) - 'A' + 'a') 54 #undef _toupper 55 #define _toupper(c) ((c) - 'a' + 'A') 56 57 49 58 #ifndef LIBPOSIX_INTERNAL 50 59 #define isxdigit posix_isxdigit … … 54 63 #define isprint posix_isprint 55 64 #define ispunct posix_ispunct 65 66 #define isascii posix_isascii 67 #define toascii posix_toascii 56 68 #endif 57 69 -
uspace/lib/posix/fcntl.c
rf5b2522 r8cd8bf6 38 38 #include "fcntl.h" 39 39 40 #include "libc/unistd.h" 41 #include "libc/vfs/vfs.h" 42 #include "errno.h" 43 40 44 /** 41 * 42 * @param fd 43 * @param cmd 44 * @param ... 45 * @return 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. 46 51 */ 47 52 int posix_fcntl(int fd, int cmd, ...) 48 53 { 49 // TODO 50 not_implemented(); 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 } 51 120 } 52 121 -
uspace/lib/posix/fcntl.h
rf5b2522 r8cd8bf6 36 36 #define POSIX_FCNTL_H_ 37 37 38 #include "sys/types.h" 38 39 #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) 39 44 40 45 /* fcntl commands */ 41 46 #undef F_DUPFD 47 #undef F_DUPFD_CLOEXEC 42 48 #undef F_GETFD 43 49 #undef F_SETFD … … 46 52 #undef F_GETOWN 47 53 #undef F_SETOWN 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. */ 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. */ 55 68 56 69 /* File descriptor flags used with F_GETFD and F_SETFD. */ 57 70 #undef FD_CLOEXEC 58 #define FD_CLOEXEC 1/* Close on exec. */71 #define FD_CLOEXEC 1 /* Close on exec. */ 59 72 60 73 extern int posix_fcntl(int fd, int cmd, ...); -
uspace/lib/posix/fnmatch.c
rf5b2522 r8cd8bf6 33 33 */ 34 34 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 35 43 #define LIBPOSIX_INTERNAL 36 44 37 45 #include "internal/common.h" 38 46 #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 } 39 486 40 487 /** … … 48 495 int posix_fnmatch(const char *pattern, const char *string, int flags) 49 496 { 50 // TODO 51 not_implemented(); 52 } 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; 513 } 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 53 603 54 604 /** @} -
uspace/lib/posix/fnmatch.h
rf5b2522 r8cd8bf6 48 48 #define FNM_NOESCAPE 4 49 49 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 50 58 extern int posix_fnmatch(const char *pattern, const char *string, int flags); 51 59 -
uspace/lib/posix/pwd.c
rf5b2522 r8cd8bf6 47 47 .pw_gid = 1, 48 48 .pw_dir = (char *) "/", 49 .pw_shell = (char *) " bdsh"49 .pw_shell = (char *) "/app/bdsh" 50 50 }; 51 51 -
uspace/lib/posix/signal.h
rf5b2522 r8cd8bf6 39 39 #include "sys/types.h" 40 40 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 */ 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); 49 44 50 45 #undef SIG_DFL 51 #define SIG_DFL ((void (*)(int)) 0)46 #define SIG_DFL ((void (*)(int)) __posix_default_signal_handler) 52 47 #undef SIG_ERR 53 #define SIG_ERR ((void (*)(int)) 0)48 #define SIG_ERR ((void (*)(int)) NULL) 54 49 #undef SIG_HOLD 55 #define SIG_HOLD ((void (*)(int)) 0)50 #define SIG_HOLD ((void (*)(int)) __posix_hold_signal_handler) 56 51 #undef SIG_IGN 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) 52 #define SIG_IGN ((void (*)(int)) __posix_ignore_signal_handler) 62 53 63 54 typedef int posix_sig_atomic_t; 64 typedef int posix_sigset_t;55 typedef uint32_t posix_sigset_t; 65 56 typedef struct posix_mcontext { 66 57 // FIXME: should not be empty to avoid compiler warnings (-pedantic) … … 87 78 int si_errno; 88 79 89 p id_t si_pid;90 uid_t si_uid;80 posix_pid_t si_pid; 81 posix_uid_t si_uid; 91 82 void *si_addr; 92 83 int si_status; … … 120 111 /* Values of posix_sigevent::sigev_notify */ 121 112 #undef SIGEV_NONE 113 #undef SIGEV_SIGNAL 114 #undef SIGEV_THREAD 122 115 #define SIGEV_NONE 0 123 #undef SIGEV_SIGNAL124 116 #define SIGEV_SIGNAL 0 125 #undef SIGEV_THREAD126 117 #define SIGEV_THREAD 0 127 118 128 119 #undef SIGRT_MIN 120 #undef SIGRT_MAX 129 121 #define SIGRT_MIN 0 130 #undef SIGRT_MAX131 122 #define SIGRT_MAX 0 132 123 133 124 #undef SIG_BLOCK 125 #undef SIG_UNBLOCK 126 #undef SIG_SETMASK 134 127 #define SIG_BLOCK 0 135 #undef SIG_UNBLOCK 136 #define SIG_UNBLOCK 0 137 #undef SIG_SETMASK 138 #define SIG_SETMASK 0 128 #define SIG_UNBLOCK 1 129 #define SIG_SETMASK 2 139 130 140 131 #undef SA_NOCLDSTOP 141 #define SA_NOCLDSTOP 0142 132 #undef SA_ONSTACK 143 #define SA_ONSTACK 0144 133 #undef SA_RESETHAND 145 #define SA_RESETHAND 0146 134 #undef SA_RESTART 147 #define SA_RESTART 0148 135 #undef SA_SIGINFO 149 #define SA_SIGINFO 0150 136 #undef SA_NOCLDWAIT 151 #define SA_NOCLDWAIT 0152 137 #undef SA_NODEFER 153 #define SA_NODEFER 0 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) 154 145 155 146 #undef SS_ONSTACK 147 #undef SS_DISABLE 156 148 #define SS_ONSTACK 0 157 #undef SS_DISABLE158 149 #define SS_DISABLE 0 159 150 160 151 #undef MINSIGSTKSZ 152 #undef SIGSTKSZ 161 153 #define MINSIGSTKSZ 0 162 #undef SIGSTKSZ163 154 #define SIGSTKSZ 0 164 155 165 156 /* full POSIX set */ 166 157 enum { 158 /* Termination Signals */ 167 159 SIGABRT, 160 SIGQUIT, 161 SIGINT, 162 SIGTERM, 163 164 /* Child Signal */ 165 SIGCHLD, 166 167 /* User signals */ 168 SIGUSR1, 169 SIGUSR2, 170 171 /* Timer */ 168 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, 169 189 SIGBUS, 170 SIGCHLD, 171 SIGCONT, 172 SIGFPE, 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 */ 173 202 SIGHUP, 174 SIGILL,175 SIGINT,176 SIGKILL,177 203 SIGPIPE, 178 SIG QUIT,179 SIG SEGV,180 SIGSTOP, 181 SIGTERM,204 SIGPOLL, /* obsolete */ 205 SIGURG, 206 207 /* Terminal Signals - not supported */ 182 208 SIGTSTP, 183 209 SIGTTIN, 184 210 SIGTTOU, 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. */ 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 198 271 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); 199 279 extern int posix_sigprocmask(int how, const posix_sigset_t *restrict set, 200 280 posix_sigset_t *restrict oset); … … 204 284 #define sigset_t posix_sigset_t 205 285 #define sigval posix_sigval 206 #define sigevent posix_sigevent 286 #ifndef sigevent 287 #define sigevent posix_sigevent 288 #endif 207 289 #define sigaction posix_sigaction 208 290 #define mcontext_t posix_mcontext_t … … 210 292 #define stack_t posix_stack_t 211 293 #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 212 303 #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 213 310 #define sigprocmask posix_sigprocmask 214 311 #endif -
uspace/lib/posix/stdbool.h
rf5b2522 r8cd8bf6 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
rf5b2522 r8cd8bf6 35 35 #ifndef POSIX_STDINT_H_ 36 36 #define POSIX_STDINT_H_ 37 38 #include "libc/stdint.h" 37 39 38 40 #undef INT8_MAX -
uspace/lib/posix/stdio.c
rf5b2522 r8cd8bf6 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include <assert.h> 39 #include <errno.h>38 /* Has to be first. */ 39 #include "stdbool.h" 40 40 41 41 #include "internal/common.h" 42 42 #include "stdio.h" 43 44 #include "assert.h" 45 #include "errno.h" 43 46 #include "string.h" 44 45 /* not the best of solutions, but freopen will eventually 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 46 55 * need to be implemented in libc anyway 47 56 */ 48 57 #include "../c/generic/private/stdio.h" 49 58 50 /** 51 * 52 * @param c 53 * @param stream 54 * @return 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. 55 96 */ 56 97 int posix_ungetc(int c, FILE *stream) 57 98 { 58 // TODO 59 not_implemented(); 60 } 61 62 /** 63 * 64 * @param filename 65 * @param mode 66 * @param stream 67 * @return 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. 68 231 */ 69 232 FILE *posix_freopen( … … 115 278 /** 116 279 * 117 * @param s 118 */ 119 void posix_perror(const char *s) 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) 120 287 { 121 288 // TODO … … 124 291 125 292 /** 126 * 127 * @param stream 128 * @param offset 129 * @param whence 293 * 294 * @param bufp 295 * @param sizep 130 296 * @return 131 297 */ 132 int posix_fseeko(FILE *stream, posix_off_t offset, int whence)298 FILE *posix_open_memstream(char **bufp, size_t *sizep) 133 299 { 134 300 // TODO … … 137 303 138 304 /** 139 * 140 * @param stream 305 * Write error messages to standard error. 306 * 307 * @param s Error message. 308 */ 309 void posix_perror(const char *s) 310 { 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. 369 */ 370 int posix_fseeko(FILE *stream, posix_off_t offset, int whence) 371 { 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. 391 */ 392 posix_off_t posix_ftello(FILE *stream) 393 { 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. 649 */ 650 int posix_remove(const char *path) 651 { 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); 655 } 656 657 /** 658 * 659 * @param s 141 660 * @return 142 661 */ 143 posix_off_t posix_ftello(FILE *stream) 144 { 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) 662 char *posix_tmpnam(char *s) 170 663 { 171 664 // TODO: low priority, just a compile-time dependency of binutils … … 173 666 } 174 667 175 /**176 *177 * @param s178 * @param format179 * @param ...180 * @return181 */182 int posix_sscanf(const char *s, const char *format, ...)183 {184 // TODO185 not_implemented();186 }187 188 /**189 *190 * @param path191 * @return192 */193 int posix_remove(const char *path)194 {195 // TODO: low priority, just a compile-time dependency of binutils196 not_implemented();197 }198 199 /**200 *201 * @param s202 * @return203 */204 char *posix_tmpnam(char *s)205 {206 // TODO: low priority, just a compile-time dependency of binutils207 not_implemented();208 }209 210 668 /** @} 211 669 */ -
uspace/lib/posix/stdio.h
rf5b2522 r8cd8bf6 40 40 #include "sys/types.h" 41 41 #include "libc/stdarg.h" 42 #include "limits.h" 42 43 43 /* Character Input/Output */ 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 */ 44 51 #undef putc 45 52 #define putc fputc … … 47 54 #define getc fgetc 48 55 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); 49 61 50 62 /* Opening Streams */ … … 54 66 FILE *restrict stream); 55 67 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 56 74 /* Error Messages */ 57 75 extern void posix_perror(const char *s); 58 76 59 77 /* 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); 60 83 extern int posix_fseeko(FILE *stream, posix_off_t offset, int whence); 84 extern long posix_ftell(FILE *stream); 61 85 extern posix_off_t posix_ftello(FILE *stream); 62 86 63 87 /* Formatted Input/Output */ 64 extern int posix_sprintf(char *restrict s, const char *restrict format, ...); 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); 65 93 extern int posix_vsprintf(char *restrict s, const char *restrict format, va_list ap); 66 extern int posix_sscanf(const char *restrict s, const char *restrict format, ...); 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); 67 116 68 117 /* Deleting Files */ … … 76 125 77 126 #ifndef LIBPOSIX_INTERNAL 127 #define clearerr posix_clearerr 128 #define ctermid posix_ctermid 129 78 130 #define ungetc posix_ungetc 131 132 #define getdelim posix_getdelim 133 #define getline posix_getline 79 134 80 135 #define freopen posix_freopen 81 136 137 #define fmemopen posix_fmemopen 138 #define open_memstream posix_open_memstream 139 82 140 #define perror posix_perror 83 141 142 #define fpos_t posix_fpos_t 143 #define fsetpos posix_fsetpos 144 #define fgetpos posix_fgetpos 145 #define fseek posix_fseek 84 146 #define fseeko posix_fseeko 147 #define ftell posix_ftell 85 148 #define ftello posix_ftello 86 149 150 #define dprintf posix_dprintf 151 #define vdprintf posix_vdprintf 87 152 #define sprintf posix_sprintf 88 153 #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 89 159 #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 90 170 91 171 #define remove posix_remove -
uspace/lib/posix/stdlib.c
rf5b2522 r8cd8bf6 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include "internal/common.h" 38 39 #include "stdlib.h" 40 41 #include "errno.h" 42 39 43 #include "libc/sort.h" 40 44 #include "libc/str.h" 41 45 #include "libc/vfs/vfs.h" 42 #include "internal/common.h"43 #include <errno.h> // FIXME: use POSIX errno44 46 45 47 /** … … 338 340 } 339 341 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 340 354 /** @} 341 355 */ -
uspace/lib/posix/stdlib.h
rf5b2522 r8cd8bf6 120 120 /* Legacy Declarations */ 121 121 extern char *posix_mktemp(char *tmpl); 122 extern int bsd_getloadavg(double loadavg[], int nelem); 122 123 123 124 #ifndef LIBPOSIX_INTERNAL … … 163 164 164 165 #define mktemp posix_mktemp 166 #define getloadavg bsd_getloadavg 165 167 #endif 166 168 -
uspace/lib/posix/stdlib/strtol.c
rf5b2522 r8cd8bf6 37 37 #include "../internal/common.h" 38 38 #include "../stdlib.h" 39 #include <errno.h> // FIXME: use POSIX errno 39 40 40 #include "../limits.h" 41 41 #include "../ctype.h" 42 #include "../errno.h" 42 43 43 44 // TODO: documentation -
uspace/lib/posix/stdlib/strtold.c
rf5b2522 r8cd8bf6 35 35 #define LIBPOSIX_INTERNAL 36 36 37 /* Must be first. */ 38 #include "../stdbool.h" 39 37 40 #include "../internal/common.h" 38 39 #include "../libc/assert.h" 41 #include "../stdlib.h" 42 43 #include "../assert.h" 40 44 #include "../ctype.h" 41 #include <errno.h> // TODO: use POSIX errno42 #include "../libc/bool.h"43 45 #include "../stdint.h" 44 #include "../stdlib.h"45 46 #include "../strings.h" 47 #include "../errno.h" 46 48 47 49 #ifndef HUGE_VALL -
uspace/lib/posix/string.c
rf5b2522 r8cd8bf6 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include "internal/common.h" 38 39 #include "string.h" 39 40 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 } 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" 59 48 60 49 /** … … 183 172 assert(src != NULL); 184 173 185 posix_strcpy( strzero(dest), src);174 posix_strcpy(posix_strchr(dest, '\0'), src); 186 175 return dest; 187 176 } … … 199 188 assert(src != NULL); 200 189 201 char *zeroptr = posix_strncpy( strzero(dest), src, n);190 char *zeroptr = posix_strncpy(posix_strchr(dest, '\0'), src, n); 202 191 /* strncpy doesn't append the nul terminator, so we do it here */ 203 192 zeroptr[n] = '\0'; … … 240 229 char *posix_strdup(const char *s) 241 230 { 242 // FIXME: SIZE_MAX doesn't work 243 return posix_strndup(s, STR_NO_LIMIT); 231 return posix_strndup(s, SIZE_MAX); 244 232 } 245 233 … … 360 348 assert(s != NULL); 361 349 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; 350 char *res = gnu_strchrnul(s, c); 351 return (*res == c) ? res : NULL; 377 352 } 378 353 … … 387 362 assert(s != NULL); 388 363 389 const char *ptr = strzero(s);364 const char *ptr = posix_strchr(s, '\0'); 390 365 391 366 /* the same as in strchr, except it loops in reverse direction */ … … 399 374 400 375 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; 401 387 } 402 388 … … 524 510 char *posix_strerror(int errnum) 525 511 { 526 /* uses function from libc, we just have to negate errno527 * (POSIX uses positive errorcodes, HelenOS has negative) 512 /* Uses function from libc, we just have to negate errno 513 * (POSIX uses positive errorcodes, HelenOS has negative). 528 514 */ 529 return (char *) str_error(-errnum); 515 // FIXME: not all POSIX error codes are in libc 516 return (char *) str_error(-posix_abs(errnum)); 530 517 } 531 518 … … 562 549 assert(s != NULL); 563 550 564 return (size_t) ( strzero(s) - s);551 return (size_t) (posix_strchr(s, '\0') - s); 565 552 } 566 553 … … 585 572 } 586 573 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 587 619 /** @} 588 620 */ -
uspace/lib/posix/string.h
rf5b2522 r8cd8bf6 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); 87 88 extern char *posix_strpbrk(const char *s1, const char *s2); 88 89 extern size_t posix_strcspn(const char *s1, const char *s2); … … 101 102 extern size_t posix_strlen(const char *s); 102 103 extern size_t posix_strnlen(const char *s, size_t n); 104 105 /* Signal messages */ 106 extern char *posix_strsignal(int signum); 103 107 104 108 /* Legacy declarations */ … … 127 131 #define strchr posix_strchr 128 132 #define strrchr posix_strrchr 133 #define strchrnul gnu_strchrnul 129 134 #define strpbrk posix_strpbrk 130 135 #define strcspn posix_strcspn … … 141 146 #define strnlen posix_strnlen 142 147 148 #define strsignal posix_strsignal 149 143 150 #define ffs posix_ffs 144 151 #define strcasecmp posix_strcasecmp -
uspace/lib/posix/strings.c
rf5b2522 r8cd8bf6 38 38 #include "internal/common.h" 39 39 #include "strings.h" 40 40 41 #include "string.h" 41 42 #include "ctype.h" -
uspace/lib/posix/sys/stat.c
rf5b2522 r8cd8bf6 36 36 #define LIBPOSIX_INTERNAL 37 37 38 #include "../internal/common.h" 38 39 #include "stat.h" 39 #include "../internal/common.h" 40 #include <mem.h> 40 41 #include "../errno.h" 42 #include "../libc/mem.h" 41 43 42 44 /** 43 * Convert HelenOS stat struct into POSIX stat struct (if possible) 45 * Convert HelenOS stat struct into POSIX stat struct (if possible). 44 46 * 45 * @param dest 46 * @param src 47 * @param dest POSIX stat struct. 48 * @param src HelenOS stat struct. 47 49 */ 48 50 static void stat_to_posix(struct posix_stat *dest, struct stat *src) … … 66 68 67 69 /** 70 * Retrieve file status for file associated with file descriptor. 68 71 * 69 * @param fd 70 * @param st 71 * @return 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. 72 75 */ 73 76 int posix_fstat(int fd, struct posix_stat *st) 74 77 { 75 78 struct stat hst; 76 if (fstat(fd, &hst) == -1) { 77 // TODO: propagate a POSIX compatible errno 79 int rc = fstat(fd, &hst); 80 if (rc < 0) { 81 /* fstat() returns negative error code instead of using errno. 82 */ 83 errno = -rc; 78 84 return -1; 79 85 } … … 83 89 84 90 /** 91 * Retrieve file status for symbolic link. 85 92 * 86 * @param path 87 * @param st 88 * @return 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. 89 96 */ 90 int posix_lstat(const char * restrict path, struct posix_stat *restrictst)97 int posix_lstat(const char *path, struct posix_stat *st) 91 98 { 92 / / TODO93 not_implemented();99 /* There are currently no symbolic links in HelenOS. */ 100 return posix_stat(path, st); 94 101 } 95 102 96 103 /** 104 * Retrieve file status for regular file (or symbolic link target). 97 105 * 98 * @param path 99 * @param st 100 * @return 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. 101 109 */ 102 110 int posix_stat(const char *path, struct posix_stat *st) 103 111 { 104 112 struct stat hst; 105 if (stat(path, &hst) == -1) { 106 // TODO: propagate a POSIX compatible errno 113 int rc = stat(path, &hst); 114 if (rc < 0) { 115 /* stat() returns negative error code instead of using errno. 116 */ 117 errno = -rc; 107 118 return -1; 108 119 } … … 112 123 113 124 /** 125 * Change permission bits for the file if possible. 114 126 * 115 * @param path 116 * @param mode 117 * @return 127 * @param path Path to the file. 128 * @param mode Permission bits to be set. 129 * @return Zero on success, -1 otherwise. 118 130 */ 119 131 int posix_chmod(const char *path, mode_t mode) 120 132 { 121 / / TODO122 not_implemented();133 /* HelenOS doesn't support permissions, return success. */ 134 return 0; 123 135 } 124 136 125 137 /** 138 * Set the file mode creation mask of the process. 126 139 * 127 * @param mask 128 * @return 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. 129 143 */ 130 144 mode_t posix_umask(mode_t mask) 131 145 { 132 / / TODO133 not_implemented();146 /* HelenOS doesn't support permissions, return empty mask. */ 147 return 0; 134 148 } 135 149 -
uspace/lib/posix/sys/types.h
rf5b2522 r8cd8bf6 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 54 58 #ifndef LIBPOSIX_INTERNAL 55 59 #define ino_t posix_ino_t … … 64 68 65 69 #define pthread_attr_t posix_thread_attr_t 70 71 #define clock_t posix_clock_t 72 #define clockid_t posix_clockid_t 66 73 #endif 67 74 -
uspace/lib/posix/time.c
rf5b2522 r8cd8bf6 36 36 #define LIBPOSIX_INTERNAL 37 37 38 /* Must be first. */ 39 #include "stdbool.h" 40 38 41 #include "internal/common.h" 39 42 #include "time.h" 40 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(<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 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(<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 41 394 /** 42 395 * … … 44 397 * @return 45 398 */ 46 struct posix_tm *posix_localtime(const time_t *timep) 47 { 48 // TODO 49 static struct posix_tm result = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 50 return &result; 399 struct posix_tm *posix_localtime(const time_t *timer) 400 { 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); 51 411 } 52 412 … … 56 416 * @return 57 417 */ 58 char *posix_asctime(const struct posix_tm *tm) 59 { 60 // TODO 61 static char result[] = "Sun Jan 01 00:00:00 1900\n"; 62 return result; 418 char *posix_asctime(const struct posix_tm *timeptr) 419 { 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; 63 446 } 64 447 … … 68 451 * @return 69 452 */ 70 char *posix_ctime(const time_t *timep) 71 { 72 return posix_asctime(posix_localtime(timep)); 453 char *posix_ctime(const time_t *timer) 454 { 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); 73 469 } 74 470 … … 81 477 * @return 82 478 */ 83 size_t posix_strftime(char *s, size_t maxsize, const char *format, const struct posix_tm *tm) 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) 84 740 { 85 741 // TODO … … 87 743 } 88 744 89 /** 90 * 91 * @return 92 */ 93 posix_clock_t posix_clock(void) 745 int posix_timer_delete(posix_timer_t timerid) 94 746 { 95 747 // TODO … … 97 749 } 98 750 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 99 792 /** @} 100 793 */ -
uspace/lib/posix/time.h
rf5b2522 r8cd8bf6 38 38 39 39 #include "libc/time.h" 40 #include "sys/types.h" 40 41 41 42 #ifndef NULL 42 43 #define NULL ((void *) 0) 43 44 #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) 44 70 45 71 struct posix_tm { … … 55 81 }; 56 82 57 typedef long posix_clock_t; 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); 58 106 59 107 /* Broken-down Time */ 60 extern struct posix_tm *posix_localtime(const time_t *timep); 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); 61 115 62 116 /* Formatting Calendar Time */ 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); 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 66 157 67 158 /* CPU Time */ 68 159 extern posix_clock_t posix_clock(void); 69 160 161 70 162 #ifndef LIBPOSIX_INTERNAL 71 163 #define tm posix_tm 72 164 73 #define clock_t posix_clock_t 74 165 #define timespec posix_timespec 166 #define itimerspec posix_itimerspec 167 #define timer_t posix_timer_t 168 169 #define difftime posix_difftime 170 #define mktime posix_mktime 171 #define gmtime posix_gmtime 172 #define gmtime_r posix_gmtime_r 75 173 #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 76 180 77 181 #define asctime posix_asctime 182 #define asctime_r posix_asctime_r 78 183 #define ctime posix_ctime 184 #define ctime_r posix_ctime_r 79 185 #define strftime posix_strftime 80 186 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 81 198 #define clock posix_clock 82 199 #endif -
uspace/lib/posix/unistd.c
rf5b2522 r8cd8bf6 38 38 #include "internal/common.h" 39 39 #include "unistd.h" 40 #include <task.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" 41 48 42 49 /* Array of environment variable strings (NAME=VALUE). */ 43 char **environ = NULL; 44 45 /** 46 * Dummy function. Always returns false, because there is no easy way to find 47 * out under HelenOS. 48 * 49 * @param fd 50 * @return Always false. 50 char **posix_environ = NULL; 51 52 /** 53 * Get current user name. 54 * 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. 51 87 */ 52 88 int posix_isatty(int fd) 53 89 { 90 /* Always returns false, because there is no easy way to find 91 * out under HelenOS. */ 54 92 return false; 55 93 } 56 94 57 95 /** 58 * 59 * @return 96 * Determine the page size of the current run of the process. 97 * 98 * @return Page size of the process. 60 99 */ 61 100 int posix_getpagesize(void) … … 65 104 66 105 /** 67 * 68 * @return 106 * Get the process ID of the calling process. 107 * 108 * @return Process ID. 69 109 */ 70 110 posix_pid_t posix_getpid(void) … … 74 114 75 115 /** 76 * 77 * @return 116 * Get the real user ID of the calling process. 117 * 118 * @return User ID. 78 119 */ 79 120 posix_uid_t posix_getuid(void) 80 121 { 81 // TODO 82 not_implemented(); 83 } 84 85 /** 86 * 87 * @return 122 /* There is currently no support for user accounts in HelenOS. */ 123 return 0; 124 } 125 126 /** 127 * Get the real group ID of the calling process. 128 * 129 * @return Group ID. 88 130 */ 89 131 posix_gid_t posix_getgid(void) 90 132 { 91 // TODO 92 not_implemented(); 93 } 94 95 /** 96 * 97 * @param path 98 * @param amode 99 * @return 133 /* There is currently no support for user accounts in HelenOS. */ 134 return 0; 135 } 136 137 /** 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. 100 143 */ 101 144 int posix_access(const char *path, int amode) 102 145 { 103 // TODO 104 not_implemented(); 105 } 106 107 /** 108 * 109 * @param name 110 * @return 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 } 165 } 166 167 /** 168 * Get configurable system variables. 169 * 170 * @param name Variable name. 171 * @return Variable value. 111 172 */ 112 173 long posix_sysconf(int name) 113 174 { 114 // TODO 115 not_implemented(); 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 } 116 207 } 117 208 -
uspace/lib/posix/unistd.h
rf5b2522 r8cd8bf6 48 48 extern int getopt(int, char * const [], const char *); 49 49 50 /* Environment al Variables*/50 /* Environment */ 51 51 extern char **posix_environ; 52 53 extern char *posix_getlogin(void); 54 extern int posix_getlogin_r(char *name, size_t namesize); 52 55 53 56 /* Identifying Terminals */ … … 126 129 #ifndef LIBPOSIX_INTERNAL 127 130 #define environ posix_environ 131 #define getlogin posix_getlogin 132 #define getlogin_r posix_getlogin_r 128 133 129 134 #define isatty posix_isatty
Note:
See TracChangeset
for help on using the changeset viewer.