Merge branch 'dfsg-orig' into dfsg-debian
[debian/tar] / lib / rtapelib.c
index 51faf3ce91dbd50496705ff15338e87d58c39466..7213031a1c77d88a28cc0df980311d0c10856ba6 100644 (file)
@@ -90,10 +90,10 @@ static int from_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
 /* The pipes for sending data to remote tape drives.  */
 static int to_remote[MAXUNIT][2] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}};
 
-char *rmt_command = DEFAULT_RMT_COMMAND;
+char const *rmt_command = DEFAULT_RMT_COMMAND;
 
 /* Temporary variable used by macros in rmt.h.  */
-char *rmt_dev_name__;
+char const *rmt_dev_name__;
 
 /* If true, always consider file names to be local, even if they contain
    colons */
@@ -121,7 +121,7 @@ do_command (int handle, const char *buffer)
   /* Save the current pipe handler and try to make the request.  */
 
   size_t length = strlen (buffer);
-  RETSIGTYPE (*pipe_handler) () = signal (SIGPIPE, SIG_IGN);
+  RETSIGTYPE (*pipe_handler) (int) = signal (SIGPIPE, SIG_IGN);
   ssize_t written = full_write (WRITE_SIDE (handle), buffer, length);
   signal (SIGPIPE, pipe_handler);
 
@@ -425,6 +425,9 @@ rmt_open__ (const char *file_name, int open_mode, int bias,
   }
 
   /* FIXME: Should somewhat validate the decoding, here.  */
+  if (gethostbyname (remote_host) == NULL)
+    error (EXIT_ON_EXEC_ERROR, 0, _("Cannot connect to %s: resolve failed"),
+          remote_host);
 
   if (remote_user && *remote_user == '\0')
     remote_user = 0;
@@ -487,15 +490,16 @@ rmt_open__ (const char *file_name, int open_mode, int bias,
       {
        /* Child.  */
 
-       close (STDIN_FILENO);
-       dup (to_remote[remote_pipe_number][PREAD]);
-       close (to_remote[remote_pipe_number][PREAD]);
-       close (to_remote[remote_pipe_number][PWRITE]);
-
-       close (STDOUT_FILENO);
-       dup (from_remote[remote_pipe_number][PWRITE]);
-       close (from_remote[remote_pipe_number][PREAD]);
-       close (from_remote[remote_pipe_number][PWRITE]);
+       if (dup2 (to_remote[remote_pipe_number][PREAD], STDIN_FILENO) < 0
+           || (to_remote[remote_pipe_number][PREAD] != STDIN_FILENO
+               && close (to_remote[remote_pipe_number][PREAD]) != 0)
+           || (to_remote[remote_pipe_number][PWRITE] != STDIN_FILENO
+               && close (to_remote[remote_pipe_number][PWRITE]) != 0)
+           || dup2 (from_remote[remote_pipe_number][PWRITE], STDOUT_FILENO) < 0
+           || close (from_remote[remote_pipe_number][PREAD]) != 0
+           || close (from_remote[remote_pipe_number][PWRITE]) != 0)
+         error (EXIT_ON_EXEC_ERROR, errno,
+                _("Cannot redirect files for remote shell"));
 
        sys_reset_uid_gid ();
 
@@ -570,7 +574,8 @@ rmt_read__ (int handle, char *buffer, size_t length)
 
   sprintf (command_buffer, "R%lu\n", (unsigned long) length);
   if (do_command (handle, command_buffer) == -1
-      || (status = get_status (handle)) == SAFE_READ_ERROR)
+      || (status = get_status (handle)) == SAFE_READ_ERROR
+      || status > length)
     return SAFE_READ_ERROR;
 
   for (counter = 0; counter < status; counter += rlen, buffer += rlen)
@@ -592,7 +597,7 @@ size_t
 rmt_write__ (int handle, char *buffer, size_t length)
 {
   char command_buffer[COMMAND_BUFFER_SIZE];
-  RETSIGTYPE (*pipe_handler) ();
+  RETSIGTYPE (*pipe_handler) (int);
   size_t written;
 
   sprintf (command_buffer, "W%lu\n", (unsigned long) length);
@@ -706,6 +711,12 @@ rmt_ioctl__ (int handle, int operation, char *argument)
            || (status = get_status (handle), status == -1))
          return -1;
 
+       if (status > sizeof (struct mtop))
+         {
+           errno = EOVERFLOW;
+           return -1;
+         }
+
        for (; status > 0; status -= counter, argument += counter)
          {
            counter = safe_read (READ_SIDE (handle), argument, status);