X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fbuffer.c;h=949505c0b912ceb1b3d52fdf3907571c1994adb9;hb=e6e72bf7ed8e6226c0d19118c6a92296e83d45c4;hp=b59efb2808c41af4b5a21343d60070aa7ba57e37;hpb=4dcebd965545a7a8ab3e0d6d4e0fdcd5f767d399;p=chaz%2Ftar diff --git a/src/buffer.c b/src/buffer.c index b59efb2..949505c 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,5 +1,8 @@ /* Buffer management for tar. - Copyright 1988, 92, 93, 94, 96, 97, 99, 2000 Free Software Foundation, Inc. + + Copyright 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001 Free + Software Foundation, Inc. + Written by John Gilmore, on 1985-08-25. This program is free software; you can redistribute it and/or modify it @@ -19,10 +22,6 @@ #include "system.h" #include -#include -#ifndef time -time_t time (); -#endif #if MSDOS # include @@ -53,14 +52,16 @@ time_t time (); static tarlong prev_written; /* bytes written on previous volumes */ static tarlong bytes_written; /* bytes written on this volume */ -/* FIXME: The following four variables should ideally be static to this - module. However, this cannot be done yet, as update.c uses the first - three a lot, and compare.c uses the fourth. The cleanup continues! */ +/* FIXME: The following variables should ideally be static to this + module. However, this cannot be done yet. The cleanup continues! */ union block *record_start; /* start of record of archive */ union block *record_end; /* last+1 block of archive record */ union block *current_block; /* current block of archive */ enum access_mode access_mode; /* how do we handle the archive */ +off_t records_read; /* number of records read from this archive */ +off_t records_written; /* likewise, for records written */ + static struct stat archive_stat; /* stat block for archive file */ static off_t record_start_block; /* block ordinal at record_start */ @@ -118,7 +119,7 @@ off_t save_totsize; /* total size of file we are writing, only off_t save_sizeleft; /* where we are in the file we are writing, only valid if save_name is nonzero */ -int write_archive_to_stdout; +bool write_archive_to_stdout; /* Used by flush_read and flush_write to store the real info about saved names. */ @@ -300,7 +301,9 @@ write_archive_buffer (void) { written += status; if (written == record_size - || _isrmt (archive) || ! S_ISFIFO (archive_stat.st_mode)) + || _isrmt (archive) + || ! (S_ISFIFO (archive_stat.st_mode) + || S_ISSOCK (archive_stat.st_mode))) break; } @@ -448,7 +451,7 @@ child_open_for_compress (void) status = write_archive_buffer (); if (status != record_size) - archive_write_error (status); + archive_write_error (status); } #if 0 @@ -463,7 +466,7 @@ child_open_for_compress (void) waitpid_error (use_compress_program_option); break; } - + if (WIFSIGNALED (wait_status)) { kill (child_pid, WTERMSIG (wait_status)); @@ -584,17 +587,8 @@ child_open_for_uncompress (void) while (maximum) { count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE; - status = full_write (STDOUT_FILENO, cursor, count); - if (status < 0) + if (full_write (STDOUT_FILENO, cursor, count) != count) write_error (use_compress_program_option); - - if (status != count) - { - ERROR ((0, 0, _("Write to compression program short %lu bytes"), - (unsigned long) (count - status))); - count = status; - } - cursor += count; maximum -= count; } @@ -613,7 +607,7 @@ child_open_for_uncompress (void) waitpid_error (use_compress_program_option); break; } - + if (WIFSIGNALED (wait_status)) { kill (child_pid, WTERMSIG (wait_status)); @@ -637,6 +631,9 @@ check_label_pattern (union block *label) char *string; int result; + if (! memchr (label->header.name, '\0', sizeof label->header.name)) + return 0; + if (fnmatch (volume_label_option, label->header.name, 0) == 0) return 1; @@ -811,8 +808,10 @@ open_archive (enum access_mode wanted_access) switch (wanted_access) { - case ACCESS_READ: case ACCESS_UPDATE: + records_written = 0; + case ACCESS_READ: + records_read = 0; record_end = record_start; /* set up for 1st record = # 0 */ find_next_block (); /* read it in, check for EOF */ @@ -831,6 +830,7 @@ open_archive (enum access_mode wanted_access) break; case ACCESS_WRITE: + records_written = 0; if (volume_label_option) { memset (record_start, 0, BLOCKSIZE); @@ -876,7 +876,10 @@ flush_write (void) archive_write_error (status); if (status > 0) - bytes_written += status; + { + records_written++; + bytes_written += status; + } if (status == record_size) { @@ -893,7 +896,7 @@ flush_write (void) } cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name); - while (*cursor == '/') + while (ISSLASH (*cursor)) cursor++; assign_string (&real_s_name, cursor); @@ -957,7 +960,7 @@ flush_write (void) strcpy (record_start->header.name, real_s_name); record_start->header.typeflag = GNUTYPE_MULTIVOL; OFF_TO_CHARS (real_s_sizeleft, record_start->header.size); - OFF_TO_CHARS (real_s_totsize - real_s_sizeleft, + OFF_TO_CHARS (real_s_totsize - real_s_sizeleft, record_start->oldgnu_header.offset); tmp = verbose_option; verbose_option = 0; @@ -990,7 +993,7 @@ flush_write (void) { char *cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name); - while (*cursor == '/') + while (ISSLASH (*cursor)) cursor++; assign_string (&real_s_name, cursor); @@ -1067,7 +1070,7 @@ flush_read (void) { char *cursor = save_name + FILESYSTEM_PREFIX_LEN (save_name); - while (*cursor == '/') + while (ISSLASH (*cursor)) cursor++; assign_string (&real_s_name, cursor); @@ -1085,7 +1088,10 @@ flush_read (void) error_loop: status = rmtread (archive, record_start->buffer, record_size); if (status == record_size) - return; + { + records_read++; + return; + } if ((status == 0 || (status < 0 && errno == ENOSPC) @@ -1162,7 +1168,7 @@ flush_read (void) char totsizebuf[UINTMAX_STRSIZE_BOUND]; char s1buf[UINTMAX_STRSIZE_BOUND]; char s2buf[UINTMAX_STRSIZE_BOUND]; - + WARN ((0, 0, _("%s is the wrong size (%s != %s + %s)"), quote (cursor->header.name), STRINGIFY_BIGINT (save_totsize, totsizebuf), @@ -1183,6 +1189,7 @@ flush_read (void) cursor++; } current_block = cursor; + records_read++; return; } else if (status < 0) @@ -1195,7 +1202,8 @@ flush_read (void) more = record_start->buffer + status; left = record_size - status; - while (left % BLOCKSIZE != 0) + while (left % BLOCKSIZE != 0 + || (left && status && read_full_records_option)) { if (status) while ((status = rmtread (archive, more, left)) < 0) @@ -1203,15 +1211,16 @@ flush_read (void) if (status == 0) { - ERROR ((0, 0, _("%d garbage bytes ignored at end of archive"), - (int) ((record_size - left) % BLOCKSIZE))); + if (left % BLOCKSIZE != 0) + ERROR ((0, 0, _("%d garbage bytes ignored at end of archive"), + (int) ((record_size - left) % BLOCKSIZE))); break; } if (! read_full_records_option) FATAL_ERROR ((0, 0, _("Unaligned block (%lu bytes) in archive"), (unsigned long) (record_size - left))); - + /* User warned us about this. Fix up. */ left -= status; @@ -1227,6 +1236,7 @@ flush_read (void) (unsigned long) ((record_size - left) / BLOCKSIZE))); record_end = record_start + (record_size - left) / BLOCKSIZE; + records_read++; } /* Flush the current buffer to/from the archive. */ @@ -1327,7 +1337,7 @@ close_archive (void) if (access_mode == ACCESS_READ && ! _isrmt (archive) - && S_ISFIFO (archive_stat.st_mode)) + && (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode))) while (rmtread (archive, record_start->buffer, record_size) > 0) continue; #endif @@ -1379,7 +1389,10 @@ init_volume_number (void) if (file) { - fscanf (file, "%d", &global_volno); + if (fscanf (file, "%d", &global_volno) != 1 + || global_volno < 0) + FATAL_ERROR ((0, 0, _("%s: contains invalid volume number"), + quotearg_colon (volno_file_option))); if (ferror (file)) read_error (volno_file_option); if (fclose (file) != 0) @@ -1428,6 +1441,8 @@ new_volume (enum access_mode access) close_warn (*archive_name_cursor); global_volno++; + if (global_volno < 0) + FATAL_ERROR ((0, 0, _("Volume number overflow"))); volno++; archive_name_cursor++; if (archive_name_cursor == archive_name_array + archive_names) @@ -1445,7 +1460,8 @@ new_volume (enum access_mode access) { if (volno_file_option) closeout_volume_number (); - system (info_script_option); + if (system (info_script_option) != 0) + FATAL_ERROR ((0, 0, _("`%s' command failed"), info_script_option)); } else while (1)