4
0
Эх сурвалжийг харах

(parse_opt): Adjust to new modechange API.

Paul Eggert 20 жил өмнө
parent
commit
82c746410d
1 өөрчлөгдсөн 126 нэмэгдсэн , 128 устгасан
  1. 126 128
      src/tar.c

+ 126 - 128
src/tar.c

@@ -1,7 +1,7 @@
 /* A tar (tape archiver) program.
 /* A tar (tape archiver) program.
 
 
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
-   2001, 2003, 2004 Free Software Foundation, Inc.
+   2001, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 
    Written by John Gilmore, starting 1985-08-25.
    Written by John Gilmore, starting 1985-08-25.
 
 
@@ -268,14 +268,14 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\n\n
    E  use extended headers (--format=posix)
    E  use extended headers (--format=posix)
    [q  alias for --occurrence=1 =/= this would better be used for quiet?]
    [q  alias for --occurrence=1 =/= this would better be used for quiet?]
    [I  same as T =/= will harm star compatibility]
    [I  same as T =/= will harm star compatibility]
-   
+
    y  per-file gzip compression
    y  per-file gzip compression
    Y  per-block gzip compression */
    Y  per-block gzip compression */
 
 
 static struct argp_option options[] = {
 static struct argp_option options[] = {
   {NULL, 0, NULL, 0,
   {NULL, 0, NULL, 0,
    N_("Main operation mode:"), 0},
    N_("Main operation mode:"), 0},
-  
+
   {"list", 't', 0, 0,
   {"list", 't', 0, 0,
    N_("list the contents of an archive"), 10 },
    N_("list the contents of an archive"), 10 },
   {"extract", 'x', 0, 0,
   {"extract", 'x', 0, 0,
@@ -343,7 +343,7 @@ static struct argp_option options[] = {
    N_("ignore exit codes of children"), 41 },
    N_("ignore exit codes of children"), 41 },
   {"no-ignore-command-error", NO_IGNORE_COMMAND_ERROR_OPTION, 0, 0,
   {"no-ignore-command-error", NO_IGNORE_COMMAND_ERROR_OPTION, 0, 0,
    N_("treat non-zero exit codes of children as error"), 41 },
    N_("treat non-zero exit codes of children as error"), 41 },
-    
+
   {NULL, 0, NULL, 0,
   {NULL, 0, NULL, 0,
    N_("Handling of file attributes:"), 50 },
    N_("Handling of file attributes:"), 50 },
 
 
@@ -377,20 +377,20 @@ static struct argp_option options[] = {
 
 
   {NULL, 0, NULL, 0,
   {NULL, 0, NULL, 0,
    N_("Device selection and switching:"), 60 },
    N_("Device selection and switching:"), 60 },
-  
+
   {"file", 'f', N_("ARCHIVE"), 0,
   {"file", 'f', N_("ARCHIVE"), 0,
    N_("use archive file or device ARCHIVE"), 61 },
    N_("use archive file or device ARCHIVE"), 61 },
   {"force-local", FORCE_LOCAL_OPTION, 0, 0,
   {"force-local", FORCE_LOCAL_OPTION, 0, 0,
    N_("archive file is local even if it has a colon"), 61 },
    N_("archive file is local even if it has a colon"), 61 },
   {"rmt-command", RMT_COMMAND_OPTION, N_("COMMAND"), 0,
   {"rmt-command", RMT_COMMAND_OPTION, N_("COMMAND"), 0,
-   N_("use given rmt COMMAND instead of rmt"), 61 }, 
+   N_("use given rmt COMMAND instead of rmt"), 61 },
   {"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
   {"rsh-command", RSH_COMMAND_OPTION, N_("COMMAND"), 0,
    N_("use remote COMMAND instead of rsh"), 61 },
    N_("use remote COMMAND instead of rsh"), 61 },
 #ifdef DEVICE_PREFIX
 #ifdef DEVICE_PREFIX
   {"-[0-7][lmh]", 0, NULL, OPTION_DOC, /* It is OK, since `name' will never be
   {"-[0-7][lmh]", 0, NULL, OPTION_DOC, /* It is OK, since `name' will never be
 					  translated */
 					  translated */
    N_("specify drive and density"), 61 },
    N_("specify drive and density"), 61 },
-#endif  
+#endif
   {NULL, '0', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '0', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '1', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '1', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '2', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '2', NULL, OPTION_HIDDEN, NULL, 61 },
@@ -401,7 +401,7 @@ static struct argp_option options[] = {
   {NULL, '7', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '7', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '8', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '8', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '9', NULL, OPTION_HIDDEN, NULL, 61 },
   {NULL, '9', NULL, OPTION_HIDDEN, NULL, 61 },
-  
+
   {"multi-volume", 'M', 0, 0,
   {"multi-volume", 'M', 0, 0,
    N_("create/list/extract multi-volume archive"), 61 },
    N_("create/list/extract multi-volume archive"), 61 },
   {"tape-length", 'L', N_("NUMBER"), 0,
   {"tape-length", 'L', N_("NUMBER"), 0,
@@ -422,11 +422,11 @@ static struct argp_option options[] = {
   {"ignore-zeros", 'i', 0, 0,
   {"ignore-zeros", 'i', 0, 0,
    N_("ignore zeroed blocks in archive (means EOF)"), 71 },
    N_("ignore zeroed blocks in archive (means EOF)"), 71 },
   {"read-full-records", 'B', 0, 0,
   {"read-full-records", 'B', 0, 0,
-   N_("reblock as we read (for 4.2BSD pipes)"), 71 }, 
+   N_("reblock as we read (for 4.2BSD pipes)"), 71 },
 
 
   {NULL, 0, NULL, 0,
   {NULL, 0, NULL, 0,
    N_("Archive format selection:"), 80 },
    N_("Archive format selection:"), 80 },
-  
+
   {"format", 'H', N_("FORMAT"), 0,
   {"format", 'H', N_("FORMAT"), 0,
    N_("create archive of the given format."), 81 },
    N_("create archive of the given format."), 81 },
 
 
@@ -441,7 +441,7 @@ static struct argp_option options[] = {
   {"  pax", 0, NULL, OPTION_DOC|OPTION_NO_TRANS,
   {"  pax", 0, NULL, OPTION_DOC|OPTION_NO_TRANS,
    N_("POSIX 1003.1-2001 (pax) format"), 83 },
    N_("POSIX 1003.1-2001 (pax) format"), 83 },
   {"  posix", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, N_("same as pax"), 83 },
   {"  posix", 0, NULL, OPTION_DOC|OPTION_NO_TRANS, N_("same as pax"), 83 },
-  
+
   {"old-archive", OLD_ARCHIVE_OPTION, 0, 0, /* FIXME */
   {"old-archive", OLD_ARCHIVE_OPTION, 0, 0, /* FIXME */
    N_("same as --format=v7"), 88 },
    N_("same as --format=v7"), 88 },
   {"portability", 0, 0, OPTION_ALIAS, NULL, 88 },
   {"portability", 0, 0, OPTION_ALIAS, NULL, 88 },
@@ -528,7 +528,7 @@ static struct argp_option options[] = {
 
 
   {NULL, 0, NULL, 0,
   {NULL, 0, NULL, 0,
    N_("Informative output:"), 100 },
    N_("Informative output:"), 100 },
-  
+
   {"verbose", 'v', 0, 0,
   {"verbose", 'v', 0, 0,
    N_("verbosely list files processed"), 101 },
    N_("verbosely list files processed"), 101 },
   {"checkpoint", CHECKPOINT_OPTION, 0, 0,
   {"checkpoint", CHECKPOINT_OPTION, 0, 0,
@@ -550,7 +550,7 @@ static struct argp_option options[] = {
    N_("Show tar defaults"), 102 },
    N_("Show tar defaults"), 102 },
   {"show-omitted-dirs", SHOW_OMITTED_DIRS_OPTION, 0, 0,
   {"show-omitted-dirs", SHOW_OMITTED_DIRS_OPTION, 0, 0,
    N_("When listing or extracting, list each directory that does not match search criteria"), 102 },
    N_("When listing or extracting, list each directory that does not match search criteria"), 102 },
-  
+
   {NULL, 0, NULL, 0,
   {NULL, 0, NULL, 0,
    N_("Compatibility options:"), 110 },
    N_("Compatibility options:"), 110 },
 
 
@@ -696,7 +696,7 @@ add_file_id (const char *filename)
   p->dev = st.st_dev;
   p->dev = st.st_dev;
   file_id_list = p;
   file_id_list = p;
 }
 }
-      
+
 static void
 static void
 update_argv (const char *filename, struct argp_state *state)
 update_argv (const char *filename, struct argp_state *state)
 {
 {
@@ -706,7 +706,7 @@ update_argv (const char *filename, struct argp_state *state)
   char **new_argv;
   char **new_argv;
   size_t new_argc;
   size_t new_argc;
   bool is_stdin = false;
   bool is_stdin = false;
-  
+
   if (!strcmp (filename, "-"))
   if (!strcmp (filename, "-"))
     {
     {
       is_stdin = true;
       is_stdin = true;
@@ -719,23 +719,23 @@ update_argv (const char *filename, struct argp_state *state)
       if ((fp = fopen (filename, "r")) == NULL)
       if ((fp = fopen (filename, "r")) == NULL)
 	open_fatal (filename);
 	open_fatal (filename);
     }
     }
-  
+
   while (read_name_from_file (fp, &argv_stk))
   while (read_name_from_file (fp, &argv_stk))
     count++;
     count++;
 
 
   if (!is_stdin)
   if (!is_stdin)
     fclose (fp);
     fclose (fp);
-  
+
   if (count == 0)
   if (count == 0)
     return;
     return;
 
 
   start = obstack_finish (&argv_stk);
   start = obstack_finish (&argv_stk);
-  
+
   if (filename_terminator == 0)
   if (filename_terminator == 0)
     for (p = start; *p; p += strlen (p) + 1)
     for (p = start; *p; p += strlen (p) + 1)
       if (p[0] == '-')
       if (p[0] == '-')
 	count++;
 	count++;
-    
+
   new_argc = state->argc + count;
   new_argc = state->argc + count;
   new_argv = xmalloc (sizeof (state->argv[0]) * (new_argc + 1));
   new_argv = xmalloc (sizeof (state->argv[0]) * (new_argc + 1));
   memcpy (new_argv, state->argv, sizeof (state->argv[0]) * (state->argc + 1));
   memcpy (new_argv, state->argv, sizeof (state->argv[0]) * (state->argc + 1));
@@ -758,7 +758,7 @@ static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 parse_opt (int key, char *arg, struct argp_state *state)
 {
 {
   struct tar_args *args = state->input;
   struct tar_args *args = state->input;
-  
+
   switch (key)
   switch (key)
     {
     {
       case ARGP_KEY_ARG:
       case ARGP_KEY_ARG:
@@ -770,7 +770,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'A':
     case 'A':
       set_subcommand_option (CAT_SUBCOMMAND);
       set_subcommand_option (CAT_SUBCOMMAND);
       break;
       break;
-      
+
     case 'b':
     case 'b':
       {
       {
 	uintmax_t u;
 	uintmax_t u;
@@ -785,12 +785,12 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
 
     case 'B':
     case 'B':
       /* Try to reblock input records.  For reading 4.2BSD pipes.  */
       /* Try to reblock input records.  For reading 4.2BSD pipes.  */
-      
+
       /* It would surely make sense to exchange -B and -R, but it seems
       /* 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
 	 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
 	 BSD-derived systems.  This is a consequence of the block/record
 	 terminology confusion.  */
 	 terminology confusion.  */
-      
+
       read_full_records_option = true;
       read_full_records_option = true;
       break;
       break;
 
 
@@ -821,57 +821,57 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'F':
     case 'F':
       /* Since -F is only useful with -M, make it implied.  Run this
       /* Since -F is only useful with -M, make it implied.  Run this
 	 script at the end of each tape.  */
 	 script at the end of each tape.  */
-      
+
       info_script_option = arg;
       info_script_option = arg;
       multi_volume_option = true;
       multi_volume_option = true;
       break;
       break;
-      
+
     case 'g':
     case 'g':
       listed_incremental_option = arg;
       listed_incremental_option = arg;
       after_date_option = true;
       after_date_option = true;
       /* Fall through.  */
       /* Fall through.  */
-      
+
     case 'G':
     case 'G':
       /* We are making an incremental dump (FIXME: are we?); save
       /* We are making an incremental dump (FIXME: are we?); save
 	 directories at the beginning of the archive, and include in each
 	 directories at the beginning of the archive, and include in each
 	 directory its contents.  */
 	 directory its contents.  */
-      
+
       incremental_option = true;
       incremental_option = true;
       break;
       break;
-      
+
     case 'h':
     case 'h':
       /* Follow symbolic links.  */
       /* Follow symbolic links.  */
       dereference_option = true;
       dereference_option = true;
       break;
       break;
-      
+
     case 'i':
     case 'i':
       /* Ignore zero blocks (eofs).  This can't be the default,
       /* Ignore zero blocks (eofs).  This can't be the default,
 	 because Unix tar writes two blocks of zeros, then pads out
 	 because Unix tar writes two blocks of zeros, then pads out
 	 the record with garbage.  */
 	 the record with garbage.  */
-      
+
       ignore_zeros_option = true;
       ignore_zeros_option = true;
       break;
       break;
-      
+
     case 'I':
     case 'I':
       USAGE_ERROR ((0, 0,
       USAGE_ERROR ((0, 0,
 		    _("Warning: the -I option is not supported;"
 		    _("Warning: the -I option is not supported;"
 		      " perhaps you meant -j or -T?")));
 		      " perhaps you meant -j or -T?")));
       break;
       break;
-      
+
     case 'j':
     case 'j':
       set_use_compress_program_option ("bzip2");
       set_use_compress_program_option ("bzip2");
       break;
       break;
-      
+
     case 'k':
     case 'k':
       /* Don't replace existing files.  */
       /* Don't replace existing files.  */
       old_files_option = KEEP_OLD_FILES;
       old_files_option = KEEP_OLD_FILES;
       break;
       break;
-      
+
     case 'K':
     case 'K':
       starting_file_option = true;
       starting_file_option = true;
       addname (arg, 0);
       addname (arg, 0);
       break;
       break;
-      
+
     case 'l':
     case 'l':
       /* Historically equivalent to --one-file-system. This usage is
       /* Historically equivalent to --one-file-system. This usage is
 	 incompatible with UNIX98 and POSIX specs and therefore is
 	 incompatible with UNIX98 and POSIX specs and therefore is
@@ -888,7 +888,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	 that are on other filesystems. */
 	 that are on other filesystems. */
       one_file_system_option = true;
       one_file_system_option = true;
       break;
       break;
-      
+
     case 'L':
     case 'L':
       {
       {
 	uintmax_t u;
 	uintmax_t u;
@@ -899,22 +899,22 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	multi_volume_option = true;
 	multi_volume_option = true;
       }
       }
       break;
       break;
-      
+
     case 'm':
     case 'm':
       touch_option = true;
       touch_option = true;
       break;
       break;
-      
+
     case 'M':
     case 'M':
       /* Make multivolume archive: when we can't write any more into
       /* Make multivolume archive: when we can't write any more into
 	 the archive, re-open it, and continue writing.  */
 	 the archive, re-open it, and continue writing.  */
-      
+
       multi_volume_option = true;
       multi_volume_option = true;
       break;
       break;
 
 
     case 'n':
     case 'n':
       seekable_archive = true;
       seekable_archive = true;
       break;
       break;
-      
+
 #if !MSDOS
 #if !MSDOS
     case 'N':
     case 'N':
       after_date_option = true;
       after_date_option = true;
@@ -923,7 +923,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case NEWER_MTIME_OPTION:
     case NEWER_MTIME_OPTION:
       if (NEWER_OPTION_INITIALIZED (newer_mtime_option))
       if (NEWER_OPTION_INITIALIZED (newer_mtime_option))
 	USAGE_ERROR ((0, 0, _("More than one threshold date")));
 	USAGE_ERROR ((0, 0, _("More than one threshold date")));
-      
+
       if (FILE_SYSTEM_PREFIX_LEN (arg) != 0
       if (FILE_SYSTEM_PREFIX_LEN (arg) != 0
 	  || ISSLASH (*arg)
 	  || ISSLASH (*arg)
 	  || *arg == '.')
 	  || *arg == '.')
@@ -948,14 +948,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	  else
 	  else
 	    args->textual_date_option = arg;
 	    args->textual_date_option = arg;
 	}
 	}
-      
+
       break;
       break;
 #endif /* not MSDOS */
 #endif /* not MSDOS */
-      
+
     case 'o':
     case 'o':
       args->o_option = true;
       args->o_option = true;
       break;
       break;
-      
+
     case 'O':
     case 'O':
       to_stdout_option = true;
       to_stdout_option = true;
       break;
       break;
@@ -963,36 +963,36 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'p':
     case 'p':
       same_permissions_option = true;
       same_permissions_option = true;
       break;
       break;
-      
+
     case 'P':
     case 'P':
       absolute_names_option = true;
       absolute_names_option = true;
       break;
       break;
-      
+
     case 'r':
     case 'r':
       set_subcommand_option (APPEND_SUBCOMMAND);
       set_subcommand_option (APPEND_SUBCOMMAND);
       break;
       break;
-      
+
     case 'R':
     case 'R':
       /* Print block numbers for debugging bad tar archives.  */
       /* Print block numbers for debugging bad tar archives.  */
-      
+
       /* It would surely make sense to exchange -B and -R, but it seems
       /* 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 ans most
 	 that -B has been used for a long while in Sun tar ans most
 	 BSD-derived systems.  This is a consequence of the block/record
 	 BSD-derived systems.  This is a consequence of the block/record
 	 terminology confusion.  */
 	 terminology confusion.  */
-      
+
       block_number_option = true;
       block_number_option = true;
       break;
       break;
-      
+
     case 's':
     case 's':
       /* Names to extr are sorted.  */
       /* Names to extr are sorted.  */
-      
+
       same_order_option = true;
       same_order_option = true;
       break;
       break;
-      
+
     case 'S':
     case 'S':
       sparse_option = true;
       sparse_option = true;
       break;
       break;
-      
+
     case 't':
     case 't':
       set_subcommand_option (LIST_SUBCOMMAND);
       set_subcommand_option (LIST_SUBCOMMAND);
       verbose_option++;
       verbose_option++;
@@ -1003,41 +1003,41 @@ parse_opt (int key, char *arg, struct argp_state *state)
       /* Indicate we've been given -T option. This is for backward
       /* Indicate we've been given -T option. This is for backward
 	 compatibility only, so that `tar cfT archive /dev/null will
 	 compatibility only, so that `tar cfT archive /dev/null will
 	 succeed */
 	 succeed */
-      files_from_option = true; 
+      files_from_option = true;
       break;
       break;
-      
+
     case 'u':
     case 'u':
       set_subcommand_option (UPDATE_SUBCOMMAND);
       set_subcommand_option (UPDATE_SUBCOMMAND);
       break;
       break;
-      
+
     case 'U':
     case 'U':
       old_files_option = UNLINK_FIRST_OLD_FILES;
       old_files_option = UNLINK_FIRST_OLD_FILES;
       break;
       break;
-      
+
     case UTC_OPTION:
     case UTC_OPTION:
       utc_option = true;
       utc_option = true;
       break;
       break;
-      
+
     case 'v':
     case 'v':
       verbose_option++;
       verbose_option++;
       break;
       break;
-      
+
     case 'V':
     case 'V':
       volume_label_option = arg;
       volume_label_option = arg;
       break;
       break;
-      
+
     case 'w':
     case 'w':
       interactive_option = true;
       interactive_option = true;
       break;
       break;
-      
+
     case 'W':
     case 'W':
       verify_option = true;
       verify_option = true;
       break;
       break;
-      
+
     case 'x':
     case 'x':
       set_subcommand_option (EXTRACT_SUBCOMMAND);
       set_subcommand_option (EXTRACT_SUBCOMMAND);
       break;
       break;
-      
+
     case 'X':
     case 'X':
       if (add_exclude_file (add_exclude, excluded, arg,
       if (add_exclude_file (add_exclude, excluded, arg,
 			    args->exclude_options | recursion_option, '\n')
 			    args->exclude_options | recursion_option, '\n')
@@ -1047,17 +1047,17 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	  FATAL_ERROR ((0, e, "%s", quotearg_colon (arg)));
 	  FATAL_ERROR ((0, e, "%s", quotearg_colon (arg)));
 	}
 	}
       break;
       break;
-      
+
     case 'y':
     case 'y':
       USAGE_ERROR ((0, 0,
       USAGE_ERROR ((0, 0,
 		    _("Warning: the -y option is not supported;"
 		    _("Warning: the -y option is not supported;"
 		      " perhaps you meant -j?")));
 		      " perhaps you meant -j?")));
       break;
       break;
-      
+
     case 'z':
     case 'z':
       set_use_compress_program_option ("gzip");
       set_use_compress_program_option ("gzip");
       break;
       break;
-      
+
     case 'Z':
     case 'Z':
       set_use_compress_program_option ("compress");
       set_use_compress_program_option ("compress");
       break;
       break;
@@ -1065,29 +1065,29 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case ANCHORED_OPTION:
     case ANCHORED_OPTION:
       args->exclude_options |= EXCLUDE_ANCHORED;
       args->exclude_options |= EXCLUDE_ANCHORED;
       break;
       break;
-      
+
     case ATIME_PRESERVE_OPTION:
     case ATIME_PRESERVE_OPTION:
       atime_preserve_option = true;
       atime_preserve_option = true;
       break;
       break;
-      
+
     case CHECKPOINT_OPTION:
     case CHECKPOINT_OPTION:
       checkpoint_option = true;
       checkpoint_option = true;
       break;
       break;
-      
+
     case BACKUP_OPTION:
     case BACKUP_OPTION:
       backup_option = true;
       backup_option = true;
       if (arg)
       if (arg)
 	args->version_control_string = arg;
 	args->version_control_string = arg;
       break;
       break;
-      
+
     case DELETE_OPTION:
     case DELETE_OPTION:
       set_subcommand_option (DELETE_SUBCOMMAND);
       set_subcommand_option (DELETE_SUBCOMMAND);
       break;
       break;
-      
+
     case EXCLUDE_OPTION:
     case EXCLUDE_OPTION:
       add_exclude (excluded, arg, args->exclude_options | recursion_option);
       add_exclude (excluded, arg, args->exclude_options | recursion_option);
       break;
       break;
-      
+
     case EXCLUDE_CACHES_OPTION:
     case EXCLUDE_CACHES_OPTION:
       exclude_caches_option = true;
       exclude_caches_option = true;
       break;
       break;
@@ -1095,15 +1095,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case FORCE_LOCAL_OPTION:
     case FORCE_LOCAL_OPTION:
       force_local_option = true;
       force_local_option = true;
       break;
       break;
-      
+
     case 'H':
     case 'H':
       set_archive_format (arg);
       set_archive_format (arg);
       break;
       break;
-      
+
     case INDEX_FILE_OPTION:
     case INDEX_FILE_OPTION:
       index_file_name = arg;
       index_file_name = arg;
       break;
       break;
-      
+
     case IGNORE_CASE_OPTION:
     case IGNORE_CASE_OPTION:
       args->exclude_options |= FNM_CASEFOLD;
       args->exclude_options |= FNM_CASEFOLD;
       break;
       break;
@@ -1111,15 +1111,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case IGNORE_COMMAND_ERROR_OPTION:
     case IGNORE_COMMAND_ERROR_OPTION:
       ignore_command_error_option = true;
       ignore_command_error_option = true;
       break;
       break;
-      
+
     case IGNORE_FAILED_READ_OPTION:
     case IGNORE_FAILED_READ_OPTION:
       ignore_failed_read_option = true;
       ignore_failed_read_option = true;
       break;
       break;
-      
+
     case KEEP_NEWER_FILES_OPTION:
     case KEEP_NEWER_FILES_OPTION:
       old_files_option = KEEP_NEWER_FILES;
       old_files_option = KEEP_NEWER_FILES;
       break;
       break;
-      
+
     case GROUP_OPTION:
     case GROUP_OPTION:
       if (! (strlen (arg) < GNAME_FIELD_SIZE
       if (! (strlen (arg) < GNAME_FIELD_SIZE
 	     && gname_to_gid (arg, &group_option)))
 	     && gname_to_gid (arg, &group_option)))
@@ -1133,25 +1133,23 @@ parse_opt (int key, char *arg, struct argp_state *state)
 			  _("%s: Invalid group")));
 			  _("%s: Invalid group")));
 	}
 	}
       break;
       break;
-      
+
     case MODE_OPTION:
     case MODE_OPTION:
-      mode_option
-	= mode_compile (arg,
-			MODE_MASK_EQUALS | MODE_MASK_PLUS | MODE_MASK_MINUS);
-      if (mode_option == MODE_INVALID)
+      mode_option = mode_compile (arg);
+      if (!mode_option)
 	FATAL_ERROR ((0, 0, _("Invalid mode given on option")));
 	FATAL_ERROR ((0, 0, _("Invalid mode given on option")));
-      if (mode_option == MODE_MEMORY_EXHAUSTED)
-	xalloc_die ();
+      initial_umask = umask (0);
+      umask (initial_umask);
       break;
       break;
-      
+
     case NO_ANCHORED_OPTION:
     case NO_ANCHORED_OPTION:
       args->exclude_options &= ~ EXCLUDE_ANCHORED;
       args->exclude_options &= ~ EXCLUDE_ANCHORED;
       break;
       break;
-      
+
     case NO_IGNORE_CASE_OPTION:
     case NO_IGNORE_CASE_OPTION:
       args->exclude_options &= ~ FNM_CASEFOLD;
       args->exclude_options &= ~ FNM_CASEFOLD;
       break;
       break;
-      
+
     case NO_IGNORE_COMMAND_ERROR_OPTION:
     case NO_IGNORE_COMMAND_ERROR_OPTION:
       ignore_command_error_option = false;
       ignore_command_error_option = false;
       break;
       break;
@@ -1159,23 +1157,23 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case NO_OVERWRITE_DIR_OPTION:
     case NO_OVERWRITE_DIR_OPTION:
       old_files_option = NO_OVERWRITE_DIR_OLD_FILES;
       old_files_option = NO_OVERWRITE_DIR_OLD_FILES;
       break;
       break;
-      
+
     case NO_WILDCARDS_OPTION:
     case NO_WILDCARDS_OPTION:
       args->exclude_options &= ~ EXCLUDE_WILDCARDS;
       args->exclude_options &= ~ EXCLUDE_WILDCARDS;
       break;
       break;
-      
+
     case NO_WILDCARDS_MATCH_SLASH_OPTION:
     case NO_WILDCARDS_MATCH_SLASH_OPTION:
       args->exclude_options |= FNM_FILE_NAME;
       args->exclude_options |= FNM_FILE_NAME;
       break;
       break;
-      
+
     case NULL_OPTION:
     case NULL_OPTION:
       filename_terminator = '\0';
       filename_terminator = '\0';
       break;
       break;
-      
+
     case NUMERIC_OWNER_OPTION:
     case NUMERIC_OWNER_OPTION:
       numeric_owner_option = true;
       numeric_owner_option = true;
       break;
       break;
-      
+
     case OCCURRENCE_OPTION:
     case OCCURRENCE_OPTION:
       if (!arg)
       if (!arg)
 	occurrence_option = 1;
 	occurrence_option = 1;
@@ -1189,7 +1187,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 			  _("Invalid number")));
 			  _("Invalid number")));
 	}
 	}
       break;
       break;
-      
+
     case OVERWRITE_OPTION:
     case OVERWRITE_OPTION:
       old_files_option = OVERWRITE_OLD_FILES;
       old_files_option = OVERWRITE_OLD_FILES;
       break;
       break;
@@ -1207,21 +1205,21 @@ parse_opt (int key, char *arg, struct argp_state *state)
 			  _("Invalid owner")));
 			  _("Invalid owner")));
 	}
 	}
       break;
       break;
