From: Andre Noll Date: Sun, 28 Aug 2016 21:04:06 +0000 (+0200) Subject: Convert oslfsck to lopsub. X-Git-Tag: v0.2.0~14 X-Git-Url: http://git.tuebingen.mpg.de/?p=osl.git;a=commitdiff_plain;h=3f0d225f1e9892d59bcc2c3b23c8945526595fcc Convert oslfsck to lopsub. The gengetopt project seems to be dead (last release was five years ago), so we eventually need to switch to something else. This commit migrates the option parser of oslfsck to the lopsub library, which turned out to be rather simple. As a result, the osl package no longer depends on gengetopt and help2man. The change only affects the oslfsck executable. No changes to the library proper. --- diff --git a/.gitignore b/.gitignore index 826d65d..907447f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *.[oa] foo bar* -*cmdline.[ch] +*lsg.[ch] osl.h osl_errors.h errtab.h diff --git a/INSTALL b/INSTALL index e370904..3bd8751 100644 --- a/INSTALL +++ b/INSTALL @@ -1,6 +1,9 @@ As the bare minimum, you'll need gcc-4 and gnu make to install -libosl. gengetopt is needed to build the oslfsck executable, and -help2man to generate its man page. +libosl. lopsub is needed to build the oslfsck executable and to +generate its man page. Download and install lopsub with + + git clone git://git.tuebingen.mpg.de/lopsub + cd lopsub && make && sudo make install If everything mentioned above is available on your system, type diff --git a/Makefile b/Makefile index eeb5dcc..a4f5fad 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ bindir := $(PREFIX)/bin mandir := $(PREFIX)/man/man1 objects := osl.o util.o rbtree.o sha1.o -fsck_objects := fsck.fsck.o osl.fsck.o util.fsck.o rbtree.fsck.o sha1.fsck.o fsck.cmdline.o +fsck_objects := fsck.fsck.o osl.fsck.o util.fsck.o rbtree.fsck.o sha1.fsck.o oslfsck.lsg.o headers := osl.h executables := oslfsck man_pages := oslfsck.1 @@ -119,31 +119,23 @@ osl.c fsck.c: -include Makefile.deps -fsck.cmdline.o: fsck.cmdline.c fsck.cmdline.h - $(CC) -c -DVERSION='"$(VERSION)"' $< - -%.fsck.o: %.c Makefile fsck.cmdline.c fsck.cmdline.h osl.h errtab.h - $(CC) -c -DVERSION='"$(VERSION)"' $(CPPFLAGS) $(CFLAGS) $< -o $@ +%.fsck.o: %.c Makefile osl.h errtab.h oslfsck.lsg.h + $(CC) -c -DOSL_VERSION='"$(VERSION)"' $(CPPFLAGS) $(CFLAGS) $< -o $@ %.o: %.c Makefile errtab.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(LIBCFLAGS) $< -fsck.cmdline.h fsck.cmdline.c: fsck.ggo Makefile - gengetopt \ - --conf-parser \ - --unamed-opts=table \ - --no-handle-version \ - --file-name=fsck.cmdline \ - --func-name=fsck_cmdline_parser \ - --set-package="oslfsck" \ - --arg-struct-name=fsck_args_info \ - < $< - oslfsck: $(fsck_objects) - $(CC) -o $@ $(fsck_objects) + $(CC) -o $@ $(fsck_objects) -llopsub + +%.lsg.c: %.suite + lopsubgen --gen-c < $< + +%.lsg.h: %.suite + lopsubgen --gen-header < $< -oslfsck.1: oslfsck - help2man -h --detailed-help -N ./$< > $@ +%.1: %.suite + lopsubgen --gen-man=$@ < $< $(realname): $(objects) $(CC) $(LDFLAGS) -o $@ $(objects) @@ -172,8 +164,8 @@ osl.h: osl.h.in osl_errors.h Makefile cat osl.h.in osl_errors.h >> $@ echo '#endif /* _OSL_H */' >> $@ clean: - rm -f *.o $(realname) osl.h osl_errors.h errtab.h fsck.cmdline.h \ - fsck.cmdline.c oslfsck *.a *.ga *.sym + rm -f *.o $(realname) osl.h osl_errors.h errtab.h \ + oslfsck *.a *.ga *.sym *.lsg.* distclean: clean rm -f web/index.html web/oslfsck.1.html web/osl.png diff --git a/fsck.c b/fsck.c index 9701f27..f96f77c 100644 --- a/fsck.c +++ b/fsck.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -16,23 +17,15 @@ #include "osl.h" #include "util.h" #include "osl_core.h" -#include "fsck.cmdline.h" - -#define VERSION_TEXT(prefix) "osl" prefix " " VERSION " " "\n" \ - "Copyright (C) 2008-2009 Andre Noll\n" \ - "This is free software with ABSOLUTELY NO WARRANTY." \ - " See COPYING for details.\n" \ - "Written by Andre Noll.\n" \ - "Report bugs to .\n" - -/** print out \p VERSION_TEXT and exit if version flag was given */ -#define HANDLE_VERSION_FLAG(_prefix, _args_info_struct) \ - if (_args_info_struct.version_given) { \ - printf("%s", VERSION_TEXT(_prefix)); \ - exit(EXIT_SUCCESS); \ - } +#include "oslfsck.lsg.h" -static struct fsck_args_info conf; +static struct lls_parse_result *lpr; +#define CMD_PTR (lls_cmd(0, oslfsck_suite)) +#define OPT_RESULT(_name) \ + (lls_opt_result(LSG_OSLFSCK_OSLFSCK_OPT_ ## _name, lpr)) +#define OPT_GIVEN(_name) (lls_opt_given(OPT_RESULT(_name))) +#define OPT_STRING_VAL(_name) (lls_string_val(0, OPT_RESULT(_name))) +#define OPT_UINT32_VAL(_name) (lls_uint32_val(0, OPT_RESULT(_name))) #define FSCK_ERRORS \ FSCK_ERROR(RANGE_VIOLATION, "range violation detected, very bad"), \ @@ -390,7 +383,7 @@ static int check_range(struct osl_table *t, uint32_t row_num, uint32_t col_num) static int fsck_mark_row_invalid(struct osl_table *t, int i) { - if (conf.dry_run_given) + if (OPT_GIVEN(DRY_RUN)) return 0; return mark_row_invalid(t, i); } @@ -474,7 +467,7 @@ static int prune_invalid_rows_from_index(struct osl_table *t) } NOTICE_LOG("index contains %u invalid row(s) (%d bytes)\n", t->num_invalid_rows, t->row_index_size * t->num_invalid_rows); - if (conf.dry_run_given) + if (OPT_GIVEN(DRY_RUN)) return 0; NOTICE_LOG("removing invalid rows from index\n"); bottom = t->num_rows - 1; @@ -683,7 +676,7 @@ static int check_disk_storage_column(struct osl_table *t, int row_num, (*num_missing_objects)++; ERROR_LOG("row %d: object %s is missing\n", row_num, path); ret = 0; - if (conf.dry_run_given) + if (OPT_GIVEN(DRY_RUN)) goto out; NOTICE_LOG("trying to delete row %d\n", row_num); ret = osl_get_row(t, dsnc, &obj, &row); @@ -804,7 +797,7 @@ static int prune_disk_storage_file(const char *path, void *private_data) invalid: ERROR_LOG("could not read hash value of %s\n", path); remove: - if (conf.dry_run_given) + if (OPT_GIVEN(DRY_RUN)) return 0; NOTICE_LOG("removing %s\n", path); unlink(path); @@ -896,7 +889,7 @@ static int fsck_init(struct osl_table_description *desc, struct osl_table **t) } DEBUG_LOG("unmapping index\n"); osl_munmap(map.data, map.size); - if (conf.force_given) + if (OPT_GIVEN(FORCE)) ret = map_table(*t, (MAP_TBL_FL_IGNORE_DIRTY)); else ret = map_table(*t, 0); @@ -1100,7 +1093,7 @@ out: return ret; } -static int dump_table(char *dump_dir, struct osl_table_description *desc) +static int dump_table(const char *dump_dir, struct osl_table_description *desc) { struct osl_table *t = NULL; int fd, ret = fsck_init(desc, &t); @@ -1154,7 +1147,8 @@ static int fsck(struct osl_table_description *desc) ret = check_for_invalid_objects(t, &lost_bytes); if (ret < 0) goto out_unmap; - if (ret > 0 && !conf.dry_run_given) { /* at least one mapped data file needs pruning */ + if (ret > 0 && !OPT_GIVEN(DRY_RUN)) { + /* at least one mapped data file needs pruning */ ret = prune_objects(t, lost_bytes); if (ret < 0) goto out_unmap; @@ -1167,7 +1161,7 @@ out: return ret; } -static int check_table(char *db_dir, char *table_name) +static int check_table(const char *db_dir, const char *table_name) { struct osl_table_description desc = { .column_descriptions = NULL, @@ -1177,15 +1171,15 @@ static int check_table(char *db_dir, char *table_name) int ret; INFO_LOG("checking table %s\n", table_name); - if (!conf.no_fsck_given) { + if (!OPT_GIVEN(NO_FSCK)) { ret = fsck(&desc); if (ret < 0) goto out; } ret = 1; - if (!conf.dump_dir_given || !*conf.dump_dir_arg) + if (!OPT_GIVEN(DUMP_DIR) || !*OPT_STRING_VAL(DUMP_DIR)) goto out; - ret = dump_table(conf.dump_dir_arg, &desc); + ret = dump_table(OPT_STRING_VAL(DUMP_DIR), &desc); out: if (ret < 0) ERROR_LOG("failed to check table %s: %s\n", table_name, @@ -1195,7 +1189,7 @@ out: return ret; } -static int check_all_tables(char *db_dir) +static int check_all_tables(const char *db_dir) { DIR *dir; struct dirent *entry; @@ -1230,37 +1224,58 @@ static int check_all_tables(char *db_dir) int main(int argc, char **argv) { int i, ret; - struct fsck_cmdline_parser_params params = { - .override = 0, - .initialize = 1, - .check_required = 1, - .check_ambiguity = 1, - .print_errors = 1 - }; - ret = fsck_cmdline_parser_ext(argc, argv, &conf, ¶ms); + char *errctx = NULL; + const char *dd; + + loglevel = 0; + ret = lls_parse(argc, argv, CMD_PTR, &lpr, &errctx); if (ret < 0) { - loglevel = EMERG; - ret = -E_FSCK_SYNTAX; - goto out; + if (errctx) + ERROR_LOG("%s\n", errctx); + EMERG_LOG("%s\n", lls_strerror(-ret)); + exit(EXIT_FAILURE); + } + loglevel = OPT_UINT32_VAL(LOGLEVEL); + if (OPT_GIVEN(DETAILED_HELP)) { + printf("%s\n", lls_long_help(CMD_PTR)); + exit(EXIT_SUCCESS); + } + if (OPT_GIVEN(HELP)) { + printf("%s\n", lls_short_help(CMD_PTR)); + exit(EXIT_SUCCESS); + } + if (OPT_GIVEN(VERSION)) { + printf( + "oslfsck " OSL_VERSION "\n" + "Copyright (C) 2008-2009 Andre Noll\n" + "This is free software with ABSOLUTELY NO WARRANTY." + " See COPYING for details.\n" + "Written by Andre Noll.\n" + "Report bugs to .\n" + ); + exit(EXIT_SUCCESS); + } + dd = OPT_STRING_VAL(DATABASE_DIR); + if (!dd) { + EMERG_LOG("--database-dir: mandatory option not given\n"); + exit(EXIT_FAILURE); } - loglevel = conf.loglevel_arg; - HANDLE_VERSION_FLAG("fsck", conf); - INFO_LOG("database dir: %s\n", conf.database_dir_arg); - if (!conf.inputs_num) { - ret = check_all_tables(conf.database_dir_arg); + INFO_LOG("database dir: %s\n", dd); + if (lls_num_inputs(lpr) == 0) { + ret = check_all_tables(dd); goto out; } - for (i = 0; i < conf.inputs_num; i++) { - ret = check_table(conf.database_dir_arg, conf.inputs[i]); + for (i = 0; i < lls_num_inputs(lpr); i++) { + ret = check_table(dd, lls_input(i, lpr)); if (ret < 0) break; } out: if (ret < 0) { ERROR_LOG("%s\n", fsck_strerror(-ret)); - if (conf.loglevel_arg > 1) + if (loglevel > 1) EMERG_LOG("re-run with \"--loglevel %d\" to increase verbosity\n", - conf.loglevel_arg - 1); + loglevel - 1); } else NOTICE_LOG("success\n"); return ret < 0? EXIT_FAILURE : EXIT_SUCCESS; diff --git a/fsck.ggo b/fsck.ggo deleted file mode 100644 index 2452e3d..0000000 --- a/fsck.ggo +++ /dev/null @@ -1,54 +0,0 @@ -option "loglevel" l -#~~~~~~~~~~~~~~~~~~ -"Set loglevel (0-6)" -int typestr="level" -default="3" -optional -details=" - Log messages are always written to stderr while normal output - goes to stdout. Lower values mean more verbose logging. -" - -option "database-dir" d -#~~~~~~~~~~~~~~~~~~~~~~ -"Full path to the database directory" -string typestr="path" -required -details=" - Unless non-option arguments are given, all subdirectories - of \"path\" are considered osl tables which oslfsck will try - to fix. -" - -option "dump-dir" D -#~~~~~~~~~~~~~~~~~~ -"Enable dump mode" -string typestr="path" -optional -default="" -details=" - If path is non-empty, oslfsck will write a dump of all - given tables to the specified path. -" - -option "no-fsck" n -#~~~~~~~~~~~~~~~~~ -"Disable fsck mode." -flag off -details=" - This is mainly useful in conjunction with the --dump-dir - option. -" - -option "force" f -#~~~~~~~~~~~~~~~ -"Enable force mode" -flag off -details=" - Ignore the dirty bit when opening osl tables. -" - -option "dry-run" - -#~~~~~~~~~~~~~~~~~ -"Only report problems, don't try to fix them." -flag off diff --git a/oslfsck.suite b/oslfsck.suite new file mode 100644 index 0000000..a58e54f --- /dev/null +++ b/oslfsck.suite @@ -0,0 +1,61 @@ +[suite oslfsck] +[supercommand oslfsck] + purpose = check and repair the tables of an osl database + non-opts-name = [table]... + [description] + oslfsck tries to recover the tables of an osl database after a crash + which potentially leaves the database in an inconsistent state. + [/description] + [option help] + summary = print help and exit + short_opt = h + [option detailed-help] + summary = print help, including all details, and exit + [option version] + summary = print version and exit + short_opt = V + [option loglevel] + short_opt = l + summary = set loglevel (0-6) + arg_info = required_arg + arg_type = uint32 + typestr = severity + default_val = 3 + [help] + Log messages are always written to stderr while normal output goes + to stdout. Lower values mean more verbose logging. + [/help] + [option database-dir] + short_opt = d + summary = full path to the database directory + arg_info = required_arg + arg_type = string + typestr = path + [help] + Unless non-option arguments are given, all subdirectories of + are considered osl tables which oslfsck will try to fix. + [/help] + [option dump-dir] + short_opt = D + summary = enable dump mode + arg_info = required_arg + arg_type = string + typestr = path + [help] + If path is non-empty, oslfsck will write a dump of all given tables + to the specified path. + [/help] + [option no-fsck] + short_opt = n + summary = disable fsck mode + [help] + This is mainly useful in conjunction with the --dump-dir option. + [/help] + [option force] + short_opt = f + summary = enable force mode + [help] + Ignore the dirty bit when opening osl tables. + [/help] + [option dry-run] + summary = only report problems, don't try to fix them