Import upstream version 1.27
[debian/tar] / gnu / modechange.c
index 97a8d1a5b22d8b5004829fb8b40f81aa00b1a060..4d003c0a41d0ce166d40a60f3c0a27ef6c22a029 100644 (file)
@@ -2,7 +2,7 @@
 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
 /* modechange.c -- file mode manipulation
 
-   Copyright (C) 1989-1990, 1997-1999, 2001, 2003-2006, 2009-2011 Free Software
+   Copyright (C) 1989-1990, 1997-1999, 2001, 2003-2006, 2009-2013 Free Software
    Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
@@ -20,7 +20,7 @@
 
 /* Written by David MacKenzie <djm@ai.mit.edu> */
 
-/* The ASCII mode string is compiled into an array of `struct
+/* The ASCII mode string is compiled into an array of 'struct
    modechange', which can then be applied to each file to be changed.
    We do this instead of re-parsing the ASCII string for each file
    because the compiled form requires less computation to use; when
@@ -92,7 +92,7 @@ enum
 
     /* Instead of the typical case, copy some existing permissions for
        u, g, or o onto the other two.  Which of u, g, or o is copied
-       is determined by which bits are set in the `value' field.  */
+       is determined by which bits are set in the 'value' field.  */
     MODE_COPY_EXISTING
   };
 
@@ -106,8 +106,8 @@ struct mode_change
   mode_t mentioned;             /* Bits explicitly mentioned.  */
 };
 
-/* Return a mode_change array with the specified `=ddd'-style
-   mode change operation, where NEW_MODE is `ddd' and MENTIONED
+/* Return a mode_change array with the specified "=ddd"-style
+   mode change operation, where NEW_MODE is "ddd" and MENTIONED
    contains the bits explicitly mentioned in the mode are MENTIONED.  */
 
 static struct mode_change *
@@ -129,7 +129,7 @@ make_node_op_equals (mode_t new_mode, mode_t mentioned)
    the form:
    [ugoa...][[+-=][rwxXstugo...]...][,...]
 