-      
+
     case PAX_OPTION:
     case PAX_OPTION:
       args->pax_option++;
       args->pax_option++;
       xheader_set_option (arg);
       xheader_set_option (arg);
       break;
       break;
-      
+
     case POSIX_OPTION:
     case POSIX_OPTION:
       set_archive_format ("posix");
       set_archive_format ("posix");
       break;
       break;
-      
+
     case PRESERVE_OPTION:
     case PRESERVE_OPTION:
       same_permissions_option = true;
       same_permissions_option = true;
       same_order_option = true;
       same_order_option = true;
       break;
       break;
-      
+
     case RECORD_SIZE_OPTION:
     case RECORD_SIZE_OPTION:
       {
       {
 	uintmax_t u;
 	uintmax_t u;
@@ -1236,27 +1234,27 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	blocking_factor = record_size / BLOCKSIZE;
 	blocking_factor = record_size / BLOCKSIZE;
       }
       }
       break;
       break;
-      
+
     case RECURSIVE_UNLINK_OPTION:
     case RECURSIVE_UNLINK_OPTION:
       recursive_unlink_option = true;
       recursive_unlink_option = true;
       break;
       break;
-      
+
     case REMOVE_FILES_OPTION:
     case REMOVE_FILES_OPTION:
       remove_files_option = true;
       remove_files_option = true;
       break;
       break;
