X-Git-Url: http://git.tuebingen.mpg.de/?p=adu.git;a=blobdiff_plain;f=fd.c;h=e661e71fa32d2c20d92f558f9f40f62f576b9ba1;hp=52569a1b4c9266c01fec1d5ddb3bc379d10e4600;hb=a159b67466fcb6cc38b9daf855051ce807669bc5;hpb=0780ea991eb8d05f7d06eb2833e49925506ae17c diff --git a/fd.c b/fd.c index 52569a1..e661e71 100644 --- a/fd.c +++ b/fd.c @@ -4,16 +4,16 @@ * Licensed under the GPL v2. For licencing details see COPYING. */ -/** \file fd.c Helper functions for file descriptor handling. */ +/** \file fd.c \brief Helper functions for file descriptor handling. */ #include #include #include -#include -#include +#include #include "adu.h" #include "error.h" +#include "string.h" /** * Wrapper for the write system call. @@ -25,12 +25,11 @@ * This function writes out the given buffer and retries if an interrupt * occurred during the write. * - * \return On success, the number of bytes written is returned, otherwise, the - * function returns \p -E_WRITE. + * \return Standard. * * \sa write(2). */ -ssize_t para_write(int fd, const void *buf, size_t size) +ssize_t __write(int fd, const void *buf, size_t size) { ssize_t ret; @@ -42,7 +41,6 @@ ssize_t para_write(int fd, const void *buf, size_t size) } } - /** * Write the whole buffer to a file descriptor. * @@ -53,17 +51,14 @@ ssize_t para_write(int fd, const void *buf, size_t size) * This function writes the given buffer and continues on short writes and * when interrupted by a signal. * - * \return Positive on success, negative on errors. Possible errors: any - * errors returned by para_write(). - * - * \sa para_write(). + * \return Standard. */ -ssize_t write_all(int fd, const void *buf, size_t size) +static ssize_t write_all(int fd, const void *buf, size_t size) { // DEBUG_LOG("writing %zu bytes\n", size); const char *b = buf; while (size) { - ssize_t ret = para_write(fd, b, size); + ssize_t ret = __write(fd, b, size); // DEBUG_LOG("ret: %zd\n", ret); if (ret < 0) return ret; @@ -87,7 +82,7 @@ ssize_t write_all(int fd, const void *buf, size_t size) * * \sa open(2). */ -int para_open(const char *path, int flags, mode_t mode) +static int __open(const char *path, int flags, mode_t mode) { int ret = open(path, flags, mode); @@ -103,16 +98,13 @@ int para_open(const char *path, int flags, mode_t mode) * \param buf The buffer to write to the file. * \param size The size of \a buf. * - * \return Positive on success, negative on errors. Possible errors include: - * any errors from para_open() or para_write(). - * - * \sa para_open(), para_write(). + * \return Standard. */ -int para_write_file(const char *filename, const void *buf, size_t size) +int adu_write_file(const char *filename, const void *buf, size_t size) { int ret, fd; - ret = para_open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644); + ret = __open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644); if (ret < 0) return ret; fd = ret; @@ -125,144 +117,6 @@ out: return ret; } - -/** - * Check whether a file exists. - * - * \param fn The file name. - * - * \return Non-zero iff file exists. - */ -int file_exists(const char *fn) -{ - struct stat statbuf; - - return !stat(fn, &statbuf); -} - -/** - * Paraslash's wrapper for select(2). - * - * It calls select(2) (with no exceptfds) and starts over if select() was - * interrupted by a signal. - * - * \param n The highest-numbered descriptor in any of the two sets, plus 1. - * \param readfds fds that should be checked for readability. - * \param writefds fds that should be checked for writablility. - * \param timeout_tv upper bound on the amount of time elapsed before select() - * returns. - * - * \return The return value of the underlying select() call on success, the - * negative system error code on errors. - * - * All arguments are passed verbatim to select(2). - * \sa select(2) select_tut(2). - */ -int para_select(int n, fd_set *readfds, fd_set *writefds, - struct timeval *timeout_tv) -{ - int ret, err; - do { - ret = select(n, readfds, writefds, NULL, timeout_tv); - err = errno; - } while (ret < 0 && err == EINTR); - if (ret < 0) - return -ERRNO_TO_ERROR(errno); - return ret; -} - -/** - * Set a file descriptor to blocking mode. - * - * \param fd The file descriptor. - * - * \return Standard. - */ -__must_check int mark_fd_blocking(int fd) -{ - int flags = fcntl(fd, F_GETFL); - if (flags < 0) - return -ERRNO_TO_ERROR(errno); - flags = fcntl(fd, F_SETFL, ((long)flags) & ~O_NONBLOCK); - if (flags < 0) - return -ERRNO_TO_ERROR(errno); - return 1; -} - -/** - * Set a file descriptor to non-blocking mode. - * - * \param fd The file descriptor. - * - * \return Standard. - */ -__must_check int mark_fd_nonblocking(int fd) -{ - int flags = fcntl(fd, F_GETFL); - if (flags < 0) - return -ERRNO_TO_ERROR(errno); - flags = fcntl(fd, F_SETFL, ((long)flags) | O_NONBLOCK); - if (flags < 0) - return -ERRNO_TO_ERROR(errno); - return 1; -} - -/** - * Set a file descriptor in a fd_set. - * - * \param fd The file descriptor to be set. - * \param fds The file descriptor set. - * \param max_fileno Highest-numbered file descriptor. - * - * This wrapper for FD_SET() passes its first two arguments to \p FD_SET. Upon - * return, \a max_fileno contains the maximum of the old_value and \a fd. - * - * \sa para_select. -*/ -void para_fd_set(int fd, fd_set *fds, int *max_fileno) -{ - - if (fd < 0 || fd >= FD_SETSIZE) { - EMERG_LOG("fatal: tried to add invalid fd %d\n", fd); - exit(EXIT_FAILURE); - } -#if 0 - { - int flags = fcntl(fd, F_GETFL); - if (!(flags & O_NONBLOCK)) { - EMERG_LOG("fd %d is a blocking file descriptor\n", fd); - exit(EXIT_FAILURE); - } - } -#endif - FD_SET(fd, fds); - *max_fileno = MAX(*max_fileno, fd); -} - -/** - * Paraslash's wrapper for mmap. - * - * \param length Number of bytes to mmap. - * \param prot Either PROT_NONE or the bitwise OR of one or more of - * PROT_EXEC PROT_READ PROT_WRITE. - * \param flags Exactly one of MAP_SHARED and MAP_PRIVATE. - * \param fd The file to mmap from. - * \param offset Mmap start. - * - * \return This function either returns a valid pointer to the mapped area - * or calls exit() on errors. - */ -void *para_mmap(size_t length, int prot, int flags, int fd, off_t offset) -{ - void *ret = mmap(NULL, length, prot, flags, fd, offset); - if (ret != MAP_FAILED) - return ret; - EMERG_LOG("mmap failed: %s\n", strerror(errno)); - EMERG_LOG("length: %zu, flags: %d, fd: %d, offset: %zu\n", - length, flags, fd, (size_t)offset); - exit(EXIT_FAILURE); -} - /** * Wrapper for chdir(2). * @@ -270,7 +124,7 @@ void *para_mmap(size_t length, int prot, int flags, int fd, off_t offset) * * \return Standard. */ -int para_chdir(const char *path) +int __chdir(const char *path) { int ret = chdir(path); @@ -303,17 +157,17 @@ int para_chdir(const char *path) * \sa getcwd(3). * */ -int para_opendir(const char *dirname, DIR **dir, int *cwd) +int adu_opendir(const char *dirname, DIR **dir, int *cwd) { int ret; if (cwd) { - ret = para_open(".", O_RDONLY, 0); + ret = __open(".", O_RDONLY, 0); if (ret < 0) return ret; *cwd = ret; } - ret = para_chdir(dirname); + ret = __chdir(dirname); if (ret < 0) goto close_cwd; *dir = opendir("."); @@ -336,28 +190,13 @@ close_cwd: * * \return Standard. */ -int para_fchdir(int fd) +int adu_fchdir(int fd) { if (fchdir(fd) < 0) return -ERRNO_TO_ERROR(errno); return 1; } -/** - * A wrapper for mkdir(2). - * - * \param path Name of the directory to create. - * \param mode The permissions to use. - * - * \return Standard. - */ -int para_mkdir(const char *path, mode_t mode) -{ - if (!mkdir(path, mode)) - return 1; - return -ERRNO_TO_ERROR(errno); -} - /** * Open a file and map it into memory. * @@ -373,7 +212,7 @@ int para_mkdir(const char *path, mode_t mode) * * \return Standard. * - * \sa para_open(), mmap(2). + * \sa mmap(2). */ int mmap_full_file(const char *path, int open_mode, void **map, size_t *size, int *fd_ptr) @@ -388,7 +227,7 @@ int mmap_full_file(const char *path, int open_mode, void **map, mmap_prot = PROT_READ | PROT_WRITE; mmap_flags = MAP_SHARED; } - ret = para_open(path, open_mode, 0); + ret = __open(path, open_mode, 0); if (ret < 0) return ret; fd = ret; @@ -426,7 +265,7 @@ out: * * \sa munmap(2), mmap_full_file(). */ -int para_munmap(void *start, size_t length) +int adu_munmap(void *start, size_t length) { int err; if (munmap(start, length) >= 0) @@ -437,27 +276,53 @@ int para_munmap(void *start, size_t length) 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; +} + /** - * Check a file descriptor for writability. + * Recursive mkdir + * + * \param p Full path that should be created. * - * \param fd The file descriptor. + * \param mode Use this mode when creating directories. * - * \return positive if fd is ready for writing, zero if it isn't, negative if - * an error occurred. + * \return 0 if successful, -E_MKDIR on errors. */ - -int write_ok(int fd) +int mkpath(const char *p, mode_t mode) { - struct timeval tv = {0, 0}; - fd_set wfds; - int ret; -again: - FD_ZERO(&wfds); - FD_SET(fd, &wfds); - tv.tv_sec = 0; - tv.tv_usec = 0; - ret = select(fd + 1, NULL, &wfds, NULL, &tv); - if (ret < 0 && errno == EINTR) - goto again; + 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; }