X-Git-Url: http://git.tuebingen.mpg.de/?p=adu.git;a=blobdiff_plain;f=fd.c;h=39e98374b3acb9ccc727426bf0b6b06d047b57e7;hp=e1d243e1e8f34006326bdfab72f24455ad801eff;hb=6744ce67f91c410f69de0763fb6faa01a8a53b28;hpb=3bb9b0ca535be1eb28b64972bdf0e205e6afc93e diff --git a/fd.c b/fd.c index e1d243e..39e9837 100644 --- a/fd.c +++ b/fd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Andre Noll + * Copyright (C) 2006-2008 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -9,9 +9,12 @@ #include #include #include +#include #include "adu.h" #include "error.h" +#include "string.h" +#include "fd.h" /** * Wrapper for the write system call. @@ -21,19 +24,20 @@ * \param size The length of \a buf in bytes. * * This function writes out the given buffer and retries if an interrupt - * occurred during the write. + * occurred during the write. The file descriptor is assumed to be in blocking + * mode (i.e., EAGAIN is treated as an error). * * \return Standard. * * \sa write(2). */ -ssize_t __write(int fd, const void *buf, size_t size) +static ssize_t __write(int fd, const void *buf, size_t size) { ssize_t ret; for (;;) { ret = write(fd, buf, size); - if ((ret < 0) && (errno == EAGAIN || errno == EINTR)) + if (ret < 0 && errno == EINTR) continue; return ret >= 0? ret : -ERRNO_TO_ERROR(errno); } @@ -122,7 +126,7 @@ out: * * \return Standard. */ -int __chdir(const char *path) +static int __chdir(const char *path) { int ret = chdir(path); @@ -172,9 +176,10 @@ int adu_opendir(const char *dirname, DIR **dir, int *cwd) if (*dir) return 1; ret = -ERRNO_TO_ERROR(errno); -/* Ignore return value of fchdir() and close(). We're busted anyway. */ - if (cwd) - fchdir(*cwd); + /* Ignore return value of fchdir() and close(). We're busted anyway. */ + if (cwd) { + int __a_unused ret2 = fchdir(*cwd); /* STFU, gcc */ + } close_cwd: if (cwd) close(*cwd); @@ -196,36 +201,25 @@ int adu_fchdir(int fd) } /** - * Open a file and map it into memory. + * Open a file read-only and map it into memory. * * \param path Name of the regular file to map. - * \param open_mode Either \p O_RDONLY or \p O_RDWR. * \param map On success, the mapping is returned here. - * \param size size of the mapping. - * \param fd_ptr The file descriptor of the mapping. + * \param size Result parameter: size of the mapping in bytes. * - * If \a fd_ptr is \p NULL, the file descriptor resulting from the underlying - * open call is closed after mmap(). Otherwise the file is kept open and the - * file descriptor is returned in \a fd_ptr. + * The file will be mapped privately with memory protection PROT_READ. The file + * descriptor resulting from the underlying open call is closed after mmap(). * * \return Standard. * * \sa mmap(2). */ -int mmap_full_file(const char *path, int open_mode, void **map, - size_t *size, int *fd_ptr) +int mmap_file_ro(const char *path, void **map, size_t *size) { - int fd, ret, mmap_prot, mmap_flags; + int fd, ret; struct stat file_status; - if (open_mode == O_RDONLY) { - mmap_prot = PROT_READ; - mmap_flags = MAP_PRIVATE; - } else { - mmap_prot = PROT_READ | PROT_WRITE; - mmap_flags = MAP_SHARED; - } - ret = __open(path, open_mode, 0); + ret = __open(path, O_RDONLY, 0); if (ret < 0) return ret; fd = ret; @@ -238,7 +232,7 @@ int mmap_full_file(const char *path, int open_mode, void **map, DEBUG_LOG("%s: size %zu\n", path, *size); if (!*size) goto out; - *map = mmap(NULL, *size, mmap_prot, mmap_flags, fd, 0); + *map = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); if (*map == MAP_FAILED) { *map = NULL; ret = -E_MMAP; @@ -246,10 +240,7 @@ int mmap_full_file(const char *path, int open_mode, void **map, } ret = 1; out: - if (ret < 0 || !fd_ptr) - close(fd); - else - *fd_ptr = fd; + close(fd); return ret; } @@ -273,3 +264,54 @@ int adu_munmap(void *start, size_t length) strerror(err)); return -ERRNO_TO_ERROR(err); } + +__must_check __malloc static char *adu_dirname(const char *name) +{ + char *p, *ret; + + if (!name || !*name) + return NULL; + ret = adu_strdup(name); + p = strrchr(ret, '/'); + if (!p) + *ret = '\0'; + else + *p = '\0'; + return ret; +} + +/** + * Recursive mkdir + * + * \param p Full path that should be created. + * + * \param mode Use this mode when creating directories. + * + * \return 0 if successful, -E_MKDIR on errors. + */ +int mkpath(const char *p, mode_t mode) +{ + char *parent, *path; + int ret = -E_MKDIR; + + DEBUG_LOG("%s\n", p); + if (strcmp(p, ".") == 0 || strcmp(p, "/") == 0 || strcmp(p, "") == 0) { + DEBUG_LOG("reached beginning of path\n"); + return 0; + } + path = adu_strdup(p); + parent = adu_dirname(p); + if (!parent) + goto out; + ret = mkpath(parent, mode); + if (ret < 0) + goto out; + INFO_LOG("making dir %s\n", path); + ret = 0; + if ((mkdir(path, mode) == -1) && (errno != EEXIST)) + ret = -E_MKDIR; +out: + free(parent); + free(path); + return ret; +}