]> Dogcows Code - chaz/tar/blobdiff - src/rmt.c
(decode_options): Adjust to addname's new signature.
[chaz/tar] / src / rmt.c
index bf2e0a128640a6fd5850104f331a85ad47c5ff22..30d665f8746f17581c99423a9ebc2339b97393ca 100644 (file)
--- a/src/rmt.c
+++ b/src/rmt.c
@@ -30,6 +30,7 @@
    MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.  */
 
 #include "system.h"
+#include "safe-read.h"
 
 #include <sys/socket.h>
 
@@ -128,7 +129,7 @@ get_string (char *string)
 
   for (counter = 0; counter < STRING_SIZE; counter++)
     {
-      if (full_read (STDIN_FILENO, string + counter, 1) != 1)
+      if (safe_read (STDIN_FILENO, string + counter, 1) != 1)
        exit (EXIT_SUCCESS);
 
       if (string[counter] == '\n')
@@ -174,6 +175,83 @@ prepare_record_buffer (size_t size)
 #endif
 }
 
+/* Decode OFLAG_STRING, which represents the 2nd argument to `open'.
+   OFLAG_STRING should contain an optional integer, followed by an optional
+   symbolic representation of an open flag using only '|' to separate its
+   components (e.g. "O_WRONLY|O_CREAT|O_TRUNC").  Prefer the symbolic
+   representation if available, falling back on the numeric
+   representation, or to zero if both formats are absent.
+
+   This function should be the inverse of encode_oflag.  The numeric
+   representation is not portable from one host to another, but it is
+   for backward compatibility with old-fashioned clients that do not
+   emit symbolic open flags.  */
+
+static int
+decode_oflag (char const *oflag_string)
+{
+  char *oflag_num_end;
+  int numeric_oflag = strtol (oflag_string, &oflag_num_end, 10);
+  int symbolic_oflag = 0;
+  
+  oflag_string = oflag_num_end;
+  while (ISSPACE ((unsigned char) *oflag_string))
+    oflag_string++;
+    
+  do
+    {
+      struct name_value_pair { char const *name; int value; };
+      static struct name_value_pair const table[] =
+      {
+       {"APPEND", O_APPEND},
+       {"CREAT", O_CREAT},
+#ifdef O_DSYNC
+       {"DSYNC", O_DSYNC},
+#endif
+       {"EXCL", O_EXCL},
+#ifdef O_LARGEFILE
+       {"LARGEFILE", O_LARGEFILE}, /* LFS extension for opening large files */
+#endif
+#ifdef O_NOCTTY
+       {"NOCTTY", O_NOCTTY},
+#endif
+#ifdef O_NONBLOCK
+       {"NONBLOCK", O_NONBLOCK},
+#endif
+       {"RDONLY", O_RDONLY},
+       {"RDWR", O_RDWR},
+#ifdef O_RSYNC
+       {"RSYNC", O_RSYNC},
+#endif
+#ifdef O_SYNC
+       {"SYNC", O_SYNC},
+#endif
+       {"TRUNC", O_TRUNC},
+       {"WRONLY", O_WRONLY}
+      };
+      struct name_value_pair const *t;
+      size_t s;
+
+      if (*oflag_string++ != 'O' || *oflag_string++ != '_')
+       return numeric_oflag;
+
+      for (t = table;
+          (strncmp (oflag_string, t->name, s = strlen (t->name)) != 0
+           || (oflag_string[s]
+               && strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789",
+                          oflag_string[s])));
+          t++)
+       if (t == table + sizeof table / sizeof *table - 1)
+         return numeric_oflag;
+
+      symbolic_oflag |= t->value;
+      oflag_string += s;
+    }
+  while (*oflag_string++ == '|');
+
+  return symbolic_oflag;
+}
+
 /*---.
 | ?  |
 `---*/
@@ -210,7 +288,7 @@ main (int argc, char *const *argv)
 top:
   errno = 0;                   /* FIXME: errno should be read-only */
   status = 0;
-  if (full_read (STDIN_FILENO, &command, 1) != 1)
+  if (safe_read (STDIN_FILENO, &command, 1) != 1)
     exit (EXIT_SUCCESS);
 
   switch (command)
@@ -220,16 +298,16 @@ top:
     case 'O':
       {
        char device_string[STRING_SIZE];
-       char mode_string[STRING_SIZE];
+       char oflag_string[STRING_SIZE];
 
        get_string (device_string);
-       get_string (mode_string);
-       DEBUG2 ("rmtd: O %s %s\n", device_string, mode_string);
+       get_string (oflag_string);
+       DEBUG2 ("rmtd: O %s %s\n", device_string, oflag_string);
 
        if (tape >= 0)
          close (tape);
 
-       tape = open (device_string, atoi (mode_string), 0666);
+       tape = open (device_string, decode_oflag (oflag_string), MODE_RW);
        if (tape < 0)
          goto ioerror;
        goto respond;
@@ -254,6 +332,7 @@ top:
        char position_string[STRING_SIZE];
        off_t count = 0;
        int negative;
+       int whence;
        char *p;
 
        get_string (count_string);
@@ -288,7 +367,16 @@ top:
              }
          }
 
-       count = lseek (tape, count, atoi (position_string));
+       switch (atoi (position_string))
+         {
+         case 0: whence = SEEK_SET; break;
+         case 1: whence = SEEK_CUR; break;
+         case 2: whence = SEEK_END; break;
+         default:
+           report_error_message (N_("Seek direction out of range"));
+           exit (EXIT_FAILURE);
+         }
+       count = lseek (tape, count, whence);
        if (count < 0)
          goto ioerror;
 
@@ -320,8 +408,8 @@ top:
        prepare_record_buffer (size);
        for (counter = 0; counter < size; counter += status)
          {
-           status = full_read (STDIN_FILENO, &record_buffer[counter],
-                          size - counter);
+           status = safe_read (STDIN_FILENO, &record_buffer[counter],
+                               size - counter);
            if (status <= 0)
              {
                DEBUG (_("rmtd: Premature eof\n"));
@@ -346,7 +434,7 @@ top:
 
        size = atol (count_string);
        prepare_record_buffer (size);
-       status = full_read (tape, record_buffer, size);
+       status = safe_read (tape, record_buffer, size);
        if (status < 0)
          goto ioerror;
        sprintf (reply_buffer, "A%ld\n", status);
This page took 0.027517 seconds and 4 git commands to generate.