aboutsummaryrefslogtreecommitdiff
path: root/tar.c
diff options
context:
space:
mode:
Diffstat (limited to 'tar.c')
-rw-r--r--tar.c513
1 files changed, 226 insertions, 287 deletions
diff --git a/tar.c b/tar.c
index 8f802de64..8f83d04a6 100644
--- a/tar.c
+++ b/tar.c
@@ -68,57 +68,84 @@ static const char tar_usage[] =
68#endif 68#endif
69 69
70 70
71/* 71/* Tar file constants */
72 * Tar file constants.
73 */
74#define TAR_BLOCK_SIZE 512
75#define TAR_NAME_SIZE 100
76 72
77 73
78/* 74/* POSIX tar Header Block, from POSIX 1003.1-1990 */
79 * The POSIX (and basic GNU) tar header format. 75struct TarHeader
80 * This structure is always embedded in a TAR_BLOCK_SIZE sized block 76{
81 * with zero padding. We only process this information minimally. 77 /* byte offset */
82 */ 78 char name[100]; /* 0 */
83typedef struct { 79 char mode[8]; /* 100 */
84 char name[TAR_NAME_SIZE]; 80 char uid[8]; /* 108 */
85 char mode[8]; 81 char gid[8]; /* 116 */
86 char uid[8]; 82 char size[12]; /* 124 */
87 char gid[8]; 83 char mtime[12]; /* 136 */
88 char size[12]; 84 char chksum[8]; /* 148 */
89 char mtime[12]; 85 char typeflag; /* 156 */
90 char checkSum[8]; 86 char linkname[100]; /* 157 */
91 char typeFlag; 87 char magic[6]; /* 257 */
92 char linkName[TAR_NAME_SIZE]; 88 char version[2]; /* 263 */
93 char magic[6]; 89 char uname[32]; /* 265 */
94 char version[2]; 90 char gname[32]; /* 297 */
95 char uname[32]; 91 char devmajor[8]; /* 329 */
96 char gname[32]; 92 char devminor[8]; /* 337 */
97 char devMajor[8]; 93 char prefix[155]; /* 345 */
98 char devMinor[8]; 94 /* padding 500 */
99 char prefix[155]; 95};
100} TarHeader; 96typedef struct TarHeader TarHeader;
101 97
102#define TAR_MAGIC "ustar" 98
103#define TAR_VERSION "00" 99/* A few useful constants */
104 100#define TAR_MAGIC "ustar" /* ustar and a null */
105#define TAR_TYPE_REGULAR '0' 101#define TAR_VERSION "00" /* 00 and no null */
106#define TAR_TYPE_HARD_LINK '1' 102#define TAR_MAGIC_LEN 6
107#define TAR_TYPE_SOFT_LINK '2' 103#define TAR_VERSION_LEN 2
104#define TAR_NAME_LEN 100
105#define TAR_BLOCK_SIZE 512
106
107/* A nice enum with all the possible tar file content types */
108enum TarFileType
109{
110 REGTYPE = '0', /* regular file */
111 REGTYPE0 = '\0', /* regular file (ancient bug compat)*/
112 LNKTYPE = '1', /* hard link */
113 SYMTYPE = '2', /* symbolic link */
114 CHRTYPE = '3', /* character special */
115 BLKTYPE = '4', /* block special */
116 DIRTYPE = '5', /* directory */
117 FIFOTYPE = '6', /* FIFO special */
118 CONTTYPE = '7', /* reserved */
119};
120typedef enum TarFileType TarFileType;
121
122/* This struct ignores magic, non-numeric user name,
123 * non-numeric group name, and the checksum, since
124 * these are all ignored by BusyBox tar. */
125struct TarInfo
126{
127 int tarFd; /* An open file descriptor for reading from the tarball */
128 char * name; /* File name */
129 mode_t mode; /* Unix mode, including device bits. */
130 uid_t uid; /* Numeric UID */
131 gid_t gid; /* Numeric GID */
132 size_t size; /* Size of file */
133 time_t mtime; /* Last-modified time */
134 enum TarFileType type; /* Regular, directory, link, etc */
135 char * linkname; /* Name for symbolic and hard links */
136 dev_t device; /* Special device for mknod() */
137};
138typedef struct TarInfo TarInfo;
139
140/* Static data */
141static const unsigned long TarChecksumOffset = (const unsigned long)&(((TarHeader *)0)->chksum);
108 142
109 143
110/* 144/*
111 * Static data. 145 * Static data.
112 */ 146 */
113static int listFlag;
114static int extractFlag;
115static int createFlag;
116static int verboseFlag;
117static int tostdoutFlag;
118
119static int inHeader; // <- check me 147static int inHeader; // <- check me
120static int badHeader; 148static int badHeader;
121static int errorFlag;
122static int skipFileFlag; 149static int skipFileFlag;
123static int warnedRoot; 150static int warnedRoot;
124static int eofFlag; 151static int eofFlag;
@@ -134,7 +161,6 @@ static time_t mtime;
134/* 161/*
135 * Static data associated with the tar file. 162 * Static data associated with the tar file.
136 */ 163 */
137static const char *tarName;
138static int tarFd; 164static int tarFd;
139static dev_t tarDev; 165static dev_t tarDev;
140static ino_t tarInode; 166static ino_t tarInode;
@@ -143,35 +169,25 @@ static ino_t tarInode;
143/* 169/*
144 * Local procedures to restore files from a tar file. 170 * Local procedures to restore files from a tar file.
145 */ 171 */
146static void readTarFile(int fileCount, char **fileTable); 172static int readTarFile(const char* tarName, int extractFlag, int listFlag,
173 int tostdoutFlag, int verboseFlag);
147static void readData(const char *cp, int count); 174static void readData(const char *cp, int count);
148static long getOctal(const char *cp, int len); 175static long getOctal(const char *cp, int len);
149 176static int parseTarHeader(struct TarHeader *rawHeader, struct TarInfo *header);
150static void readHeader(const TarHeader * hp,
151
152 int fileCount, char **fileTable);
153
154static int wantFileName(const char *fileName, 177static int wantFileName(const char *fileName,
155 178 int argc, char **argv);
156 int fileCount, char **fileTable);
157 179
158#ifdef BB_FEATURE_TAR_CREATE 180#ifdef BB_FEATURE_TAR_CREATE
159/* 181/*
160 * Local procedures to save files into a tar file. 182 * Local procedures to save files into a tar file.
161 */ 183 */
162static void saveFile(const char *fileName, int seeLinks); 184static void saveFile(const char *fileName, int seeLinks);
163
164static void saveRegularFile(const char *fileName, 185static void saveRegularFile(const char *fileName,
165
166 const struct stat *statbuf); 186 const struct stat *statbuf);
167
168static void saveDirectory(const char *fileName, 187static void saveDirectory(const char *fileName,
169
170 const struct stat *statbuf); 188 const struct stat *statbuf);
171
172static void writeHeader(const char *fileName, const struct stat *statbuf); 189static void writeHeader(const char *fileName, const struct stat *statbuf);
173 190static void writeTarFile(int argc, char **argv);
174static void writeTarFile(int fileCount, char **fileTable);
175static void writeTarBlock(const char *buf, int len); 191static void writeTarBlock(const char *buf, int len);
176static int putOctal(char *cp, int len, long value); 192static int putOctal(char *cp, int len, long value);
177 193
@@ -180,7 +196,13 @@ static int putOctal(char *cp, int len, long value);
180 196
181extern int tar_main(int argc, char **argv) 197extern int tar_main(int argc, char **argv)
182{ 198{
199 const char *tarName=NULL;
183 const char *options; 200 const char *options;
201 int listFlag = FALSE;
202 int extractFlag = FALSE;
203 int createFlag = FALSE;
204 int verboseFlag = FALSE;
205 int tostdoutFlag = FALSE;
184 206
185 argc--; 207 argc--;
186 argv++; 208 argv++;
@@ -188,21 +210,7 @@ extern int tar_main(int argc, char **argv)
188 if (argc < 1) 210 if (argc < 1)
189 usage(tar_usage); 211 usage(tar_usage);
190 212
191 213 /* Parse options */
192 errorFlag = FALSE;
193 extractFlag = FALSE;
194 createFlag = FALSE;
195 listFlag = FALSE;
196 verboseFlag = FALSE;
197 tostdoutFlag = FALSE;
198 tarName = NULL;
199 tarDev = 0;
200 tarInode = 0;
201 tarFd = -1;
202
203 /*
204 * Parse the options.
205 */
206 if (**argv == '-') 214 if (**argv == '-')
207 options = (*argv++) + 1; 215 options = (*argv++) + 1;
208 else 216 else
@@ -212,13 +220,12 @@ extern int tar_main(int argc, char **argv)
212 for (; *options; options++) { 220 for (; *options; options++) {
213 switch (*options) { 221 switch (*options) {
214 case 'f': 222 case 'f':
215 if (tarName != NULL) { 223 if (tarName != NULL)
216 fprintf(stderr, "Only one 'f' option allowed\n"); 224 fatalError( "Only one 'f' option allowed\n");
217
218 exit(FALSE);
219 }
220 225
221 tarName = *argv++; 226 tarName = *argv++;
227 if (tarName == NULL)
228 fatalError( "Option requires an argument: No file specified\n");
222 argc--; 229 argc--;
223 230
224 break; 231 break;
@@ -253,9 +260,8 @@ extern int tar_main(int argc, char **argv)
253 break; 260 break;
254 261
255 default: 262 default:
256 fprintf(stderr, "Unknown tar flag '%c'\n" 263 fatalError( "Unknown tar flag '%c'\n"
257 "Try `tar --help' for more information\n", *options); 264 "Try `tar --help' for more information\n", *options);
258 exit(FALSE);
259 } 265 }
260 } 266 }
261 267
@@ -265,23 +271,22 @@ extern int tar_main(int argc, char **argv)
265 */ 271 */
266 if (createFlag == TRUE) { 272 if (createFlag == TRUE) {
267#ifndef BB_FEATURE_TAR_CREATE 273#ifndef BB_FEATURE_TAR_CREATE
268 fprintf(stderr, 274 fatalError( "This version of tar was not compiled with tar creation support.\n");
269 "This version of tar was not compiled with tar creation support.\n");
270 exit(FALSE);
271#else 275#else
272 writeTarFile(argc, argv); 276 exit(writeTarFile(argc, argv));
273#endif 277#endif
274 } else { 278 } else {
275 readTarFile(argc, argv); 279 exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag));
276 } 280 }
277 if (errorFlag == TRUE) {
278 fprintf(stderr, "\n");
279 }
280 exit(!errorFlag);
281 281
282 flagError: 282 flagError:
283 fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n"); 283 fatalError( "Exactly one of 'c', 'x' or 't' must be specified\n");
284 exit(FALSE); 284}
285
286static void
287tarExtractRegularFile(TarInfo *header, int extractFlag, int listFlag, int tostdoutFlag, int verboseFlag)
288{
289
285} 290}
286 291
287 292
@@ -289,178 +294,148 @@ extern int tar_main(int argc, char **argv)
289 * Read a tar file and extract or list the specified files within it. 294 * Read a tar file and extract or list the specified files within it.
290 * If the list is empty than all files are extracted or listed. 295 * If the list is empty than all files are extracted or listed.
291 */ 296 */
292static void readTarFile(int fileCount, char **fileTable) 297static int readTarFile(const char* tarName, int extractFlag, int listFlag,
298 int tostdoutFlag, int verboseFlag)
293{ 299{
294 const char *cp; 300 int status, tarFd=0;
295 int cc; 301 int errorFlag=FALSE;
296 int inCc; 302 TarHeader rawHeader;
297 int blockSize; 303 TarInfo header;
298 char buf[BUF_SIZE];
299
300 skipFileFlag = FALSE;
301 badHeader = FALSE;
302 warnedRoot = FALSE;
303 eofFlag = FALSE;
304 inHeader = TRUE;
305 inCc = 0;
306 dataCc = 0;
307 outFd = -1;
308 blockSize = sizeof(buf);
309 cp = buf;
310 304
311 /* 305 /* Open the tar file for reading. */
312 * Open the tar file for reading. 306 if (!strcmp(tarName, "-"))
313 */
314 if ((tarName == NULL) || !strcmp(tarName, "-")) {
315 tarFd = fileno(stdin); 307 tarFd = fileno(stdin);
316 } else 308 else
317 tarFd = open(tarName, O_RDONLY); 309 tarFd = open(tarName, O_RDONLY);
318
319 if (tarFd < 0) { 310 if (tarFd < 0) {
320 perror(tarName); 311 errorMsg( "Error opening '%s': %s", tarName, strerror(errno));
321 errorFlag = TRUE; 312 return ( FALSE);
322 return;
323 } 313 }
324 314
325 /* 315 /* Read the tar file */
326 * Read blocks from the file until an end of file header block 316 while ( (status = fullRead(tarFd, (char*)&rawHeader, TAR_BLOCK_SIZE)) == TAR_BLOCK_SIZE ) {
327 * has been seen. (A real end of file from a read is an error.) 317 /* Now see if the header looks ok */
328 */ 318 if ( parseTarHeader(&rawHeader, &header) == FALSE ) {
329 while (eofFlag == FALSE) { 319 close( tarFd);
330 /* 320 if ( *(header.name) == '\0' ) {
331 * Read the next block of data if necessary. 321 goto endgame;
332 * This will be a large block if possible, which we will 322 } else {
333 * then process in the small tar blocks. 323 errorFlag=TRUE;
334 */ 324 errorMsg("Bad tar header, skipping\n");
335 if (inCc <= 0) { 325 continue;
336 cp = buf;
337 inCc = fullRead(tarFd, buf, blockSize);
338
339 if (inCc < 0) {
340 perror(tarName);
341 errorFlag = TRUE;
342 goto done;
343 }
344
345 if (inCc == 0) {
346 fprintf(stderr,
347 "Unexpected end of file from \"%s\"", tarName);
348 errorFlag = TRUE;
349 goto done;
350 } 326 }
351 } 327 }
352 328 if ( *(header.name) == '\0' )
353 /* 329 goto endgame;
354 * If we are expecting a header block then examine it. 330
355 */ 331 /* If we got here, we can be certain we have a legitimate
356 if (inHeader == TRUE) { 332 * header to work with. So work with it. */
357 readHeader((const TarHeader *) cp, fileCount, fileTable); 333 switch ( header.type ) {
358 334 case REGTYPE:
359 cp += TAR_BLOCK_SIZE; 335 case REGTYPE0:
360 inCc -= TAR_BLOCK_SIZE; 336 /* If the name ends in a '/' then assume it is
361 337 * supposed to be a directory, and fall through */
362 continue; 338 if (header.name[strlen(header.name)-1] != '/') {
339 tarExtractRegularFile(&header, extractFlag, listFlag, tostdoutFlag, verboseFlag);
340 break;
341 }
342#if 0
343 case Directory:
344 tarExtractDirectory( &header, extractFlag, listFlag, tostdoutFlag, verboseFlag);
345 break;
346 case HardLink:
347 tarExtractHardLink( &header, extractFlag, listFlag, tostdoutFlag, verboseFlag);
348 break;
349 case SymbolicLink:
350 tarExtractSymLink( &header, extractFlag, listFlag, tostdoutFlag, verboseFlag);
351 break;
352 case CharacterDevice:
353 case BlockDevice:
354 case FIFO:
355 tarExtractSpecial( &header, extractFlag, listFlag, tostdoutFlag, verboseFlag);
356 break;
357#endif
358 default:
359 close( tarFd);
360 return( FALSE);
363 } 361 }
364
365 /*
366 * We are currently handling the data for a file.
367 * Process the minimum of the amount of data we have available
368 * and the amount left to be processed for the file.
369 */
370 cc = inCc;
371
372 if (cc > dataCc)
373 cc = dataCc;
374
375 readData(cp, cc);
376
377 /*
378 * If the amount left isn't an exact multiple of the tar block
379 * size then round it up to the next block boundary since there
380 * is padding at the end of the file.
381 */
382 if (cc % TAR_BLOCK_SIZE)
383 cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
384
385 cp += cc;
386 inCc -= cc;
387 } 362 }
388 363
389 done: 364 close(tarFd);
390 /* 365 if (status > 0) {
391 * Close the tar file if needed. 366 /* Bummer - we read a partial header */
392 */ 367 errorMsg( "Error reading '%s': %s", tarName, strerror(errno));
393 if ((tarFd >= 0) && (close(tarFd) < 0)) 368 return ( FALSE);
394 perror(tarName);
395
396 /*
397 * Close the output file if needed.
398 * This is only done here on a previous error and so no
399 * message is required on errors.
400 */
401 if (tostdoutFlag == FALSE) {
402 if (outFd >= 0) {
403 close(outFd);
404 }
405 } 369 }
370 else
371 return( status);
372
373 /* Stuff we do when we know we are done with the file */
374endgame:
375 close( tarFd);
376 if ( *(header.name) == '\0' ) {
377 if (errorFlag==FALSE)
378 return( TRUE);
379 }
380 return( FALSE);
406} 381}
407 382
408
409/* 383/*
410 * Examine the header block that was just read. 384 * Read an octal value in a field of the specified width, with optional
411 * This can specify the information for another file, or it can mark 385 * spaces on both sides of the number and with an optional null character
412 * the end of the tar file. 386 * at the end. Returns -1 on an illegal format.
413 */ 387 */
414static void 388static long getOctal(const char *cp, int size)
415readHeader(const TarHeader * hp, int fileCount, char **fileTable)
416{ 389{
417 int checkSum; 390 long val = 0;
418 int cc;
419 int hardLink;
420 int softLink;
421 int devFileFlag;
422 unsigned int major;
423 unsigned int minor;
424 long size;
425 struct utimbuf utb;
426
427 /*
428 * If the block is completely empty, then this is the end of the
429 * archive file. If the name is null, then just skip this header.
430 */
431 outName = hp->name;
432
433 if (*outName == '\0') {
434 for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
435 if (*outName++)
436 return;
437 }
438 391
439 eofFlag = TRUE; 392 for(;(size > 0) && (*cp == ' '); cp++, size--);
440 393 if ((size == 0) || !isOctal(*cp))
441 return; 394 return -1;
395 for(; (size > 0) && isOctal(*cp); size--) {
396 val = val * 8 + *cp++ - '0';
442 } 397 }
398 for (;(size > 0) && (*cp == ' '); cp++, size--);
399 if ((size > 0) && *cp)
400 return -1;
401 return val;
402}
443 403
444 /* 404/* Parse the tar header and fill in the nice struct with the details */
445 * There is another file in the archive to examine. 405static int
446 * Extract the encoded information and check it. 406parseTarHeader(struct TarHeader *rawHeader, struct TarInfo *header)
447 */ 407{
448 mode = getOctal(hp->mode, sizeof(hp->mode)); 408 long major, minor, chksum, sum;
449 uid = getOctal(hp->uid, sizeof(hp->uid)); 409
450 gid = getOctal(hp->gid, sizeof(hp->gid)); 410 header->name = rawHeader->name;
451 size = getOctal(hp->size, sizeof(hp->size)); 411 header->mode = getOctal(rawHeader->mode, sizeof(rawHeader->mode));
452 mtime = getOctal(hp->mtime, sizeof(hp->mtime)); 412 header->uid = getOctal(rawHeader->uid, sizeof(rawHeader->uid));
453 checkSum = getOctal(hp->checkSum, sizeof(hp->checkSum)); 413 header->gid = getOctal(rawHeader->gid, sizeof(rawHeader->gid));
454 major = getOctal(hp->devMajor, sizeof(hp->devMajor)); 414 header->size = getOctal(rawHeader->size, sizeof(rawHeader->size));
455 minor = getOctal(hp->devMinor, sizeof(hp->devMinor)); 415 header->mtime = getOctal(rawHeader->mtime, sizeof(rawHeader->mtime));
456 416 chksum = getOctal(rawHeader->chksum, sizeof(rawHeader->chksum));
457 if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) { 417 header->type = rawHeader->typeflag;
458 if (badHeader == FALSE) 418 header->linkname = rawHeader->linkname;
459 fprintf(stderr, "Bad tar header, skipping\n"); 419 header->device = MAJOR(getOctal(rawHeader->devmajor, sizeof(rawHeader->devmajor))) |
460 420 MINOR(getOctal(rawHeader->devminor, sizeof(rawHeader->devminor)));
461 badHeader = TRUE; 421
422 /* Check the checksum */
423 sum = ' ' * sizeof(rawHeader->chksum);
424 for ( i = TarChecksumOffset; i > 0; i-- )
425 sum += *s++;
426 s += sizeof(h->chksum);
427 for ( i = (512 - TarChecksumOffset - sizeof(h->chksum)); i > 0; i-- )
428 sum += *s++;
429 if (sum == checksum )
430 return ( TRUE);
431 return( FALSE);
432}
462 433
463 return; 434#if 0
435 if ((header->mode < 0) || (header->uid < 0) ||
436 (header->gid < 0) || (header->size < 0)) {
437 errorMsg(stderr, "Bad tar header, skipping\n");
438 return( FALSE);
464 } 439 }
465 440
466 badHeader = FALSE; 441 badHeader = FALSE;
@@ -502,7 +477,7 @@ readHeader(const TarHeader * hp, int fileCount, char **fileTable)
502 * See if we want this file to be restored. 477 * See if we want this file to be restored.
503 * If not, then set up to skip it. 478 * If not, then set up to skip it.
504 */ 479 */
505 if (wantFileName(outName, fileCount, fileTable) == FALSE) { 480 if (wantFileName(outName, argc, argv) == FALSE) {
506 if (!hardLink && !softLink && (S_ISREG(mode) || S_ISCHR(mode) 481 if (!hardLink && !softLink && (S_ISREG(mode) || S_ISCHR(mode)
507 || S_ISBLK(mode) || S_ISSOCK(mode) 482 || S_ISBLK(mode) || S_ISSOCK(mode)
508 || S_ISFIFO(mode))) { 483 || S_ISFIFO(mode))) {
@@ -726,7 +701,7 @@ static void readData(const char *cp, int count)
726 * Returns TRUE if the file is selected. 701 * Returns TRUE if the file is selected.
727 */ 702 */
728static int 703static int
729wantFileName(const char *fileName, int fileCount, char **fileTable) 704wantFileName(const char *fileName, int argc, char **argv)
730{ 705{
731 const char *pathName; 706 const char *pathName;
732 int fileLength; 707 int fileLength;
@@ -735,7 +710,7 @@ wantFileName(const char *fileName, int fileCount, char **fileTable)
735 /* 710 /*
736 * If there are no files in the list, then the file is wanted. 711 * If there are no files in the list, then the file is wanted.
737 */ 712 */
738 if (fileCount == 0) 713 if (argc == 0)
739 return TRUE; 714 return TRUE;
740 715
741 fileLength = strlen(fileName); 716 fileLength = strlen(fileName);
@@ -743,8 +718,8 @@ wantFileName(const char *fileName, int fileCount, char **fileTable)
743 /* 718 /*
744 * Check each of the test paths. 719 * Check each of the test paths.
745 */ 720 */
746 while (fileCount-- > 0) { 721 while (argc-- > 0) {
747 pathName = *fileTable++; 722 pathName = *argv++;
748 723
749 pathLength = strlen(pathName); 724 pathLength = strlen(pathName);
750 725
@@ -762,43 +737,6 @@ wantFileName(const char *fileName, int fileCount, char **fileTable)
762 return FALSE; 737 return FALSE;
763} 738}
764 739
765/*
766 * Read an octal value in a field of the specified width, with optional
767 * spaces on both sides of the number and with an optional null character
768 * at the end. Returns -1 on an illegal format.
769 */
770static long getOctal(const char *cp, int len)
771{
772 long val;
773
774 while ((len > 0) && (*cp == ' ')) {
775 cp++;
776 len--;
777 }
778
779 if ((len == 0) || !isOctal(*cp))
780 return -1;
781
782 val = 0;
783
784 while ((len > 0) && isOctal(*cp)) {
785 val = val * 8 + *cp++ - '0';
786 len--;
787 }
788
789 while ((len > 0) && (*cp == ' ')) {
790 cp++;
791 len--;
792 }
793
794 if ((len > 0) && *cp)
795 return -1;
796
797 return val;
798}
799
800
801
802 740
803/* From here to the end of the file is the tar writing stuff. 741/* From here to the end of the file is the tar writing stuff.
804 * If you do not have BB_FEATURE_TAR_CREATE defined, this will 742 * If you do not have BB_FEATURE_TAR_CREATE defined, this will
@@ -809,14 +747,14 @@ static long getOctal(const char *cp, int len)
809/* 747/*
810 * Write a tar file containing the specified files. 748 * Write a tar file containing the specified files.
811 */ 749 */
812static void writeTarFile(int fileCount, char **fileTable) 750static void writeTarFile(int argc, char **argv)
813{ 751{
814 struct stat statbuf; 752 struct stat statbuf;
815 753
816 /* 754 /*
817 * Make sure there is at least one file specified. 755 * Make sure there is at least one file specified.
818 */ 756 */
819 if (fileCount <= 0) { 757 if (argc <= 0) {
820 fprintf(stderr, "No files specified to be saved\n"); 758 fprintf(stderr, "No files specified to be saved\n");
821 errorFlag = TRUE; 759 errorFlag = TRUE;
822 } 760 }
@@ -852,8 +790,8 @@ static void writeTarFile(int fileCount, char **fileTable)
852 * Append each file name into the archive file. 790 * Append each file name into the archive file.
853 * Follow symbolic links for these top level file names. 791 * Follow symbolic links for these top level file names.
854 */ 792 */
855 while (errorFlag == FALSE && (fileCount-- > 0)) { 793 while (errorFlag == FALSE && (argc-- > 0)) {
856 saveFile(*fileTable++, FALSE); 794 saveFile(*argv++, FALSE);
857 } 795 }
858 796
859 /* 797 /*
@@ -1284,3 +1222,4 @@ static int putOctal(char *cp, int len, long value)
1284#endif 1222#endif
1285 1223
1286/* END CODE */ 1224/* END CODE */
1225#endif