More stuff
[oweals/busybox.git] / tar.c
1 /*
2  * Copyright (c) 1999 by David I. Bell
3  * Permission is granted to use, distribute, or modify this source,
4  * provided that this copyright notice remains intact.
5  *
6  * The "tar" command, taken from sash.
7  * This allows creation, extraction, and listing of tar files.
8  *
9  * Permission to distribute this code under the GPL has been granted.
10  * Modified for busybox by Erik Andersen <andersee@debian.org>
11  */
12
13
14 #include "internal.h"
15
16 #ifdef BB_TAR
17
18 const char tar_usage[] =
19     "Create, extract, or list files from a TAR file\n\n"
20     "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n"
21     "\tc=create, x=extract, t=list contents, v=verbose,\n"
22     "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n";
23
24
25
26 #include <stdio.h>
27 #include <dirent.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <time.h>
32
33 /*
34  * Tar file constants.
35  */
36 #define TAR_BLOCK_SIZE  512
37 #define TAR_NAME_SIZE   100
38
39
40 /*
41  * The POSIX (and basic GNU) tar header format.
42  * This structure is always embedded in a TAR_BLOCK_SIZE sized block
43  * with zero padding.  We only process this information minimally.
44  */
45 typedef struct {
46     char name[TAR_NAME_SIZE];
47     char mode[8];
48     char uid[8];
49     char gid[8];
50     char size[12];
51     char mtime[12];
52     char checkSum[8];
53     char typeFlag;
54     char linkName[TAR_NAME_SIZE];
55     char magic[6];
56     char version[2];
57     char uname[32];
58     char gname[32];
59     char devMajor[8];
60     char devMinor[8];
61     char prefix[155];
62 } TarHeader;
63
64 #define TAR_MAGIC       "ustar"
65 #define TAR_VERSION     "00"
66
67 #define TAR_TYPE_REGULAR        '0'
68 #define TAR_TYPE_HARD_LINK      '1'
69 #define TAR_TYPE_SOFT_LINK      '2'
70
71
72 /*
73  * Static data.
74  */
75 static int listFlag;
76 static int extractFlag;
77 static int createFlag;
78 static int verboseFlag;
79 static int tostdoutFlag;
80
81 static int inHeader;
82 static int badHeader;
83 static int errorFlag;
84 static int skipFileFlag;
85 static int warnedRoot;
86 static int eofFlag;
87 static long dataCc;
88 static int outFd;
89 static char outName[TAR_NAME_SIZE];
90
91
92 /*
93  * Static data associated with the tar file.
94  */
95 static const char *tarName;
96 static int tarFd;
97 static dev_t tarDev;
98 static ino_t tarInode;
99
100
101 /*
102  * Local procedures to restore files from a tar file.
103  */
104 static void readTarFile (int fileCount, char **fileTable);
105 static void readData (const char *cp, int count);
106 static long getOctal (const char *cp, int len);
107
108 static void readHeader (const TarHeader * hp,
109                         int fileCount, char **fileTable);
110
111
112 /*
113  * Local procedures to save files into a tar file.
114  */
115 static void saveFile (const char *fileName, int seeLinks);
116
117 static void saveRegularFile (const char *fileName,
118                              const struct stat *statbuf);
119
120 static void saveDirectory (const char *fileName,
121                            const struct stat *statbuf);
122
123 static int wantFileName (const char *fileName,
124                          int fileCount, char **fileTable);
125
126 static void writeHeader (const char *fileName, const struct stat *statbuf);
127
128 static void writeTarFile (int fileCount, char **fileTable);
129 static void writeTarBlock (const char *buf, int len);
130 static int putOctal (char *cp, int len, long value);
131
132
133 extern int tar_main (int argc, char **argv)
134 {
135     const char *options;
136
137     argc--;
138     argv++;
139
140     if (argc < 1) {
141         fprintf (stderr, "%s", tar_usage);
142         exit (FALSE);
143     }
144
145
146     errorFlag = FALSE;
147     extractFlag = FALSE;
148     createFlag = FALSE;
149     listFlag = FALSE;
150     verboseFlag = FALSE;
151     tostdoutFlag = FALSE;
152     tarName = NULL;
153     tarDev = 0;
154     tarInode = 0;
155     tarFd = -1;
156
157     /* 
158      * Parse the options.
159      */
160     options = *argv++;
161     argc--;
162
163     if (**argv == '-') {
164         for (; *options; options++) {
165             switch (*options) {
166             case 'f':
167                 if (tarName != NULL) {
168                     fprintf (stderr, "Only one 'f' option allowed\n");
169
170                     exit (FALSE);
171                 }
172
173                 tarName = *argv++;
174                 argc--;
175
176                 break;
177
178             case 't':
179                 listFlag = TRUE;
180                 break;
181
182             case 'x':
183                 extractFlag = TRUE;
184                 break;
185
186             case 'c':
187                 createFlag = TRUE;
188                 break;
189
190             case 'v':
191                 verboseFlag = TRUE;
192                 break;
193
194             case 'O':
195                 tostdoutFlag = TRUE;
196                 break;
197
198             case '-':
199                 break;
200
201             default:
202                 fprintf (stderr, "Unknown tar flag '%c'\n", *options);
203
204                 exit (FALSE);
205             }
206         }
207     }
208
209     /* 
210      * Validate the options.
211      */
212     if (extractFlag + listFlag + createFlag != 1) {
213         fprintf (stderr,
214                  "Exactly one of 'c', 'x' or 't' must be specified\n");
215
216         exit (FALSE);
217     }
218
219     /* 
220      * Do the correct type of action supplying the rest of the
221      * command line arguments as the list of files to process.
222      */
223     if (createFlag)
224         writeTarFile (argc, argv);
225     else
226         readTarFile (argc, argv);
227     if (errorFlag)
228         fprintf (stderr, "\n");
229     exit (errorFlag);
230 }
231
232
233 /*
234  * Read a tar file and extract or list the specified files within it.
235  * If the list is empty than all files are extracted or listed.
236  */
237 static void readTarFile (int fileCount, char **fileTable)
238 {
239     const char *cp;
240     int cc;
241     int inCc;
242     int blockSize;
243     char buf[BUF_SIZE];
244
245     skipFileFlag = FALSE;
246     badHeader = FALSE;
247     warnedRoot = FALSE;
248     eofFlag = FALSE;
249     inHeader = TRUE;
250     inCc = 0;
251     dataCc = 0;
252     outFd = -1;
253     blockSize = sizeof (buf);
254     cp = buf;
255
256     /* 
257      * Open the tar file for reading.
258      */
259     if ((tarName == NULL) || !strcmp (tarName, "-")) {
260         tarFd = STDIN;
261     } else
262         tarFd = open (tarName, O_RDONLY);
263
264     if (tarFd < 0) {
265         perror (tarName);
266         errorFlag = TRUE;
267         return;
268     }
269
270     /* 
271      * Read blocks from the file until an end of file header block
272      * has been seen.  (A real end of file from a read is an error.)
273      */
274     while (!eofFlag) {
275         /* 
276          * Read the next block of data if necessary.
277          * This will be a large block if possible, which we will
278          * then process in the small tar blocks.
279          */
280         if (inCc <= 0) {
281             cp = buf;
282             inCc = fullRead (tarFd, buf, blockSize);
283
284             if (inCc < 0) {
285                 perror (tarName);
286                 errorFlag = TRUE;
287                 goto done;
288             }
289
290             if (inCc == 0) {
291                 fprintf (stderr,
292                          "Unexpected end of file from \"%s\"", tarName);
293                 errorFlag = TRUE;
294                 goto done;
295             }
296         }
297
298         /* 
299          * If we are expecting a header block then examine it.
300          */
301         if (inHeader) {
302             readHeader ((const TarHeader *) cp, fileCount, fileTable);
303
304             cp += TAR_BLOCK_SIZE;
305             inCc -= TAR_BLOCK_SIZE;
306
307             continue;
308         }
309
310         /* 
311          * We are currently handling the data for a file.
312          * Process the minimum of the amount of data we have available
313          * and the amount left to be processed for the file.
314          */
315         cc = inCc;
316
317         if (cc > dataCc)
318             cc = dataCc;
319
320         readData (cp, cc);
321
322         /* 
323          * If the amount left isn't an exact multiple of the tar block
324          * size then round it up to the next block boundary since there
325          * is padding at the end of the file.
326          */
327         if (cc % TAR_BLOCK_SIZE)
328             cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE);
329
330         cp += cc;
331         inCc -= cc;
332     }
333
334   done:
335     /* 
336      * Close the tar file if needed.
337      */
338     if ((tarFd >= 0) && (close (tarFd) < 0))
339         perror (tarName);
340
341     /* 
342      * Close the output file if needed.
343      * This is only done here on a previous error and so no
344      * message is required on errors.
345      */
346     if (tostdoutFlag == FALSE) {
347         if (outFd >= 0)
348             (void) close (outFd);
349     }
350 }
351
352
353 /*
354  * Examine the header block that was just read.
355  * This can specify the information for another file, or it can mark
356  * the end of the tar file.
357  */
358 static void
359 readHeader (const TarHeader * hp, int fileCount, char **fileTable)
360 {
361     int mode;
362     int uid;
363     int gid;
364     int checkSum;
365     long size;
366     time_t mtime;
367     const char *name;
368     int cc;
369     int hardLink;
370     int softLink;
371
372     /* 
373      * If the block is completely empty, then this is the end of the
374      * archive file.  If the name is null, then just skip this header.
375      */
376     name = hp->name;
377
378     if (*name == '\0') {
379         for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) {
380             if (*name++)
381                 return;
382         }
383
384         eofFlag = TRUE;
385
386         return;
387     }
388
389     /* 
390      * There is another file in the archive to examine.
391      * Extract the encoded information and check it.
392      */
393     mode = getOctal (hp->mode, sizeof (hp->mode));
394     uid = getOctal (hp->uid, sizeof (hp->uid));
395     gid = getOctal (hp->gid, sizeof (hp->gid));
396     size = getOctal (hp->size, sizeof (hp->size));
397     mtime = getOctal (hp->mtime, sizeof (hp->mtime));
398     checkSum = getOctal (hp->checkSum, sizeof (hp->checkSum));
399
400     if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) {
401         if (!badHeader)
402             fprintf (stderr, "Bad tar header, skipping\n");
403
404         badHeader = TRUE;
405
406         return;
407     }
408
409     badHeader = FALSE;
410     skipFileFlag = FALSE;
411
412     /* 
413      * Check for the file modes.
414      */
415     hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
416                 (hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));
417
418     softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
419                 (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));
420
421     /* 
422      * Check for a directory or a regular file.
423      */
424     if (name[strlen (name) - 1] == '/')
425         mode |= S_IFDIR;
426     else if ((mode & S_IFMT) == 0)
427         mode |= S_IFREG;
428
429     /* 
430      * Check for absolute paths in the file.
431      * If we find any, then warn the user and make them relative.
432      */
433     if (*name == '/') {
434         while (*name == '/')
435             name++;
436
437         if (!warnedRoot) {
438             fprintf (stderr,
439                      "Absolute path detected, removing leading slashes\n");
440         }
441
442         warnedRoot = TRUE;
443     }
444
445     /* 
446      * See if we want this file to be restored.
447      * If not, then set up to skip it.
448      */
449     if (!wantFileName (name, fileCount, fileTable)) {
450         if (!hardLink && !softLink && S_ISREG (mode)) {
451             inHeader = (size == 0);
452             dataCc = size;
453         }
454
455         skipFileFlag = TRUE;
456
457         return;
458     }
459
460     /* 
461      * This file is to be handled.
462      * If we aren't extracting then just list information about the file.
463      */
464     if (!extractFlag) {
465         if (verboseFlag) {
466             printf ("%s %3d/%-d %9ld %s %s", modeString (mode),
467                     uid, gid, size, timeString (mtime), name);
468         } else
469             printf ("%s", name);
470
471         if (hardLink)
472             printf (" (link to \"%s\")", hp->linkName);
473         else if (softLink)
474             printf (" (symlink to \"%s\")", hp->linkName);
475         else if (S_ISREG (mode)) {
476             inHeader = (size == 0);
477             dataCc = size;
478         }
479
480         printf ("\n");
481
482         return;
483     }
484
485     /* 
486      * We really want to extract the file.
487      */
488     if (verboseFlag)
489         printf ("x %s\n", name);
490
491     if (hardLink) {
492         if (link (hp->linkName, name) < 0)
493             perror (name);
494
495         return;
496     }
497
498     if (softLink) {
499 #ifdef  S_ISLNK
500         if (symlink (hp->linkName, name) < 0)
501             perror (name);
502 #else
503         fprintf (stderr, "Cannot create symbolic links\n");
504 #endif
505         return;
506     }
507
508     /* 
509      * If the file is a directory, then just create the path.
510      */
511     if (S_ISDIR (mode)) {
512         createPath (name, mode);
513
514         return;
515     }
516
517     /* 
518      * There is a file to write.
519      * First create the path to it if necessary with a default permission.
520      */
521     createPath (name, 0777);
522
523     inHeader = (size == 0);
524     dataCc = size;
525
526     /* 
527      * Start the output file.
528      */
529     if (tostdoutFlag == TRUE)
530         outFd = STDOUT;
531     else
532         outFd = open (name, O_WRONLY | O_CREAT | O_TRUNC, mode);
533
534     if (outFd < 0) {
535         perror (name);
536         skipFileFlag = TRUE;
537         return;
538     }
539
540     /* 
541      * If the file is empty, then that's all we need to do.
542      */
543     if (size == 0 && tostdoutFlag == FALSE) {
544         (void) close (outFd);
545         outFd = -1;
546     }
547 }
548
549
550 /*
551  * Handle a data block of some specified size that was read.
552  */
553 static void readData (const char *cp, int count)
554 {
555     /* 
556      * Reduce the amount of data left in this file.
557      * If there is no more data left, then we need to read
558      * the header again.
559      */
560     dataCc -= count;
561
562     if (dataCc <= 0)
563         inHeader = TRUE;
564
565     /* 
566      * If we aren't extracting files or this file is being
567      * skipped then do nothing more.
568      */
569     if (!extractFlag || skipFileFlag)
570         return;
571
572     /* 
573      * Write the data to the output file.
574      */
575     if (fullWrite (outFd, cp, count) < 0) {
576         perror (outName);
577         if (tostdoutFlag == FALSE) {
578             (void) close (outFd);
579             outFd = -1;
580         }
581         skipFileFlag = TRUE;
582         return;
583     }
584
585     /* 
586      * If the write failed, close the file and disable further
587      * writes to this file.
588      */
589     if (dataCc <= 0 && tostdoutFlag == FALSE) {
590         if (close (outFd))
591             perror (outName);
592
593         outFd = -1;
594     }
595 }
596
597
598 /*
599  * Write a tar file containing the specified files.
600  */
601 static void writeTarFile (int fileCount, char **fileTable)
602 {
603     struct stat statbuf;
604
605     /* 
606      * Make sure there is at least one file specified.
607      */
608     if (fileCount <= 0) {
609         fprintf (stderr, "No files specified to be saved\n");
610         errorFlag = TRUE;
611     }
612
613     /* 
614      * Create the tar file for writing.
615      */
616     if ((tarName == NULL) || !strcmp (tarName, "-")) {
617         tostdoutFlag = TRUE;
618         tarFd = STDOUT;
619     } else
620         tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666);
621
622     if (tarFd < 0) {
623         perror (tarName);
624         errorFlag = TRUE;
625         return;
626     }
627
628     /* 
629      * Get the device and inode of the tar file for checking later.
630      */
631     if (fstat (tarFd, &statbuf) < 0) {
632         perror (tarName);
633         errorFlag = TRUE;
634         goto done;
635     }
636
637     tarDev = statbuf.st_dev;
638     tarInode = statbuf.st_ino;
639
640     /* 
641      * Append each file name into the archive file.
642      * Follow symbolic links for these top level file names.
643      */
644     while (!errorFlag && (fileCount-- > 0)) {
645         saveFile (*fileTable++, FALSE);
646     }
647
648     /* 
649      * Now write an empty block of zeroes to end the archive.
650      */
651     writeTarBlock ("", 1);
652
653
654   done:
655     /* 
656      * Close the tar file and check for errors if it was opened.
657      */
658     if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close (tarFd) < 0))
659         perror (tarName);
660 }
661
662
663 /*
664  * Save one file into the tar file.
665  * If the file is a directory, then this will recursively save all of
666  * the files and directories within the directory.  The seeLinks
667  * flag indicates whether or not we want to see symbolic links as
668  * they really are, instead of blindly following them.
669  */
670 static void saveFile (const char *fileName, int seeLinks)
671 {
672     int status;
673     int mode;
674     struct stat statbuf;
675
676     if (verboseFlag)
677         printf ("a %s\n", fileName);
678
679     /* 
680      * Check that the file name will fit in the header.
681      */
682     if (strlen (fileName) >= TAR_NAME_SIZE) {
683         fprintf (stderr, "%s: File name is too long\n", fileName);
684
685         return;
686     }
687
688     /* 
689      * Find out about the file.
690      */
691 #ifdef  S_ISLNK
692     if (seeLinks)
693         status = lstat (fileName, &statbuf);
694     else
695 #endif
696         status = stat (fileName, &statbuf);
697
698     if (status < 0) {
699         perror (fileName);
700
701         return;
702     }
703
704     /* 
705      * Make sure we aren't trying to save our file into itself.
706      */
707     if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) {
708         fprintf (stderr, "Skipping saving of archive file itself\n");
709
710         return;
711     }
712
713     /* 
714      * Check the type of file.
715      */
716     mode = statbuf.st_mode;
717
718     if (S_ISDIR (mode)) {
719         saveDirectory (fileName, &statbuf);
720
721         return;
722     }
723
724     if (S_ISREG (mode)) {
725         saveRegularFile (fileName, &statbuf);
726
727         return;
728     }
729
730     /* 
731      * The file is a strange type of file, ignore it.
732      */
733     fprintf (stderr, "%s: not a directory or regular file\n", fileName);
734 }
735
736
737 /*
738  * Save a regular file to the tar file.
739  */
740 static void
741 saveRegularFile (const char *fileName, const struct stat *statbuf)
742 {
743     int sawEof;
744     int fileFd;
745     int cc;
746     int dataCount;
747     long fullDataCount;
748     char data[TAR_BLOCK_SIZE * 16];
749
750     /* 
751      * Open the file for reading.
752      */
753     fileFd = open (fileName, O_RDONLY);
754
755     if (fileFd < 0) {
756         perror (fileName);
757
758         return;
759     }
760
761     /* 
762      * Write out the header for the file.
763      */
764     writeHeader (fileName, statbuf);
765
766     /* 
767      * Write the data blocks of the file.
768      * We must be careful to write the amount of data that the stat
769      * buffer indicated, even if the file has changed size.  Otherwise
770      * the tar file will be incorrect.
771      */
772     fullDataCount = statbuf->st_size;
773     sawEof = FALSE;
774
775     while (fullDataCount > 0) {
776         /* 
777          * Get the amount to write this iteration which is
778          * the minumum of the amount left to write and the
779          * buffer size.
780          */
781         dataCount = sizeof (data);
782
783         if (dataCount > fullDataCount)
784             dataCount = (int) fullDataCount;
785
786         /* 
787          * Read the data from the file if we haven't seen the
788          * end of file yet.
789          */
790         cc = 0;
791
792         if (!sawEof) {
793             cc = fullRead (fileFd, data, dataCount);
794
795             if (cc < 0) {
796                 perror (fileName);
797
798                 (void) close (fileFd);
799                 errorFlag = TRUE;
800
801                 return;
802             }
803
804             /* 
805              * If the file ended too soon, complain and set
806              * a flag so we will zero fill the rest of it.
807              */
808             if (cc < dataCount) {
809                 fprintf (stderr,
810                          "%s: Short read - zero filling", fileName);
811
812                 sawEof = TRUE;
813             }
814         }
815
816         /* 
817          * Zero fill the rest of the data if necessary.
818          */
819         if (cc < dataCount)
820             memset (data + cc, 0, dataCount - cc);
821
822         /* 
823          * Write the buffer to the TAR file.
824          */
825         writeTarBlock (data, dataCount);
826
827         fullDataCount -= dataCount;
828     }
829
830     /* 
831      * Close the file.
832      */
833     if ((tostdoutFlag == FALSE) && close (fileFd) < 0)
834         fprintf (stderr, "%s: close: %s\n", fileName, strerror (errno));
835 }
836
837
838 /*
839  * Save a directory and all of its files to the tar file.
840  */
841 static void saveDirectory (const char *dirName, const struct stat *statbuf)
842 {
843     DIR *dir;
844     struct dirent *entry;
845     int needSlash;
846     char fullName[NAME_MAX];
847
848     /* 
849      * Construct the directory name as used in the tar file by appending
850      * a slash character to it.
851      */
852     strcpy (fullName, dirName);
853     strcat (fullName, "/");
854
855     /* 
856      * Write out the header for the directory entry.
857      */
858     writeHeader (fullName, statbuf);
859
860     /* 
861      * Open the directory.
862      */
863     dir = opendir (dirName);
864
865     if (dir == NULL) {
866         fprintf (stderr, "Cannot read directory \"%s\": %s\n",
867                  dirName, strerror (errno));
868
869         return;
870     }
871
872     /* 
873      * See if a slash is needed.
874      */
875     needSlash = (*dirName && (dirName[strlen (dirName) - 1] != '/'));
876
877     /* 
878      * Read all of the directory entries and check them,
879      * except for the current and parent directory entries.
880      */
881     while (!errorFlag && ((entry = readdir (dir)) != NULL)) {
882         if ((strcmp (entry->d_name, ".") == 0) ||
883             (strcmp (entry->d_name, "..") == 0)) {
884             continue;
885         }
886
887         /* 
888          * Build the full path name to the file.
889          */
890         strcpy (fullName, dirName);
891
892         if (needSlash)
893             strcat (fullName, "/");
894
895         strcat (fullName, entry->d_name);
896
897         /* 
898          * Write this file to the tar file, noticing whether or not
899          * the file is a symbolic link.
900          */
901         saveFile (fullName, TRUE);
902     }
903
904     /* 
905      * All done, close the directory.
906      */
907     closedir (dir);
908 }
909
910
911 /*
912  * Write a tar header for the specified file name and status.
913  * It is assumed that the file name fits.
914  */
915 static void writeHeader (const char *fileName, const struct stat *statbuf)
916 {
917     long checkSum;
918     const unsigned char *cp;
919     int len;
920     TarHeader header;
921
922     /* 
923      * Zero the header block in preparation for filling it in.
924      */
925     memset ((char *) &header, 0, sizeof (header));
926
927     /* 
928      * Fill in the header.
929      */
930     strcpy (header.name, fileName);
931
932     strncpy (header.magic, TAR_MAGIC, sizeof (header.magic));
933     strncpy (header.version, TAR_VERSION, sizeof (header.version));
934
935     putOctal (header.mode, sizeof (header.mode), statbuf->st_mode & 0777);
936     putOctal (header.uid, sizeof (header.uid), statbuf->st_uid);
937     putOctal (header.gid, sizeof (header.gid), statbuf->st_gid);
938     putOctal (header.size, sizeof (header.size), statbuf->st_size);
939     putOctal (header.mtime, sizeof (header.mtime), statbuf->st_mtime);
940
941     header.typeFlag = TAR_TYPE_REGULAR;
942
943     /* 
944      * Calculate and store the checksum.
945      * This is the sum of all of the bytes of the header,
946      * with the checksum field itself treated as blanks.
947      */
948     memset (header.checkSum, ' ', sizeof (header.checkSum));
949
950     cp = (const unsigned char *) &header;
951     len = sizeof (header);
952     checkSum = 0;
953
954     while (len-- > 0)
955         checkSum += *cp++;
956
957     putOctal (header.checkSum, sizeof (header.checkSum), checkSum);
958
959     /* 
960      * Write the tar header.
961      */
962     writeTarBlock ((const char *) &header, sizeof (header));
963 }
964
965
966 /*
967  * Write data to one or more blocks of the tar file.
968  * The data is always padded out to a multiple of TAR_BLOCK_SIZE.
969  * The errorFlag static variable is set on an error.
970  */
971 static void writeTarBlock (const char *buf, int len)
972 {
973     int partialLength;
974     int completeLength;
975     char fullBlock[TAR_BLOCK_SIZE];
976
977     /* 
978      * If we had a write error before, then do nothing more.
979      */
980     if (errorFlag)
981         return;
982
983     /* 
984      * Get the amount of complete and partial blocks.
985      */
986     partialLength = len % TAR_BLOCK_SIZE;
987     completeLength = len - partialLength;
988
989     /* 
990      * Write all of the complete blocks.
991      */
992     if ((completeLength > 0) && !fullWrite (tarFd, buf, completeLength)) {
993         perror (tarName);
994
995         errorFlag = TRUE;
996
997         return;
998     }
999
1000     /* 
1001      * If there are no partial blocks left, we are done.
1002      */
1003     if (partialLength == 0)
1004         return;
1005
1006     /* 
1007      * Copy the partial data into a complete block, and pad the rest
1008      * of it with zeroes.
1009      */
1010     memcpy (fullBlock, buf + completeLength, partialLength);
1011     memset (fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength);
1012
1013     /* 
1014      * Write the last complete block.
1015      */
1016     if (!fullWrite (tarFd, fullBlock, TAR_BLOCK_SIZE)) {
1017         perror (tarName);
1018
1019         errorFlag = TRUE;
1020     }
1021 }
1022
1023
1024 /*
1025  * Read an octal value in a field of the specified width, with optional
1026  * spaces on both sides of the number and with an optional null character
1027  * at the end.  Returns -1 on an illegal format.
1028  */
1029 static long getOctal (const char *cp, int len)
1030 {
1031     long val;
1032
1033     while ((len > 0) && (*cp == ' ')) {
1034         cp++;
1035         len--;
1036     }
1037
1038     if ((len == 0) || !isOctal (*cp))
1039         return -1;
1040
1041     val = 0;
1042
1043     while ((len > 0) && isOctal (*cp)) {
1044         val = val * 8 + *cp++ - '0';
1045         len--;
1046     }
1047
1048     while ((len > 0) && (*cp == ' ')) {
1049         cp++;
1050         len--;
1051     }
1052
1053     if ((len > 0) && *cp)
1054         return -1;
1055
1056     return val;
1057 }
1058
1059
1060 /*
1061  * Put an octal string into the specified buffer.
1062  * The number is zero and space padded and possibly null padded.
1063  * Returns TRUE if successful.
1064  */
1065 static int putOctal (char *cp, int len, long value)
1066 {
1067     int tempLength;
1068     char *tempString;
1069     char tempBuffer[32];
1070
1071     /* 
1072      * Create a string of the specified length with an initial space,
1073      * leading zeroes and the octal number, and a trailing null.
1074      */
1075     tempString = tempBuffer;
1076
1077     sprintf (tempString, " %0*lo", len - 2, value);
1078
1079     tempLength = strlen (tempString) + 1;
1080
1081     /* 
1082      * If the string is too large, suppress the leading space.
1083      */
1084     if (tempLength > len) {
1085         tempLength--;
1086         tempString++;
1087     }
1088
1089     /* 
1090      * If the string is still too large, suppress the trailing null.
1091      */
1092     if (tempLength > len)
1093         tempLength--;
1094
1095     /* 
1096      * If the string is still too large, fail.
1097      */
1098     if (tempLength > len)
1099         return FALSE;
1100
1101     /* 
1102      * Copy the string to the field.
1103      */
1104     memcpy (cp, tempString, len);
1105
1106     return TRUE;
1107 }
1108
1109
1110 /*
1111  * See if the specified file name belongs to one of the specified list
1112  * of path prefixes.  An empty list implies that all files are wanted.
1113  * Returns TRUE if the file is selected.
1114  */
1115 static int
1116 wantFileName (const char *fileName, int fileCount, char **fileTable)
1117 {
1118     const char *pathName;
1119     int fileLength;
1120     int pathLength;
1121
1122     /* 
1123      * If there are no files in the list, then the file is wanted.
1124      */
1125     if (fileCount == 0)
1126         return TRUE;
1127
1128     fileLength = strlen (fileName);
1129
1130     /* 
1131      * Check each of the test paths.
1132      */
1133     while (fileCount-- > 0) {
1134         pathName = *fileTable++;
1135
1136         pathLength = strlen (pathName);
1137
1138         if (fileLength < pathLength)
1139             continue;
1140
1141         if (memcmp (fileName, pathName, pathLength) != 0)
1142             continue;
1143
1144         if ((fileLength == pathLength) || (fileName[pathLength] == '/')) {
1145             return TRUE;
1146         }
1147     }
1148
1149     return FALSE;
1150 }
1151
1152
1153
1154 #endif
1155 /* END CODE */