X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=fd.c;h=0fb796025945b2c33e59c6c8508d370626ac0c02;hp=8759d5099200c4f6c1b6c31e84b66da3372b5540;hb=80b5eac6e7363199f62fc39e583a28ce898a0b2b;hpb=9627e8157c8c916555b993d7254b0b638815ebc1 diff --git a/fd.c b/fd.c index 8759d509..0fb79602 100644 --- a/fd.c +++ b/fd.c @@ -6,6 +6,7 @@ /** \file fd.c Helper functions for file descriptor handling. */ +#include #include #include #include @@ -14,6 +15,7 @@ #include "para.h" #include "error.h" +#include "string.h" /** * Write a buffer to a file descriptor, re-write on short writes. @@ -114,11 +116,10 @@ int file_exists(const char *fn) int para_select(int n, fd_set *readfds, fd_set *writefds, struct timeval *timeout_tv) { - int ret, err; - do { + int ret; + do ret = select(n, readfds, writefds, NULL, timeout_tv); - err = errno; - } while (ret < 0 && err == EINTR); + while (ret < 0 && errno == EINTR); if (ret < 0) return -ERRNO_TO_PARA_ERROR(errno); return ret; @@ -420,7 +421,7 @@ out: * \param start The start address of the memory mapping. * \param length The size of the mapping. * - * \return Positive on success, \p -E_MUNMAP on errors. + * \return Standard. * * \sa munmap(2), mmap_full_file(). */ @@ -446,18 +447,14 @@ int para_munmap(void *start, size_t length) int write_ok(int fd) { - struct timeval tv = {0, 0}; + struct timeval tv; 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; - return ret; + return para_select(fd + 1, NULL, &wfds, &tv); } /** @@ -480,3 +477,65 @@ void valid_fd_012(void) } } } + +/** + * Traverse the given directory recursively. + * + * \param dirname The directory to traverse. + * \param func The function to call for each entry. + * \param private_data Pointer to an arbitrary data structure. + * + * For each regular file under \a dirname, the supplied function \a func is + * called. The full path of the regular file and the \a private_data pointer + * are passed to \a func. Directories for which the calling process has no + * permissions to change to are silently ignored. + * + * \return Standard. + */ +int for_each_file_in_dir(const char *dirname, + int (*func)(const char *, void *), void *private_data) +{ + DIR *dir; + struct dirent *entry; + int cwd_fd, ret2, ret = para_opendir(dirname, &dir, &cwd_fd); + + if (ret < 0) + return ret == -ERRNO_TO_PARA_ERROR(EACCES)? 1 : ret; + /* scan cwd recursively */ + while ((entry = readdir(dir))) { + mode_t m; + char *tmp; + struct stat s; + + if (!strcmp(entry->d_name, ".")) + continue; + if (!strcmp(entry->d_name, "..")) + continue; + if (lstat(entry->d_name, &s) == -1) + continue; + m = s.st_mode; + if (!S_ISREG(m) && !S_ISDIR(m)) + continue; + tmp = make_message("%s/%s", dirname, entry->d_name); + if (!S_ISDIR(m)) { + ret = func(tmp, private_data); + free(tmp); + if (ret < 0) + goto out; + continue; + } + /* directory */ + ret = for_each_file_in_dir(tmp, func, private_data); + free(tmp); + if (ret < 0) + goto out; + } + ret = 1; +out: + closedir(dir); + ret2 = para_fchdir(cwd_fd); + if (ret2 < 0 && ret >= 0) + ret = ret2; + close(cwd_fd); + return ret; +}