Changeset ee24574 in mainline for uspace/lib/posix
- Timestamp:
- 2011-08-18T08:00:42Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a92cf94f
- Parents:
- 0f963cb (diff), c53a705 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib/posix
- Files:
-
- 21 edited
-
ctype.c (modified) (1 diff)
-
errno.h (modified) (2 diffs)
-
fnmatch.c (modified) (20 diffs)
-
locale.c (modified) (7 diffs)
-
locale.h (modified) (1 diff)
-
signal.c (modified) (23 diffs)
-
signal.h (modified) (2 diffs)
-
stdbool.h (modified) (1 diff)
-
stdint.h (modified) (1 diff)
-
stdio.c (modified) (2 diffs)
-
stdio.h (modified) (2 diffs)
-
stdio/scanf.c (modified) (2 diffs)
-
stdlib.c (modified) (3 diffs)
-
stdlib/strtold.c (modified) (1 diff)
-
string.c (modified) (2 diffs)
-
string.h (modified) (1 diff)
-
strings.h (modified) (1 diff)
-
sys/stat.c (modified) (1 diff)
-
time.c (modified) (30 diffs)
-
time.h (modified) (4 diffs)
-
unistd.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/ctype.c
r0f963cb ree24574 37 37 38 38 #include "ctype.h" 39 40 // TODO: propose for inclusion in libc41 39 42 40 /** -
uspace/lib/posix/errno.h
r0f963cb ree24574 57 57 * redefinition for such error codes. 58 58 * 59 * FIXME: maybe all HOS error codes should be redefined59 * XXX: maybe all HOS error codes should be redefined 60 60 * 61 61 * NOTE: This redefinition is slightly POSIX incompatible, since the … … 135 135 POSIX_ENOTTY = __TOP_ERRNO + 37, 136 136 POSIX_ENXIO = __TOP_ERRNO + 38, 137 POSIX_EOPNOTSUPP = POSIX_ENOTSUP,137 POSIX_EOPNOTSUPP = __TOP_ERRNO + 39, 138 138 POSIX_EOVERFLOW = -EOVERFLOW, 139 POSIX_EOWNERDEAD = __TOP_ERRNO + 39,139 POSIX_EOWNERDEAD = __TOP_ERRNO + 40, 140 140 POSIX_EPERM = -EPERM, 141 POSIX_EPIPE = __TOP_ERRNO + 4 0,142 POSIX_EPROTO = __TOP_ERRNO + 4 1,141 POSIX_EPIPE = __TOP_ERRNO + 41, 142 POSIX_EPROTO = __TOP_ERRNO + 42, 143 143 POSIX_EPROTONOSUPPORT = -EPROTONOSUPPORT, 144 POSIX_EPROTOTYPE = __TOP_ERRNO + 4 2,144 POSIX_EPROTOTYPE = __TOP_ERRNO + 43, 145 145 POSIX_ERANGE = -ERANGE, 146 POSIX_EROFS = __TOP_ERRNO + 4 3,147 POSIX_ESPIPE = __TOP_ERRNO + 4 4,148 POSIX_ESRCH = __TOP_ERRNO + 4 5,149 POSIX_ESTALE = __TOP_ERRNO + 4 6,150 POSIX_ETIME = __TOP_ERRNO + 4 7,151 POSIX_ETIMEDOUT = __TOP_ERRNO + 4 8,152 POSIX_ETXTBSY = __TOP_ERRNO + 49,153 POSIX_EWOULDBLOCK = POSIX_EAGAIN,146 POSIX_EROFS = __TOP_ERRNO + 44, 147 POSIX_ESPIPE = __TOP_ERRNO + 45, 148 POSIX_ESRCH = __TOP_ERRNO + 46, 149 POSIX_ESTALE = __TOP_ERRNO + 47, 150 POSIX_ETIME = __TOP_ERRNO + 48, 151 POSIX_ETIMEDOUT = __TOP_ERRNO + 49, 152 POSIX_ETXTBSY = __TOP_ERRNO + 50, 153 POSIX_EWOULDBLOCK = __TOP_ERRNO + 51, 154 154 POSIX_EXDEV = -EXDEV, 155 155 }; -
uspace/lib/posix/fnmatch.c
r0f963cb ree24574 33 33 */ 34 34 35 // TODO: clean this up a bit 35 /* This file contains an implementation of the fnmatch() pattern matching 36 * function. There is more code than necessary to account for the possibility 37 * of adding POSIX-like locale support to the system in the future. Functions 38 * that are only necessary for locale support currently simply use single 39 * characters for "collation elements". 40 * When (or if) locales are properly implemented, extending this implementation 41 * will be fairly straightforward. 42 */ 36 43 37 44 #include "stdbool.h" … … 46 53 #include "fnmatch.h" 47 54 48 // TODO: documentation 49 55 /* Returned by _match... functions. */ 50 56 #define INVALID_PATTERN -1 51 57 … … 53 59 * but may be extended for better locale support. 54 60 */ 55 typedef int _coll_elm_t; 56 61 typedef int coll_elm_t; 62 63 /** Return value indicating that the element in question 64 * is not valid in the current locale. (That is, if locales are supported.) 65 */ 57 66 #define COLL_ELM_INVALID -1 58 67 59 /** Get collating element matching a string. 60 * 61 * @param str 62 * @return 63 */ 64 static _coll_elm_t _coll_elm_get(const char* str) 68 /** 69 * Get collating element matching a string. 70 * 71 * @param str String representation of the element. 72 * @return Matching collating element or COLL_ELM_INVALID. 73 */ 74 static coll_elm_t _coll_elm_get(const char* str) 65 75 { 66 76 if (str[0] == '\0' || str[1] != '\0') { … … 70 80 } 71 81 72 /** Get collating element matching a single character. 73 * 74 * @param c 75 * @return 76 */ 77 static _coll_elm_t _coll_elm_char(int c) 82 /** 83 * Get collating element matching a single character. 84 * 85 * @param c Character representation of the element. 86 * @return Matching collating element. 87 */ 88 static coll_elm_t _coll_elm_char(int c) 78 89 { 79 90 return c; 80 91 } 81 92 82 /** Match collating element with a beginning of a string. 83 * 84 * @param elm 85 * @param str 93 /** 94 * Match collating element with a beginning of a string. 95 * 96 * @param elm Collating element to match. 97 * @param str String which beginning should match the element. 86 98 * @return 0 if the element doesn't match, or the number of characters matched. 87 99 */ 88 static int _coll_elm_match( _coll_elm_t elm, const char *str)100 static int _coll_elm_match(coll_elm_t elm, const char *str) 89 101 { 90 102 return elm == *str; 91 103 } 92 104 93 static int _coll_elm_between(_coll_elm_t first, _coll_elm_t second, 105 /** 106 * Checks whether a string begins with a collating element in the given range. 107 * Ordering depends on the locale (if locales are supported). 108 * 109 * @param first First element of the range. 110 * @param second Last element of the range. 111 * @param str String to match. 112 * @return 0 if there is no match, or the number of characters matched. 113 */ 114 static int _coll_elm_between(coll_elm_t first, coll_elm_t second, 94 115 const char *str) 95 116 { … … 97 118 } 98 119 99 /** Read a string delimited by [? and ?]. 120 /** 121 * Read a string delimited by [? and ?]. 100 122 * 101 123 * @param pattern Pointer to the string to read from. Its position is moved … … 105 127 * @param buf_sz Read buffer's size. If the buffer is not large enough for 106 128 * the entire string, the string is cut with no error indication. 107 * @return 129 * @param flags Flags modifying the behavior. 130 * @return True on success, false if the pattern is invalid. 108 131 */ 109 132 static bool _get_delimited( … … 172 195 173 196 /** 197 * Compare function for binary search in the _char_classes array. 174 198 * 175 * @param key 176 * @param elem 177 * @return 199 * @param key Key of the searched element. 200 * @param elem Element of _char_classes array. 201 * @return Ordering indicator (-1 less than, 0 equal, 1 greater than). 178 202 */ 179 203 static int _class_compare(const void *key, const void *elem) … … 184 208 185 209 /** 210 * Returns whether the given character belongs to the specified character class. 186 211 * 187 * @param cname 188 * @param c 189 * @return 212 * @param cname Name of the character class. 213 * @param c Character. 214 * @return True if the character belongs to the class, false otherwise. 190 215 */ 191 216 static bool _is_in_class (const char *cname, int c) … … 206 231 207 232 /** 233 * Tries to parse an initial part of the pattern as a character class pattern, 234 * and if successful, matches the beginning of the given string against the class. 208 235 * 209 * @param pattern 210 * @param str 211 * @param flags 212 * @return 236 * @param pattern Pointer to the pattern to match. Must begin with a class 237 * specifier and is repositioned to the first character after the specifier 238 * if successful. 239 * @param str String to match. 240 * @param flags Flags modifying the behavior (see fnmatch()). 241 * @return INVALID_PATTERN if the pattern doesn't start with a valid class 242 * specifier, 0 if the beginning of the matched string doesn't belong 243 * to the class, or positive number of characters matched. 213 244 */ 214 245 static int _match_char_class(const char **pattern, const char *str, int flags) … … 226 257 227 258 /** 259 * Reads the next collating element in the pattern, taking into account 260 * locale (if supported) and flags (see fnmatch()). 228 261 * 229 * @param pattern 230 * @param flags 231 * @return 232 */ 233 static _coll_elm_t _next_coll_elm(const char **pattern, int flags) 234 { 262 * @param pattern Pattern. 263 * @param flags Flags given to fnmatch(). 264 * @return Collating element on success, 265 * or COLL_ELM_INVALID if the pattern is invalid. 266 */ 267 static coll_elm_t _next_coll_elm(const char **pattern, int flags) 268 { 269 assert(pattern != NULL); 270 assert(*pattern != NULL); 271 assert(**pattern != '\0'); 272 235 273 const char *p = *pattern; 236 274 const bool noescape = (flags & FNM_NOESCAPE) != 0; … … 257 295 if (!noescape && *p == '\\') { 258 296 p++; 297 if (*p == '\0') { 298 *pattern = p; 299 return COLL_ELM_INVALID; 300 } 259 301 } 260 302 if (pathname && *p == '/') { 261 303 return COLL_ELM_INVALID; 262 304 } 263 305 264 306 *pattern = p + 1; 265 307 return _coll_elm_char(*p); … … 267 309 268 310 /** 311 * Matches the beginning of the given string against a bracket expression 312 * the pattern begins with. 269 313 * 270 * @param pattern 271 * @param str 272 * @param flags 273 * @return 314 * @param pattern Pointer to the beginning of a bracket expression in a pattern. 315 * On success, the pointer is moved to the first character after the 316 * bracket expression. 317 * @param str Unmatched part of the string. 318 * @param flags Flags given to fnmatch(). 319 * @return INVALID_PATTERN if the pattern is invalid, 0 if there is no match 320 * or the number of matched characters on success. 274 321 */ 275 322 static int _match_bracket_expr(const char **pattern, const char *str, int flags) … … 315 362 } 316 363 317 _coll_elm_t current_elm = COLL_ELM_INVALID;364 coll_elm_t current_elm = COLL_ELM_INVALID; 318 365 319 366 while (*p != ']') { … … 322 369 /* Range expression. */ 323 370 p++; 324 _coll_elm_t end_elm = _next_coll_elm(&p, flags);371 coll_elm_t end_elm = _next_coll_elm(&p, flags); 325 372 if (end_elm == COLL_ELM_INVALID) { 326 373 return INVALID_PATTERN; … … 358 405 359 406 /** 407 * Matches a portion of the pattern containing no asterisks (*) against 408 * the given string. 360 409 * 361 * @param pattern 362 * @param string 363 * @param flags 364 * @return 410 * @param pattern Pointer to the unmatched portion of the pattern. 411 * On success, the pointer is moved to the first asterisk, or to the 412 * terminating nul character, whichever occurs first. 413 * @param string Pointer to the input string. On success, the pointer is moved 414 * to the first character that wasn't explicitly matched. 415 * @param flags Flags given to fnmatch(). 416 * @return True if the entire subpattern matched. False otherwise. 365 417 */ 366 418 static bool _partial_match(const char **pattern, const char **string, int flags) … … 457 509 458 510 /** 511 * Match string against a pattern. 459 512 * 460 * @param pattern 461 * @param string 462 * @param flags 463 * @return 513 * @param pattern Pattern. 514 * @param string String to match. 515 * @param flags Flags given to fnmatch(). 516 * @return True if the string matched the pattern, false otherwise. 464 517 */ 465 518 static bool _full_match(const char *pattern, const char *string, int flags) … … 496 549 end = string; 497 550 } else { 498 end = strchrnul(string, pathname ? '/' : '\0');551 end = strchrnul(string, pathname ? '/' : '\0'); 499 552 } 500 553 … … 519 572 520 573 /** 574 * Transform the entire string to lowercase. 521 575 * 522 * @param s 523 * @return 576 * @param s Input string. 577 * @return Newly allocated copy of the input string with all uppercase 578 * characters folded to their lowercase variants. 524 579 */ 525 580 static char *_casefold(const char *s) … … 536 591 * Filename pattern matching. 537 592 * 538 * @param pattern 539 * @param string 540 * @param flags 541 * @return 593 * @param pattern Pattern to match the string against. 594 * @param string Matched string. 595 * @param flags Flags altering the matching of special characters 596 * (mainly for dot and slash). 597 * @return Zero if the string matches the pattern, FNM_NOMATCH otherwise. 542 598 */ 543 599 int posix_fnmatch(const char *pattern, const char *string, int flags) … … 568 624 } 569 625 570 // FIXME: put the testcases somewhere else626 // FIXME: put the testcases to the app/tester after fnmatch is included into libc 571 627 572 628 #if 0 -
uspace/lib/posix/locale.c
r0f963cb ree24574 42 42 #include "string.h" 43 43 44 // TODO: documentation 44 /* Just a very basic dummy implementation. 45 * This should allow code using locales to work properly, but doesn't provide 46 * any localization functionality. 47 * Should be extended/rewritten when or if HelenOS supports locales natively. 48 */ 45 49 46 50 struct __posix_locale { … … 76 80 77 81 /** 82 * Set program locale. 78 83 * 79 * @param category 80 * @param locale 81 * @return 84 * @param category What category to set. 85 * @param locale Locale name. 86 * @return Original locale name on success, NULL on failure. 82 87 */ 83 88 char *posix_setlocale(int category, const char *locale) … … 92 97 93 98 /** 99 * Return locale-specific information. 94 100 * 95 * @return 101 * @return Information about the current locale. 96 102 */ 97 103 struct posix_lconv *posix_localeconv(void) … … 102 108 103 109 /** 110 * Duplicate locale object. 104 111 * 105 * @param locobj 106 * @return 112 * @param locobj Object to duplicate. 113 * @return Duplicated object. 107 114 */ 108 115 posix_locale_t posix_duplocale(posix_locale_t locobj) … … 122 129 123 130 /** 131 * Free locale object. 124 132 * 125 * @param locobj 133 * @param locobj Object to free. 126 134 */ 127 135 void posix_freelocale(posix_locale_t locobj) … … 133 141 134 142 /** 143 * Create or modify a locale object. 135 144 * 136 * @param category_mask 137 * @param locale 138 * @param base 139 * @return 145 * @param category_mask Mask of categories to be set or modified. 146 * @param locale Locale to be used. 147 * @param base Object to modify. 0 if new object is to be created. 148 * @return The new/modified locale object. 140 149 */ 141 150 posix_locale_t posix_newlocale(int category_mask, const char *locale, … … 160 169 161 170 /** 171 * Set locale for the current thread. 162 172 * 163 * @param newloc 164 * @return 173 * @param newloc Locale to use. 174 * @return The previously set locale or LC_GLOBAL_LOCALE 165 175 */ 166 176 posix_locale_t posix_uselocale(posix_locale_t newloc) 167 177 { 168 178 // TODO 169 return NULL;179 return LC_GLOBAL_LOCALE; 170 180 } 171 181 -
uspace/lib/posix/locale.h
r0f963cb ree24574 35 35 #ifndef POSIX_LOCALE_H_ 36 36 #define POSIX_LOCALE_H_ 37 38 // TODO: documentation39 37 40 38 #ifndef NULL -
uspace/lib/posix/signal.c
r0f963cb ree24574 45 45 #include "libc/task.h" 46 46 47 // TODO: documentation 47 /* This file implements a fairly dumb and incomplete "simulation" of 48 * POSIX signals. Since HelenOS doesn't support signals and mostly doesn't 49 * have any equivalent functionality, most of the signals are useless. The 50 * main purpose of this implementation is thus to help port applications using 51 * signals with minimal modification, but if the application uses signals for 52 * anything non-trivial, it's quite probable it won't work properly even if 53 * it builds without problems. 54 */ 48 55 49 56 /* Used to serialize signal handling. */ 50 57 static FIBRIL_MUTEX_INITIALIZE(_signal_mutex); 51 58 59 static LIST_INITIALIZE(_signal_queue); 60 52 61 static posix_sigset_t _signal_mask = 0; 53 62 … … 55 64 .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL } 56 65 66 /* Actions associated with each signal number. */ 57 67 static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = { 58 68 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, … … 127 137 128 138 /** 129 * 130 * @param signo 139 * Just an empty function to get an unique pointer value for comparison. 140 * 141 * @param signo Signal number. 131 142 */ 132 143 void __posix_hold_signal_handler(int signo) … … 136 147 137 148 /** 138 * 139 * @param signo 149 * Empty function to be used as ignoring handler. 150 * 151 * @param signo Signal number. 140 152 */ 141 153 void __posix_ignore_signal_handler(int signo) … … 145 157 146 158 /** 147 * 148 * @param set 149 * @return 159 * Clear the signal set. 160 * 161 * @param set Pointer to the signal set. 162 * @return Always returns zero. 150 163 */ 151 164 int posix_sigemptyset(posix_sigset_t *set) … … 158 171 159 172 /** 160 * 161 * @param set 162 * @return 173 * Fill the signal set (i.e. add all signals). 174 * 175 * @param set Pointer to the signal set. 176 * @return Always returns zero. 163 177 */ 164 178 int posix_sigfillset(posix_sigset_t *set) … … 171 185 172 186 /** 173 * 174 * @param set 175 * @param signo 176 * @return 187 * Add a signal to the set. 188 * 189 * @param set Pointer to the signal set. 190 * @param signo Signal number to add. 191 * @return Always returns zero. 177 192 */ 178 193 int posix_sigaddset(posix_sigset_t *set, int signo) … … 185 200 186 201 /** 187 * 188 * @param set 189 * @param signo 190 * @return 202 * Delete a signal from the set. 203 * 204 * @param set Pointer to the signal set. 205 * @param signo Signal number to remove. 206 * @return Always returns zero. 191 207 */ 192 208 int posix_sigdelset(posix_sigset_t *set, int signo) … … 199 215 200 216 /** 201 * 202 * @param set 203 * @param signo 204 * @return 217 * Inclusion test for a signal set. 218 * 219 * @param set Pointer to the signal set. 220 * @param signo Signal number to query. 221 * @return 1 if the signal is in the set, 0 otherwise. 205 222 */ 206 223 int posix_sigismember(const posix_sigset_t *set, int signo) … … 212 229 213 230 /** 231 * Unsafe variant of the sigaction() function. 232 * Doesn't do any checking of its arguments and 233 * does not deal with thread-safety. 214 234 * 215 235 * @param sig … … 232 252 233 253 /** 234 * 235 * @param sig 236 * @param act 237 * @param oact 238 * @return 254 * Sets a new action for the given signal number. 255 * 256 * @param sig Signal number to set action for. 257 * @param act If not NULL, contents of this structure are 258 * used as the new action for the signal. 259 * @param oact If not NULL, the original action associated with the signal 260 * is stored in the structure pointer to. 261 * @return -1 with errno set on failure, 0 on success. 239 262 */ 240 263 int posix_sigaction(int sig, const struct posix_sigaction *restrict act, … … 263 286 264 287 /** 265 * 266 * @param sig 267 * @param func 268 * @return 288 * Sets a new handler for the given signal number. 289 * 290 * @param sig Signal number to set handler for. 291 * @param func Handler function. 292 * @return SIG_ERR on failure, original handler on success. 269 293 */ 270 294 void (*posix_signal(int sig, void (*func)(int)))(int) … … 284 308 } 285 309 286 /** 287 * 288 * @param signo 289 * @param siginfo 290 * @return 291 */ 292 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo) 310 typedef struct { 311 link_t link; 312 int signo; 313 posix_siginfo_t siginfo; 314 } signal_queue_item; 315 316 /** 317 * Queue blocked signal. 318 * 319 * @param signo Signal number. 320 * @param siginfo Additional information about the signal. 321 */ 322 static void _queue_signal(int signo, posix_siginfo_t *siginfo) 293 323 { 294 324 assert(signo >= 0 && signo <= _TOP_SIGNAL); 295 325 assert(siginfo != NULL); 326 327 signal_queue_item *item = malloc(sizeof(signal_queue_item)); 328 link_initialize(&(item->link)); 329 item->signo = signo; 330 memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t)); 331 list_append(&(item->link), &_signal_queue); 332 } 333 334 335 /** 336 * Executes an action associated with the given signal. 337 * 338 * @param signo Signal number. 339 * @param siginfo Additional information about the circumstances of this raise. 340 * @return 0 if the action has been successfully executed. -1 if the signal is 341 * blocked. 342 */ 343 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo) 344 { 345 assert(signo >= 0 && signo <= _TOP_SIGNAL); 346 assert(siginfo != NULL); 296 347 297 348 fibril_mutex_lock(&_signal_mutex); … … 301 352 if (posix_sigismember(&_signal_mask, signo) || 302 353 action.sa_handler == SIG_HOLD) { 303 // TODO: queue signal354 _queue_signal(signo, siginfo); 304 355 fibril_mutex_unlock(&_signal_mutex); 305 356 return -1; … … 312 363 if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) { 313 364 _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER; 314 } ;365 } 315 366 316 367 if (action.sa_flags & SA_SIGINFO) { … … 328 379 329 380 /** 330 * 331 * @param sig 332 * @return 381 * Raise all unblocked previously queued signals. 382 */ 383 static void _dequeue_unblocked_signals() 384 { 385 link_t *iterator = _signal_queue.head.next; 386 link_t *next; 387 388 while (iterator != &(_signal_queue).head) { 389 next = iterator->next; 390 391 signal_queue_item *item = 392 list_get_instance(iterator, signal_queue_item, link); 393 394 if (!posix_sigismember(&_signal_mask, item->signo) && 395 _signal_actions[item->signo].sa_handler != SIG_HOLD) { 396 list_remove(&(item->link)); 397 _raise_sigaction(item->signo, &(item->siginfo)); 398 free(item); 399 } 400 401 iterator = next; 402 } 403 } 404 405 /** 406 * Raise a signal for the calling process. 407 * 408 * @param sig Signal number. 409 * @return -1 with errno set on failure, 0 on success. 333 410 */ 334 411 int posix_raise(int sig) … … 347 424 348 425 /** 349 * 350 * @param pid 351 * @param signo 352 * @return 426 * Raises a signal for a selected process. 427 * 428 * @param pid PID of the process for which the signal shall be raised. 429 * @param signo Signal to raise. 430 * @return -1 with errno set on failure (possible errors include unsupported 431 * action, invalid signal number, lack of permissions, etc.), 0 on success. 353 432 */ 354 433 int posix_kill(posix_pid_t pid, int signo) … … 383 462 384 463 /** 385 * 386 * @param pid 387 * @param sig 388 * @return 464 * Send a signal to a process group. Always fails at the moment because of 465 * lack of this functionality in HelenOS. 466 * 467 * @param pid PID of the process group. 468 * @param sig Signal number. 469 * @return -1 on failure, 0 on success (see kill()). 389 470 */ 390 471 int posix_killpg(posix_pid_t pid, int sig) … … 395 476 396 477 /** 397 * 398 * @param pinfo 399 * @param message 478 * Outputs information about the signal to the standard error stream. 479 * 480 * @param pinfo SigInfo struct to write. 481 * @param message String to output alongside human-readable signal description. 400 482 */ 401 483 void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message) … … 407 489 408 490 /** 409 * 410 * @param signum 411 * @param message 491 * Outputs information about the signal to the standard error stream. 492 * 493 * @param signum Signal number. 494 * @param message String to output alongside human-readable signal description. 412 495 */ 413 496 void posix_psignal(int signum, const char *message) … … 422 505 423 506 /** 424 * 425 * @param how 426 * @param set 427 * @param oset 428 * @return 507 * Manipulate the signal mask of the calling thread. 508 * 509 * @param how What to do with the mask. 510 * @param set Signal set to work with. 511 * @param oset If not NULL, the original signal mask is coppied here. 512 * @return 0 success, errorcode on failure. 429 513 */ 430 514 int posix_thread_sigmask(int how, const posix_sigset_t *restrict set, … … 452 536 } 453 537 } 454 455 // TODO: queued signal handling538 539 _dequeue_unblocked_signals(); 456 540 457 541 fibril_mutex_unlock(&_signal_mutex); … … 461 545 462 546 /** 463 * 464 * @param how 465 * @param set 466 * @param oset 467 * @return 547 * Manipulate the signal mask of the process. 548 * 549 * @param how What to do with the mask. 550 * @param set Signal set to work with. 551 * @param oset If not NULL, the original signal mask is coppied here. 552 * @return 0 on success, -1 with errno set on failure. 468 553 */ 469 554 int posix_sigprocmask(int how, const posix_sigset_t *restrict set, -
uspace/lib/posix/signal.h
r0f963cb ree24574 36 36 #define POSIX_SIGNAL_H_ 37 37 38 // TODO: documentation39 40 38 #include "libc/errno.h" 41 39 #include "sys/types.h" … … 57 55 typedef uint32_t posix_sigset_t; 58 56 typedef struct posix_mcontext { 59 / / FIXME: should not be empty to avoid compiler warnings (-pedantic)57 /* must not be empty to avoid compiler warnings (-pedantic) */ 60 58 int dummy; 61 59 } posix_mcontext_t; -
uspace/lib/posix/stdbool.h
r0f963cb ree24574 36 36 #define POSIX_STDBOOL_H_ 37 37 38 // TODO: propose for inclusion in libc and drop bool.h,39 // it's a very silly incompatibility with standard C40 41 38 #ifdef LIBC_BOOL_H_ 42 39 #error "You can't include bool.h and stdbool.h at the same time." -
uspace/lib/posix/stdint.h
r0f963cb ree24574 103 103 typedef uint64_t posix_uintmax_t; 104 104 105 // FIXME: should be integrated into build process similarly to uintptr_t106 typedef ssize_t posix_intptr_t;107 108 105 #ifndef LIBPOSIX_INTERNAL 109 106 #define intmax_t posix_intmax_t 110 107 #define uintmax_t posix_uintmax_t 111 112 #define intptr_t posix_intptr_t113 108 #endif 114 109 -
uspace/lib/posix/stdio.c
r0f963cb ree24574 284 284 fdi_node_t node = { 285 285 .fs_handle = st.fs_handle, 286 . devmap_handle = st.devmap_handle,286 .service_id = st.service_id, 287 287 .index = st.index 288 288 }; … … 317 317 318 318 return stream; 319 }320 321 /**322 *323 * @param buf324 * @param size325 * @param mode326 * @return327 */328 FILE *posix_fmemopen(void *restrict buf, size_t size,329 const char *restrict mode)330 {331 // TODO332 not_implemented();333 }334 335 /**336 *337 * @param bufp338 * @param sizep339 * @return340 */341 FILE *posix_open_memstream(char **bufp, size_t *sizep)342 {343 // TODO344 not_implemented();345 319 } 346 320 -
uspace/lib/posix/stdio.h
r0f963cb ree24574 65 65 extern FILE *posix_freopen(const char *restrict filename, 66 66 const char *restrict mode, FILE *restrict stream); 67 extern FILE *posix_fmemopen(void *restrict buf, size_t size,68 const char *restrict mode);69 extern FILE *posix_open_memstream(char **bufp, size_t *sizep);70 67 71 68 /* Error Messages */ … … 143 140 144 141 #define freopen posix_freopen 145 #define fmemopen posix_fmemopen146 #define open_memstream posix_open_memstream147 142 148 143 #define perror posix_perror -
uspace/lib/posix/stdio/scanf.c
r0f963cb ree24574 707 707 break; 708 708 case LMOD_t: ; 709 // FIXME: What is unsigned counterpart of the ptrdiff_t?709 // XXX: What is unsigned counterpart of the ptrdiff_t? 710 710 size_t *pt = va_arg(arg, size_t *); 711 711 *pt = (size_t) ures; … … 1221 1221 } 1222 1222 1223 // FIXME: put the testcases somewhere else1223 // FIXME: put the testcases to the app/tester after scanf is included into libc 1224 1224 1225 1225 #if 0 -
uspace/lib/posix/stdlib.c
r0f963cb ree24574 49 49 #include "libc/str.h" 50 50 #include "libc/vfs/vfs.h" 51 #include "libc/stats.h" 51 52 52 53 /** … … 473 474 * Get system load average statistics. 474 475 * 475 * Not supported. Always returns -1.476 *477 476 * @param loadavg Array where the load averages shall be placed. 478 477 * @param nelem Maximum number of elements to be placed into the array. … … 481 480 int bsd_getloadavg(double loadavg[], int nelem) 482 481 { 483 return -1; 482 assert(nelem > 0); 483 484 size_t count; 485 load_t *loads = stats_get_load(&count); 486 487 if (loads == NULL) { 488 return -1; 489 } 490 491 if (((size_t) nelem) < count) { 492 count = nelem; 493 } 494 495 for (size_t i = 0; i < count; ++i) { 496 loadavg[i] = (double) loads[i]; 497 } 498 499 free(loads); 500 return count; 484 501 } 485 502 -
uspace/lib/posix/stdlib/strtold.c
r0f963cb ree24574 48 48 #include "../limits.h" 49 49 50 // FIXME: #include <float.h> 50 #include "../float.h" 51 51 52 52 #ifndef HUGE_VALL -
uspace/lib/posix/string.c
r0f963cb ree24574 553 553 char *posix_strerror(int errnum) 554 554 { 555 /* Uses function from libc, we just have to negate errno 556 * (POSIX uses positive errorcodes, HelenOS has negative). 557 */ 558 // FIXME: not all POSIX error codes are in libc 559 return (char *) str_error(-posix_abs(errnum)); 555 static const char *error_msgs[] = { 556 [E2BIG] = "[E2BIG] Argument list too long", 557 [EACCES] = "[EACCES] Permission denied", 558 [EADDRINUSE] = "[EADDRINUSE] Address in use", 559 [EADDRNOTAVAIL] = "[EADDRNOTAVAIL] Address not available", 560 [EAFNOSUPPORT] = "[EAFNOSUPPORT] Address family not supported", 561 [EAGAIN] = "[EAGAIN] Resource unavailable, try again", 562 [EALREADY] = "[EALREADY] Connection already in progress", 563 [EBADF] = "[EBADF] Bad file descriptor", 564 [EBADMSG] = "[EBADMSG] Bad message", 565 [EBUSY] = "[EBUSY] Device or resource busy", 566 [ECANCELED] = "[ECANCELED] Operation canceled", 567 [ECHILD] = "[ECHILD] No child processes", 568 [ECONNABORTED] = "[ECONNABORTED] Connection aborted", 569 [ECONNREFUSED] = "[ECONNREFUSED] Connection refused", 570 [ECONNRESET] = "[ECONNRESET] Connection reset", 571 [EDEADLK] = "[EDEADLK] Resource deadlock would occur", 572 [EDESTADDRREQ] = "[EDESTADDRREQ] Destination address required", 573 [EDOM] = "[EDOM] Mathematics argument out of domain of function", 574 [EDQUOT] = "[EDQUOT] Reserved", 575 [EEXIST] = "[EEXIST] File exists", 576 [EFAULT] = "[EFAULT] Bad address", 577 [EFBIG] = "[EFBIG] File too large", 578 [EHOSTUNREACH] = "[EHOSTUNREACH] Host is unreachable", 579 [EIDRM] = "[EIDRM] Identifier removed", 580 [EILSEQ] = "[EILSEQ] Illegal byte sequence", 581 [EINPROGRESS] = "[EINPROGRESS] Operation in progress", 582 [EINTR] = "[EINTR] Interrupted function", 583 [EINVAL] = "[EINVAL] Invalid argument", 584 [EIO] = "[EIO] I/O error", 585 [EISCONN] = "[EISCONN] Socket is connected", 586 [EISDIR] = "[EISDIR] Is a directory", 587 [ELOOP] = "[ELOOP] Too many levels of symbolic links", 588 [EMFILE] = "[EMFILE] File descriptor value too large", 589 [EMLINK] = "[EMLINK] Too many links", 590 [EMSGSIZE] = "[EMSGSIZE] Message too large", 591 [EMULTIHOP] = "[EMULTIHOP] Reserved", 592 [ENAMETOOLONG] = "[ENAMETOOLONG] Filename too long", 593 [ENETDOWN] = "[ENETDOWN] Network is down", 594 [ENETRESET] = "[ENETRESET] Connection aborted by network", 595 [ENETUNREACH] = "[ENETUNREACH] Network unreachable", 596 [ENFILE] = "[ENFILE] Too many files open in system", 597 [ENOBUFS] = "[ENOBUFS] No buffer space available", 598 [ENODATA] = "[ENODATA] No message is available on the STREAM head read queue", 599 [ENODEV] = "[ENODEV] No such device", 600 [ENOENT] = "[ENOENT] No such file or directory", 601 [ENOEXEC] = "[ENOEXEC] Executable file format error", 602 [ENOLCK] = "[ENOLCK] No locks available", 603 [ENOLINK] = "[ENOLINK] Reserved", 604 [ENOMEM] = "[ENOMEM] Not enough space", 605 [ENOMSG] = "[ENOMSG] No message of the desired type", 606 [ENOPROTOOPT] = "[ENOPROTOOPT] Protocol not available", 607 [ENOSPC] = "[ENOSPC] No space left on device", 608 [ENOSR] = "[ENOSR] No STREAM resources.", 609 [ENOSTR] = "[ENOSTR] Not a STREAM", 610 [ENOSYS] = "[ENOSYS] Function not supported", 611 [ENOTCONN] = "[ENOTCONN] The socket is not connected", 612 [ENOTDIR] = "[ENOTDIR] Not a directory", 613 [ENOTEMPTY] = "[ENOTEMPTY] Directory not empty", 614 [ENOTRECOVERABLE] = "[ENOTRECOVERABLE] State not recoverable", 615 [ENOTSOCK] = "[ENOTSOCK] Not a socket", 616 [ENOTSUP] = "[ENOTSUP] Not supported", 617 [ENOTTY] = "[ENOTTY] Inappropriate I/O control operation", 618 [ENXIO] = "[ENXIO] No such device or address", 619 [EOPNOTSUPP] = "[EOPNOTSUPP] Operation not supported", 620 [EOVERFLOW] = "[EOVERFLOW] Value too large to be stored in data type", 621 [EOWNERDEAD] = "[EOWNERDEAD] Previous owned died", 622 [EPERM] = "[EPERM] Operation not permitted", 623 [EPIPE] = "[EPIPE] Broken pipe", 624 [EPROTO] = "[EPROTO] Protocol error", 625 [EPROTONOSUPPORT] = "[EPROTONOSUPPORT] Protocol not supported", 626 [EPROTOTYPE] = "[EPROTOTYPE] Protocol wrong type for socket", 627 [ERANGE] = "[ERANGE] Result too large", 628 [EROFS] = "[EROFS] Read-only file system", 629 [ESPIPE] = "[ESPIPE] Invalid seek", 630 [ESRCH] = "[ESRCH] No such process", 631 [ESTALE] = "[ESTALE] Reserved", 632 [ETIME] = "[ETIME] Stream ioctl() timeout", 633 [ETIMEDOUT] = "[ETIMEDOUT] Connection timed out", 634 [ETXTBSY] = "[ETXTBSY] Text file busy", 635 [EWOULDBLOCK] = "[EWOULDBLOCK] Operation would block", 636 [EXDEV] = "[EXDEV] Cross-device link", 637 }; 638 639 return (char *) error_msgs[posix_abs(errnum)]; 560 640 } 561 641 … … 573 653 574 654 char *errstr = posix_strerror(errnum); 575 /* HelenOS str_error can't fail */576 655 577 656 if (posix_strlen(errstr) + 1 > bufsz) { 578 return -ERANGE;657 return ERANGE; 579 658 } else { 580 659 posix_strcpy(buf, errstr); -
uspace/lib/posix/string.h
r0f963cb ree24574 51 51 * void *memmove(void *, const void *, size_t); 52 52 * 53 * unimplemented due to missing locales53 * TODO: not implemented due to missing locale support 54 54 * 55 55 * int strcoll_l(const char *, const char *, locale_t); 56 56 * char *strerror_l(int, locale_t); 57 57 * size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t); 58 *59 58 */ 60 61 // TODO: provide *_l once there is locale.h62 59 63 60 #ifndef NULL -
uspace/lib/posix/strings.h
r0f963cb ree24574 48 48 #endif 49 49 50 /* TODO: not implemented due to missing locale .h50 /* TODO: not implemented due to missing locale support 51 51 * 52 52 * int strcasecmp_l(const char *, const char *, locale_t); -
uspace/lib/posix/sys/stat.c
r0f963cb ree24574 52 52 memset(dest, 0, sizeof(struct posix_stat)); 53 53 54 dest->st_dev = src-> device;54 dest->st_dev = src->service; 55 55 dest->st_ino = src->index; 56 56 -
uspace/lib/posix/time.c
r0f963cb ree24574 51 51 #include "libc/sys/time.h" 52 52 53 // TODO: documentation54 53 // TODO: test everything in this file 54 55 /* In some places in this file, phrase "normalized broken-down time" is used. 56 * This means time broken down to components (year, month, day, hour, min, sec), 57 * in which every component is in its proper bounds. Non-normalized time could 58 * e.g. be 2011-54-5 29:13:-5, which would semantically mean start of year 2011 59 * + 53 months + 4 days + 29 hours + 13 minutes - 5 seconds. 60 */ 61 62 55 63 56 64 /* Helper functions ***********************************************************/ … … 64 72 65 73 /** 66 * 67 * @param year 68 * @return 74 * Checks whether the year is a leap year. 75 * 76 * @param year Year since 1900 (e.g. for 1970, the value is 70). 77 * @return true if year is a leap year, false otherwise 69 78 */ 70 79 static bool _is_leap_year(time_t year) … … 82 91 83 92 /** 84 * 85 * @param year 86 * @param mon 87 * @return 93 * Returns how many days there are in the given month of the given year. 94 * Note that year is only taken into account if month is February. 95 * 96 * @param year Year since 1900 (can be negative). 97 * @param mon Month of the year. 0 for January, 11 for December. 98 * @return Number of days in the specified month. 88 99 */ 89 100 static int _days_in_month(time_t year, time_t mon) 90 101 { 91 102 assert(mon >= 0 && mon <= 11); 92 year += 1900;93 103 94 104 static int month_days[] = … … 96 106 97 107 if (mon == 1) { 108 year += 1900; 98 109 /* february */ 99 110 return _is_leap_year(year) ? 29 : 28; … … 104 115 105 116 /** 106 * 107 * @param year 108 * @param mon 109 * @param mday 110 * @return 117 * For specified year, month and day of month, returns which day of that year 118 * it is. 119 * 120 * For example, given date 2011-01-03, the corresponding expression is: 121 * _day_of_year(111, 0, 3) == 2 122 * 123 * @param year Year (year 1900 = 0, can be negative). 124 * @param mon Month (January = 0). 125 * @param mday Day of month (First day is 1). 126 * @return Day of year (First day is 0). 111 127 */ 112 128 static int _day_of_year(time_t year, time_t mon, time_t mday) … … 122 138 /** 123 139 * Integer division that rounds to negative infinity. 124 * 125 * @param op1 126 * @param op2 127 * @return 140 * Used by some functions in this file. 141 * 142 * @param op1 Divident. 143 * @param op2 Divisor. 144 * @return Rounded quotient. 128 145 */ 129 146 static time_t _floor_div(time_t op1, time_t op2) … … 138 155 /** 139 156 * Modulo that rounds to negative infinity. 140 * 141 * @param op1 142 * @param op2 143 * @return 157 * Used by some functions in this file. 158 * 159 * @param op1 Divident. 160 * @param op2 Divisor. 161 * @return Remainder. 144 162 */ 145 163 static time_t _floor_mod(time_t op1, time_t op2) … … 161 179 162 180 /** 163 * 164 * @param year 165 * @param mon 166 * @param mday 167 * @return 181 * Number of days since the Epoch. 182 * Epoch is 1970-01-01, which is also equal to day 0. 183 * 184 * @param year Year (year 1900 = 0, may be negative). 185 * @param mon Month (January = 0). 186 * @param mday Day of month (first day = 1). 187 * @return Number of days since the Epoch. 168 188 */ 169 189 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday) … … 175 195 176 196 /** 177 * Assumes normalized broken-down time.178 * 179 * @param tm 180 * @return 197 * Seconds since the Epoch. see also _days_since_epoch(). 198 * 199 * @param tm Normalized broken-down time. 200 * @return Number of seconds since the epoch, not counting leap seconds. 181 201 */ 182 202 static time_t _secs_since_epoch(const struct posix_tm *tm) … … 188 208 189 209 /** 190 * 191 * @param year 192 * @param mon 193 * @param mday 194 * @return 210 * Which day of week the specified date is. 211 * 212 * @param year Year (year 1900 = 0). 213 * @param mon Month (January = 0). 214 * @param mday Day of month (first = 1). 215 * @return Day of week (Sunday = 0). 195 216 */ 196 217 static int _day_of_week(time_t year, time_t mon, time_t mday) 197 218 { 198 219 /* 1970-01-01 is Thursday */ 199 return (_days_since_epoch(year, mon, mday) + 4) % 7; 200 } 201 202 struct _long_tm { 203 time_t tm_sec; 204 time_t tm_min; 205 time_t tm_hour; 206 time_t tm_mday; 207 time_t tm_mon; 208 time_t tm_year; 209 int tm_wday; 210 int tm_yday; 211 int tm_isdst; 212 }; 213 214 /** 215 * 216 * @param ltm 217 * @param ptm 218 */ 219 static void _posix_to_long_tm(struct _long_tm *ltm, struct posix_tm *ptm) 220 { 221 assert(ltm != NULL && ptm != NULL); 222 ltm->tm_sec = ptm->tm_sec; 223 ltm->tm_min = ptm->tm_min; 224 ltm->tm_hour = ptm->tm_hour; 225 ltm->tm_mday = ptm->tm_mday; 226 ltm->tm_mon = ptm->tm_mon; 227 ltm->tm_year = ptm->tm_year; 228 ltm->tm_wday = ptm->tm_wday; 229 ltm->tm_yday = ptm->tm_yday; 230 ltm->tm_isdst = ptm->tm_isdst; 231 } 232 233 /** 234 * 235 * @param ptm 236 * @param ltm 237 */ 238 static void _long_to_posix_tm(struct posix_tm *ptm, struct _long_tm *ltm) 239 { 240 assert(ltm != NULL && ptm != NULL); 241 // FIXME: the cast should be unnecessary, libarch/common.h brain-damage 242 assert((ltm->tm_year >= (int) INT_MIN) && (ltm->tm_year <= (int) INT_MAX)); 243 244 ptm->tm_sec = ltm->tm_sec; 245 ptm->tm_min = ltm->tm_min; 246 ptm->tm_hour = ltm->tm_hour; 247 ptm->tm_mday = ltm->tm_mday; 248 ptm->tm_mon = ltm->tm_mon; 249 ptm->tm_year = ltm->tm_year; 250 ptm->tm_wday = ltm->tm_wday; 251 ptm->tm_yday = ltm->tm_yday; 252 ptm->tm_isdst = ltm->tm_isdst; 253 } 254 255 /** 256 * 257 * @param tm 258 */ 259 static void _normalize_time(struct _long_tm *tm) 220 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7); 221 } 222 223 /** 224 * Normalizes the broken-down time and optionally adds specified amount of 225 * seconds. 226 * 227 * @param tm Broken-down time to normalize. 228 * @param sec_add Seconds to add. 229 * @return 0 on success, -1 on overflow 230 */ 231 static int _normalize_time(struct posix_tm *tm, time_t sec_add) 260 232 { 261 233 // TODO: DST correction 262 234 235 /* Set initial values. */ 236 time_t sec = tm->tm_sec + sec_add; 237 time_t min = tm->tm_min; 238 time_t hour = tm->tm_hour; 239 time_t day = tm->tm_mday - 1; 240 time_t mon = tm->tm_mon; 241 time_t year = tm->tm_year; 242 263 243 /* Adjust time. */ 264 tm->tm_min += _floor_div(tm->tm_sec, SECS_PER_MIN);265 tm->tm_sec = _floor_mod(tm->tm_sec, SECS_PER_MIN);266 tm->tm_hour += _floor_div(tm->tm_min, MINS_PER_HOUR);267 tm->tm_min = _floor_mod(tm->tm_min, MINS_PER_HOUR);268 tm->tm_mday += _floor_div(tm->tm_hour, HOURS_PER_DAY);269 tm->tm_hour = _floor_mod(tm->tm_hour, HOURS_PER_DAY);244 min += _floor_div(sec, SECS_PER_MIN); 245 sec = _floor_mod(sec, SECS_PER_MIN); 246 hour += _floor_div(min, MINS_PER_HOUR); 247 min = _floor_mod(min, MINS_PER_HOUR); 248 day += _floor_div(hour, HOURS_PER_DAY); 249 hour = _floor_mod(hour, HOURS_PER_DAY); 270 250 271 251 /* Adjust month. */ 272 tm->tm_year += _floor_div(tm->tm_mon, 12);273 tm->tm_mon = _floor_mod(tm->tm_mon, 12);252 year += _floor_div(mon, 12); 253 mon = _floor_mod(mon, 12); 274 254 275 255 /* Now the difficult part - days of month. */ 276 /* Slow, but simple. */ 277 // FIXME: do this faster 278 279 while (tm->tm_mday < 1) { 280 tm->tm_mon--; 281 if (tm->tm_mon == -1) { 282 tm->tm_mon = 11; 283 tm->tm_year--; 256 257 /* First, deal with whole cycles of 400 years = 146097 days. */ 258 year += _floor_div(day, 146097) * 400; 259 day = _floor_mod(day, 146097); 260 261 /* Then, go in one year steps. */ 262 if (mon <= 1) { 263 /* January and February. */ 264 while (day > 365) { 265 day -= _is_leap_year(year) ? 366 : 365; 266 year++; 284 267 } 285 286 tm->tm_mday += _days_in_month(tm->tm_year, tm->tm_mon); 287 } 288 289 while (tm->tm_mday > _days_in_month(tm->tm_year, tm->tm_mon)) { 290 tm->tm_mday -= _days_in_month(tm->tm_year, tm->tm_mon); 291 292 tm->tm_mon++; 293 if (tm->tm_mon == 12) { 294 tm->tm_mon = 0; 295 tm->tm_year++; 268 } else { 269 /* Rest of the year. */ 270 while (day > 365) { 271 day -= _is_leap_year(year + 1) ? 366 : 365; 272 year++; 296 273 } 297 274 } 298 275 276 /* Finally, finish it off month per month. */ 277 while (day >= _days_in_month(year, mon)) { 278 day -= _days_in_month(year, mon); 279 mon++; 280 if (mon >= 12) { 281 mon -= 12; 282 year++; 283 } 284 } 285 299 286 /* Calculate the remaining two fields. */ 300 tm->tm_yday = _day_of_year(tm->tm_year, tm->tm_mon, tm->tm_mday); 301 tm->tm_wday = _day_of_week(tm->tm_year, tm->tm_mon, tm->tm_mday); 302 } 303 304 /** 305 * Which day the week-based year starts on relative to the first calendar day. 287 tm->tm_yday = _day_of_year(year, mon, day + 1); 288 tm->tm_wday = _day_of_week(year, mon, day + 1); 289 290 /* And put the values back to the struct. */ 291 tm->tm_sec = (int) sec; 292 tm->tm_min = (int) min; 293 tm->tm_hour = (int) hour; 294 tm->tm_mday = (int) day + 1; 295 tm->tm_mon = (int) mon; 296 297 /* Casts to work around libc brain-damage. */ 298 if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) { 299 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX); 300 return -1; 301 } 302 303 tm->tm_year = (int) year; 304 return 0; 305 } 306 307 /** 308 * Which day the week-based year starts on, relative to the first calendar day. 306 309 * E.g. if the year starts on December 31st, the return value is -1. 307 310 * 308 * @param year309 * @return 311 * @param Year since 1900. 312 * @return Offset of week-based year relative to calendar year. 310 313 */ 311 314 static int _wbyear_offset(int year) … … 317 320 /** 318 321 * Returns week-based year of the specified time. 319 * Assumes normalized broken-down time. 320 * 321 * @param tm 322 * @return 322 * 323 * @param tm Normalized broken-down time. 324 * @return Week-based year. 323 325 */ 324 326 static int _wbyear(const struct posix_tm *tm) … … 329 331 return tm->tm_year - 1; 330 332 } 331 if (day > 364 + _is_leap_year(tm->tm_year)) {333 if (day > 364 + _is_leap_year(tm->tm_year)) { 332 334 /* First week of next year. */ 333 335 return tm->tm_year + 1; … … 368 370 return 53; 369 371 } 370 if (day > 364 + _is_leap_year(tm->tm_year)) {372 if (day > 364 + _is_leap_year(tm->tm_year)) { 371 373 /* First week of next year. */ 372 374 return 1; … … 397 399 398 400 /** 399 * 401 * Set timezone conversion information. 400 402 */ 401 403 void posix_tzset(void) … … 409 411 410 412 /** 411 * 412 * @param time1 413 * @param time0 414 * @return 413 * Calculate the difference between two times, in seconds. 414 * 415 * @param time1 First time. 416 * @param time0 Second time. 417 * @return Time in seconds. 415 418 */ 416 419 double posix_difftime(time_t time1, time_t time0) … … 425 428 * 426 429 * @param tm Broken-down time. 427 * @return time_t representation of the time, undefined value on overflow 430 * @return time_t representation of the time, undefined value on overflow. 428 431 */ 429 432 time_t posix_mktime(struct posix_tm *tm) … … 432 435 // TODO: detect overflow 433 436 434 struct _long_tm ltm; 435 _posix_to_long_tm(<m, tm); 436 _normalize_time(<m); 437 _long_to_posix_tm(tm, <m); 438 437 _normalize_time(tm, 0); 439 438 return _secs_since_epoch(tm); 440 439 } 441 440 442 441 /** 443 * 444 * @param timer 445 * @return 442 * Converts a time value to a broken-down UTC time. 443 * 444 * @param timer Time to convert. 445 * @return Normalized broken-down time in UTC, NULL on overflow. 446 446 */ 447 447 struct posix_tm *posix_gmtime(const time_t *timer) 448 448 { 449 assert(timer != NULL); 450 449 451 static struct posix_tm result; 450 452 return posix_gmtime_r(timer, &result); … … 452 454 453 455 /** 454 * 455 * @param timer 456 * @param result 457 * @return 456 * Converts a time value to a broken-down UTC time. 457 * 458 * @param timer Time to convert. 459 * @param result Structure to store the result to. 460 * @return Value of result on success, NULL on overflow. 458 461 */ 459 462 struct posix_tm *posix_gmtime_r(const time_t *restrict timer, … … 463 466 assert(result != NULL); 464 467 465 /* Set epoch and seconds to _long_tm struct and normalize to get 466 * correct values. 467 */ 468 struct _long_tm ltm = { 469 .tm_sec = *timer, 470 .tm_min = 0, 471 .tm_hour = 0, /* 00:00:xx */ 472 .tm_mday = 1, 473 .tm_mon = 0, /* January 1st */ 474 .tm_year = 70, /* 1970 */ 475 }; 476 _normalize_time(<m); 477 478 if (ltm.tm_year < (int) INT_MIN || ltm.tm_year > (int) INT_MAX) { 468 /* Set result to epoch. */ 469 result->tm_sec = 0; 470 result->tm_min = 0; 471 result->tm_hour = 0; 472 result->tm_mday = 1; 473 result->tm_mon = 0; 474 result->tm_year = 70; /* 1970 */ 475 476 if (_normalize_time(result, *timer) == -1) { 479 477 errno = EOVERFLOW; 480 478 return NULL; 481 479 } 482 480 483 _long_to_posix_tm(result, <m);484 481 return result; 485 482 } 486 483 487 484 /** 488 * 489 * @param timer 490 * @return 485 * Converts a time value to a broken-down local time. 486 * 487 * @param timer Time to convert. 488 * @return Normalized broken-down time in local timezone, NULL on overflow. 491 489 */ 492 490 struct posix_tm *posix_localtime(const time_t *timer) … … 497 495 498 496 /** 499 * 500 * @param timer 501 * @param result 502 * @return 497 * Converts a time value to a broken-down local time. 498 * 499 * @param timer Time to convert. 500 * @param result Structure to store the result to. 501 * @return Value of result on success, NULL on overflow. 503 502 */ 504 503 struct posix_tm *posix_localtime_r(const time_t *restrict timer, … … 511 510 512 511 /** 513 * 514 * @param timeptr 515 * @return 512 * Converts broken-down time to a string in format 513 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 514 * 515 * @param timeptr Broken-down time structure. 516 * @return Pointer to a statically allocated string. 516 517 */ 517 518 char *posix_asctime(const struct posix_tm *timeptr) … … 522 523 523 524 /** 524 * 525 * @param timeptr 526 * @param buf 527 * @return 525 * Converts broken-down time to a string in format 526 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 527 * 528 * @param timeptr Broken-down time structure. 529 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN 530 * bytes long. 531 * @return Value of buf. 528 532 */ 529 533 char *posix_asctime_r(const struct posix_tm *restrict timeptr, … … 552 556 553 557 /** 554 * 555 * @param timer 556 * @return 558 * Equivalent to asctime(localtime(clock)). 559 * 560 * @param timer Time to convert. 561 * @return Pointer to a statically allocated string holding the date. 557 562 */ 558 563 char *posix_ctime(const time_t *timer) … … 566 571 567 572 /** 568 * 569 * @param timer 570 * @param buf 571 * @return 573 * Reentrant variant of ctime(). 574 * 575 * @param timer Time to convert. 576 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN 577 * bytes long. 578 * @return Pointer to buf on success, NULL on falure. 572 579 */ 573 580 char *posix_ctime_r(const time_t *timer, char *buf) … … 581 588 582 589 /** 583 * 584 * @param s 585 * @param maxsize 586 * @param format 587 * @param tm 588 * @return 590 * Convert time and date to a string, based on a specified format and 591 * current locale. 592 * 593 * @param s Buffer to write string to. 594 * @param maxsize Size of the buffer. 595 * @param format Format of the output. 596 * @param tm Broken-down time to format. 597 * @return Number of bytes written. 589 598 */ 590 599 size_t posix_strftime(char *restrict s, size_t maxsize, 591 600 const char *restrict format, const struct posix_tm *restrict tm) 592 601 { 602 assert(s != NULL); 603 assert(format != NULL); 604 assert(tm != NULL); 605 593 606 // TODO: use locale 594 607 static const char *wday_abbr[] = { … … 767 780 768 781 /** 769 * 770 * @param s 771 * @param maxsize 772 * @param format 773 * @param tm 774 * @param loc 775 * @return 776 */ 777 extern size_t posix_strftime_l(char *restrict s, size_t maxsize, 778 const char *restrict format, const struct posix_tm *restrict tm, 779 posix_locale_t loc) 780 { 781 // TODO 782 not_implemented(); 783 } 784 785 /** 786 * 787 * @param clock_id 788 * @param res 789 * @return 782 * Get clock resolution. Only CLOCK_REALTIME is supported. 783 * 784 * @param clock_id Clock ID. 785 * @param res Pointer to the variable where the resolution is to be written. 786 * @return 0 on success, -1 with errno set on failure. 790 787 */ 791 788 int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res) … … 805 802 806 803 /** 807 * 808 * @param clock_id 809 * @param tp 810 * @return 804 * Get time. Only CLOCK_REALTIME is supported. 805 * 806 * @param clock_id ID of the clock to query. 807 * @param tp Pointer to the variable where the time is to be written. 808 * @return 0 on success, -1 with errno on failure. 811 809 */ 812 810 int posix_clock_gettime(posix_clockid_t clock_id, struct posix_timespec *tp) … … 829 827 830 828 /** 831 * 832 * @param clock_id 833 * @param tp 834 * @return 829 * Set time on a specified clock. As HelenOS doesn't support this yet, 830 * this function always fails. 831 * 832 * @param clock_id ID of the clock to set. 833 * @param tp Time to set. 834 * @return 0 on success, -1 with errno on failure. 835 835 */ 836 836 int posix_clock_settime(posix_clockid_t clock_id, … … 853 853 854 854 /** 855 * 856 * @param clock_id 857 * @param flags 858 * @param rqtp 859 * @param rmtp 860 * @return 855 * Sleep on a specified clock. 856 * 857 * @param clock_id ID of the clock to sleep on (only CLOCK_REALTIME supported). 858 * @param flags Flags (none supported). 859 * @param rqtp Sleep time. 860 * @param rmtp Remaining time is written here if sleep is interrupted. 861 * @return 0 on success, -1 with errno set on failure. 861 862 */ 862 863 int posix_clock_nanosleep(posix_clockid_t clock_id, int flags, … … 882 883 } 883 884 884 #if 0885 886 struct __posix_timer {887 posix_clockid_t clockid;888 struct posix_sigevent evp;889 };890 891 /**892 *893 * @param clockid894 * @param evp895 * @param timerid896 * @return897 */898 int posix_timer_create(posix_clockid_t clockid,899 struct posix_sigevent *restrict evp,900 posix_timer_t *restrict timerid)901 {902 // TODO903 not_implemented();904 }905 906 /**907 *908 * @param timerid909 * @return910 */911 int posix_timer_delete(posix_timer_t timerid)912 {913 // TODO914 not_implemented();915 }916 917 /**918 *919 * @param timerid920 * @return921 */922 int posix_timer_getoverrun(posix_timer_t timerid)923 {924 // TODO925 not_implemented();926 }927 928 /**929 *930 * @param timerid931 * @param value932 * @return933 */934 int posix_timer_gettime(posix_timer_t timerid,935 struct posix_itimerspec *value)936 {937 // TODO938 not_implemented();939 }940 941 /**942 *943 * @param timerid944 * @param flags945 * @param value946 * @param ovalue947 * @return948 */949 int posix_timer_settime(posix_timer_t timerid, int flags,950 const struct posix_itimerspec *restrict value,951 struct posix_itimerspec *restrict ovalue)952 {953 // TODO954 not_implemented();955 }956 957 #endif958 959 885 /** 960 886 * Get CPU time used since the process invocation. -
uspace/lib/posix/time.h
r0f963cb ree24574 119 119 extern size_t posix_strftime(char *restrict s, size_t maxsize, 120 120 const char *restrict format, const struct posix_tm *restrict tm); 121 extern size_t posix_strftime_l(char *restrict s, size_t maxsize,122 const char *restrict format, const struct posix_tm *restrict tm,123 posix_locale_t loc);124 121 125 122 /* Clocks */ … … 132 129 extern int posix_clock_nanosleep(posix_clockid_t clock_id, int flags, 133 130 const struct posix_timespec *rqtp, struct posix_timespec *rmtp); 134 135 #if 0136 137 /* Timers */138 extern int posix_timer_create(posix_clockid_t clockid,139 struct posix_sigevent *restrict evp,140 posix_timer_t *restrict timerid);141 extern int posix_timer_delete(posix_timer_t timerid);142 extern int posix_timer_getoverrun(posix_timer_t timerid);143 extern int posix_timer_gettime(posix_timer_t timerid,144 struct posix_itimerspec *value);145 extern int posix_timer_settime(posix_timer_t timerid, int flags,146 const struct posix_itimerspec *restrict value,147 struct posix_itimerspec *restrict ovalue);148 149 #endif150 131 151 132 /* CPU Time */ … … 176 157 #define ctime_r posix_ctime_r 177 158 #define strftime posix_strftime 178 #define strftime_l posix_strftime_l179 159 180 160 #define clock_getres posix_clock_getres … … 182 162 #define clock_settime posix_clock_settime 183 163 #define clock_nanosleep posix_clock_nanosleep 184 185 #define timer_create posix_timer_create 186 #define timer_delete posix_timer_delete 187 #define timer_getoverrun posix_timer_getoverrun 188 #define timer_gettime posix_timer_gettime 189 #define timer_settime posix_timer_settime 190 164 191 165 #define clock posix_clock 192 166 #endif -
uspace/lib/posix/unistd.c
r0f963cb ree24574 88 88 int posix_isatty(int fd) 89 89 { 90 // TODO 90 91 /* Always returns false, because there is no easy way to find 91 92 * out under HelenOS. */
Note:
See TracChangeset
for help on using the changeset viewer.
