X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Frtapelib.c;h=4e04c515d9be2c1bab95f594d27455df10a41d20;hb=dab18c15bd99344245c9ecf6be7e5dea7d76e58d;hp=7361bb245cb5217c9f5bae8260d961142835e2ef;hpb=88ea940c0e3db80904f2405b01f1a3d01c522859;p=chaz%2Ftar diff --git a/src/rtapelib.c b/src/rtapelib.c index 7361bb2..4e04c51 100644 --- a/src/rtapelib.c +++ b/src/rtapelib.c @@ -112,14 +112,14 @@ _rmt_shutdown (int handle, int errno_value) static int do_command (int handle, const char *buffer) { - int length; + size_t length; RETSIGTYPE (*pipe_handler) (); /* Save the current pipe handler and try to make the request. */ pipe_handler = signal (SIGPIPE, SIG_IGN); length = strlen (buffer); - if (write (WRITE_SIDE (handle), buffer, (size_t) length) == length) + if (write (WRITE_SIDE (handle), buffer, length) == length) { signal (SIGPIPE, pipe_handler); return 0; @@ -132,15 +132,9 @@ do_command (int handle, const char *buffer) return -1; } -/*----------------------------------------------------------------------. -| Read and return the status from remote tape connection HANDLE. If an | -| error occurred, return -1 and set errno. | -`----------------------------------------------------------------------*/ - -static int -get_status (int handle) +static char * +get_status_string (int handle, char *command_buffer) { - char command_buffer[COMMAND_BUFFER_SIZE]; char *cursor; int counter; @@ -153,7 +147,7 @@ get_status (int handle) if (read (READ_SIDE (handle), cursor, 1) != 1) { _rmt_shutdown (handle, EIO); - return -1; + return 0; } if (*cursor == '\n') { @@ -165,7 +159,7 @@ get_status (int handle) if (counter == COMMAND_BUFFER_SIZE) { _rmt_shutdown (handle, EIO); - return -1; + return 0; } /* Check the return status. */ @@ -194,7 +188,7 @@ get_status (int handle) if (*cursor == 'F') _rmt_shutdown (handle, errno); - return -1; + return 0; } /* Check for mis-synced pipes. */ @@ -202,12 +196,67 @@ get_status (int handle) if (*cursor != 'A') { _rmt_shutdown (handle, EIO); - return -1; + return 0; } /* Got an `A' (success) response. */ - return atoi (cursor + 1); + return cursor + 1; +} + +/*----------------------------------------------------------------------. +| Read and return the status from remote tape connection HANDLE. If an | +| error occurred, return -1 and set errno. | +`----------------------------------------------------------------------*/ + +static long +get_status (int handle) +{ + char command_buffer[COMMAND_BUFFER_SIZE]; + const char *status = get_status_string (handle, command_buffer); + return status ? atol (status) : -1L; +} + +static off_t +get_status_off (int handle) +{ + char command_buffer[COMMAND_BUFFER_SIZE]; + const char *status = get_status_string (handle, command_buffer); + + if (! status) + return -1; + else + { + /* Parse status, taking care to check for overflow. + We can't use standard functions, + since off_t might be longer than long. */ + + off_t count = 0; + int negative; + + for (; *status == ' ' || *status == '\t'; status++) + continue; + + negative = *status == '-'; + status += negative || *status == '+'; + + for (;;) + { + int digit = *status++ - '0'; + if (9 < (unsigned) digit) + break; + else + { + off_t c10 = 10 * count; + off_t nc = negative ? c10 - digit : c10 + digit; + if (c10 / 10 != count || (negative ? c10 < nc : nc < c10)) + return -1; + count = nc; + } + } + + return count; + } } #if HAVE_NETDB_H @@ -347,7 +396,7 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell) #else /* not HAVE_NETDB_H */ { const char *remote_shell_basename; - int status; + pid_t status; /* Identify the remote command to be executed. */ @@ -464,22 +513,22 @@ rmt_close__ (int handle) | Return the number of bytes read on success, -1 on error. | `-------------------------------------------------------------------------*/ -int -rmt_read__ (int handle, char *buffer, unsigned int length) +ssize_t +rmt_read__ (int handle, char *buffer, size_t length) { char command_buffer[COMMAND_BUFFER_SIZE]; - int status; - int counter; + ssize_t status, rlen; + size_t counter; - sprintf (command_buffer, "R%d\n", length); + sprintf (command_buffer, "R%lu\n", (unsigned long) length); if (do_command (handle, command_buffer) == -1 || (status = get_status (handle)) == -1) return -1; - for (counter = 0; counter < status; counter += length, buffer += length) + for (counter = 0; counter < status; counter += rlen, buffer += rlen) { - length = read (READ_SIDE (handle), buffer, (size_t) (status - counter)); - if (length <= 0) + rlen = read (READ_SIDE (handle), buffer, status - counter); + if (rlen <= 0) { _rmt_shutdown (handle, EIO); return -1; @@ -494,13 +543,13 @@ rmt_read__ (int handle, char *buffer, unsigned int length) | the number of bytes written on success, -1 on error. | `-------------------------------------------------------------------------*/ -int -rmt_write__ (int handle, char *buffer, unsigned int length) +ssize_t +rmt_write__ (int handle, char *buffer, size_t length) { char command_buffer[COMMAND_BUFFER_SIZE]; RETSIGTYPE (*pipe_handler) (); - sprintf (command_buffer, "W%d\n", length); + sprintf (command_buffer, "W%lu\n", (unsigned long) length); if (do_command (handle, command_buffer) == -1) return -1; @@ -523,16 +572,26 @@ rmt_write__ (int handle, char *buffer, unsigned int length) | Return the new file offset if successful, -1 if on error. | `------------------------------------------------------------------------*/ -long +off_t rmt_lseek__ (int handle, off_t offset, int whence) { char command_buffer[COMMAND_BUFFER_SIZE]; + char operand_buffer[UINTMAX_STRSIZE_BOUND]; + uintmax_t u = offset < 0 ? - (uintmax_t) offset : (uintmax_t) offset; + char *p = operand_buffer + sizeof operand_buffer; + + do + *--p = '0' + (int) (u % 10); + while ((u /= 10) != 0); + if (offset < 0) + *--p = '-'; + + sprintf (command_buffer, "L%s\n%d\n", p, whence); - sprintf (command_buffer, "L%ld\n%d\n", offset, whence); if (do_command (handle, command_buffer) == -1) return -1; - return get_status (handle); + return get_status_off (handle); } /*-----------------------------------------------------------------------. @@ -553,16 +612,25 @@ rmt_ioctl__ (int handle, int operation, char *argument) case MTIOCTOP: { char command_buffer[COMMAND_BUFFER_SIZE]; + char operand_buffer[UINTMAX_STRSIZE_BOUND]; + uintmax_t u = (((struct mtop *) argument)->mt_count < 0 + ? - (uintmax_t) ((struct mtop *) argument)->mt_count + : (uintmax_t) ((struct mtop *) argument)->mt_count); + char *p = operand_buffer + sizeof operand_buffer; + + do + *--p = '0' + (int) (u % 10); + while ((u /= 10) != 0); + if (((struct mtop *) argument)->mt_count < 0) + *--p = '-'; /* MTIOCTOP is the easy one. Nothing is transfered in binary. */ - sprintf (command_buffer, "I%d\n%d\n", ((struct mtop *) argument)->mt_op, - ((struct mtop *) argument)->mt_count); + sprintf (command_buffer, "I%d\n%s\n", + ((struct mtop *) argument)->mt_op, p); if (do_command (handle, command_buffer) == -1) return -1; - /* Return the count. */ - return get_status (handle); } #endif /* MTIOCTOP */ @@ -570,8 +638,8 @@ rmt_ioctl__ (int handle, int operation, char *argument) #ifdef MTIOCGET case MTIOCGET: { - int status; - int counter; + ssize_t status; + ssize_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