Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/src/stdio.c

    r4e6a610 r5a6c28d1  
    22 * Copyright (c) 2011 Jiri Zarevucky
    33 * Copyright (c) 2011 Petr Koupy
    4  * Copyright (c) 2018 Jiri Svoboda
    54 * All rights reserved.
    65 *
     
    3938
    4039#include <assert.h>
     40
    4141#include <errno.h>
    42 #include <stdbool.h>
    43 #include <tmpfile.h>
    44 
    45 #include "posix/fcntl.h"
     42
    4643#include "posix/stdlib.h"
    4744#include "posix/string.h"
    48 #include "posix/sys/stat.h"
    4945#include "posix/sys/types.h"
    5046#include "posix/unistd.h"
     
    173169
    174170/**
     171 * Write error messages to standard error.
     172 *
     173 * @param s Error message.
     174 */
     175void 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 */
     190int 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 */
     201int 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/**
    175213 * Reposition a file-position indicator in a stream.
    176214 *
     
    282320
    283321/**
     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 */
     329int 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 */
     347int vsprintf(char *s, const char *restrict format, va_list ap)
     348{
     349        return vsnprintf(s, INT_MAX, format, ap);
     350}
     351
     352/**
    284353 * Acquire file stream for the thread.
    285354 *
     
    357426}
    358427
    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 */
     434char *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).
    393456 *
    394457 * @param dir Path to directory, where the file should be created.
     
    398461char *tempnam(const char *dir, const char *pfx)
    399462{
    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;
    421481                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;
    426510                return NULL;
    427511        }
    428512
    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 */
     524FILE *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+");
    430536}
    431537
Note: See TracChangeset for help on using the changeset viewer.