Changeset 3e01316f in mainline for uspace/lib/posix
- Timestamp:
- 2011-08-17T18:04:50Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0cf27ee
- Parents:
- e898296d (diff), e6165be (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:
-
- 18 edited
-
errno.h (modified) (1 diff)
-
fnmatch.c (modified) (18 diffs)
-
locale.c (modified) (7 diffs)
-
locale.h (modified) (1 diff)
-
signal.c (modified) (25 diffs)
-
signal.h (modified) (2 diffs)
-
stdio.c (modified) (7 diffs)
-
stdio.h (modified) (3 diffs)
-
stdlib.c (modified) (3 diffs)
-
stdlib.h (modified) (2 diffs)
-
stdlib/strtold.c (modified) (1 diff)
-
string.c (modified) (2 diffs)
-
sys/stat.c (modified) (1 diff)
-
sys/wait.c (modified) (2 diffs)
-
time.c (modified) (32 diffs)
-
time.h (modified) (3 diffs)
-
unistd.c (modified) (6 diffs)
-
unistd.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/errno.h
re898296d r3e01316f 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
re898296d r3e01316f 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 … … 60 69 * 61 70 * @param str 62 * @return 63 */ 64 static _coll_elm_t _coll_elm_get(const char* str)71 * @return Matching collating element or COLL_ELM_INVALID. 72 */ 73 static coll_elm_t _coll_elm_get(const char* str) 65 74 { 66 75 if (str[0] == '\0' || str[1] != '\0') { … … 75 84 * @return 76 85 */ 77 static _coll_elm_t _coll_elm_char(int c)86 static coll_elm_t _coll_elm_char(int c) 78 87 { 79 88 return c; … … 86 95 * @return 0 if the element doesn't match, or the number of characters matched. 87 96 */ 88 static int _coll_elm_match( _coll_elm_t elm, const char *str)97 static int _coll_elm_match(coll_elm_t elm, const char *str) 89 98 { 90 99 return elm == *str; 91 100 } 92 101 93 static int _coll_elm_between(_coll_elm_t first, _coll_elm_t second, 102 /** Checks whether a string begins with a collating element in the given range. 103 * Ordering depends on the locale (if locales are supported). 104 * 105 * @param first First element of the range. 106 * @param second Last element of the range. 107 * @param str String to match. 108 * @return 0 if there is no match, or the number of characters matched. 109 */ 110 static int _coll_elm_between(coll_elm_t first, coll_elm_t second, 94 111 const char *str) 95 112 { … … 105 122 * @param buf_sz Read buffer's size. If the buffer is not large enough for 106 123 * the entire string, the string is cut with no error indication. 107 * @return 124 * @param flags Flags modifying the behavior. 125 * @return True on success, false if the pattern is invalid. 108 126 */ 109 127 static bool _get_delimited( … … 171 189 }; 172 190 173 /** 191 /** Compare function for binary search in the _char_classes array. 174 192 * 175 193 * @param key … … 183 201 } 184 202 185 /** 203 /** Returns whether the given character belongs to the specified character class. 186 204 * 187 * @param cname 188 * @param c 189 * @return 205 * @param cname Name of the character class. 206 * @param c Character. 207 * @return True if the character belongs to the class, false otherwise. 190 208 */ 191 209 static bool _is_in_class (const char *cname, int c) … … 205 223 } 206 224 207 /** 225 /** Tries to parse an initial part of the pattern as a character class pattern, 226 * and if successful, matches the beginning of the given string against the class. 208 227 * 209 * @param pattern 210 * @param str 211 * @param flags 212 * @return 228 * @param pattern Pointer to the pattern to match. Must begin with a class 229 * specifier and is repositioned to the first character after the specifier 230 * if successful. 231 * @param str String to match. 232 * @param flags Flags modifying the behavior (see fnmatch()). 233 * @return INVALID_PATTERN if the pattern doesn't start with a valid class 234 * specifier, 0 if the beginning of the matched string doesn't belong 235 * to the class, or positive number of characters matched. 213 236 */ 214 237 static int _match_char_class(const char **pattern, const char *str, int flags) … … 225 248 /************** END CHARACTER CLASSES ****************/ 226 249 227 /** 250 /** Reads the next collating element in the pattern, taking into account 251 * locale (if supported) and flags (see fnmatch()). 228 252 * 229 * @param pattern 230 * @param flags 231 * @return 232 */ 233 static _coll_elm_t _next_coll_elm(const char **pattern, int flags) 234 { 253 * @param pattern Pattern. 254 * @param flags Flags given to fnmatch(). 255 * @return Collating element on success, 256 * or COLL_ELM_INVALID if the pattern is invalid. 257 */ 258 static coll_elm_t _next_coll_elm(const char **pattern, int flags) 259 { 260 assert(pattern != NULL); 261 assert(*pattern != NULL); 262 assert(**pattern != '\0'); 263 235 264 const char *p = *pattern; 236 265 const bool noescape = (flags & FNM_NOESCAPE) != 0; … … 257 286 if (!noescape && *p == '\\') { 258 287 p++; 288 if (*p == '\0') { 289 *pattern = p; 290 return COLL_ELM_INVALID; 291 } 259 292 } 260 293 if (pathname && *p == '/') { 261 294 return COLL_ELM_INVALID; 262 295 } 263 296 264 297 *pattern = p + 1; 265 298 return _coll_elm_char(*p); 266 299 } 267 300 268 /** 301 /** Matches the beginning of the given string against a bracket expression 302 * the pattern begins with. 269 303 * 270 * @param pattern 271 * @param str 272 * @param flags 273 * @return 304 * @param pattern Pointer to the beginning of a bracket expression in a pattern. 305 * On success, the pointer is moved to the first character after the 306 * bracket expression. 307 * @param str Unmatched part of the string. 308 * @param flags Flags given to fnmatch(). 309 * @return INVALID_PATTERN if the pattern is invalid, 0 if there is no match 310 * or the number of matched characters on success. 274 311 */ 275 312 static int _match_bracket_expr(const char **pattern, const char *str, int flags) … … 315 352 } 316 353 317 _coll_elm_t current_elm = COLL_ELM_INVALID;354 coll_elm_t current_elm = COLL_ELM_INVALID; 318 355 319 356 while (*p != ']') { … … 322 359 /* Range expression. */ 323 360 p++; 324 _coll_elm_t end_elm = _next_coll_elm(&p, flags);361 coll_elm_t end_elm = _next_coll_elm(&p, flags); 325 362 if (end_elm == COLL_ELM_INVALID) { 326 363 return INVALID_PATTERN; … … 357 394 } 358 395 359 /** 396 /** Matches a portion of the pattern containing no asterisks (*) against 397 * the given string. 360 398 * 361 * @param pattern 362 * @param string 363 * @param flags 364 * @return 399 * @param pattern Pointer to the unmatched portion of the pattern. 400 * On success, the pointer is moved to the first asterisk, or to the 401 * terminating nul character, whichever occurs first. 402 * @param string Pointer to the input string. On success, the pointer is moved 403 * to the first character that wasn't explicitly matched. 404 * @param flags Flags given to fnmatch(). 405 * @return True if the entire subpattern matched. False otherwise. 365 406 */ 366 407 static bool _partial_match(const char **pattern, const char **string, int flags) … … 456 497 } 457 498 458 /** 499 /** Match string against a pattern. 459 500 * 460 * @param pattern 461 * @param string 462 * @param flags 463 * @return 501 * @param pattern Pattern. 502 * @param string String to match. 503 * @param flags Flags given to fnmatch(). 504 * @return True if the string matched the pattern, false otherwise. 464 505 */ 465 506 static bool _full_match(const char *pattern, const char *string, int flags) … … 496 537 end = string; 497 538 } else { 498 end = strchrnul(string, pathname ? '/' : '\0');539 end = strchrnul(string, pathname ? '/' : '\0'); 499 540 } 500 541 … … 518 559 } 519 560 520 /** 561 /** Transform the entire string to lowercase. 521 562 * 522 * @param s 523 * @return 563 * @param s Input string. 564 * @return Newly allocated copy of the input string with all uppercase 565 * characters folded to their lowercase variants. 524 566 */ 525 567 static char *_casefold(const char *s) -
uspace/lib/posix/locale.c
re898296d r3e01316f 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 { … … 75 79 }; 76 80 77 /** 81 /** Set program locale. 78 82 * 79 * @param category 80 * @param locale 81 * @return 83 * @param category What category to set. 84 * @param locale Locale name. 85 * @return Original locale name on success, NULL on failure. 82 86 */ 83 87 char *posix_setlocale(int category, const char *locale) … … 91 95 } 92 96 93 /** 97 /** Return locale-specific information. 94 98 * 95 * @return 99 * @return Information about the current locale. 96 100 */ 97 101 struct posix_lconv *posix_localeconv(void) … … 101 105 } 102 106 103 /** 107 /** Duplicate locale object. 104 108 * 105 * @param locobj 106 * @return 109 * @param locobj Object to duplicate. 110 * @return Duplicated object. 107 111 */ 108 112 posix_locale_t posix_duplocale(posix_locale_t locobj) … … 121 125 } 122 126 123 /** 127 /** Free locale object. 124 128 * 125 * @param locobj 129 * @param locobj Object to free. 126 130 */ 127 131 void posix_freelocale(posix_locale_t locobj) … … 132 136 } 133 137 134 /** 138 /** Create or modify a locale object. 135 139 * 136 * @param category_mask 137 * @param locale 138 * @param base 139 * @return 140 * @param category_mask Mask of categories to be set or modified. 141 * @param locale Locale to be used. 142 * @param base Object to modify. 0 if new object is to be created. 143 * @return The new/modified locale object. 140 144 */ 141 145 posix_locale_t posix_newlocale(int category_mask, const char *locale, … … 159 163 } 160 164 161 /** 165 /** Set locale for the current thread. 162 166 * 163 * @param newloc 164 * @return 167 * @param newloc Locale to use. 168 * @return The previously set locale or LC_GLOBAL_LOCALE 165 169 */ 166 170 posix_locale_t posix_uselocale(posix_locale_t newloc) 167 171 { 168 172 // TODO 169 return NULL;173 return LC_GLOBAL_LOCALE; 170 174 } 171 175 -
uspace/lib/posix/locale.h
re898296d r3e01316f 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
re898296d r3e01316f 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, … … 126 136 } 127 137 128 /** 138 /** Just an empty function to get an unique pointer value for comparison. 129 139 * 130 140 * @param signo … … 135 145 } 136 146 137 /** 147 /** Empty function to be used as ignoring handler. 138 148 * 139 149 * @param signo … … 144 154 } 145 155 146 /** 147 * 148 * @param set 149 * @return 156 /** Clear the signal set. 157 * 158 * @param set Pointer to the signal set. 159 * @return Always returns zero. 150 160 */ 151 161 int posix_sigemptyset(posix_sigset_t *set) … … 157 167 } 158 168 159 /** 160 * 161 * @param set 162 * @return 169 /** Fill the signal set (i.e. add all signals). 170 * 171 * @param set Pointer to the signal set. 172 * @return Always returns zero. 163 173 */ 164 174 int posix_sigfillset(posix_sigset_t *set) … … 170 180 } 171 181 172 /** 173 * 174 * @param set 175 * @param signo 176 * @return 182 /** Add a signal to the set. 183 * 184 * @param set Pointer to the signal set. 185 * @param signo Signal number to add. 186 * @return Always returns zero. 177 187 */ 178 188 int posix_sigaddset(posix_sigset_t *set, int signo) … … 184 194 } 185 195 186 /** 187 * 188 * @param set 189 * @param signo 190 * @return 196 /** Delete a signal from the set. 197 * 198 * @param set Pointer to the signal set. 199 * @param signo Signal number to remove. 200 * @return Always returns zero. 191 201 */ 192 202 int posix_sigdelset(posix_sigset_t *set, int signo) … … 198 208 } 199 209 200 /** 201 * 202 * @param set 203 * @param signo 204 * @return 210 /** Inclusion test for a signal set. 211 * 212 * @param set Pointer to the signal set. 213 * @param signo Signal number to query. 214 * @return 1 if the signal is in the set, 0 otherwise. 205 215 */ 206 216 int posix_sigismember(const posix_sigset_t *set, int signo) … … 211 221 } 212 222 213 /** 223 /** Unsafe variant of the sigaction() function. 224 * Doesn't do any checking of its arguments and 225 * does not deal with thread-safety. 214 226 * 215 227 * @param sig … … 231 243 } 232 244 233 /** 234 * 235 * @param sig 236 * @param act 237 * @param oact 238 * @return 245 /** Sets a new action for the given signal number. 246 * 247 * @param sig Signal number to set action for. 248 * @param act If not NULL, contents of this structure are 249 * used as the new action for the signal. 250 * @param oact If not NULL, the original action associated with the signal 251 * is stored in the structure pointer to. 252 * @return -1 with errno set on failure, 0 on success. 239 253 */ 240 254 int posix_sigaction(int sig, const struct posix_sigaction *restrict act, … … 252 266 " or fully unsupported signal. This handler may only be" 253 267 " invoked by the raise() function, which may not be what" 254 " the application developer intended .\nSignal name");268 " the application developer intended"); 255 269 } 256 270 … … 262 276 } 263 277 264 /** 265 * 266 * @param sig 267 * @param func 268 * @return 278 /** Sets a new handler for the given signal number. 279 * 280 * @param sig Signal number to set handler for. 281 * @param func Handler function. 282 * @return SIG_ERR on failure, original handler on success. 269 283 */ 270 284 void (*posix_signal(int sig, void (*func)(int)))(int) … … 284 298 } 285 299 286 /** 287 * 288 * @param signo 289 * @param siginfo 290 * @return 291 */ 292 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo) 300 typedef struct { 301 link_t link; 302 int signo; 303 posix_siginfo_t siginfo; 304 } signal_queue_item; 305 306 /** Queue blocked signal. 307 * 308 * @param signo Signal number. 309 * @param siginfo Additional information about the signal. 310 */ 311 static void _queue_signal(int signo, posix_siginfo_t *siginfo) 293 312 { 294 313 assert(signo >= 0 && signo <= _TOP_SIGNAL); 295 314 assert(siginfo != NULL); 315 316 signal_queue_item *item = malloc(sizeof(signal_queue_item)); 317 link_initialize(&(item->link)); 318 item->signo = signo; 319 memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t)); 320 list_append(&(item->link), &_signal_queue); 321 } 322 323 324 /** Executes an action associated with the given signal. 325 * 326 * @param signo Signal number. 327 * @param siginfo Additional information about the circumstances of this raise. 328 * @return 0 if the action has been successfully executed. -1 if the signal is 329 * blocked. 330 */ 331 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo) 332 { 333 assert(signo >= 0 && signo <= _TOP_SIGNAL); 334 assert(siginfo != NULL); 296 335 297 336 fibril_mutex_lock(&_signal_mutex); … … 301 340 if (posix_sigismember(&_signal_mask, signo) || 302 341 action.sa_handler == SIG_HOLD) { 303 // TODO: queue signal342 _queue_signal(signo, siginfo); 304 343 fibril_mutex_unlock(&_signal_mutex); 305 344 return -1; … … 312 351 if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) { 313 352 _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER; 314 } ;353 } 315 354 316 355 if (action.sa_flags & SA_SIGINFO) { … … 327 366 } 328 367 329 /** 330 * 331 * @param sig 332 * @return 368 /** Raise all unblocked previously queued signals. 369 */ 370 static void _dequeue_unblocked_signals() 371 { 372 link_t *iterator = _signal_queue.head.next; 373 link_t *next; 374 375 while (iterator != &(_signal_queue).head) { 376 next = iterator->next; 377 378 signal_queue_item *item = 379 list_get_instance(iterator, signal_queue_item, link); 380 381 if (!posix_sigismember(&_signal_mask, item->signo) && 382 _signal_actions[item->signo].sa_handler != SIG_HOLD) { 383 list_remove(&(item->link)); 384 _raise_sigaction(item->signo, &(item->siginfo)); 385 free(item); 386 } 387 388 iterator = next; 389 } 390 } 391 392 /** Raise a signal for the calling process. 393 * 394 * @param sig Signal number. 395 * @return -1 with errno set on failure, 0 on success. 333 396 */ 334 397 int posix_raise(int sig) … … 346 409 } 347 410 348 /** 349 * 350 * @param pid 351 * @param signo 352 * @return 411 /** Raises a signal for a selected process. 412 * 413 * @param pid PID of the process for which the signal shall be raised. 414 * @param signo Signal to raise. 415 * @return -1 with errno set on failure (possible errors include unsupported 416 * action, invalid signal number, lack of permissions, etc.), 0 on success. 353 417 */ 354 418 int posix_kill(posix_pid_t pid, int signo) … … 360 424 } 361 425 426 if (signo > _TOP_SIGNAL) { 427 errno = EINVAL; 428 return -1; 429 } 430 362 431 if (pid == (posix_pid_t) task_get_id()) { 363 432 return posix_raise(signo); 364 }365 366 if (pid > _TOP_SIGNAL) {367 errno = EINVAL;368 return -1;369 433 } 370 434 … … 382 446 } 383 447 384 /** 385 * 386 * @param pid 387 * @param sig 388 * @return 448 /** Send a signal to a process group. Always fails at the moment because of 449 * lack of this functionality in HelenOS. 450 * 451 * @param pid PID of the process group. 452 * @param sig Signal number. 453 * @return -1 on failure, 0 on success (see kill()). 389 454 */ 390 455 int posix_killpg(posix_pid_t pid, int sig) … … 394 459 } 395 460 396 /** 397 * 398 * @param pinfo 399 * @param message 461 /** Outputs information about the signal to the standard error stream. 462 * 463 * @param pinfo SigInfo struct to write. 464 * @param message String to output alongside human-readable signal description. 400 465 */ 401 466 void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message) … … 406 471 } 407 472 408 /** 409 * 410 * @param signum 411 * @param message 473 /** Outputs information about the signal to the standard error stream. 474 * 475 * @param signum Signal number. 476 * @param message String to output alongside human-readable signal description. 412 477 */ 413 478 void posix_psignal(int signum, const char *message) … … 421 486 } 422 487 423 /** 424 * 425 * @param how 426 * @param set 427 * @param oset 428 * @return 488 /** Manipulate the signal mask of the calling thread. 489 * 490 * @param how What to do with the mask. 491 * @param set Signal set to work with. 492 * @param oset If not NULL, the original signal mask is coppied here. 493 * @return 0 success, errorcode on failure. 429 494 */ 430 495 int posix_thread_sigmask(int how, const posix_sigset_t *restrict set, … … 452 517 } 453 518 } 454 455 // TODO: queued signal handling519 520 _dequeue_unblocked_signals(); 456 521 457 522 fibril_mutex_unlock(&_signal_mutex); … … 460 525 } 461 526 462 /** 463 * 464 * @param how 465 * @param set 466 * @param oset 467 * @return 527 /** Manipulate the signal mask of the process. 528 * 529 * @param how What to do with the mask. 530 * @param set Signal set to work with. 531 * @param oset If not NULL, the original signal mask is coppied here. 532 * @return 0 on success, -1 with errno set on failure. 468 533 */ 469 534 int posix_sigprocmask(int how, const posix_sigset_t *restrict set, -
uspace/lib/posix/signal.h
re898296d r3e01316f 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/stdio.c
re898296d r3e01316f 44 44 #include "assert.h" 45 45 #include "errno.h" 46 #include "stdlib.h" 46 47 #include "string.h" 47 48 #include "sys/types.h" 49 #include "unistd.h" 48 50 49 51 #include "libc/io/printf_core.h" … … 255 257 assert(stream != NULL); 256 258 257 /* Ret ieve the node. */259 /* Retrieve the node. */ 258 260 struct stat st; 259 261 int rc; … … 263 265 } else { 264 266 rc = stat(filename, &st); 267 if (-rc == ENOENT) { 268 /* file does not exist, create new file */ 269 FILE* tmp = fopen(filename, mode); 270 if (tmp != NULL) { 271 fclose(tmp); 272 /* try again */ 273 rc = stat(filename, &st); 274 } 275 } 265 276 } 266 277 … … 273 284 fdi_node_t node = { 274 285 .fs_handle = st.fs_handle, 275 . devmap_handle = st.devmap_handle,286 .service_id = st.service_id, 276 287 .index = st.index 277 288 }; … … 306 317 307 318 return stream; 308 }309 310 /**311 *312 * @param buf313 * @param size314 * @param mode315 * @return316 */317 FILE *posix_fmemopen(void *restrict buf, size_t size,318 const char *restrict mode)319 {320 // TODO321 not_implemented();322 }323 324 /**325 *326 * @param bufp327 * @param sizep328 * @return329 */330 FILE *posix_open_memstream(char **bufp, size_t *sizep)331 {332 // TODO333 not_implemented();334 319 } 335 320 … … 724 709 * Rename a file or directory. 725 710 * 726 * @param old 727 * @param new 711 * @param old Old pathname. 712 * @param new New pathname. 728 713 * @return Zero on success, -1 (with errno set) otherwise. 729 714 */ … … 734 719 735 720 /** 736 * 737 * @param s 738 * @return 721 * Get a unique temporary file name (obsolete). 722 * 723 * @param s Buffer for the file name. Must be at least L_tmpnam bytes long. 724 * @return The value of s on success, NULL on failure. 739 725 */ 740 726 char *posix_tmpnam(char *s) 741 727 { 742 // TODO: low priority, just a compile-time dependency of binutils 743 not_implemented(); 728 assert(L_tmpnam >= posix_strlen("/tmp/tnXXXXXX")); 729 730 static char buffer[L_tmpnam + 1]; 731 if (s == NULL) { 732 s = buffer; 733 } 734 735 posix_strcpy(s, "/tmp/tnXXXXXX"); 736 posix_mktemp(s); 737 738 if (*s == '\0') { 739 /* Errno set by mktemp(). */ 740 return NULL; 741 } 742 743 return s; 744 } 745 746 /** 747 * Get an unique temporary file name with additional constraints (obsolete). 748 * 749 * @param dir Path to directory, where the file should be created. 750 * @param pfx Optional prefix up to 5 characters long. 751 * @return Newly allocated unique path for temporary file. NULL on failure. 752 */ 753 char *posix_tempnam(const char *dir, const char *pfx) 754 { 755 /* Sequence number of the filename. */ 756 static int seq = 0; 757 758 size_t dir_len = posix_strlen(dir); 759 if (dir[dir_len - 1] == '/') { 760 dir_len--; 761 } 762 763 size_t pfx_len = posix_strlen(pfx); 764 if (pfx_len > 5) { 765 pfx_len = 5; 766 } 767 768 char *result = malloc(dir_len + /* slash*/ 1 + 769 pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1); 770 771 if (result == NULL) { 772 errno = ENOMEM; 773 return NULL; 774 } 775 776 char *res_ptr = result; 777 posix_strncpy(res_ptr, dir, dir_len); 778 res_ptr += dir_len; 779 posix_strncpy(res_ptr, pfx, pfx_len); 780 res_ptr += pfx_len; 781 782 for (; seq < 1000; ++seq) { 783 snprintf(res_ptr, 8, "%03d.tmp", seq); 784 785 int orig_errno = errno; 786 errno = 0; 787 /* Check if the file exists. */ 788 if (posix_access(result, F_OK) == -1) { 789 if (errno == ENOENT) { 790 errno = orig_errno; 791 break; 792 } else { 793 /* errno set by access() */ 794 return NULL; 795 } 796 } 797 } 798 799 if (seq == 1000) { 800 free(result); 801 errno = EINVAL; 802 return NULL; 803 } 804 805 return result; 806 } 807 808 /** 809 * Create and open an unique temporary file. 810 * The file is automatically removed when the stream is closed. 811 * 812 * @param dir Path to directory, where the file should be created. 813 * @param pfx Optional prefix up to 5 characters long. 814 * @return Newly allocated unique path for temporary file. NULL on failure. 815 */ 816 FILE *posix_tmpfile(void) 817 { 818 char filename[] = "/tmp/tfXXXXXX"; 819 int fd = posix_mkstemp(filename); 820 if (fd == -1) { 821 /* errno set by mkstemp(). */ 822 return NULL; 823 } 824 825 /* Unlink the created file, so that it's removed on close(). */ 826 posix_unlink(filename); 827 return fdopen(fd, "w+"); 744 828 } 745 829 -
uspace/lib/posix/stdio.h
re898296d r3e01316f 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 */ … … 123 120 #define L_tmpnam PATH_MAX 124 121 extern char *posix_tmpnam(char *s); 122 extern char *posix_tempnam(const char *dir, const char *pfx); 123 extern FILE *posix_tmpfile(void); 125 124 126 125 #ifndef LIBPOSIX_INTERNAL 126 /* DEBUG macro does not belong to POSIX stdio.h. Its unconditional 127 * definition in the native stdio.h causes unexpected behaviour of 128 * applications which uses their own DEBUG macro (e.g. debugging 129 * output is printed even if not desirable). */ 130 #undef DEBUG 131 127 132 #define ctermid posix_ctermid 128 133 … … 176 181 177 182 #define tmpnam posix_tmpnam 183 #define tempnam posix_tempnam 184 #define tmpfile posix_tmpfile 178 185 #endif 179 186 -
uspace/lib/posix/stdlib.c
re898296d r3e01316f 40 40 41 41 #include "errno.h" 42 #include "fcntl.h" 42 43 #include "limits.h" 44 #include "string.h" 45 #include "sys/stat.h" 46 #include "unistd.h" 43 47 44 48 #include "libc/sort.h" 45 49 #include "libc/str.h" 46 50 #include "libc/vfs/vfs.h" 51 #include "libc/stats.h" 47 52 48 53 /** … … 385 390 386 391 /** 387 * 388 * @param tmpl 389 * @return 392 * Creates and opens an unique temporary file from template. 393 * 394 * @param tmpl Template. Last six characters must be XXXXXX. 395 * @return The opened file descriptor or -1 on error. 396 */ 397 int posix_mkstemp(char *tmpl) 398 { 399 int fd = -1; 400 401 char *tptr = tmpl + posix_strlen(tmpl) - 6; 402 403 while (fd < 0) { 404 if (*posix_mktemp(tmpl) == '\0') { 405 /* Errno set by mktemp(). */ 406 return -1; 407 } 408 409 fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); 410 411 if (fd == -1) { 412 /* Restore template to it's original state. */ 413 snprintf(tptr, 7, "XXXXXX"); 414 } 415 } 416 417 return fd; 418 } 419 420 /** 421 * Creates an unique temporary file name from template. 422 * 423 * @param tmpl Template. Last six characters must be XXXXXX. 424 * @return The value of tmpl. The template is modified in place. 425 * If no temporary file name can be created, template is 426 * reduced to an empty string. 390 427 */ 391 428 char *posix_mktemp(char *tmpl) 392 429 { 393 // TODO: low priority, just a compile-time dependency of binutils 394 not_implemented(); 430 int tmpl_len = posix_strlen(tmpl); 431 if (tmpl_len < 6) { 432 errno = EINVAL; 433 *tmpl = '\0'; 434 return tmpl; 435 } 436 437 char *tptr = tmpl + tmpl_len - 6; 438 if (posix_strcmp(tptr, "XXXXXX") != 0) { 439 errno = EINVAL; 440 *tmpl = '\0'; 441 return tmpl; 442 } 443 444 static int seq = 0; 445 446 for (; seq < 1000000; ++seq) { 447 snprintf(tptr, 7, "%06d", seq); 448 449 int orig_errno = errno; 450 errno = 0; 451 /* Check if the file exists. */ 452 if (posix_access(tmpl, F_OK) == -1) { 453 if (errno == ENOENT) { 454 errno = orig_errno; 455 break; 456 } else { 457 /* errno set by access() */ 458 *tmpl = '\0'; 459 return tmpl; 460 } 461 } 462 } 463 464 if (seq == 10000000) { 465 errno = EEXIST; 466 *tmpl = '\0'; 467 return tmpl; 468 } 469 470 return tmpl; 395 471 } 396 472 397 473 /** 398 474 * Get system load average statistics. 399 *400 * Not supported. Always returns -1.401 475 * 402 476 * @param loadavg Array where the load averages shall be placed. … … 406 480 int bsd_getloadavg(double loadavg[], int nelem) 407 481 { 408 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; 409 501 } 410 502 -
uspace/lib/posix/stdlib.h
re898296d r3e01316f 113 113 extern void posix_free(void *ptr); 114 114 115 /* Temporary Files */ 116 extern int posix_mkstemp(char *tmpl); 117 115 118 /* Legacy Declarations */ 116 119 extern char *posix_mktemp(char *tmpl); … … 158 161 #define free posix_free 159 162 163 #define mkstemp posix_mkstemp 164 160 165 #define mktemp posix_mktemp 161 166 #define getloadavg bsd_getloadavg -
uspace/lib/posix/stdlib/strtold.c
re898296d r3e01316f 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
re898296d r3e01316f 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/sys/stat.c
re898296d r3e01316f 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/sys/wait.c
re898296d r3e01316f 67 67 68 68 /** 69 * Wait for any child process to stop or terminate. 69 70 * 70 * @param stat_ptr 71 * @return 71 * @param stat_ptr Location of the final status code of the child process. 72 * @return ID of the child process for which status is reported, 73 * -1 on signal interrupt, (pid_t)-1 otherwise. 72 74 */ 73 75 posix_pid_t posix_wait(int *stat_ptr) … … 79 81 80 82 /** 83 * Wait for a child process to stop or terminate. 81 84 * 82 * @param pid 83 * @param stat_ptr 84 * @param options 85 * @return 85 * @param pid What child process shall the caller wait for. See POSIX manual 86 * for details. 87 * @param stat_ptr Location of the final status code of the child process. 88 * @param options Constraints of the waiting. See POSIX manual for details. 89 * @return ID of the child process for which status is reported, 90 * -1 on signal interrupt, 0 if non-blocking wait is requested but there is 91 * no child process whose status can be reported, (pid_t)-1 otherwise. 86 92 */ 87 93 posix_pid_t posix_waitpid(posix_pid_t pid, int *stat_ptr, int options) -
uspace/lib/posix/time.c
re898296d r3e01316f 54 54 // TODO: test everything in this file 55 55 56 /* In some places in this file, phrase "normalized broken-down time" is used. 57 * This means time broken down to components (year, month, day, hour, min, sec), 58 * in which every component is in its proper bounds. Non-normalized time could 59 * e.g. be 2011-54-5 29:13:-5, which would semantically mean start of year 2011 60 * + 53 months + 4 days + 29 hours + 13 minutes - 5 seconds. 61 */ 62 63 64 56 65 /* Helper functions ***********************************************************/ 57 66 … … 63 72 #define SECS_PER_DAY (SECS_PER_HOUR * HOURS_PER_DAY) 64 73 65 /** 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) … … 81 90 } 82 91 83 /** 84 * 85 * @param year 86 * @param mon 87 * @return 92 /** Returns how many days there are in the given month of the given year. 93 * Note that year is only taken into account if month is February. 94 * 95 * @param year Year since 1900 (can be negative). 96 * @param mon Month of the year. 0 for January, 11 for December. 97 * @return Number of days in the specified month. 88 98 */ 89 99 static int _days_in_month(time_t year, time_t mon) 90 100 { 91 101 assert(mon >= 0 && mon <= 11); 92 year += 1900;93 102 94 103 static int month_days[] = … … 96 105 97 106 if (mon == 1) { 107 year += 1900; 98 108 /* february */ 99 109 return _is_leap_year(year) ? 29 : 28; … … 103 113 } 104 114 105 /** 106 * 107 * @param year 108 * @param mon 109 * @param mday 110 * @return 115 /** For specified year, month and day of month, returns which day of that year 116 * it is. 117 * 118 * For example, given date 2011-01-03, the corresponding expression is: 119 * _day_of_year(111, 0, 3) == 2 120 * 121 * @param year Year (year 1900 = 0, can be negative). 122 * @param mon Month (January = 0). 123 * @param mday Day of month (First day is 1). 124 * @return Day of year (First day is 0). 111 125 */ 112 126 static int _day_of_year(time_t year, time_t mon, time_t mday) … … 120 134 } 121 135 122 /** 123 * Integer division that rounds to negative infinity.136 /** Integer division that rounds to negative infinity. 137 * Used by some functions in this file. 124 138 * 125 139 * @param op1 … … 136 150 } 137 151 138 /** 139 * Modulo that rounds to negative infinity.152 /** Modulo that rounds to negative infinity. 153 * Used by some functions in this file. 140 154 * 141 155 * @param op1 … … 160 174 } 161 175 162 /** 163 * 164 * @param year 165 * @param mon 166 * @param mday 167 * @return 176 /** Number of days since the Epoch. 177 * Epoch is 1970-01-01, which is also equal to day 0. 178 * 179 * @param year Year (year 1900 = 0, may be negative). 180 * @param mon Month (January = 0). 181 * @param mday Day of month (first day = 1). 182 * @return Number of days since the Epoch. 168 183 */ 169 184 static time_t _days_since_epoch(time_t year, time_t mon, time_t mday) … … 174 189 } 175 190 176 /** 177 * Assumes normalized broken-down time. 178 * 179 * @param tm 180 * @return 191 /** Seconds since the Epoch. see also _days_since_epoch(). 192 * 193 * @param tm Normalized broken-down time. 194 * @return Number of seconds since the epoch, not counting leap seconds. 181 195 */ 182 196 static time_t _secs_since_epoch(const struct posix_tm *tm) … … 187 201 } 188 202 189 /** 190 * 191 * @param year 192 * @param mon 193 * @param mday 194 * @return 203 /** Which day of week the specified date is. 204 * 205 * @param year Year (year 1900 = 0). 206 * @param mon Month (January = 0). 207 * @param mday Day of month (first = 1). 208 * @return Day of week (Sunday = 0). 195 209 */ 196 210 static int _day_of_week(time_t year, time_t mon, time_t mday) 197 211 { 198 212 /* 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) 213 return _floor_mod((_days_since_epoch(year, mon, mday) + 4), 7); 214 } 215 216 /** Normalizes the broken-down time and optionally adds specified amount of 217 * seconds. 218 * 219 * @param tm Broken-down time to normalize. 220 * @param sec_add Seconds to add. 221 * @return 0 on success, -1 on overflow 222 */ 223 static int _normalize_time(struct posix_tm *tm, time_t sec_add) 260 224 { 261 225 // TODO: DST correction 262 226 227 /* Set initial values. */ 228 time_t sec = tm->tm_sec + sec_add; 229 time_t min = tm->tm_min; 230 time_t hour = tm->tm_hour; 231 time_t day = tm->tm_mday - 1; 232 time_t mon = tm->tm_mon; 233 time_t year = tm->tm_year; 234 263 235 /* 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);236 min += _floor_div(sec, SECS_PER_MIN); 237 sec = _floor_mod(sec, SECS_PER_MIN); 238 hour += _floor_div(min, MINS_PER_HOUR); 239 min = _floor_mod(min, MINS_PER_HOUR); 240 day += _floor_div(hour, HOURS_PER_DAY); 241 hour = _floor_mod(hour, HOURS_PER_DAY); 270 242 271 243 /* Adjust month. */ 272 tm->tm_year += _floor_div(tm->tm_mon, 12);273 tm->tm_mon = _floor_mod(tm->tm_mon, 12);244 year += _floor_div(mon, 12); 245 mon = _floor_mod(mon, 12); 274 246 275 247 /* 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--; 248 249 /* First, deal with whole cycles of 400 years = 146097 days. */ 250 year += _floor_div(day, 146097) * 400; 251 day = _floor_mod(day, 146097); 252 253 /* Then, go in one year steps. */ 254 if (mon <= 1) { 255 /* January and February. */ 256 while (day > 365) { 257 day -= _is_leap_year(year) ? 366 : 365; 258 year++; 284 259 } 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++; 260 } else { 261 /* Rest of the year. */ 262 while (day > 365) { 263 day -= _is_leap_year(year + 1) ? 366 : 365; 264 year++; 296 265 } 297 266 } 298 267 268 /* Finally, finish it off month per month. */ 269 while (day >= _days_in_month(year, mon)) { 270 day -= _days_in_month(year, mon); 271 mon++; 272 if (mon >= 12) { 273 mon -= 12; 274 year++; 275 } 276 } 277 299 278 /* 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. 306 * E.g. if the year starts on December 31st, the return value is -1. 307 * 308 * @param year 309 * @return 279 tm->tm_yday = _day_of_year(year, mon, day + 1); 280 tm->tm_wday = _day_of_week(year, mon, day + 1); 281 282 /* And put the values back to the struct. */ 283 tm->tm_sec = (int) sec; 284 tm->tm_min = (int) min; 285 tm->tm_hour = (int) hour; 286 tm->tm_mday = (int) day + 1; 287 tm->tm_mon = (int) mon; 288 289 /* Casts to work around libc brain-damage. */ 290 if (year > ((int)INT_MAX) || year < ((int)INT_MIN)) { 291 tm->tm_year = (year < 0) ? ((int)INT_MIN) : ((int)INT_MAX); 292 return -1; 293 } 294 295 tm->tm_year = (int) year; 296 return 0; 297 } 298 299 /** Which day the week-based year starts on, relative to the first calendar day. 300 * E.g. if the year starts on December 31st, the return value is -1. 301 * 302 * @param Year since 1900. 303 * @return Offset of week-based year relative to calendar year. 310 304 */ 311 305 static int _wbyear_offset(int year) … … 315 309 } 316 310 317 /** 318 * Returns week-based year of the specified time. 319 * Assumes normalized broken-down time. 320 * 321 * @param tm 322 * @return 311 /** Returns week-based year of the specified time. 312 * 313 * @param tm Normalized broken-down time. 314 * @return Week-based year. 323 315 */ 324 316 static int _wbyear(const struct posix_tm *tm) … … 329 321 return tm->tm_year - 1; 330 322 } 331 if (day > 364 + _is_leap_year(tm->tm_year)) {323 if (day > 364 + _is_leap_year(tm->tm_year)) { 332 324 /* First week of next year. */ 333 325 return tm->tm_year + 1; … … 337 329 } 338 330 339 /** 340 * Week number of the year, assuming weeks start on sunday. 341 * The first Sunday of January is the first day of week 1; 342 * days in the new year before this are in week 0. 331 /** Week number of the year, assuming weeks start on sunday. 332 * The first Sunday of January is the first day of week 1; 333 * days in the new year before this are in week 0. 343 334 * 344 335 * @param tm Normalized broken-down time. … … 351 342 } 352 343 353 /** 354 * Week number of the year, assuming weeks start on monday. 355 * If the week containing January 1st has four or more days in the new year, 356 * then it is considered week 1. Otherwise, it is the last week of the previous 357 * year, and the next week is week 1. Both January 4th and the first Thursday 358 * of January are always in week 1. 344 /** Week number of the year, assuming weeks start on monday. 345 * If the week containing January 1st has four or more days in the new year, 346 * then it is considered week 1. Otherwise, it is the last week of the previous 347 * year, and the next week is week 1. Both January 4th and the first Thursday 348 * of January are always in week 1. 359 349 * 360 350 * @param tm Normalized broken-down time. … … 368 358 return 53; 369 359 } 370 if (day > 364 + _is_leap_year(tm->tm_year)) {360 if (day > 364 + _is_leap_year(tm->tm_year)) { 371 361 /* First week of next year. */ 372 362 return 1; … … 376 366 } 377 367 378 /** 379 * Week number of the year, assuming weeks start on monday. 380 * The first Monday of January is the first day of week 1; 381 * days in the new year before this are in week 0. 368 /** Week number of the year, assuming weeks start on monday. 369 * The first Monday of January is the first day of week 1; 370 * days in the new year before this are in week 0. 382 371 * 383 372 * @param tm Normalized broken-down time. … … 396 385 char *posix_tzname[2]; 397 386 398 /** 387 /** Set timezone conversion information. 399 388 * 400 389 */ … … 408 397 } 409 398 410 /** 399 /** Calculate the difference between two times, in seconds. 411 400 * 412 401 * @param time1 413 402 * @param time0 414 * @return 403 * @return Time in seconds. 415 404 */ 416 405 double posix_difftime(time_t time1, time_t time0) … … 419 408 } 420 409 421 /** 422 * This function first normalizes the provided broken-down time 423 * (moves all values to their proper bounds) and then tries to 424 * calculate the appropriate time_t representation. 410 /** This function first normalizes the provided broken-down time 411 * (moves all values to their proper bounds) and then tries to 412 * calculate the appropriate time_t representation. 425 413 * 426 414 * @param tm Broken-down time. … … 432 420 // TODO: detect overflow 433 421 434 struct _long_tm ltm; 435 _posix_to_long_tm(<m, tm); 436 _normalize_time(<m); 437 _long_to_posix_tm(tm, <m); 438 422 _normalize_time(tm, 0); 439 423 return _secs_since_epoch(tm); 440 424 } 441 425 442 /** 443 * 444 * @param timer 445 * @return 426 /** Converts a time value to a broken-down UTC time. 427 * 428 * @param timer Time to convert. 429 * @return Normalized broken-down time in UTC, NULL on overflow. 446 430 */ 447 431 struct posix_tm *posix_gmtime(const time_t *timer) 448 432 { 433 assert(timer != NULL); 434 449 435 static struct posix_tm result; 450 436 return posix_gmtime_r(timer, &result); 451 437 } 452 438 453 /** 454 * 455 * @param timer 456 * @param result 457 * @return 439 /** Converts a time value to a broken-down UTC time. 440 * 441 * @param timer Time to convert. 442 * @param result Structure to store the result to. 443 * @return Value of result on success, NULL on overflow. 458 444 */ 459 445 struct posix_tm *posix_gmtime_r(const time_t *restrict timer, … … 463 449 assert(result != NULL); 464 450 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) { 451 /* Set result to epoch. */ 452 result->tm_sec = 0; 453 result->tm_min = 0; 454 result->tm_hour = 0; 455 result->tm_mday = 1; 456 result->tm_mon = 0; 457 result->tm_year = 70; /* 1970 */ 458 459 if (_normalize_time(result, *timer) == -1) { 479 460 errno = EOVERFLOW; 480 461 return NULL; 481 462 } 482 463 483 _long_to_posix_tm(result, <m);484 464 return result; 485 465 } 486 466 487 /** 488 * 489 * @param timer 490 * @return 467 /** Converts a time value to a broken-down local time. 468 * 469 * @param timer Time to convert. 470 * @return Normalized broken-down time in local timezone, NULL on overflow. 491 471 */ 492 472 struct posix_tm *posix_localtime(const time_t *timer) … … 496 476 } 497 477 498 /** 499 * 500 * @param timer 501 * @param result 502 * @return 478 /** Converts a time value to a broken-down local time. 479 * 480 * @param timer Time to convert. 481 * @param result Structure to store the result to. 482 * @return Value of result on success, NULL on overflow. 503 483 */ 504 484 struct posix_tm *posix_localtime_r(const time_t *restrict timer, … … 510 490 } 511 491 512 /** 513 * 514 * @param timeptr 515 * @return 492 /** Converts broken-down time to a string in format 493 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 494 * 495 * @param timeptr Broken-down time structure. 496 * @return Pointer to a statically allocated string. 516 497 */ 517 498 char *posix_asctime(const struct posix_tm *timeptr) … … 521 502 } 522 503 523 /** 524 * 525 * @param timeptr 526 * @param buf 527 * @return 504 /** Converts broken-down time to a string in format 505 * "Sun Jan 1 00:00:00 1970\n". (Obsolete) 506 * 507 * @param timeptr Broken-down time structure. 508 * @param buf Buffer to store string to, must be at least ASCTIME_BUF_LEN 509 * bytes long. 510 * @return Value of buf. 528 511 */ 529 512 char *posix_asctime_r(const struct posix_tm *restrict timeptr, … … 551 534 } 552 535 553 /** 554 * 555 * @param timer 556 * @return 536 /** Equivalent to asctime(localtime(clock)). 537 * 538 * @param timer Time to convert. 539 * @return Pointer to a statically allocated string holding the date. 557 540 */ 558 541 char *posix_ctime(const time_t *timer) … … 565 548 } 566 549 567 /** 568 * 569 * @param timer 570 * @param buf 571 * @return 550 /** Reentrant variant of ctime(). 551 * 552 * @param timer Time to convert. 553 * @param buf Buffer to store string to. Must be at least ASCTIME_BUF_LEN 554 * bytes long. 555 * @return Pointer to buf on success, NULL on falure. 572 556 */ 573 557 char *posix_ctime_r(const time_t *timer, char *buf) … … 580 564 } 581 565 582 /** 583 * 584 * @param s 585 * @param maxsize 586 * @param format 587 * @param tm 588 * @return 566 /** Convert time and date to a string, based on a specified format and 567 * current locale. 568 * 569 * @param s Buffer to write string to. 570 * @param maxsize Size of the buffer. 571 * @param format Format of the output. 572 * @param tm Broken-down time to format. 573 * @return Number of bytes written. 589 574 */ 590 575 size_t posix_strftime(char *restrict s, size_t maxsize, 591 576 const char *restrict format, const struct posix_tm *restrict tm) 592 577 { 578 assert(s != NULL); 579 assert(format != NULL); 580 assert(tm != NULL); 581 593 582 // TODO: use locale 594 583 static const char *wday_abbr[] = { … … 766 755 } 767 756 768 /** 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 757 /** Get clock resolution. Only CLOCK_REALTIME is supported. 758 * 759 * @param clock_id Clock ID. 760 * @param res Pointer to the variable where the resolution is to be written. 761 * @return 0 on success, -1 with errno set on failure. 790 762 */ 791 763 int posix_clock_getres(posix_clockid_t clock_id, struct posix_timespec *res) … … 804 776 } 805 777 806 /** 807 * 808 * @param clock_id 809 * @param tp 778 /** Get time. Only CLOCK_REALTIME is supported. 779 * 780 * @param clock_id ID of the clock to query. 781 * @param tp Pointer to the variable where the time is to be written. 810 782 * @return 811 783 */ … … 828 800 } 829 801 830 /** 831 * 832 * @param clock_id 833 * @param tp 834 * @return 802 /** Set time on a specified clock. As HelenOS doesn't support this yet, 803 * this function always fails. 804 * 805 * @param clock_id ID of the clock to set. 806 * @param tp Time to set. 807 * @return 0 on success, -1 with errno on failure. 835 808 */ 836 809 int posix_clock_settime(posix_clockid_t clock_id, … … 852 825 } 853 826 854 /** 855 * 856 * @param clock_id 857 * @param flags 858 * @param rqtp 859 * @param rmtp 860 * @return 827 /** Sleep on a specified clock. 828 * 829 * @param clock_id ID of the clock to sleep on (only CLOCK_REALTIME supported). 830 * @param flags Flags (none supported). 831 * @param rqtp Sleep time. 832 * @param rmtp Remaining time is written here if sleep is interrupted. 833 * @return 0 on success, -1 with errno set on failure. 861 834 */ 862 835 int posix_clock_nanosleep(posix_clockid_t clock_id, int flags, … … 882 855 } 883 856 884 #if 0 885 886 struct __posix_timer { 887 posix_clockid_t clockid; 888 struct posix_sigevent evp; 889 }; 890 891 /** 892 * 893 * @param clockid 894 * @param evp 895 * @param timerid 896 * @return 897 */ 898 int posix_timer_create(posix_clockid_t clockid, 899 struct posix_sigevent *restrict evp, 900 posix_timer_t *restrict timerid) 901 { 902 // TODO 903 not_implemented(); 904 } 905 906 /** 907 * 908 * @param timerid 909 * @return 910 */ 911 int posix_timer_delete(posix_timer_t timerid) 912 { 913 // TODO 914 not_implemented(); 915 } 916 917 /** 918 * 919 * @param timerid 920 * @return 921 */ 922 int posix_timer_getoverrun(posix_timer_t timerid) 923 { 924 // TODO 925 not_implemented(); 926 } 927 928 /** 929 * 930 * @param timerid 931 * @param value 932 * @return 933 */ 934 int posix_timer_gettime(posix_timer_t timerid, 935 struct posix_itimerspec *value) 936 { 937 // TODO 938 not_implemented(); 939 } 940 941 /** 942 * 943 * @param timerid 944 * @param flags 945 * @param value 946 * @param ovalue 947 * @return 948 */ 949 int posix_timer_settime(posix_timer_t timerid, int flags, 950 const struct posix_itimerspec *restrict value, 951 struct posix_itimerspec *restrict ovalue) 952 { 953 // TODO 954 not_implemented(); 955 } 956 957 #endif 958 959 /** 960 * Get CPU time used since the process invocation. 857 /** Get CPU time used since the process invocation. 961 858 * 962 859 * @return Consumed CPU cycles by this process or -1 if not available. -
uspace/lib/posix/time.h
re898296d r3e01316f 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 -
uspace/lib/posix/unistd.c
re898296d r3e01316f 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. */ … … 186 187 * Close a file. 187 188 * 188 * @param fildes 189 * @param fildes File descriptor of the opened file. 189 190 * @return 0 on success, -1 on error. 190 191 */ … … 223 224 * Requests outstanding data to be written to the underlying storage device. 224 225 * 225 * @param fildes 226 * @param fildes File descriptor of the opened file. 227 * @return Zero on success, -1 otherwise. 226 228 */ 227 229 int posix_fsync(int fildes) … … 230 232 } 231 233 234 /** 235 * Truncate a file to a specified length. 236 * 237 * @param fildes File descriptor of the opened file. 238 * @param length New length of the file. 239 * @return Zero on success, -1 otherwise. 240 */ 232 241 int posix_ftruncate(int fildes, posix_off_t length) 233 242 { … … 257 266 } 258 267 268 /** 269 * Duplicate an open file descriptor. 270 * 271 * @param fildes File descriptor to be duplicated. 272 * @return On success, new file descriptor for the same file, otherwise -1. 273 */ 259 274 int posix_dup(int fildes) 260 275 { … … 262 277 } 263 278 279 /** 280 * Duplicate an open file descriptor. 281 * 282 * @param fildes File descriptor to be duplicated. 283 * @param fildes2 File descriptor to be paired with the same file description 284 * as is paired fildes. 285 * @return fildes2 on success, -1 otherwise. 286 */ 264 287 int posix_dup2(int fildes, int fildes2) 265 288 { -
uspace/lib/posix/unistd.h
re898296d r3e01316f 72 72 /* File Manipulation */ 73 73 extern int posix_close(int fildes); 74 75 74 extern ssize_t posix_read(int fildes, void *buf, size_t nbyte); 76 75 extern ssize_t posix_write(int fildes, const void *buf, size_t nbyte); 77 78 76 extern int posix_fsync(int fildes); 79 77 extern int posix_ftruncate(int fildes, posix_off_t length); 80 81 78 extern int posix_rmdir(const char *path); 82 79 extern int posix_unlink(const char *path); 83 84 80 extern int posix_dup(int fildes); 85 81 extern int posix_dup2(int fildes, int fildes2);
Note:
See TracChangeset
for help on using the changeset viewer.
