X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=fsck.c;h=48fae27d490bf2021f85682616e2503341f5fe83;hp=bc4083aed2cf988922a259e9a391f553eb96fc00;hb=192417698d9dab017ef6108fa6e9fd5ea1dc5633;hpb=e95fc5a017e89dd9004836d759163056b0dc7095 diff --git a/fsck.c b/fsck.c index bc4083ae..48fae27d 100644 --- a/fsck.c +++ b/fsck.c @@ -1,18 +1,25 @@ +/* + * Copyright (C) 1997-2007 Andre Noll + * + * Licensed under the GPL v2. For licencing details see COPYING. + */ + +/** \file fsck.c The program used to check an osl table. */ + + +#include +#include + #include "para.h" +#include "fd.h" #include "error.h" #include "osl_core.h" +#include "fsck.cmdline.h" -#define OSL_DUMP_DIR "/tmp/osldump" - -enum errors { - E_FSCK_SYNTAX = 501, - E_RANGE_VIOLATION, - E_NO_DS_FILE, - E_NOT_A_REGULAR_FILE, - E_BAD_HASH_PATH, -}; +static struct fsck_args_info conf; -INIT_STDERR_LOGGING(1); +INIT_FSCK_ERRLISTS; +INIT_STDERR_LOGGING(conf.loglevel_arg); /* taken from git */ signed char hexval_table[256] = { @@ -93,7 +100,8 @@ static int check_range(struct osl_table *t, uint32_t row_num, uint32_t col_num) // PARA_INFO_LOG("obj: %p..%p\n", obj_start, obj_start + obj.size); // PARA_INFO_LOG("map: %p..%p\n", map_start, map_start + col->data_map.size); if (obj_start < map_start || obj_start + obj.size > map_start + col->data_map.size) { - PARA_CRIT_LOG("row %u, col %u: range violation, very bad\n", row_num, col_num); + PARA_CRIT_LOG("range violation in row %u, col %u\n", row_num, + col_num); return -E_RANGE_VIOLATION; } PARA_DEBUG_LOG("col %u: ok\n", col_num); @@ -168,7 +176,7 @@ static int map_index(const struct osl_table_description *desc, struct osl_object char *filename = index_filename(desc); int ret; - ret = mmap_full_file(filename, O_RDWR, map); + ret = mmap_full_file(filename, O_RDWR, &map->data, &map->size, NULL); PARA_INFO_LOG("mapping index %s: ret: %d, size: %zu\n", filename, ret, map->size); free(filename); return ret; @@ -563,15 +571,12 @@ static int check_disk_storage_columns(struct osl_table *t) out_close_hash_tree: osl_close_table(hash_tree_table, 0); free(hashes); + hashes = NULL; out: clear_rbtrees(t); /* TODO why are we doing that here? Seems odd */ return ret; } -#define FSCK 1 -#define FORCE 1 -#define DUMP 0 - static void set_dummy_contents(struct osl_table_description *desc) { int i; @@ -603,7 +608,7 @@ static int fsck_init(struct osl_table_description *desc, struct osl_table **t) } PARA_INFO_LOG("unmapping index\n"); para_munmap(map.data, map.size); - if (FORCE) + if (conf.force_given) ret = map_table(*t, (MAP_TBL_FL_IGNORE_DIRTY)); else ret = map_table(*t, 0); @@ -746,14 +751,14 @@ static int dump_row(struct osl_table *t, unsigned row_num, const char *row_dir) if (!t->num_disk_storage_columns) return 1; dsnc = t->disk_storage_name_column; - ret = get_mapped_object(t, dsnc, i, &obj); + ret = get_mapped_object(t, dsnc, row_num, &obj); if (ret < 0) return ret; hash_object(&obj, hash); ds_name = disk_storage_name_of_hash(t, hash); FOR_EACH_DISK_STORAGE_COLUMN(i, t, cd) { filename = disk_storage_path(t, i, ds_name); - ret = mmap_full_file(filename, O_RDONLY, &obj); + ret = mmap_full_file(filename, O_RDONLY, &obj.data, &obj.size, NULL); free(filename); if (ret < 0) goto out; @@ -784,12 +789,12 @@ static int dump_rows(char *dump_dir, struct osl_table *t) current_dir = make_message("%s/rows_%u-%u", dump_dir, i, i + 999); PARA_NOTICE_LOG("dumping rows %u - %u\n", i, i + 999); ret = para_mkdir(current_dir, 0777); - if (ret < 0) + if (ret < 0 && !is_errno(-ret, EEXIST)) goto out; } row_dir = make_message("%s/row_%03u", current_dir, i); ret = para_mkdir(row_dir, 0777); - if (ret < 0) { + if (ret < 0 && !is_errno(-ret, EEXIST)) { free(row_dir); goto out; } @@ -808,13 +813,18 @@ static int dump_table(char *dump_dir, struct osl_table_description *desc) struct osl_table *t = NULL; int fd, ret = fsck_init(desc, &t); char *desc_file; + char *table_dump_dir = NULL; if (ret < 0) goto out; ret = para_mkdir(dump_dir, 0777); - if (ret < 0) + if (ret < 0 && !is_errno(-ret, EEXIST)) + goto out; + table_dump_dir = make_message("%s/%s", dump_dir, desc->name); + ret = para_mkdir(table_dump_dir, 0777); + if (ret < 0 && !is_errno(-ret, EEXIST)) goto out; - desc_file = make_message("%s/table_description.c", dump_dir); + desc_file = make_message("%s/table_description.c", table_dump_dir); ret = para_open(desc_file, O_WRONLY | O_CREAT | O_EXCL, 0644); free(desc_file); if (ret < 0) @@ -824,8 +834,9 @@ static int dump_table(char *dump_dir, struct osl_table_description *desc) close(fd); if (ret < 0) goto out; - ret = dump_rows(dump_dir, t); + ret = dump_rows(table_dump_dir, t); out: + free(table_dump_dir); fsck_cleanup(t); return ret; } @@ -864,25 +875,89 @@ out: fsck_cleanup(t); return ret; } -int main(__a_unused int argc, __a_unused char **argv) + +static int check_table(char *base_dir, char *table_name) { + struct osl_table_description desc = { + .column_descriptions = NULL, + .dir = base_dir, + .name = table_name + }; int ret; - struct osl_table_description desc = {.column_descriptions = NULL}; - ret = -E_FSCK_SYNTAX; - if (argc < 3) - goto out; - desc.dir = argv[1]; - desc.name = argv[2]; - if (FSCK) { + if (!conf.no_fsck_given) { ret = fsck(&desc); if (ret < 0) - goto out; + return ret; + } + if (!conf.dump_dir_given || !*conf.dump_dir_arg) + return 1; + return dump_table(conf.dump_dir_arg, &desc); +} + +static int check_all_tables(char *base_dir) +{ + DIR *dir; + struct dirent *entry; + int cwd_fd, ret2, ret = para_opendir(base_dir, &dir, &cwd_fd); + + if (ret < 0) + return ret; + while ((entry = readdir(dir))) { + mode_t m; + 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_ISDIR(m)) + continue; + ret = check_table(base_dir, entry->d_name); + if (ret < 0) + break; + } + closedir(dir); + ret2 = para_fchdir(cwd_fd); + if (ret2 < 0 && ret >= 0) + ret = ret2; + close(cwd_fd); + return ret; +} + +int main(int argc, char **argv) +{ + int i, ret; + char *base_dir = NULL; + + ret = fsck_cmdline_parser(argc, argv, &conf); + if (ret < 0) { + ret = -E_FSCK_SYNTAX; + goto out; + } + HANDLE_VERSION_FLAG("fsck", conf); + if (conf.base_dir_given) + base_dir = conf.base_dir_arg; + else { + char *home = para_homedir(); + base_dir = make_message("%s/.paraslash/afs_database", home); + free(home); + } + if (!conf.inputs_num) { + ret = check_all_tables(base_dir); + goto out; + } + for (i = 0; i < conf.inputs_num; i++) { + ret = check_table(base_dir, conf.inputs[i]); + if (ret < 0) + break; } - if (DUMP) - ret = dump_table(OSL_DUMP_DIR, &desc); out: + if (!conf.base_dir_given) + free(base_dir); if (ret < 0) - PARA_ERROR_LOG("error %d\n", ret); - return ret < 0? EXIT_FAILURE: EXIT_SUCCESS; + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); + return ret < 0? EXIT_FAILURE : EXIT_SUCCESS; }