Changes in uspace/lib/posix/src/stdio.c [7c3fb9b:4e6a610] in mainline
- File:
-
- 1 edited
-
uspace/lib/posix/src/stdio.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/src/stdio.c
r7c3fb9b r4e6a610 2 2 * Copyright (c) 2011 Jiri Zarevucky 3 3 * Copyright (c) 2011 Petr Koupy 4 * Copyright (c) 2018 Jiri Svoboda 4 5 * All rights reserved. 5 6 * … … 38 39 39 40 #include <assert.h> 40 41 41 #include <errno.h> 42 42 #include <stdbool.h> 43 #include <tmpfile.h> 44 45 #include "posix/fcntl.h" 43 46 #include "posix/stdlib.h" 44 47 #include "posix/string.h" 48 #include "posix/sys/stat.h" 45 49 #include "posix/sys/types.h" 46 50 #include "posix/unistd.h" … … 169 173 170 174 /** 171 * Write error messages to standard error.172 *173 * @param s Error message.174 */175 void perror(const char *s)176 {177 if (s == NULL || s[0] == '\0') {178 fprintf(stderr, "%s\n", strerror(errno));179 } else {180 fprintf(stderr, "%s: %s\n", s, strerror(errno));181 }182 }183 184 /** Restores stream a to position previously saved with fgetpos().185 *186 * @param stream Stream to restore187 * @param pos Position to restore188 * @return Zero on success, non-zero (with errno set) on failure189 */190 int fsetpos(FILE *stream, const fpos_t *pos)191 {192 return fseek64(stream, pos->offset, SEEK_SET);193 }194 195 /** Saves the stream's position for later use by fsetpos().196 *197 * @param stream Stream to save198 * @param pos Place to store the position199 * @return Zero on success, non-zero (with errno set) on failure200 */201 int fgetpos(FILE *restrict stream, fpos_t *restrict pos)202 {203 off64_t ret = ftell64(stream);204 if (ret != -1) {205 pos->offset = ret;206 return 0;207 } else {208 return -1;209 }210 }211 212 /**213 175 * Reposition a file-position indicator in a stream. 214 176 * … … 320 282 321 283 /** 322 * Print formatted output to the string.323 *324 * @param s Output string.325 * @param format Format description.326 * @return Either the number of printed characters (excluding null byte) or327 * negative value on error.328 */329 int sprintf(char *s, const char *restrict format, ...)330 {331 va_list list;332 va_start(list, format);333 int result = vsprintf(s, format, list);334 va_end(list);335 return result;336 }337 338 /**339 * Print formatted output to the string.340 *341 * @param s Output string.342 * @param format Format description.343 * @param ap Print arguments.344 * @return Either the number of printed characters (excluding null byte) or345 * negative value on error.346 */347 int vsprintf(char *s, const char *restrict format, va_list ap)348 {349 return vsnprintf(s, INT_MAX, format, ap);350 }351 352 /**353 * Convert formatted input from the stream.354 *355 * @param stream Input stream.356 * @param format Format description.357 * @return The number of converted output items or EOF on failure.358 */359 int fscanf(FILE *restrict stream, const char *restrict format, ...)360 {361 va_list list;362 va_start(list, format);363 int result = vfscanf(stream, format, list);364 va_end(list);365 return result;366 }367 368 /**369 * Convert formatted input from the standard input.370 *371 * @param format Format description.372 * @return The number of converted output items or EOF on failure.373 */374 int scanf(const char *restrict format, ...)375 {376 va_list list;377 va_start(list, format);378 int result = vscanf(format, list);379 va_end(list);380 return result;381 }382 383 /**384 * Convert formatted input from the standard input.385 *386 * @param format Format description.387 * @param arg Output items.388 * @return The number of converted output items or EOF on failure.389 */390 int vscanf(const char *restrict format, va_list arg)391 {392 return vfscanf(stdin, format, arg);393 }394 395 /**396 * Convert formatted input from the string.397 *398 * @param s Input string.399 * @param format Format description.400 * @return The number of converted output items or EOF on failure.401 */402 int sscanf(const char *restrict s, const char *restrict format, ...)403 {404 va_list list;405 va_start(list, format);406 int result = vsscanf(s, format, list);407 va_end(list);408 return result;409 }410 411 /**412 284 * Acquire file stream for the thread. 413 285 * … … 485 357 } 486 358 487 /** 488 * Get a unique temporary file name (obsolete). 489 * 490 * @param s Buffer for the file name. Must be at least L_tmpnam bytes long. 491 * @return The value of s on success, NULL on failure. 492 */ 493 char *tmpnam(char *s) 494 { 495 assert(L_tmpnam >= strlen("/tmp/tnXXXXXX")); 496 497 static char buffer[L_tmpnam + 1]; 498 if (s == NULL) { 499 s = buffer; 500 } 501 502 strcpy(s, "/tmp/tnXXXXXX"); 503 mktemp(s); 504 505 if (*s == '\0') { 506 /* Errno set by mktemp(). */ 507 return NULL; 508 } 509 510 return s; 511 } 512 513 /** 514 * Get an unique temporary file name with additional constraints (obsolete). 359 /** Determine if directory is an 'appropriate' temporary directory. 360 * 361 * @param dir Directory path 362 * @return @c true iff directory is appropriate. 363 */ 364 static bool is_appropriate_tmpdir(const char *dir) 365 { 366 struct stat sbuf; 367 368 /* Must not be NULL */ 369 if (dir == NULL) 370 return false; 371 372 /* Must not be empty */ 373 if (dir[0] == '\0') 374 return false; 375 376 if (stat(dir, &sbuf) != 0) 377 return false; 378 379 /* Must be a directory */ 380 if ((sbuf.st_mode & S_IFMT) != S_IFDIR) 381 return false; 382 383 /* Must be writable */ 384 if (access(dir, W_OK) != 0) 385 return false; 386 387 return true; 388 } 389 390 /** Construct unique file name. 391 * 392 * Never use this function. 515 393 * 516 394 * @param dir Path to directory, where the file should be created. … … 520 398 char *tempnam(const char *dir, const char *pfx) 521 399 { 522 /* Sequence number of the filename. */ 523 static int seq = 0; 524 525 size_t dir_len = strlen(dir); 526 if (dir[dir_len - 1] == '/') { 527 dir_len--; 528 } 529 530 size_t pfx_len = strlen(pfx); 531 if (pfx_len > 5) { 532 pfx_len = 5; 533 } 534 535 char *result = malloc(dir_len + /* slash*/ 1 + 536 pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1); 537 538 if (result == NULL) { 539 errno = ENOMEM; 400 const char *dpref; 401 char *d; 402 char *buf; 403 int rc; 404 405 d = getenv("TMPDIR"); 406 if (is_appropriate_tmpdir(d)) 407 dpref = d; 408 else if (is_appropriate_tmpdir(dir)) 409 dpref = dir; 410 else if (is_appropriate_tmpdir(P_tmpdir)) 411 dpref = P_tmpdir; 412 else 413 dpref = "/"; 414 415 if (dpref[strlen(dpref) - 1] != '/') 416 rc = asprintf(&buf, "%s/%sXXXXXX", dpref, pfx); 417 else 418 rc = asprintf(&buf, "%s%sXXXXXX", dpref, pfx); 419 420 if (rc < 0) 421 return NULL; 422 423 rc = __tmpfile_templ(buf, false); 424 if (rc != 0) { 425 free(buf); 540 426 return NULL; 541 427 } 542 428 543 char *res_ptr = result; 544 strncpy(res_ptr, dir, dir_len); 545 res_ptr += dir_len; 546 strncpy(res_ptr, pfx, pfx_len); 547 res_ptr += pfx_len; 548 549 for (; seq < 1000; ++seq) { 550 snprintf(res_ptr, 8, "%03d.tmp", seq); 551 552 int orig_errno = errno; 553 errno = EOK; 554 /* Check if the file exists. */ 555 if (access(result, F_OK) == -1) { 556 if (errno == ENOENT) { 557 errno = orig_errno; 558 break; 559 } else { 560 /* errno set by access() */ 561 return NULL; 562 } 563 } 564 } 565 566 if (seq == 1000) { 567 free(result); 568 errno = EINVAL; 569 return NULL; 570 } 571 572 return result; 573 } 574 575 /** 576 * Create and open an unique temporary file. 577 * The file is automatically removed when the stream is closed. 578 * 579 * @param dir Path to directory, where the file should be created. 580 * @param pfx Optional prefix up to 5 characters long. 581 * @return Newly allocated unique path for temporary file. NULL on failure. 582 */ 583 FILE *tmpfile(void) 584 { 585 char filename[] = "/tmp/tfXXXXXX"; 586 int fd = mkstemp(filename); 587 if (fd == -1) { 588 /* errno set by mkstemp(). */ 589 return NULL; 590 } 591 592 /* Unlink the created file, so that it's removed on close(). */ 593 unlink(filename); 594 return fdopen(fd, "w+"); 429 return buf; 595 430 } 596 431
Note:
See TracChangeset
for help on using the changeset viewer.
