📄 tar.c
字号:
set_stat_signal (const char *name){ static struct sigtab { char *name; int signo; } sigtab[] = { { "SIGUSR1", SIGUSR1 }, { "USR1", SIGUSR1 }, { "SIGUSR2", SIGUSR2 }, { "USR2", SIGUSR2 }, { "SIGHUP", SIGHUP }, { "HUP", SIGHUP }, { "SIGINT", SIGINT }, { "INT", SIGINT }, { "SIGQUIT", SIGQUIT }, { "QUIT", SIGQUIT } }; struct sigtab *p; for (p = sigtab; p < sigtab + sizeof (sigtab) / sizeof (sigtab[0]); p++) if (strcmp (p->name, name) == 0) { stat_on_signal (p->signo); return; } FATAL_ERROR ((0, 0, _("Unknown signal name: %s"), name));}struct textual_date{ struct textual_date *next; struct timespec *ts; const char *option; const char *date;};static voidget_date_or_file (struct tar_args *args, const char *option, const char *str, struct timespec *ts){ if (FILE_SYSTEM_PREFIX_LEN (str) != 0 || ISSLASH (*str) || *str == '.') { struct stat st; if (deref_stat (dereference_option, str, &st) != 0) { stat_error (str); USAGE_ERROR ((0, 0, _("Date sample file not found"))); } *ts = get_stat_mtime (&st); } else { if (! get_date (ts, str, NULL)) { WARN ((0, 0, _("Substituting %s for unknown date format %s"), tartime (*ts, false), quote (str))); ts->tv_nsec = 0; } else { struct textual_date *p = xmalloc (sizeof (*p)); p->ts = ts; p->option = option; p->date = str; p->next = args->textual_date; args->textual_date = p; } }}static voidreport_textual_dates (struct tar_args *args){ struct textual_date *p; for (p = args->textual_date; p; ) { struct textual_date *next = p->next; char const *treated_as = tartime (*p->ts, true); if (strcmp (p->date, treated_as) != 0) WARN ((0, 0, _("Option %s: Treating date `%s' as %s"), p->option, p->date, treated_as)); free (p); p = next; }}static volatile int _argp_hang;enum read_file_list_state /* Result of reading file name from the list file */ { file_list_success, /* OK, name read successfully */ file_list_end, /* End of list file */ file_list_zero, /* Zero separator encountered where it should not */ file_list_skip /* Empty (zero-length) entry encountered, skip it */ };/* Read from FP a sequence of characters up to FILENAME_TERMINATOR and put them into STK. */static enum read_file_list_stateread_name_from_file (FILE *fp, struct obstack *stk){ int c; size_t counter = 0; for (c = getc (fp); c != EOF && c != filename_terminator; c = getc (fp)) { if (c == 0) { /* We have read a zero separator. The file possibly is zero-separated */ return file_list_zero; } obstack_1grow (stk, c); counter++; } if (counter == 0 && c != EOF) return file_list_skip; obstack_1grow (stk, 0); return (counter == 0 && c == EOF) ? file_list_end : file_list_success;}static bool files_from_option; /* When set, tar will not refuse to create empty archives */static struct obstack argv_stk; /* Storage for additional command line options read using -T option *//* Prevent recursive inclusion of the same file */struct file_id_list{ struct file_id_list *next; ino_t ino; dev_t dev;};static struct file_id_list *file_id_list;static voidadd_file_id (const char *filename){ struct file_id_list *p; struct stat st; if (stat (filename, &st)) stat_fatal (filename); for (p = file_id_list; p; p = p->next) if (p->ino == st.st_ino && p->dev == st.st_dev) { FATAL_ERROR ((0, 0, _("%s: file list already read"), quotearg_colon (filename))); } p = xmalloc (sizeof *p); p->next = file_id_list; p->ino = st.st_ino; p->dev = st.st_dev; file_id_list = p;}/* Default density numbers for [0-9][lmh] device specifications */#ifndef LOW_DENSITY_NUM# define LOW_DENSITY_NUM 0#endif#ifndef MID_DENSITY_NUM# define MID_DENSITY_NUM 8#endif#ifndef HIGH_DENSITY_NUM# define HIGH_DENSITY_NUM 16#endifstatic voidupdate_argv (const char *filename, struct argp_state *state){ FILE *fp; size_t count = 0, i; char *start, *p; char **new_argv; size_t new_argc; bool is_stdin = false; enum read_file_list_state read_state; if (!strcmp (filename, "-")) { is_stdin = true; request_stdin ("-T"); fp = stdin; } else { add_file_id (filename); if ((fp = fopen (filename, "r")) == NULL) open_fatal (filename); } while ((read_state = read_name_from_file (fp, &argv_stk)) != file_list_end) { switch (read_state) { case file_list_success: count++; break; case file_list_end: /* won't happen, just to pacify gcc */ break; case file_list_zero: { size_t size; WARN ((0, 0, N_("%s: file name read contains nul character"), quotearg_colon (filename))); /* Prepare new stack contents */ size = obstack_object_size (&argv_stk); p = obstack_finish (&argv_stk); for (; size > 0; size--, p++) if (*p) obstack_1grow (&argv_stk, *p); else obstack_1grow (&argv_stk, '\n'); obstack_1grow (&argv_stk, 0); count = 1; /* Read rest of files using new filename terminator */ filename_terminator = 0; break; } case file_list_skip: break; } } if (!is_stdin) fclose (fp); if (count == 0) return; start = obstack_finish (&argv_stk); if (filename_terminator == 0) for (p = start; *p; p += strlen (p) + 1) if (p[0] == '-') count++; new_argc = state->argc + count; new_argv = xmalloc (sizeof (state->argv[0]) * (new_argc + 1)); memcpy (new_argv, state->argv, sizeof (state->argv[0]) * (state->argc + 1)); state->argv = new_argv; memmove (&state->argv[state->next + count], &state->argv[state->next], (state->argc - state->next + 1) * sizeof (state->argv[0])); state->argc = new_argc; for (i = state->next, p = start; *p; p += strlen (p) + 1, i++) { if (filename_terminator == 0 && p[0] == '-') state->argv[i++] = "--add-file"; state->argv[i] = p; }}static voidtar_help (struct argp_state *state){ argp_fmtstream_t fs; state->flags |= ARGP_NO_EXIT; argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP & ~ARGP_HELP_BUG_ADDR); /* FIXME: use struct uparams.rmargin (from argp-help.c) instead of 79 */ fs = argp_make_fmtstream (state->out_stream, 0, 79, 0); argp_fmtstream_printf (fs, "\n%s\n\n", _("Valid arguments for --quoting-style options are:")); tar_list_quoting_styles (fs, " "); argp_fmtstream_puts (fs, _("\n*This* tar defaults to:\n")); show_default_settings_fs (fs); argp_fmtstream_putc (fs, '\n'); argp_fmtstream_printf (fs, _("Report bugs to %s.\n"), argp_program_bug_address); argp_fmtstream_free (fs);}static error_tparse_opt (int key, char *arg, struct argp_state *state){ struct tar_args *args = state->input; switch (key) { case ARGP_KEY_ARG: /* File name or non-parsed option, because of ARGP_IN_ORDER */ name_add_name (arg, MAKE_INCL_OPTIONS (args)); args->input_files = true; break; case 'A': set_subcommand_option (CAT_SUBCOMMAND); break; case 'a': args->compress_autodetect = true; break; case 'b': { uintmax_t u; if (! (xstrtoumax (arg, 0, 10, &u, "") == LONGINT_OK && u == (blocking_factor = u) && 0 < blocking_factor && u == (record_size = u * BLOCKSIZE) / BLOCKSIZE)) USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg), _("Invalid blocking factor"))); } break; case 'B': /* Try to reblock input records. For reading 4.2BSD pipes. */ /* It would surely make sense to exchange -B and -R, but it seems that -B has been used for a long while in Sun tar and most BSD-derived systems. This is a consequence of the block/record terminology confusion. */ read_full_records_option = true; break; case 'c': set_subcommand_option (CREATE_SUBCOMMAND); break; case 'C': name_add_dir (arg); break; case 'd': set_subcommand_option (DIFF_SUBCOMMAND); break; case 'f': if (archive_names == allocated_archive_names) archive_name_array = x2nrealloc (archive_name_array, &allocated_archive_names, sizeof (archive_name_array[0])); archive_name_array[archive_names++] = arg; break; case 'F': /* Since -F is only useful with -M, make it implied. Run this script at the end of each tape. */ info_script_option = arg; multi_volume_option = true; break; case 'g': listed_incremental_option = arg; after_date_option = true; /* Fall through. */ case 'G': /* We are making an incremental dump (FIXME: are we?); save directories at the beginning of the archive, and include in each directory its contents. */ incremental_option = true; break; case 'h': /* Follow symbolic links. */ dereference_option = true; break; case HARD_DEREFERENCE_OPTION: hard_dereference_option = true; break; case 'i': /* Ignore zero blocks (eofs). This can't be the default, because Unix tar writes two blocks of zeros, then pads out the record with garbage. */ ignore_zeros_option = true; break; case 'I': USAGE_ERROR ((0, 0, _("Warning: the -I option is not supported;" " perhaps you meant -j or -T?"))); break; case 'j': set_use_compress_program_option ("bzip2"); break; case 'k': /* Don't replace existing files. */ old_files_option = KEEP_OLD_FILES; break; case 'K': starting_file_option = true; addname (arg, 0); break; case ONE_FILE_SYSTEM_OPTION: /* When dumping directories, don't dump files/subdirectories that are on other filesystems. */ one_file_system_option = true; break; case 'l': check_links_option = 1; break; case 'L': { uintmax_t u; if (xstrtoumax (arg, 0, 10, &u, "") != LONGINT_OK) USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (arg), _("Invalid tape length"))); tape_length_option = 1024 * (tarlong) u; multi_volume_option = true; } break; case LZMA_OPTION: set_use_compress_program_option ("lzma"); break; case 'm': touch_option = true; break; case 'M': /* Make multivolume archive: when we can't write any more into the archive, re-open it, and continue writing. */ multi_volume_option = true; break; case MTIME_OPTION: get_date_or_file (args, "--mtime", arg, &mtime_option); set_mtime_option = true; break; case 'n': seekable_archive = true; break; case 'N': after_date_option = true; /* Fall through. */ case NEWER_MTIME_OPTION:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -