X-Git-Url: http://git.tuebingen.mpg.de/?p=osl.git;a=blobdiff_plain;f=fsck.c;h=29c4e2c7dc9d72d940dbb7c4298f24d84f3dcfc8;hp=574509fcebdda24c52a8a1e45d0f4c94f6c6eef3;hb=53c4162f4a1fd70343332b9596e89d73c8547e51;hpb=68aa66b6f051083b8f9fe9cf65b0a20fed4363f9 diff --git a/fsck.c b/fsck.c index 574509f..29c4e2c 100644 --- a/fsck.c +++ b/fsck.c @@ -15,7 +15,7 @@ #include "log.h" #include "osl.h" #include "error.h" -#include "fd.h" +#include "util.h" #include "osl_core.h" #include "fsck.cmdline.h" @@ -208,6 +208,86 @@ static int uint32_compare(const struct osl_object *obj1, const struct osl_object return 0; } +/** + * A wrapper for fchdir(). + * + * \param fd An open file descriptor. + * + * \return Standard. + */ +static inline int __fchdir(int fd) +{ + if (fchdir(fd) < 0) + return -ERRNO_TO_ERROR(errno); + return 1; +} + +/** + * Wrapper for chdir(2). + * + * \param path The specified directory. + * + * \return Standard. + */ +_static_inline_ int __chdir(const char *path) +{ + if (chdir(path) >= 0) + return 1; + return -ERRNO_TO_ERROR(errno); +} + +/** + * Save the cwd and open a given directory. + * + * \param dirname Path to the directory to open. + * \param dir Result pointer. + * \param cwd File descriptor of the current working directory. + * + * \return Standard. + * + * Opening the current directory (".") and calling fchdir() to return is + * usually faster and more reliable than saving cwd in some buffer and calling + * chdir() afterwards. + * + * If \a cwd is not \p NULL "." is opened and the resulting file descriptor is + * stored in \a cwd. If the function returns success, and \a cwd is not \p + * NULL, the caller must close this file descriptor (probably after calling + * fchdir(*cwd)). + * + * On errors, the function undos everything, so the caller needs neither close + * any files, nor change back to the original working directory. + * + * \sa getcwd(3). + * + */ +static int fsck_opendir(const char *dirname, DIR **dir, int *cwd) +{ + int ret; + + if (cwd) { + ret = osl_open(".", O_RDONLY, 0); + if (ret < 0) + return ret; + *cwd = ret; + } + ret = __chdir(dirname); + if (ret < 0) + goto close_cwd; + *dir = opendir("."); + if (*dir) + return 1; + ret = -ERRNO_TO_ERROR(errno); +/* Ignore return value of fchdir() and close(). We're busted anyway. */ + if (cwd) + fchdir(*cwd); +close_cwd: + if (cwd) + close(*cwd); + return ret; +} + + + /** * Traverse the given directory recursively. * @@ -227,7 +307,7 @@ static int for_each_file_in_dir(const char *dirname, { DIR *dir; struct dirent *entry; - int cwd_fd, ret2, ret = para_opendir(dirname, &dir, &cwd_fd); + int cwd_fd, ret2, ret = fsck_opendir(dirname, &dir, &cwd_fd); if (ret < 0) return ret == -ERRNO_TO_ERROR(EACCES)? 1 : ret; @@ -263,7 +343,7 @@ static int for_each_file_in_dir(const char *dirname, ret = 1; out: closedir(dir); - ret2 = para_fchdir(cwd_fd); + ret2 = __fchdir(cwd_fd); if (ret2 < 0 && ret >= 0) ret = ret2; close(cwd_fd); @@ -1105,7 +1185,7 @@ static int check_all_tables(char *db_dir) { DIR *dir; struct dirent *entry; - int cwd_fd, ret2, ret = para_opendir(db_dir, &dir, &cwd_fd); + int cwd_fd, ret2, ret = fsck_opendir(db_dir, &dir, &cwd_fd); if (ret < 0) return ret; @@ -1126,7 +1206,7 @@ static int check_all_tables(char *db_dir) break; } closedir(dir); - ret2 = para_fchdir(cwd_fd); + ret2 = __fchdir(cwd_fd); if (ret2 < 0 && ret >= 0) ret = ret2; close(cwd_fd);