X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Frmt.c;h=ac0317d31bc1b01a93180a35b6d55f6cc121dece;hb=00a2b4708fc77a09c9b5ca372b2846341c12c75e;hp=27b3f094ca2ca79681a83694c79e7d7e4728524a;hpb=10797cd27b13ab09e09fa5b994dda79564b8e6b4;p=chaz%2Ftar diff --git a/src/rmt.c b/src/rmt.c index 27b3f09..ac0317d 100644 --- a/src/rmt.c +++ b/src/rmt.c @@ -51,7 +51,7 @@ static int tape = -1; /* Buffer containing transferred data, and its allocated size. */ static char *record_buffer = NULL; -static int allocated_size = -1; +static size_t allocated_size = 0; /* Buffer for constructing the reply. */ static char reply_buffer[BUFSIZ]; @@ -142,7 +142,7 @@ get_string (char *string) `---*/ static void -prepare_record_buffer (int size) +prepare_record_buffer (size_t size) { if (size <= allocated_size) return; @@ -150,7 +150,7 @@ prepare_record_buffer (int size) if (record_buffer) free (record_buffer); - record_buffer = malloc ((size_t) size); + record_buffer = malloc (size); if (record_buffer == NULL) { @@ -180,7 +180,7 @@ int main (int argc, char *const *argv) { char command; - int status; + long status; /* FIXME: Localisation is meaningless, unless --help and --version are locally used. Localisation would be best accomplished by the calling @@ -227,34 +227,7 @@ top: if (tape >= 0) close (tape); -#if defined (i386) && defined (AIX) - - /* This is alleged to fix a byte ordering problem. I'm quite - suspicious if it's right. -- mib. */ - - { - int old_mode = atoi (mode_string); - int new_mode = 0; - - if ((old_mode & 3) == 0) - new_mode |= O_RDONLY; - if (old_mode & 1) - new_mode |= O_WRONLY; - if (old_mode & 2) - new_mode |= O_RDWR; - if (old_mode & 0x0008) - new_mode |= O_APPEND; - if (old_mode & 0x0200) - new_mode |= O_CREAT; - if (old_mode & 0x0400) - new_mode |= O_TRUNC; - if (old_mode & 0x0800) - new_mode |= O_EXCL; - tape = open (device_string, new_mode, 0666); - } -#else tape = open (device_string, atoi (mode_string), 0666); -#endif if (tape < 0) goto ioerror; goto respond; @@ -277,26 +250,69 @@ top: { char count_string[STRING_SIZE]; char position_string[STRING_SIZE]; + off_t count = 0; + int negative; + char *p; get_string (count_string); get_string (position_string); DEBUG2 ("rmtd: L %s %s\n", count_string, position_string); - status - = lseek (tape, (off_t) atol (count_string), atoi (position_string)); - if (status < 0) + /* Parse count_string, taking care to check for overflow. + We can't use standard functions, + since off_t might be longer than long. */ + + for (p = count_string; *p == ' ' || *p == '\t'; p++) + continue; + + negative = *p == '-'; + p += negative || *p == '+'; + + for (;;) + { + int digit = *p++ - '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)) + { + report_error_message (N_("Seek offset out of range")); + exit (EXIT_FAILURE); + } + count = nc; + } + } + + count = lseek (tape, count, atoi (position_string)); + if (count < 0) goto ioerror; - goto respond; + + /* Convert count back to string for reply. + We can't use sprintf, since off_t might be longer than long. */ + p = count_string + sizeof count_string; + *--p = '\0'; + do + *--p = '0' + (int) (count % 10); + while ((count /= 10) != 0); + + DEBUG1 ("rmtd: A %s\n", p); + + sprintf (reply_buffer, "A%s\n", p); + write (1, reply_buffer, strlen (reply_buffer)); + goto top; } case 'W': { char count_string[STRING_SIZE]; - int size; - int counter; + size_t size; + size_t counter; get_string (count_string); - size = atoi (count_string); + size = atol (count_string); DEBUG1 ("rmtd: W %s\n", count_string); prepare_record_buffer (size); @@ -320,19 +336,19 @@ top: case 'R': { char count_string[STRING_SIZE]; - int size; + size_t size; get_string (count_string); DEBUG1 ("rmtd: R %s\n", count_string); - size = atoi (count_string); + size = atol (count_string); prepare_record_buffer (size); status = read (tape, record_buffer, size); if (status < 0) goto ioerror; - sprintf (reply_buffer, "A%d\n", status); + sprintf (reply_buffer, "A%ld\n", status); write (1, reply_buffer, strlen (reply_buffer)); - write (1, record_buffer, status); + write (1, record_buffer, (size_t) status); goto top; } @@ -348,12 +364,48 @@ top: #ifdef MTIOCTOP { struct mtop mtop; - + const char *p; + off_t count = 0; + int negative; + + /* Parse count_string, taking care to check for overflow. + We can't use standard functions, + since off_t might be longer than long. */ + + for (p = count_string; *p == ' ' || *p == '\t'; p++) + continue; + + negative = *p == '-'; + p += negative || *p == '+'; + + for (;;) + { + int digit = *p++ - '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)) + { + report_error_message (N_("Seek offset out of range")); + exit (EXIT_FAILURE); + } + count = nc; + } + } + + mtop.mt_count = count; + if (mtop.mt_count != count) + { + report_error_message (N_("Seek offset out of range")); + exit (EXIT_FAILURE); + } mtop.mt_op = atoi (operation_string); - mtop.mt_count = atoi (count_string); + if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0) goto ioerror; - status = mtop.mt_count; } #endif goto respond; @@ -370,7 +422,7 @@ top: if (ioctl (tape, MTIOCGET, (char *) &operation) < 0) goto ioerror; status = sizeof (operation); - sprintf (reply_buffer, "A%d\n", status); + sprintf (reply_buffer, "A%ld\n", status); write (1, reply_buffer, strlen (reply_buffer)); write (1, (char *) &operation, sizeof (operation)); } @@ -386,9 +438,9 @@ top: } respond: - DEBUG1 ("rmtd: A %d\n", status); + DEBUG1 ("rmtd: A %ld\n", status); - sprintf (reply_buffer, "A%d\n", status); + sprintf (reply_buffer, "A%ld\n", status); write (1, reply_buffer, strlen (reply_buffer)); goto top;