X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Frtapelib.c;h=138425fcfe075b33a128faa8bf00f8f7df64acc3;hb=f9d278ba35f0c34d33b0a0b7158e355cc91e6c85;hp=0afdec9716f05c4ff2cc6e8064a8430174407075;hpb=db6dc02fa83b1010e02e67472ae22c61542a7ba8;p=chaz%2Ftar diff --git a/src/rtapelib.c b/src/rtapelib.c index 0afdec9..138425f 100644 --- a/src/rtapelib.c +++ b/src/rtapelib.c @@ -1,5 +1,5 @@ /* Functions for communicating with a remote tape drive. - Copyright (C) 1988, 1992, 1994, 1996 Free Software Foundation, Inc. + Copyright 1988, 1992, 1994, 1996, 1997, 1999 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,6 +32,9 @@ #include "system.h" +#include "basename.h" +#include "safe-read.h" + /* Try hard to get EOPNOTSUPP defined. 486/ISC has it in net/errno.h, 3B2/SVR3 has it in sys/inet.h. Otherwise, like on MSDOS, use EINVAL. */ @@ -144,7 +147,7 @@ get_status_string (int handle, char *command_buffer) counter < COMMAND_BUFFER_SIZE; counter++, cursor++) { - if (full_read (READ_SIDE (handle), cursor, 1) != 1) + if (safe_read (READ_SIDE (handle), cursor, 1) != 1) { _rmt_shutdown (handle, EIO); return 0; @@ -180,7 +183,7 @@ get_status_string (int handle, char *command_buffer) { char character; - while (full_read (READ_SIDE (handle), &character, 1) == 1) + while (safe_read (READ_SIDE (handle), &character, 1) == 1) if (character == '\n') break; } @@ -309,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 | @@ -356,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) { @@ -387,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; } @@ -405,30 +458,30 @@ 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 } - remote_shell_basename = strrchr (remote_shell, '/'); - if (remote_shell_basename) - remote_shell_basename++; - else - remote_shell_basename = remote_shell; + remote_shell_basename = base_name (remote_shell); /* Set up the pipes for the `rsh' command, and fork. */ 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; } @@ -474,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); @@ -527,7 +585,7 @@ rmt_read__ (int handle, char *buffer, size_t length) for (counter = 0; counter < status; counter += rlen, buffer += rlen) { - rlen = full_read (READ_SIDE (handle), buffer, status - counter); + rlen = safe_read (READ_SIDE (handle), buffer, status - counter); if (rlen <= 0) { _rmt_shutdown (handle, EIO); @@ -661,7 +719,7 @@ rmt_ioctl__ (int handle, int operation, char *argument) for (; status > 0; status -= counter, argument += counter) { - counter = full_read (READ_SIDE (handle), + counter = safe_read (READ_SIDE (handle), argument, (size_t) status); if (counter <= 0) {