-      
+
     case RMT_COMMAND_OPTION:
     case RMT_COMMAND_OPTION:
       rmt_command = arg;
       rmt_command = arg;
       break;
       break;
-      
+
     case RSH_COMMAND_OPTION:
     case RSH_COMMAND_OPTION:
       rsh_command_option = arg;
       rsh_command_option = arg;
       break;
       break;
-      
+
     case SHOW_DEFAULTS_OPTION:
     case SHOW_DEFAULTS_OPTION:
       show_default_settings (stdout);
       show_default_settings (stdout);
       exit(0);
       exit(0);
-      
+
     case STRIP_COMPONENTS_OPTION:
     case STRIP_COMPONENTS_OPTION:
       {
       {
 	uintmax_t u;
 	uintmax_t u;
@@ -1271,7 +1269,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case SHOW_OMITTED_DIRS_OPTION:
     case SHOW_OMITTED_DIRS_OPTION:
       show_omitted_dirs_option = true;
       show_omitted_dirs_option = true;
       break;
       break;
-      
+
     case SUFFIX_OPTION:
     case SUFFIX_OPTION:
       backup_option = true;
       backup_option = true;
       args->backup_suffix_string = arg;
       args->backup_suffix_string = arg;
@@ -1282,23 +1280,23 @@ parse_opt (int key, char *arg, struct argp_state *state)
         USAGE_ERROR ((0, 0, _("Only one --to-command option allowed")));
         USAGE_ERROR ((0, 0, _("Only one --to-command option allowed")));
       to_command_option = arg;
       to_command_option = arg;
       break;
       break;
-      
+
     case TOTALS_OPTION:
     case TOTALS_OPTION:
       totals_option = true;
       totals_option = true;
       break;
       break;
-      
+
     case USE_COMPRESS_PROGRAM_OPTION:
     case USE_COMPRESS_PROGRAM_OPTION:
       set_use_compress_program_option (arg);
       set_use_compress_program_option (arg);
       break;
       break;
-      
+
     case VOLNO_FILE_OPTION:
     case VOLNO_FILE_OPTION:
       volno_file_option = arg;
       volno_file_option = arg;
       break;
       break;
-      
+
     case WILDCARDS_OPTION:
     case WILDCARDS_OPTION:
       args->exclude_options |= EXCLUDE_WILDCARDS;
       args->exclude_options |= EXCLUDE_WILDCARDS;
       break;
       break;
-      
+
     case WILDCARDS_MATCH_SLASH_OPTION:
     case WILDCARDS_MATCH_SLASH_OPTION:
       args->exclude_options &= ~ FNM_FILE_NAME;
       args->exclude_options &= ~ FNM_FILE_NAME;
       break;
       break;
@@ -1306,7 +1304,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case CHECK_LINKS_OPTION:
     case CHECK_LINKS_OPTION:
       check_links_option = 1;
       check_links_option = 1;
       break;
       break;
-      
+
     case NO_RECURSION_OPTION:
     case NO_RECURSION_OPTION:
       recursion_option = 0;
       recursion_option = 0;
       break;
       break;
@@ -1334,7 +1332,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case NO_UNQUOTE_OPTION:
     case NO_UNQUOTE_OPTION:
       unquote_option = false;
       unquote_option = false;
       break;
       break;
-      
+
     case '0':
     case '0':
     case '1':
     case '1':
     case '2':
     case '2':
@@ -1353,14 +1351,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
 
 	if (arg[1])
 	if (arg[1])
 	  argp_error (state, _("Malformed density argument: %s"), quote (arg));
 	  argp_error (state, _("Malformed density argument: %s"), quote (arg));
-	
+
 	strcpy (buf, DEVICE_PREFIX);
 	strcpy (buf, DEVICE_PREFIX);
 	cursor = buf + strlen (buf);
 	cursor = buf + strlen (buf);
 
 
 #ifdef DENSITY_LETTER
 #ifdef DENSITY_LETTER
 
 
 	sprintf (cursor, "%d%c", device, arg[0]);
 	sprintf (cursor, "%d%c", device, arg[0]);
-	
+
 #else /* not DENSITY_LETTER */
 #else /* not DENSITY_LETTER */
 
 
 	switch (arg[0])
 	switch (arg[0])
@@ -1370,7 +1368,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	    device += LOW_NUM;
 	    device += LOW_NUM;
 #endif
 #endif
 	    break;
 	    break;
-	    
+
 	  case 'm':
 	  case 'm':
 #ifdef MID_NUM
 #ifdef MID_NUM
 	    device += MID_NUM;
 	    device += MID_NUM;
@@ -1378,7 +1376,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	    device += 8;
 	    device += 8;
 #endif
 #endif
 	    break;
 	    break;
-	    
+
 	  case 'h':
 	  case 'h':
 #ifdef HGH_NUM
 #ifdef HGH_NUM
 	    device += HGH_NUM;
 	    device += HGH_NUM;
@@ -1391,7 +1389,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	    argp_error (state, _("Unknown density: `%c'"), arg[0]);
 	    argp_error (state, _("Unknown density: `%c'"), arg[0]);
 	  }
 	  }
 	sprintf (cursor, "%d", device);
 	sprintf (cursor, "%d", device);
