/* cmd-inventory.c: file inventories * * vim:smartindent ts=8:sts=2:sta:et:ai:shiftwidth=2 **************************************************************** * Copyright (C) 2002, 2003 Tom Lord * * See the file "COPYING" for further information about * the copyright and warranty status of this work. */ #include "config-options.h" #include "po/gettext.h" #include "hackerlab/bugs/exception.h" #include "hackerlab/cmd/main.h" #include "hackerlab/vu/safe.h" #include "hackerlab/char/pika-escaping-utils.h" #include "hackerlab/os/errno-to-string.h" #include "libarch/project-tree.h" #include "libarch/invent.h" #include "commands/cmd.h" #include "commands/inventory.h" #include "commands/version.h" static t_uchar * usage = N_("[options] [dir]*"); #define OPTS(OP) \ OP (opt_help_msg, "h", "help", 0, \ N_("display help")) \ OP (opt_long_help, "H", 0, 0, \ N_("Display a verbose help message and exit.")) \ OP (opt_version, "V", "version", 0, \ N_("display version info\n")) \ OP (opt_source, "s", "source", 0, \ N_("list source files")) \ OP (opt_precious, "p", "precious", 0, \ N_("list precious files")) \ OP (opt_backups, "b", "backups", 0, \ N_("list backup files")) \ OP (opt_junk, "j", "junk", 0, \ N_("list junk files")) \ OP (opt_unrecognized, "u", "unrecognized", 0, \ N_("list unrecognized files")) \ OP (opt_trees, "t", "trees", 0, \ N_("list roots of nested trees\n")) \ OP (opt_directories, "d", "directories", 0, \ N_("list only directories")) \ OP (opt_files, "f", "files", 0, \ N_("list only non-directories")) \ OP (opt_both, "B", "both", 0, \ N_("list both dirs and files")) \ OP (opt_kind, 0, "kind", 0, \ N_("indicate file kinds\n")) \ OP (opt_all, 0, "all", 0, \ N_("include arch control files")) \ OP (opt_nested, 0, "nested", 0, \ N_("include nested trees")) \ OP (opt_no_recursion, 0, "no-recursion", 0, \ N_("do not list content of directory\n")) \ OP (opt_ids, 0, "ids", 0, \ N_("list with ids (source files only)")) \ OP (opt_untagged, 0, "untagged", 0, \ N_("include files that are missing ids\n")) \ OP (opt_explicit, 0, "explicit", 0, \ N_("use explicit file ids")) \ OP (opt_implicit, 0, "implicit", 0, \ N_("permit implicit file ids")) \ OP (opt_tagline, 0, "tagline", 0, \ N_("permit tagline file ids")) \ OP (opt_names, 0, "names", 0, \ N_("use name-based file ids")) \ OP (opt_unescaped, 0, "unescaped", 0, \ N_("show filenames in unescaped form")) t_uchar arch_cmd_inventory_help[] = N_("inventory a source tree\n" "With no arguments, print a human-readable inventory report.\n" "\n" "With category options (--source etc) limit the report to just\n" "those files. With no other options, the report includes all\n" "sections and files.\n" "\n" "The options -d, -f, and -b cancel each other.\n" "\n" "The options --nested and --no-recursion cancel each other.\n" "\n" "If a directory is precious, junk, or unrecognized, only the\n" "directory name itself is printed -- its contents are not\n" "searched.\n"); enum options { OPTS (OPT_ENUM) }; static struct opt_desc opts[] = { OPTS (OPT_DESC) {-1, 0, 0, 0, 0} }; /* __STDC__ prototypes for static functions */ static void inventory_printer (void * closure, invent_callback_data_t const * const data); static int show_dirs = 0; static int show_files = 1; static int show_kind = 0; static int show_ids; static int n_categories = 0; int arch_cmd_inventory (t_uchar * program_name, int argc, char * argv[]) { int o; struct opt_parsed * option; struct arch_inventory_options inv_options; int escape_classes = arch_escape_classes; option = 0; mem_set0 ((t_uchar *)&inv_options, sizeof (inv_options)); while (1) { o = opt_standard (lim_use_must_malloc, &option, opts, &argc, argv, program_name, usage, libarch_version_string, arch_cmd_inventory_help, opt_help_msg, opt_long_help, opt_version); if (o == opt_none) break; switch (o) { default: safe_printfmt (2, "unhandled option `%s'\n", option->opt_string); panic ("internal error parsing arguments"); usage_error: opt_usage (2, argv[0], program_name, usage, 1); exit (1); /* bogus_arg: */ safe_printfmt (2, "ill-formed argument for `%s' (`%s')\n", option->opt_string, option->arg_string); goto usage_error; case opt_source: inv_options.categories |= arch_inventory_source; break; case opt_precious: inv_options.categories |= arch_inventory_precious; break; case opt_backups: inv_options.categories |= arch_inventory_backup; break; case opt_junk: inv_options.categories |= arch_inventory_junk; break; case opt_unrecognized: inv_options.categories |= arch_inventory_unrecognized; break; case opt_trees: inv_options.categories |= arch_inventory_tree; break; case opt_no_recursion: inv_options.no_recursion = 1; inv_options.nested = 0; break; case opt_directories: show_dirs = 1; show_files = 0; break; case opt_files: show_dirs = 0; show_files = 1; break; case opt_both: show_dirs = 1; show_files = 1; break; case opt_kind: show_kind = 1; break; case opt_all: inv_options.include_excluded = 1; break; case opt_nested: inv_options.nested = 1; inv_options.no_recursion = 0; break; case opt_ids: inv_options.want_ids = 1; show_ids = 1; break; case opt_untagged: inv_options.treat_unrecognized_source_as_source = 1; break; case opt_explicit: inv_options.override_method = 1; inv_options.method = arch_explicit_id_tagging; break; case opt_implicit: inv_options.override_method = 1; inv_options.method = arch_implicit_id_tagging; break; case opt_tagline: inv_options.override_method = 1; inv_options.method = arch_tagline_id_tagging; break; case opt_names: inv_options.override_method = 1; inv_options.method = arch_names_id_tagging; break; case opt_unescaped: escape_classes = 0; break; } } lim_free (lim_use_must_malloc, option); n_categories = 0; if (inv_options.categories & arch_inventory_source) ++n_categories; if (inv_options.categories & arch_inventory_precious) ++n_categories; if (inv_options.categories & arch_inventory_backup) ++n_categories; if (inv_options.categories & arch_inventory_junk) ++n_categories; if (inv_options.categories & arch_inventory_tree) ++n_categories; if (inv_options.categories & arch_inventory_unrecognized) ++n_categories; if (!n_categories) { n_categories = 6; inv_options.categories = arch_inventory_source | arch_inventory_precious | arch_inventory_backup | arch_inventory_tree | arch_inventory_unrecognized; } if (argc == 1) { argv[1] = "."; ++argc; } { int x; int errn; int re_error; for (x = 1; x < argc; ++x) { arch_project_tree_t * tree; char * bad_file; errn = 0; re_error = 0; if ( vu_access(&errn, argv[x], X_OK | F_OK ) == -1) { safe_printfmt (2, "inventory: Cannot access directory %s\n%s\n", argv[x], errno_to_string(errn)); exit (2); } tree = arch_project_tree_new_ext (talloc_context, argv[x], 1, 0); arch_get_inventory_naming_conventions (&inv_options, tree); bad_file = 0; arch_inventory_traversal_path (&inv_options, tree, argv[x], inventory_printer, &escape_classes); arch_free_inventory_naming_conventions (&inv_options); arch_project_tree_delete (tree); } } return 0; } static void inventory_printer (void * closure, invent_callback_data_t const * const data) { t_uchar * path = data->path; if ((data->category != arch_inventory_tree) && !show_dirs && S_ISDIR (data->stat_buf.st_mode)) return; if (!show_files && !S_ISDIR (data->stat_buf.st_mode)) return; if (n_categories > 1) { t_uchar * quest = (data->has_source_name ? "?" : " "); switch (data->category) { case arch_inventory_source: safe_printfmt (1, "S "); break; case arch_inventory_precious: safe_printfmt (1, "P%s ", quest); break; case arch_inventory_backup: safe_printfmt (1, "B%s ", quest); break; case arch_inventory_junk: safe_printfmt (1, "J%s ", quest); break; case arch_inventory_tree: safe_printfmt (1, "T%s ", quest); break; case arch_inventory_unrecognized: safe_printfmt (1, "U%s ", quest); break; case arch_inventory_excludes: break; } } if (show_kind) { if (S_ISDIR (data->stat_buf.st_mode)) safe_printfmt (1, "d "); else if (S_ISLNK (data->stat_buf.st_mode)) safe_printfmt (1, "> "); else safe_printfmt (1, "r "); } if (path[0] == '.' && path[1] == '/') path += 2; { t_uchar * item; item = pika_save_escape_iso8859_1 (0, 0, *(int *)closure, path); safe_printfmt (1, "%s%s%s\n", item, (show_ids ? "\t" : ""), (show_ids ? (data->id ? (char *)data->id : "???") : "")); lim_free (0, item); } } /* tag: Tom Lord Wed May 14 10:52:12 2003 (srcfind.c) */