Changeset b7ee0369 in mainline for uspace/lib/posix/stdio.c


Ignore:
Timestamp:
2011-07-31T05:08:44Z (13 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d3e241a
Parents:
051e6ac (diff), 27a8d1d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge libposix changes.

File:
1 edited

Legend:

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

    r051e6ac rb7ee0369  
    4444#include "assert.h"
    4545#include "errno.h"
     46#include "stdlib.h"
    4647#include "string.h"
    4748#include "sys/types.h"
     49#include "unistd.h"
    4850
    4951#include "libc/io/printf_core.h"
    5052#include "libc/str.h"
    5153#include "libc/malloc.h"
     54#include "libc/adt/list.h"
     55#include "libc/sys/stat.h"
    5256
    5357
     
    252256        assert(mode != NULL);
    253257        assert(stream != NULL);
    254 
     258       
     259        /* Retieve the node. */
     260        struct stat st;
     261        int rc;
     262       
    255263        if (filename == NULL) {
    256                 // TODO
    257                
    258                 /* print error to stderr as well, to avoid hard to find problems
    259                  * with buggy apps that expect this to work
    260                  */
    261                 fprintf(stderr,
    262                     "ERROR: Application wants to use freopen() to change mode of opened stream.\n"
    263                     "       libposix does not support that yet, the application may function improperly.\n");
    264                 errno = ENOTSUP;
     264                rc = fstat(stream->fd, &st);
     265        } else {
     266                rc = stat(filename, &st);
     267        }
     268       
     269        if (rc != EOK) {
     270                fclose(stream);
     271                errno = -rc;
    265272                return NULL;
    266273        }
    267 
    268         FILE* copy = malloc(sizeof(FILE));
    269         if (copy == NULL) {
    270                 errno = ENOMEM;
     274       
     275        fdi_node_t node = {
     276                .fs_handle = st.fs_handle,
     277                .devmap_handle = st.devmap_handle,
     278                .index = st.index
     279        };
     280       
     281        /* Open a new stream. */
     282        FILE* new = fopen_node(&node, mode);
     283        if (new == NULL) {
     284                fclose(stream);
     285                /* fopen_node() sets errno. */
    271286                return NULL;
    272287        }
    273         memcpy(copy, stream, sizeof(FILE));
    274         fclose(copy); /* copy is now freed */
    275        
    276         copy = fopen(filename, mode); /* open new stream */
    277         if (copy == NULL) {
    278                 /* fopen() sets errno */
    279                 return NULL;
    280         }
    281        
    282         /* move the new stream to the original location */
    283         memcpy(stream, copy, sizeof (FILE));
    284         free(copy);
    285        
    286         /* update references in the file list */
     288       
     289        /* Close the original stream without freeing it (ignoring errors). */
     290        if (stream->buf != NULL) {
     291                fflush(stream);
     292        }
     293        if (stream->sess != NULL) {
     294                async_hangup(stream->sess);
     295        }
     296        if (stream->fd >= 0) {
     297                close(stream->fd);
     298        }
     299        list_remove(&stream->link);
     300       
     301        /* Move the new stream to the original location. */
     302        memcpy(stream, new, sizeof (FILE));
     303        free(new);
     304       
     305        /* Update references in the file list. */
    287306        stream->link.next->prev = &stream->link;
    288307        stream->link.prev->next = &stream->link;
     
    676695
    677696/**
    678  * Remove a file.
     697 * Remove a file or directory.
    679698 *
    680699 * @param path Pathname of the file that shall be removed.
    681  * @return Zero on success, -1 otherwise.
     700 * @return Zero on success, -1 (with errno set) otherwise.
    682701 */
    683702int posix_remove(const char *path)
    684703{
    685         // FIXME: unlink() and rmdir() seem to be equivalent at the moment,
    686         //        but that does not have to be true forever
    687         return unlink(path);
    688 }
    689 
    690 /**
    691  *
    692  * @param s
    693  * @return
     704        struct stat st;
     705        int rc = stat(path, &st);
     706       
     707        if (rc != EOK) {
     708                errno = -rc;
     709                return -1;
     710        }
     711       
     712        if (st.is_directory) {
     713                rc = rmdir(path);
     714        } else {
     715                rc = unlink(path);
     716        }
     717       
     718        if (rc != EOK) {
     719                errno = -rc;
     720                return -1;
     721        }
     722        return 0;
     723}
     724
     725/**
     726 * Rename a file or directory.
     727 *
     728 * @param old Old pathname.
     729 * @param new New pathname.
     730 * @return Zero on success, -1 (with errno set) otherwise.
     731 */
     732int posix_rename(const char *old, const char *new)
     733{
     734        return errnify(rename, old, new);
     735}
     736
     737/**
     738 * Get a unique temporary file name (obsolete).
     739 *
     740 * @param s Buffer for the file name. Must be at least L_tmpnam bytes long.
     741 * @return The value of s on success, NULL on failure.
    694742 */
    695743char *posix_tmpnam(char *s)
    696744{
    697         // TODO: low priority, just a compile-time dependency of binutils
    698         not_implemented();
     745        assert(L_tmpnam >= posix_strlen("/tmp/tnXXXXXX"));
     746       
     747        static char buffer[L_tmpnam + 1];
     748        if (s == NULL) {
     749                s = buffer;
     750        }
     751       
     752        posix_strcpy(s, "/tmp/tnXXXXXX");
     753        posix_mktemp(s);
     754       
     755        if (*s == '\0') {
     756                /* Errno set by mktemp(). */
     757                return NULL;
     758        }
     759       
     760        return s;
     761}
     762
     763/**
     764 * Get an unique temporary file name with additional constraints (obsolete).
     765 *
     766 * @param dir Path to directory, where the file should be created.
     767 * @param pfx Optional prefix up to 5 characters long.
     768 * @return Newly allocated unique path for temporary file. NULL on failure.
     769 */
     770char *posix_tempnam(const char *dir, const char *pfx)
     771{
     772        /* Sequence number of the filename. */
     773        static int seq = 0;
     774       
     775        size_t dir_len = posix_strlen(dir);
     776        if (dir[dir_len - 1] == '/') {
     777                dir_len--;
     778        }
     779       
     780        size_t pfx_len = posix_strlen(pfx);
     781        if (pfx_len > 5) {
     782                pfx_len = 5;
     783        }
     784       
     785        char *result = malloc(dir_len + /* slash*/ 1 +
     786            pfx_len + /* three-digit seq */ 3 + /* .tmp */ 4 + /* nul */ 1);
     787       
     788        if (result == NULL) {
     789                errno = ENOMEM;
     790                return NULL;
     791        }
     792       
     793        char *res_ptr = result;
     794        posix_strncpy(res_ptr, dir, dir_len);
     795        res_ptr += dir_len;
     796        posix_strncpy(res_ptr, pfx, pfx_len);
     797        res_ptr += pfx_len;
     798       
     799        for (; seq < 1000; ++seq) {
     800                snprintf(res_ptr, 8, "%03d.tmp", seq);
     801               
     802                int orig_errno = errno;
     803                errno = 0;
     804                /* Check if the file exists. */
     805                if (posix_access(result, F_OK) == -1) {
     806                        if (errno == ENOENT) {
     807                                errno = orig_errno;
     808                                break;
     809                        } else {
     810                                /* errno set by access() */
     811                                return NULL;
     812                        }
     813                }
     814        }
     815       
     816        if (seq == 1000) {
     817                free(result);
     818                errno = EINVAL;
     819                return NULL;
     820        }
     821       
     822        return result;
     823}
     824
     825/**
     826 * Create and open an unique temporary file.
     827 * The file is automatically removed when the stream is closed.
     828 *
     829 * @param dir Path to directory, where the file should be created.
     830 * @param pfx Optional prefix up to 5 characters long.
     831 * @return Newly allocated unique path for temporary file. NULL on failure.
     832 */
     833FILE *posix_tmpfile(void)
     834{
     835        char filename[] = "/tmp/tfXXXXXX";
     836        int fd = posix_mkstemp(filename);
     837        if (fd == -1) {
     838                /* errno set by mkstemp(). */
     839                return NULL;
     840        }
     841       
     842        /* Unlink the created file, so that it's removed on close(). */
     843        posix_unlink(filename);
     844        return fdopen(fd, "w+");
    699845}
    700846
Note: See TracChangeset for help on using the changeset viewer.