X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=fsck.c;h=27004a65694131b020d527177a9269ec2711f2ed;hb=368cbd78587922ec3620b72bdb1c9f8cdf9297d1;hp=55c134aaa87b40bca139d5cbb32bf3e022f54353;hpb=af89ce791ead29cb2a86e257f8e8d113c6ac205f;p=osl.git diff --git a/fsck.c b/fsck.c index 55c134a..27004a6 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); @@ -412,7 +492,7 @@ static int prune_invalid_rows_from_index(struct osl_table *t) DEBUG_LOG("unmapping index\n"); osl_munmap(t->index_map.data, t->index_map.size); filename = index_filename(t->desc); - ret = para_truncate(filename, t->row_index_size + ret = truncate_file(filename, t->row_index_size * t->num_invalid_rows); free(filename); if (ret < 0) @@ -674,7 +754,7 @@ static unsigned files_pruned; int prune_disk_storage_file(const char *path, void *private_data) { HASH_TYPE hash[HASH_SIZE]; - unsigned flags = *(unsigned *)private_data; + uint8_t flags = *(uint8_t *)private_data; struct osl_object obj = {.data = hash, .size = HASH_SIZE}; struct osl_row *row; int ret = -1; @@ -731,8 +811,9 @@ static int prune_disk_storage_files(struct osl_table *t) INFO_LOG("looking for unreferenced disk storage files\n"); FOR_EACH_DISK_STORAGE_COLUMN(i, t, cd) { char *dirname = column_filename(t, i); + uint8_t flags = t->desc->flags; ret = for_each_file_in_dir(dirname, prune_disk_storage_file, - (unsigned *)&t->desc->flags); + &flags); free(dirname); } if (files_pruned) @@ -1105,7 +1186,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 +1207,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);