Pārlūkot izejas kodu

(encode_oflag): New function.
(rmt_open__): Do not allow newlines in the path.
Propagate errno correctly.
Decode symbolic open flags, if present.

Paul Eggert 26 gadi atpakaļ
vecāks
revīzija
8af82f2c4e
1 mainītis faili ar 64 papildinājumiem un 5 dzēšanām
  1. 64 5
      src/rtapelib.c

+ 64 - 5
src/rtapelib.c

@@ -312,6 +312,47 @@ _rmt_rexec (char *host, char *user)
 
 #endif /* WITH_REXEC */
 
+/* Place into BUF a string representing OFLAG, which must be suitable
+   as argument 2 of `open'.  BUF must be large enough to hold the
+   result.  This function should generate a string that decode_oflag
+   can parse.  */
+static void
+encode_oflag (char *buf, int oflag)
+{
+  sprintf (buf, "%d ", oflag);
+
+  switch (oflag & O_ACCMODE)
+    {
+    case O_RDONLY: strcat (buf, "O_RDONLY"); break;
+    case O_RDWR: strcat (buf, "O_RDWR"); break;
+    case O_WRONLY: strcat (buf, "O_WRONLY"); break;
+    default: abort ();
+    }
+
+  if (oflag & O_APPEND) strcat (buf, "|O_APPEND");
+  if (oflag & O_CREAT) strcat (buf, "|O_CREAT");
+#ifdef O_DSYNC
+  if (oflag & O_DSYNC) strcat (buf, "|O_DSYNC");
+#endif
+  if (oflag & O_EXCL) strcat (buf, "|O_EXCL");
+#ifdef O_LARGEFILE
+  if (oflag & O_LARGEFILE) strcat (buf, "|O_LARGEFILE");
+#endif
+#ifdef O_NOCTTY
+  if (oflag & O_NOCTTY) strcat (buf, "|O_NOCTTY");
+#endif
+#ifdef O_NONBLOCK
+  if (oflag & O_NONBLOCK) strcat (buf, "|O_NONBLOCK");
+#endif
+#ifdef O_RSYNC
+  if (oflag & O_RSYNC) strcat (buf, "|O_RSYNC");
+#endif
+#ifdef O_SYNC
+  if (oflag & O_SYNC) strcat (buf, "|O_SYNC");
+#endif
+  if (oflag & O_TRUNC) strcat (buf, "|O_TRUNC");
+}
+
 /*------------------------------------------------------------------------.
 | Open a file (a magnetic tape device?) on the system specified in PATH,  |
 | as the given user.  PATH has the form `[USER@]HOST:FILE'.  OPEN_MODE is |
@@ -359,6 +400,13 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
 	default:
 	  break;
 
+	case '\n':
+	  /* Do not allow newlines in the path, since the protocol
+	     uses newline delimiters.  */
+	  free (path_copy);
+	  errno = ENOENT;
+	  return -1;
+
 	case '@':
 	  if (!remote_user)
 	    {
@@ -390,7 +438,9 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
   READ_SIDE (remote_pipe_number) = _rmt_rexec (remote_host, remote_user);
   if (READ_SIDE (remote_pipe_number) < 0)
     {
+      int e = errno;
       free (path_copy);
+      errno = e;
       return -1;
     }
 
@@ -408,8 +458,8 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
 #ifdef REMOTE_SHELL
 	remote_shell = REMOTE_SHELL;
 #else
-	errno = EIO;		/* FIXME: errno should be read-only */
 	free (path_copy);
+	errno = EIO;
 	return -1;
 #endif
       }
@@ -420,14 +470,18 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
     if (pipe (to_remote[remote_pipe_number]) == -1
 	|| pipe (from_remote[remote_pipe_number]) == -1)
       {
+	int e = errno;
 	free (path_copy);
+	errno = e;
 	return -1;
       }
 
     status = fork ();
     if (status == -1)
       {
+	int e = errno;
 	free (path_copy);
+	errno = e;
 	return -1;
       }
 
@@ -473,16 +527,21 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
   /* Attempt to open the tape device.  */
 
   {
-    char command_buffer[COMMAND_BUFFER_SIZE];
-
-    sprintf (command_buffer, "O%s\n%d\n", remote_file, open_mode);
+    size_t remote_file_len = strlen (remote_file);
+    char *command_buffer = xmalloc (remote_file_len + 1000);
+    sprintf (command_buffer, "O%s\n", remote_file);
+    encode_oflag (command_buffer + remote_file_len + 2, open_mode);
+    strcat (command_buffer, "\n");
     if (do_command (remote_pipe_number, command_buffer) == -1
 	|| get_status (remote_pipe_number) == -1)
       {
-	_rmt_shutdown (remote_pipe_number, errno);
+	int e = errno;
+	free (command_buffer);
 	free (path_copy);
+	_rmt_shutdown (remote_pipe_number, e);
 	return -1;
       }
+    free (command_buffer);
   }
 
   free (path_copy);