diff options
author | Erik Andersen <andersen@codepoet.org> | 2000-04-08 03:08:21 +0000 |
---|---|---|
committer | Erik Andersen <andersen@codepoet.org> | 2000-04-08 03:08:21 +0000 |
commit | ecd512453ce8f7a7c8a3b5d523855a2b52d626c5 (patch) | |
tree | 85d71f517408081f99a9ad52ed3dc233c3db082e /archival | |
parent | 5dd853ad2a8da4d1e85a2221ce3e15bfb1e5885c (diff) | |
download | busybox-w32-ecd512453ce8f7a7c8a3b5d523855a2b52d626c5.tar.gz busybox-w32-ecd512453ce8f7a7c8a3b5d523855a2b52d626c5.tar.bz2 busybox-w32-ecd512453ce8f7a7c8a3b5d523855a2b52d626c5.zip |
Latest and greatest
-Erik
Diffstat (limited to 'archival')
-rw-r--r-- | archival/tar.c | 174 |
1 files changed, 103 insertions, 71 deletions
diff --git a/archival/tar.c b/archival/tar.c index 91baa2ddb..49d4d2ecf 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -55,24 +55,27 @@ | |||
55 | #ifdef BB_FEATURE_TAR_CREATE | 55 | #ifdef BB_FEATURE_TAR_CREATE |
56 | 56 | ||
57 | static const char tar_usage[] = | 57 | static const char tar_usage[] = |
58 | "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" | 58 | "tar -[cxtvOf] [tarFile] [-X excludeFile] [FILE] ...\n\n" |
59 | "Create, extract, or list files from a tar file. Note that\n" | 59 | "Create, extract, or list files from a tar file. Note that\n" |
60 | "this version of tar packs hard links as separate files.\n\n" | 60 | "this version of tar packs hard links as separate files.\n\n" |
61 | "Options:\n" | 61 | "Options:\n" |
62 | 62 | ||
63 | "\tc=create, x=extract, t=list contents, v=verbose,\n" | 63 | "\tc=create, x=extract, t=list contents, v=verbose,\n" |
64 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; | 64 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n" |
65 | "\tX=exclude file\n"; | ||
65 | 66 | ||
66 | #else | 67 | #else |
67 | 68 | ||
68 | static const char tar_usage[] = | 69 | static const char tar_usage[] = |
69 | "tar -[xtvOf] [tarFileName] [FILE] ...\n\n" | 70 | "tar -[xtvO] [-f tarFile] [-X excludeFile] [FILE] ...\n\n" |
70 | "Extract, or list files stored in a tar file. This\n" | 71 | "Extract, or list files stored in a tar file. This\n" |
71 | "version of tar does not support creation of tar files.\n\n" | 72 | "version of tar does not support creation of tar files.\n\n" |
72 | "Options:\n" | 73 | "Options:\n" |
73 | 74 | ||
74 | "\tx=extract, t=list contents, v=verbose,\n" | 75 | "\tx=extract, t=list contents, v=verbose,\n" |
75 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; | 76 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n" |
77 | "\tX=exclude file\n"; | ||
78 | |||
76 | 79 | ||
77 | #endif | 80 | #endif |
78 | 81 | ||
@@ -157,90 +160,106 @@ static const unsigned long TarChecksumOffset = (const unsigned long)&(((TarHeade | |||
157 | 160 | ||
158 | /* Local procedures to restore files from a tar file. */ | 161 | /* Local procedures to restore files from a tar file. */ |
159 | static int readTarFile(const char* tarName, int extractFlag, int listFlag, | 162 | static int readTarFile(const char* tarName, int extractFlag, int listFlag, |
160 | int tostdoutFlag, int verboseFlag); | 163 | int tostdoutFlag, int verboseFlag, char** excludeList); |
161 | 164 | ||
162 | 165 | ||
163 | 166 | ||
164 | #ifdef BB_FEATURE_TAR_CREATE | 167 | #ifdef BB_FEATURE_TAR_CREATE |
165 | /* Local procedures to save files into a tar file. */ | 168 | /* Local procedures to save files into a tar file. */ |
166 | static int writeTarFile(const char* tarName, int tostdoutFlag, | 169 | static int writeTarFile(const char* tarName, int tostdoutFlag, |
167 | int verboseFlag, int argc, char **argv); | 170 | int verboseFlag, int argc, char **argv, char** excludeList); |
168 | static int putOctal(char *cp, int len, long value); | ||
169 | |||
170 | #endif | 171 | #endif |
171 | 172 | ||
172 | 173 | ||
173 | extern int tar_main(int argc, char **argv) | 174 | extern int tar_main(int argc, char **argv) |
174 | { | 175 | { |
176 | char** excludeList=NULL; | ||
177 | int excludeListSize=0; | ||
175 | const char *tarName=NULL; | 178 | const char *tarName=NULL; |
176 | const char *options; | ||
177 | int listFlag = FALSE; | 179 | int listFlag = FALSE; |
178 | int extractFlag = FALSE; | 180 | int extractFlag = FALSE; |
179 | int createFlag = FALSE; | 181 | int createFlag = FALSE; |
180 | int verboseFlag = FALSE; | 182 | int verboseFlag = FALSE; |
181 | int tostdoutFlag = FALSE; | 183 | int tostdoutFlag = FALSE; |
184 | int stopIt; | ||
182 | 185 | ||
183 | argc--; | 186 | if (argc <= 1) |
184 | argv++; | ||
185 | |||
186 | if (argc < 1) | ||
187 | usage(tar_usage); | 187 | usage(tar_usage); |
188 | 188 | ||
189 | /* Parse options */ | 189 | /* Parse any options */ |
190 | if (**argv == '-') | 190 | while (--argc > 0 && **(++argv) == '-') { |
191 | options = (*argv++) + 1; | 191 | stopIt=FALSE; |
192 | else | 192 | while (stopIt==FALSE && *(++(*argv))) { |
193 | options = (*argv++); | 193 | switch (**argv) { |
194 | argc--; | 194 | case 'f': |
195 | 195 | if (--argc == 0) { | |
196 | for (; *options; options++) { | 196 | fatalError( "Option requires an argument: No file specified\n"); |
197 | switch (*options) { | 197 | } |
198 | case 'f': | 198 | if (tarName != NULL) |
199 | if (tarName != NULL) | 199 | fatalError( "Only one 'f' option allowed\n"); |
200 | fatalError( "Only one 'f' option allowed\n"); | 200 | tarName = *(++argv); |
201 | 201 | if (tarName == NULL) | |
202 | tarName = *argv++; | 202 | fatalError( "Option requires an argument: No file specified\n"); |
203 | if (tarName == NULL) | 203 | stopIt=TRUE; |
204 | fatalError( "Option requires an argument: No file specified\n"); | 204 | break; |
205 | argc--; | 205 | |
206 | 206 | case 't': | |
207 | break; | 207 | if (extractFlag == TRUE || createFlag == TRUE) |
208 | 208 | goto flagError; | |
209 | case 't': | 209 | listFlag = TRUE; |
210 | if (extractFlag == TRUE || createFlag == TRUE) | 210 | break; |
211 | goto flagError; | 211 | |
212 | listFlag = TRUE; | 212 | case 'x': |
213 | break; | 213 | if (listFlag == TRUE || createFlag == TRUE) |
214 | 214 | goto flagError; | |
215 | case 'x': | 215 | extractFlag = TRUE; |
216 | if (listFlag == TRUE || createFlag == TRUE) | 216 | break; |
217 | goto flagError; | 217 | case 'c': |
218 | extractFlag = TRUE; | 218 | if (extractFlag == TRUE || listFlag == TRUE) |
219 | break; | 219 | goto flagError; |
220 | case 'c': | 220 | createFlag = TRUE; |
221 | if (extractFlag == TRUE || listFlag == TRUE) | 221 | break; |
222 | goto flagError; | 222 | |
223 | createFlag = TRUE; | 223 | case 'v': |
224 | break; | 224 | verboseFlag = TRUE; |
225 | 225 | break; | |
226 | case 'v': | 226 | |
227 | verboseFlag = TRUE; | 227 | case 'O': |
228 | break; | 228 | tostdoutFlag = TRUE; |
229 | 229 | tarName = "-"; | |
230 | case 'O': | 230 | break; |
231 | tostdoutFlag = TRUE; | 231 | case 'X': |
232 | tarName = "-"; | 232 | if (--argc == 0) { |
233 | break; | 233 | fatalError( "Option requires an argument: No file specified\n"); |
234 | 234 | } | |
235 | case '-': | 235 | excludeList=realloc( excludeList, sizeof(char**) * (excludeListSize+1)); |
236 | usage(tar_usage); | 236 | excludeList[excludeListSize] = *(++argv); |
237 | break; | 237 | /* Remove leading "/"s */ |
238 | 238 | if (*excludeList[excludeListSize] =='/') { | |
239 | default: | 239 | excludeList[excludeListSize] = (excludeList[excludeListSize])+1; |
240 | fatalError( "Unknown tar flag '%c'\n" | 240 | } |
241 | "Try `tar --help' for more information\n", *options); | 241 | if (excludeList[excludeListSize++] == NULL) |
242 | fatalError( "Option requires an argument: No file specified\n"); | ||
243 | stopIt=TRUE; | ||
244 | break; | ||
245 | |||
246 | case '-': | ||
247 | usage(tar_usage); | ||
248 | break; | ||
249 | |||
250 | default: | ||
251 | fatalError( "Unknown tar flag '%c'\n" | ||
252 | "Try `tar --help' for more information\n", **argv); | ||
253 | } | ||
242 | } | 254 | } |
243 | } | 255 | } |
256 | #if 0 | ||
257 | for (i=0; i<excludeListSize; i++) { | ||
258 | printf( "%s\n", excludeList[i]); | ||
259 | fflush(stdout); | ||
260 | } | ||
261 | #endif | ||
262 | |||
244 | 263 | ||
245 | /* | 264 | /* |
246 | * Do the correct type of action supplying the rest of the | 265 | * Do the correct type of action supplying the rest of the |
@@ -250,10 +269,10 @@ extern int tar_main(int argc, char **argv) | |||
250 | #ifndef BB_FEATURE_TAR_CREATE | 269 | #ifndef BB_FEATURE_TAR_CREATE |
251 | fatalError( "This version of tar was not compiled with tar creation support.\n"); | 270 | fatalError( "This version of tar was not compiled with tar creation support.\n"); |
252 | #else | 271 | #else |
253 | exit(writeTarFile(tarName, tostdoutFlag, verboseFlag, argc, argv)); | 272 | exit(writeTarFile(tarName, tostdoutFlag, verboseFlag, argc, argv, excludeList)); |
254 | #endif | 273 | #endif |
255 | } else { | 274 | } else { |
256 | exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag)); | 275 | exit(readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, verboseFlag, excludeList)); |
257 | } | 276 | } |
258 | 277 | ||
259 | flagError: | 278 | flagError: |
@@ -486,7 +505,7 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) | |||
486 | * If the list is empty than all files are extracted or listed. | 505 | * If the list is empty than all files are extracted or listed. |
487 | */ | 506 | */ |
488 | static int readTarFile(const char* tarName, int extractFlag, int listFlag, | 507 | static int readTarFile(const char* tarName, int extractFlag, int listFlag, |
489 | int tostdoutFlag, int verboseFlag) | 508 | int tostdoutFlag, int verboseFlag, char** excludeList) |
490 | { | 509 | { |
491 | int status, tarFd=0; | 510 | int status, tarFd=0; |
492 | int errorFlag=FALSE; | 511 | int errorFlag=FALSE; |
@@ -675,6 +694,7 @@ struct TarBallInfo | |||
675 | tarball lives, so we can avoid trying | 694 | tarball lives, so we can avoid trying |
676 | to include the tarball into itself */ | 695 | to include the tarball into itself */ |
677 | int verboseFlag; /* Whether to print extra stuff or not */ | 696 | int verboseFlag; /* Whether to print extra stuff or not */ |
697 | char** excludeList; /* List of files to not include */ | ||
678 | }; | 698 | }; |
679 | typedef struct TarBallInfo TarBallInfo; | 699 | typedef struct TarBallInfo TarBallInfo; |
680 | 700 | ||
@@ -719,6 +739,7 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st | |||
719 | { | 739 | { |
720 | long chksum=0; | 740 | long chksum=0; |
721 | struct TarHeader header; | 741 | struct TarHeader header; |
742 | char** tmpList; | ||
722 | const unsigned char *cp = (const unsigned char *) &header; | 743 | const unsigned char *cp = (const unsigned char *) &header; |
723 | ssize_t size = sizeof(struct TarHeader); | 744 | ssize_t size = sizeof(struct TarHeader); |
724 | 745 | ||
@@ -735,6 +756,17 @@ writeTarHeader(struct TarBallInfo *tbInfo, const char *fileName, struct stat *st | |||
735 | else { | 756 | else { |
736 | strcpy(header.name, fileName); | 757 | strcpy(header.name, fileName); |
737 | } | 758 | } |
759 | #if 0 | ||
760 | /* Now that leading '/''s have been removed */ | ||
761 | for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { | ||
762 | printf( "comparing '%s' and '%s'", *tmpList, header.name); | ||
763 | if (strcmp( *tmpList, header.name)==0) | ||
764 | printf( ": match\n"); | ||
765 | else | ||
766 | printf( "\n"); | ||
767 | } | ||
768 | #endif | ||
769 | |||
738 | putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); | 770 | putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); |
739 | putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); | 771 | putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); |
740 | putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); | 772 | putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); |
@@ -868,12 +900,11 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* | |||
868 | } | 900 | } |
869 | 901 | ||
870 | static int writeTarFile(const char* tarName, int tostdoutFlag, | 902 | static int writeTarFile(const char* tarName, int tostdoutFlag, |
871 | int verboseFlag, int argc, char **argv) | 903 | int verboseFlag, int argc, char **argv, char** excludeList) |
872 | { | 904 | { |
873 | int tarFd=-1; | 905 | int tarFd=-1; |
874 | int errorFlag=FALSE; | 906 | int errorFlag=FALSE; |
875 | ssize_t size; | 907 | ssize_t size; |
876 | //int skipFileFlag=FALSE; | ||
877 | struct TarBallInfo tbInfo; | 908 | struct TarBallInfo tbInfo; |
878 | tbInfo.verboseFlag = verboseFlag; | 909 | tbInfo.verboseFlag = verboseFlag; |
879 | 910 | ||
@@ -890,6 +921,7 @@ static int writeTarFile(const char* tarName, int tostdoutFlag, | |||
890 | errorMsg( "tar: Error opening '%s': %s\n", tarName, strerror(errno)); | 921 | errorMsg( "tar: Error opening '%s': %s\n", tarName, strerror(errno)); |
891 | return ( FALSE); | 922 | return ( FALSE); |
892 | } | 923 | } |
924 | tbInfo.excludeList=excludeList; | ||
893 | /* Store the stat info for the tarball's file, so | 925 | /* Store the stat info for the tarball's file, so |
894 | * can avoid including the tarball into itself.... */ | 926 | * can avoid including the tarball into itself.... */ |
895 | if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) | 927 | if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) |