X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Frtapelib.c;h=a31a8930c912cffca617ac4e9f9e2c294983c70a;hb=e3bd2a63a62aede213fe3b451952c254b095090d;hp=cd00fd56605ae3e164f6a77db6dc49036e331e4d;hpb=1329cfe9f887ca5ce8075360a83ec67eb56e9f61;p=chaz%2Ftar diff --git a/src/rtapelib.c b/src/rtapelib.c index cd00fd5..a31a893 100644 --- a/src/rtapelib.c +++ b/src/rtapelib.c @@ -1,7 +1,7 @@ /* Functions for communicating with a remote tape drive. - Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001 Free Software - Foundation, Inc. + Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 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 @@ -88,8 +88,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}}; +#define RMT_COMMAND (rmt_command_option ? rmt_command_option : "/etc/rmt") + /* Temporary variable used by macros in rmt.h. */ -char *rmt_path__; +char *rmt_dev_name__; /* Close remote tape connection HANDLE, and reset errno to ERRNO_VALUE. */ @@ -163,8 +165,6 @@ get_status_string (int handle, char *command_buffer) if (*cursor == 'E' || *cursor == 'F') { - errno = atoi (cursor + 1); - /* Skip the error message line. */ /* FIXME: there is better to do than merely ignoring error messages @@ -178,6 +178,8 @@ get_status_string (int handle, char *command_buffer) break; } + errno = atoi (cursor + 1); + if (*cursor == 'F') _rmt_shutdown (handle, errno); @@ -199,12 +201,19 @@ get_status_string (int handle, char *command_buffer) /* Read and return the status from remote tape connection HANDLE. If an error occurred, return -1 and set errno. */ -static long +static long int get_status (int handle) { char command_buffer[COMMAND_BUFFER_SIZE]; const char *status = get_status_string (handle, command_buffer); - return status ? atol (status) : -1L; + if (status) + { + long int result = atol (status); + if (0 <= result) + return result; + errno = EIO; + } + return -1; } static off_t @@ -226,10 +235,10 @@ get_status_off (int handle) for (; *status == ' ' || *status == '\t'; status++) continue; - + negative = *status == '-'; status += negative || *status == '+'; - + for (;;) { int digit = *status++ - '0'; @@ -282,7 +291,7 @@ _rmt_rexec (char *host, char *user) if (rexecserv = getservbyname ("exec", "tcp"), !rexecserv) error (EXIT_ON_EXEC_ERROR, 0, _("exec/tcp: Service not available")); - result = rexec (&host, rexecserv->s_port, user, 0, "/etc/rmt", 0); + result = rexec (&host, rexecserv->s_port, user, 0, RMT_COMMAND, 0); if (fclose (stdin) == EOF) error (0, errno, _("stdin")); fdopen (saved_stdin, "r"); @@ -339,15 +348,16 @@ encode_oflag (char *buf, int oflag) } /* Open a file (a magnetic tape device?) on the system specified in - PATH, as the given user. PATH has the form `[USER@]HOST:FILE'. + FILE_NAME, as the given user. FILE_NAME has the form `[USER@]HOST:FILE'. OPEN_MODE is O_RDONLY, O_WRONLY, etc. If successful, return the remote pipe number plus BIAS. REMOTE_SHELL may be overridden. On error, return -1. */ int -rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) +rmt_open__ (const char *file_name, int open_mode, int bias, + const char *remote_shell) { int remote_pipe_number; /* pseudo, biased file descriptor */ - char *path_copy ; /* copy of path string */ + char *file_name_copy; /* copy of file_name string */ char *remote_host; /* remote host name */ char *remote_file; /* remote file name (often a device) */ char *remote_user; /* remote user name */ @@ -372,21 +382,21 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) { char *cursor; - path_copy = xstrdup (path); - remote_host = path_copy; + file_name_copy = xstrdup (file_name); + remote_host = file_name_copy; remote_user = 0; remote_file = 0; - for (cursor = path_copy; *cursor; cursor++) + for (cursor = file_name_copy; *cursor; cursor++) switch (*cursor) { default: break; case '\n': - /* Do not allow newlines in the path, since the protocol + /* Do not allow newlines in the file_name, since the protocol uses newline delimiters. */ - free (path_copy); + free (file_name_copy); errno = ENOENT; return -1; @@ -422,7 +432,7 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) if (READ_SIDE (remote_pipe_number) < 0) { int e = errno; - free (path_copy); + free (file_name_copy); errno = e; return -1; } @@ -441,7 +451,7 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) #ifdef REMOTE_SHELL remote_shell = REMOTE_SHELL; #else - free (path_copy); + free (file_name_copy); errno = EIO; return -1; #endif @@ -454,7 +464,7 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) || pipe (from_remote[remote_pipe_number]) == -1) { int e = errno; - free (path_copy); + free (file_name_copy); errno = e; return -1; } @@ -463,7 +473,7 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) if (status == -1) { int e = errno; - free (path_copy); + free (file_name_copy); errno = e; return -1; } @@ -486,10 +496,10 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) if (remote_user) execl (remote_shell, remote_shell_basename, remote_host, - "-l", remote_user, "/etc/rmt", (char *) 0); + "-l", remote_user, RMT_COMMAND, (char *) 0); else execl (remote_shell, remote_shell_basename, remote_host, - "/etc/rmt", (char *) 0); + RMT_COMMAND, (char *) 0); /* Bad problems if we get here. */ @@ -517,14 +527,14 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) { int e = errno; free (command_buffer); - free (path_copy); + free (file_name_copy); _rmt_shutdown (remote_pipe_number, e); return -1; } free (command_buffer); } - free (path_copy); + free (file_name_copy); return remote_pipe_number + bias; } @@ -533,7 +543,7 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) int rmt_close__ (int handle) { - int status; + long int status; if (do_command (handle, "C\n") == -1) return -1; @@ -544,26 +554,27 @@ rmt_close__ (int handle) } /* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE. - Return the number of bytes read on success, -1 on error. */ -ssize_t + Return the number of bytes read on success, SAFE_READ_ERROR on error. */ +size_t rmt_read__ (int handle, char *buffer, size_t length) { char command_buffer[COMMAND_BUFFER_SIZE]; - ssize_t status, rlen; + size_t status; + size_t rlen; size_t counter; sprintf (command_buffer, "R%lu\n", (unsigned long) length); if (do_command (handle, command_buffer) == -1 - || (status = get_status (handle)) == -1) - return -1; + || (status = get_status (handle)) == SAFE_READ_ERROR) + return SAFE_READ_ERROR; for (counter = 0; counter < status; counter += rlen, buffer += rlen) { rlen = safe_read (READ_SIDE (handle), buffer, status - counter); - if (rlen <= 0) + if (rlen == SAFE_READ_ERROR || rlen == 0) { _rmt_shutdown (handle, EIO); - return -1; + return SAFE_READ_ERROR; } } @@ -571,8 +582,8 @@ rmt_read__ (int handle, char *buffer, size_t length) } /* Write LENGTH bytes from BUFFER to remote tape connection HANDLE. - Return the number of bytes written on success, -1 on error. */ -ssize_t + Return the number of bytes written. */ +size_t rmt_write__ (int handle, char *buffer, size_t length) { char command_buffer[COMMAND_BUFFER_SIZE]; @@ -581,18 +592,25 @@ rmt_write__ (int handle, char *buffer, size_t length) sprintf (command_buffer, "W%lu\n", (unsigned long) length); if (do_command (handle, command_buffer) == -1) - return -1; + return 0; pipe_handler = signal (SIGPIPE, SIG_IGN); written = full_write (WRITE_SIDE (handle), buffer, length); signal (SIGPIPE, pipe_handler); if (written == length) - return get_status (handle); + { + long int r = get_status (handle); + if (r < 0) + return 0; + if (r == length) + return length; + written = r; + } /* Write error. */ _rmt_shutdown (handle, EIO); - return -1; + return written; } /* Perform an imitation lseek operation on remote tape connection @@ -648,7 +666,7 @@ rmt_ioctl__ (int handle, int operation, char *argument) ? - (uintmax_t) ((struct mtop *) argument)->mt_count : (uintmax_t) ((struct mtop *) argument)->mt_count); char *p = operand_buffer + sizeof operand_buffer; - + *--p = 0; do *--p = '0' + (int) (u % 10); @@ -671,7 +689,7 @@ rmt_ioctl__ (int handle, int operation, char *argument) case MTIOCGET: { ssize_t status; - ssize_t counter; + size_t counter; /* Grab the status and read it directly into the structure. This assumes that the status buffer is not padded and that 2 shorts @@ -686,7 +704,7 @@ rmt_ioctl__ (int handle, int operation, char *argument) for (; status > 0; status -= counter, argument += counter) { counter = safe_read (READ_SIDE (handle), argument, status); - if (counter <= 0) + if (counter == SAFE_READ_ERROR || counter == 0) { _rmt_shutdown (handle, EIO); return -1;