Changes in uspace/lib/posix/src/stdio.c [5a6c28d1:4e6a610] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/src/stdio.c
r5a6c28d1 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 284 * Acquire file stream for the thread. 354 285 * … … 426 357 } 427 358 428 /** 429 * Get a unique temporary file name (obsolete). 430 * 431 * @param s Buffer for the file name. Must be at least L_tmpnam bytes long. 432 * @return The value of s on success, NULL on failure. 433 */ 434 char *tmpnam(char *s) 435 { 436 assert(L_tmpnam >= strlen("/tmp/tnXXXXXX")); 437 438 static char buffer[L_tmpnam + 1]; 439 if (s == NULL) { 440 s = buffer; 441 } 442 443 strcpy(s, "/tmp/tnXXXXXX"); 444 mktemp(s); 445 446 if (*s == '\0') { 447 /* Errno set by mktemp(). */ 448 return NULL; 449 } 450 451 return s; 452 } 453 454 /** 455 * 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. 456 393 * 457 394 * @param dir Path to directory, where the file should be created. … … 461 398 char *tempnam(const char *dir, const char *pfx) 462 399 { 463 /* Sequence number of the filename. */ 464 static int seq = 0; 465 466 size_t dir_len = strlen(dir); 467 if (dir[dir_len - 1] == '/') { 468 dir_len--; 469 } 470 471 size_t pfx_len = strlen(pfx); 472 if (pfx_len > 5) { 473 pfx_len = 5; 474 } 475 476 char *result = malloc(dir_len + /* slash*/ 1 + 477 pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1); 478 479 if (result == NULL) { 480 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); 481 426 return NULL; 482 427 } 483 428 484 char *res_ptr = result; 485 strncpy(res_ptr, dir, dir_len); 486 res_ptr += dir_len; 487 strncpy(res_ptr, pfx, pfx_len); 488 res_ptr += pfx_len; 489 490 for (; seq < 1000; ++seq) { 491 snprintf(res_ptr, 8, "%03d.tmp", seq); 492 493 int orig_errno = errno; 494 errno = EOK; 495 /* Check if the file exists. */ 496 if (access(result, F_OK) == -1) { 497 if (errno == ENOENT) { 498 errno = orig_errno; 499 break; 500 } else { 501 /* errno set by access() */ 502 return NULL; 503 } 504 } 505 } 506 507 if (seq == 1000) { 508 free(result); 509 errno = EINVAL; 510 return NULL; 511 } 512 513 return result; 514 } 515 516 /** 517 * Create and open an unique temporary file. 518 * The file is automatically removed when the stream is closed. 519 * 520 * @param dir Path to directory, where the file should be created. 521 * @param pfx Optional prefix up to 5 characters long. 522 * @return Newly allocated unique path for temporary file. NULL on failure. 523 */ 524 FILE *tmpfile(void) 525 { 526 char filename[] = "/tmp/tfXXXXXX"; 527 int fd = mkstemp(filename); 528 if (fd == -1) { 529 /* errno set by mkstemp(). */ 530 return NULL; 531 } 532 533 /* Unlink the created file, so that it's removed on close(). */ 534 unlink(filename); 535 return fdopen(fd, "w+"); 429 return buf; 536 430 } 537 431
Note:
See TracChangeset
for help on using the changeset viewer.