Changeset 4e6a610 in mainline for uspace/lib/posix/src/stdio.c
- Timestamp:
- 2018-06-25T09:54:28Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- bfe90b6
- Parents:
- fb0ec570
- git-author:
- Jiri Svoboda <jiri@…> (2018-06-24 17:51:54)
- git-committer:
- Jiri Svoboda <jiri@…> (2018-06-25 09:54:28)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/src/stdio.c
rfb0ec570 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" … … 353 357 } 354 358 355 /** 356 * Get a unique temporary file name (obsolete). 357 * 358 * @param s Buffer for the file name. Must be at least L_tmpnam bytes long. 359 * @return The value of s on success, NULL on failure. 360 */ 361 char *tmpnam(char *s) 362 { 363 assert(L_tmpnam >= strlen("/tmp/tnXXXXXX")); 364 365 static char buffer[L_tmpnam + 1]; 366 if (s == NULL) { 367 s = buffer; 368 } 369 370 strcpy(s, "/tmp/tnXXXXXX"); 371 mktemp(s); 372 373 if (*s == '\0') { 374 /* Errno set by mktemp(). */ 375 return NULL; 376 } 377 378 return s; 379 } 380 381 /** 382 * 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. 383 393 * 384 394 * @param dir Path to directory, where the file should be created. … … 388 398 char *tempnam(const char *dir, const char *pfx) 389 399 { 390 /* Sequence number of the filename. */ 391 static int seq = 0; 392 393 size_t dir_len = strlen(dir); 394 if (dir[dir_len - 1] == '/') { 395 dir_len--; 396 } 397 398 size_t pfx_len = strlen(pfx); 399 if (pfx_len > 5) { 400 pfx_len = 5; 401 } 402 403 char *result = malloc(dir_len + /* slash*/ 1 + 404 pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1); 405 406 if (result == NULL) { 407 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); 408 426 return NULL; 409 427 } 410 428 411 char *res_ptr = result; 412 strncpy(res_ptr, dir, dir_len); 413 res_ptr += dir_len; 414 strncpy(res_ptr, pfx, pfx_len); 415 res_ptr += pfx_len; 416 417 for (; seq < 1000; ++seq) { 418 snprintf(res_ptr, 8, "%03d.tmp", seq); 419 420 int orig_errno = errno; 421 errno = EOK; 422 /* Check if the file exists. */ 423 if (access(result, F_OK) == -1) { 424 if (errno == ENOENT) { 425 errno = orig_errno; 426 break; 427 } else { 428 /* errno set by access() */ 429 return NULL; 430 } 431 } 432 } 433 434 if (seq == 1000) { 435 free(result); 436 errno = EINVAL; 437 return NULL; 438 } 439 440 return result; 441 } 442 443 /** 444 * Create and open an unique temporary file. 445 * The file is automatically removed when the stream is closed. 446 * 447 * @param dir Path to directory, where the file should be created. 448 * @param pfx Optional prefix up to 5 characters long. 449 * @return Newly allocated unique path for temporary file. NULL on failure. 450 */ 451 FILE *tmpfile(void) 452 { 453 char filename[] = "/tmp/tfXXXXXX"; 454 int fd = mkstemp(filename); 455 if (fd == -1) { 456 /* errno set by mkstemp(). */ 457 return NULL; 458 } 459 460 /* Unlink the created file, so that it's removed on close(). */ 461 unlink(filename); 462 return fdopen(fd, "w+"); 429 return buf; 463 430 } 464 431
Note:
See TracChangeset
for help on using the changeset viewer.