-   Return NULL if `mode_string' does not contain a valid
+   Return NULL if 'mode_string' does not contain a valid
    representation of file mode change operations.  */
 
 struct mode_change *
@@ -138,6 +138,7 @@ mode_compile (char const *mode_string)
   /* The array of mode-change directives to be returned.  */
   struct mode_change *mc;
   size_t used = 0;
+  char const *p;
 
   if ('0' <= *mode_string && *mode_string < '8')
     {
@@ -145,40 +146,43 @@ mode_compile (char const *mode_string)
       mode_t mode;
       mode_t mentioned;
 
+      p = mode_string;
       do
         {
-          octal_mode = 8 * octal_mode + *mode_string++ - '0';
+          octal_mode = 8 * octal_mode + *p++ - '0';
           if (ALLM < octal_mode)
             return NULL;
         }
-      while ('0' <= *mode_string && *mode_string < '8');
+      while ('0' <= *p && *p < '8');
 
-      if (*mode_string)
+      if (*p)
         return NULL;
 
       mode = octal_to_mode (octal_mode);
-      mentioned = (mode & (S_ISUID | S_ISGID)) | S_ISVTX | S_IRWXUGO;
+      mentioned = (p - mode_string < 5
+                   ? (mode & (S_ISUID | S_ISGID)) | S_ISVTX | S_IRWXUGO
+                   : CHMOD_MODE_BITS);
       return make_node_op_equals (mode, mentioned);
     }
 
   /* Allocate enough space to hold the result.  */
   {
     size_t needed = 1;
-    char const *p;
     for (p = mode_string; *p; p++)
       needed += (*p == '=' || *p == '+' || *p == '-');
     mc = xnmalloc (needed, sizeof *mc);
   }
 
-  /* One loop iteration for each `[ugoa]*([-+=]([rwxXst]*|[ugo]))+'.  */
-  for (;; mode_string++)
+  /* One loop iteration for each
+     '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=][0-7]+'.  */
+  for (p = mode_string; ; p++)
     {
       /* Which bits in the mode are operated on.  */
       mode_t affected = 0;
 
-      /* Turn on all the bits in `affected' for each group given.  */
-      for (;; mode_string++)
-        switch (*mode_string)
+      /* Turn on all the bits in 'affected' for each group given.  */
+      for (;; p++)
+        switch (*p)
           {
           default:
             goto invalid;
@@ -201,35 +205,60 @@ mode_compile (char const *mode_string)
 
       do
         {
-          char op = *mode_string++;
+          char op = *p++;
           mode_t value;
+          mode_t mentioned = 0;
           char flag = MODE_COPY_EXISTING;
           struct mode_change *change;
 
-          switch (*mode_string++)
+          switch (*p)
             {
+            case '0': case '1': case '2': case '3':
+            case '4': case '5': case '6': case '7':
+              {
+                unsigned int octal_mode = 0;
+
+                do
+                  {
+                    octal_mode = 8 * octal_mode + *p++ - '0';
+                    if (ALLM < octal_mode)
+                      return NULL;
+                  }
+                while ('0' <= *p && *p < '8');
+
+                if (affected || (*p && *p != ','))
+                  return NULL;
+                affected = mentioned = CHMOD_MODE_BITS;
+                value = octal_to_mode (octal_mode);
+                flag = MODE_ORDINARY_CHANGE;
+                break;
+              }
+
             case 'u':
-              /* Set the affected bits to the value of the `u' bits
+              /* Set the affected bits to the value of the "u" bits
                  on the same file.  */
               value = S_IRWXU;
+              p++;
               break;
             case 'g':
-              /* Set the affected bits to the value of the `g' bits
+              /* Set the affected bits to the value of the "g" bits
                  on the same file.  */
               value = S_IRWXG;
+              p++;
               break;
             case 'o':
-              /* Set the affected bits to the value of the `o' bits
+              /* Set the affected bits to the value of the "o" bits
                  on the same file.  */
               value = S_IRWXO;
+              p++;
               break;
 
             default:
               value = 0;
               flag = MODE_ORDINARY_CHANGE;
 
-              for (mode_string--;; mode_string++)
-                switch (*mode_string)
+              for (;; p++)
+                switch (*p)
                   {
                   case 'r':
                     value |= S_IRUSR | S_IRGRP | S_IROTH;
@@ -244,11 +273,11 @@ mode_compile (char const *mode_string)
                     flag = MODE_X_IF_ANY_X;
                     break;
                   case 's':
-                    /* Set the setuid/gid bits if `u' or `g' is selected.  */
+                    /* Set the setuid/gid bits if 'u' or 'g' is selected.  */
                     value |= S_ISUID | S_ISGID;
                     break;
                   case 't':
-                    /* Set the "save text image" bit if `o' is selected.  */
+                    /* Set the "save text image" bit if 'o' is selected.  */
                     value |= S_ISVTX;
                     break;
                   default:
@@ -262,16 +291,16 @@ mode_compile (char const *mode_string)
           change->flag = flag;
           change->affected = affected;
           change->value = value;
-          change->mentioned = (affected ? affected & value : value);
+          change->mentioned =
+            (mentioned ? mentioned : affected ? affected & value : value);
         }
-      while (*mode_string == '=' || *mode_string == '+'
-             || *mode_string == '-');
+      while (*p == '=' || *p == '+' || *p == '-');
 
-      if (*mode_string != ',')
+      if (*p != ',')
         break;
     }
 
-  if (*mode_string == 0)
+  if (*p == 0)
     {
       mc[used].flag = MODE_DONE;
       return mc;
@@ -331,7 +360,7 @@ mode_adjust (mode_t oldmode, bool dir, mode_t umask_value,
           break;
 
         case MODE_COPY_EXISTING:
-          /* Isolate in `value' the bits in `newmode' to copy.  */
+          /* Isolate in 'value' the bits in 'newmode' to copy.  */
           value &= newmode;
 
           /* Copy the isolated bits to the other two parts.  */