-	
+
 #endif /* not DENSITY_LETTER */
 #endif /* not DENSITY_LETTER */
 
 
 	if (archive_names == allocated_archive_names)
 	if (archive_names == allocated_archive_names)
@@ -1407,11 +1405,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
 
 #else /* not DEVICE_PREFIX */
 #else /* not DEVICE_PREFIX */
 
 
-      argp_error (state, 
+      argp_error (state,
 		  _("Options `-[0-7][lmh]' not supported by *this* tar"));
 		  _("Options `-[0-7][lmh]' not supported by *this* tar"));
-      
+
 #endif /* not DEVICE_PREFIX */
 #endif /* not DEVICE_PREFIX */
-      
+
     case '?':
     case '?':
       state->flags |= ARGP_NO_EXIT;
       state->flags |= ARGP_NO_EXIT;
       argp_state_help (state, state->out_stream,
       argp_state_help (state, state->out_stream,
@@ -1419,7 +1417,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       fprintf (state->out_stream, _("\n*This* tar defaults to:\n"));
       fprintf (state->out_stream, _("\n*This* tar defaults to:\n"));
       show_default_settings (state->out_stream);
       show_default_settings (state->out_stream);
       fprintf (state->out_stream, "\n");
       fprintf (state->out_stream, "\n");
-      fprintf (state->out_stream, _("Report bugs to %s.\n"), 
+      fprintf (state->out_stream, _("Report bugs to %s.\n"),
 	       argp_program_bug_address);
 	       argp_program_bug_address);
       exit (0);
       exit (0);
 
 
@@ -1441,7 +1439,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       while (_argp_hang-- > 0)
       while (_argp_hang-- > 0)
 	sleep (1);
 	sleep (1);
       break;
       break;
-      
+
     default:
     default:
       return ARGP_ERR_UNKNOWN;
       return ARGP_ERR_UNKNOWN;
     }
     }
