Changes in uspace/lib/posix/src/stdio.c [4e6a610:5a6c28d1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/src/stdio.c
r4e6a610 r5a6c28d1 2 2 * Copyright (c) 2011 Jiri Zarevucky 3 3 * Copyright (c) 2011 Petr Koupy 4 * Copyright (c) 2018 Jiri Svoboda5 4 * All rights reserved. 6 5 * … … 39 38 40 39 #include <assert.h> 40 41 41 #include <errno.h> 42 #include <stdbool.h> 43 #include <tmpfile.h> 44 45 #include "posix/fcntl.h" 42 46 43 #include "posix/stdlib.h" 47 44 #include "posix/string.h" 48 #include "posix/sys/stat.h"49 45 #include "posix/sys/types.h" 50 46 #include "posix/unistd.h" … … 173 169 174 170 /** 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 restore 187 * @param pos Position to restore 188 * @return Zero on success, non-zero (with errno set) on failure 189 */ 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 save 198 * @param pos Place to store the position 199 * @return Zero on success, non-zero (with errno set) on failure 200 */ 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 /** 175 213 * Reposition a file-position indicator in a stream. 176 214 * … … 282 320 283 321 /** 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) or 327 * 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) or 345 * 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 /** 284 353 * Acquire file stream for the thread. 285 354 * … … 357 426 } 358 427 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. 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). 393 456 * 394 457 * @param dir Path to directory, where the file should be created. … … 398 461 char *tempnam(const char *dir, const char *pfx) 399 462 { 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) 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; 421 481 return NULL; 422 423 rc = __tmpfile_templ(buf, false); 424 if (rc != 0) { 425 free(buf); 482 } 483 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; 426 510 return NULL; 427 511 } 428 512 429 return buf; 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+"); 430 536 } 431 537
Note:
See TracChangeset
for help on using the changeset viewer.