@@ -1486,7 +1484,7 @@ decode_options (int argc, char **argv)
 {
 {
   int index;
   int index;
   struct tar_args args;
   struct tar_args args;
-  
+
   /* Set some default option values.  */
   /* Set some default option values.  */
   args.textual_date_option = NULL;
   args.textual_date_option = NULL;
   args.exclude_options = EXCLUDE_WILDCARDS;
   args.exclude_options = EXCLUDE_WILDCARDS;
@@ -1505,7 +1503,7 @@ decode_options (int argc, char **argv)
   newer_mtime_option.tv_nsec = -1;
   newer_mtime_option.tv_nsec = -1;
   recursion_option = FNM_LEADING_DIR;
   recursion_option = FNM_LEADING_DIR;
   unquote_option = true;
   unquote_option = true;
-  
+
   owner_option = -1;
   owner_option = -1;
   group_option = -1;
   group_option = -1;
 
 
@@ -1540,7 +1538,7 @@ decode_options (int argc, char **argv)
       for (letter = *in++; *letter; letter++)
       for (letter = *in++; *letter; letter++)
 	{
 	{
 	  struct argp_option *opt;
 	  struct argp_option *opt;
-	  
+
 	  buffer[1] = *letter;
 	  buffer[1] = *letter;
 	  *out++ = xstrdup (buffer);
 	  *out++ = xstrdup (buffer);
 	  opt = find_argp_option (options, *letter);
 	  opt = find_argp_option (options, *letter);
@@ -1573,7 +1571,7 @@ decode_options (int argc, char **argv)
   if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
   if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
 		  &index, &args))
 		  &index, &args))
     exit (1);
     exit (1);
-      
+
 
 
   /* Special handling for 'o' option:
   /* Special handling for 'o' option:
 
 
@@ -1652,7 +1650,7 @@ decode_options (int argc, char **argv)
 	 problem. */
 	 problem. */
       seekable_archive = false;
       seekable_archive = false;
     }
     }
-  
+
   if (archive_names == 0)
   if (archive_names == 0)
     {
     {
       /* If no archive file name given, try TAPE from the environment, or
       /* If no archive file name given, try TAPE from the environment, or
@@ -1821,7 +1819,7 @@ main (int argc, char **argv)
   archive_names = 0;
   archive_names = 0;
 
 
   obstack_init (&argv_stk);
   obstack_init (&argv_stk);
-  
+
 #ifdef SIGCHLD
 #ifdef SIGCHLD
   /* System V fork+wait does not work if SIGCHLD is ignored.  */
   /* System V fork+wait does not work if SIGCHLD is ignored.  */
   signal (SIGCHLD, SIG_DFL);
   signal (SIGCHLD, SIG_DFL);