diff options
Diffstat (limited to 'tar.c')
-rw-r--r-- | tar.c | 513 |
1 files changed, 226 insertions, 287 deletions
@@ -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. | 75 | struct 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 */ |
83 | typedef 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; | 96 | typedef 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 */ | ||
108 | enum 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 | }; | ||
120 | typedef 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. */ | ||
125 | struct 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 | }; | ||
138 | typedef struct TarInfo TarInfo; | ||
139 | |||
140 | /* Static data */ | ||
141 | static const unsigned long TarChecksumOffset = (const unsigned long)&(((TarHeader *)0)->chksum); | ||
108 | 142 | ||
109 | 143 | ||
110 | /* | 144 | /* |
111 | * Static data. | 145 | * Static data. |
112 | */ | 146 | */ |
113 | static int listFlag; | ||
114 | static int extractFlag; | ||
115 | static int createFlag; | ||
116 | static int verboseFlag; | ||
117 | static int tostdoutFlag; | ||
118 | |||
119 | static int inHeader; // <- check me | 147 | static int inHeader; // <- check me |
120 | static int badHeader; | 148 | static int badHeader; |
121 | static int errorFlag; | ||
122 | static int skipFileFlag; | 149 | static int skipFileFlag; |
123 | static int warnedRoot; | 150 | static int warnedRoot; |
124 | static int eofFlag; | 151 | static 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 | */ |
137 | static const char *tarName; | ||
138 | static int tarFd; | 164 | static int tarFd; |
139 | static dev_t tarDev; | 165 | static dev_t tarDev; |
140 | static ino_t tarInode; | 166 | static 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 | */ |
146 | static void readTarFile(int fileCount, char **fileTable); | 172 | static int readTarFile(const char* tarName, int extractFlag, int listFlag, |
173 | int tostdoutFlag, int verboseFlag); | ||
147 | static void readData(const char *cp, int count); | 174 | static void readData(const char *cp, int count); |
148 | static long getOctal(const char *cp, int len); | 175 | static long getOctal(const char *cp, int len); |
149 | 176 | static int parseTarHeader(struct TarHeader *rawHeader, struct TarInfo *header); | |
150 | static void readHeader(const TarHeader * hp, | ||
151 | |||
152 | int fileCount, char **fileTable); | ||
153 | |||
154 | static int wantFileName(const char *fileName, | 177 | static 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 | */ |
162 | static void saveFile(const char *fileName, int seeLinks); | 184 | static void saveFile(const char *fileName, int seeLinks); |
163 | |||
164 | static void saveRegularFile(const char *fileName, | 185 | static void saveRegularFile(const char *fileName, |
165 | |||
166 | const struct stat *statbuf); | 186 | const struct stat *statbuf); |
167 | |||
168 | static void saveDirectory(const char *fileName, | 187 | static void saveDirectory(const char *fileName, |
169 | |||
170 | const struct stat *statbuf); | 188 | const struct stat *statbuf); |
171 | |||
172 | static void writeHeader(const char *fileName, const struct stat *statbuf); | 189 | static void writeHeader(const char *fileName, const struct stat *statbuf); |
173 | 190 | static void writeTarFile(int argc, char **argv); | |
174 | static void writeTarFile(int fileCount, char **fileTable); | ||
175 | static void writeTarBlock(const char *buf, int len); | 191 | static void writeTarBlock(const char *buf, int len); |
176 | static int putOctal(char *cp, int len, long value); | 192 | static 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 | ||
181 | extern int tar_main(int argc, char **argv) | 197 | extern 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 | |||
286 | static void | ||
287 | tarExtractRegularFile(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 | */ |
292 | static void readTarFile(int fileCount, char **fileTable) | 297 | static 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 */ | ||
374 | endgame: | ||
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 | */ |
414 | static void | 388 | static long getOctal(const char *cp, int size) |
415 | readHeader(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. | 405 | static int |
446 | * Extract the encoded information and check it. | 406 | parseTarHeader(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 | */ |
728 | static int | 703 | static int |
729 | wantFileName(const char *fileName, int fileCount, char **fileTable) | 704 | wantFileName(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 | */ | ||
770 | static 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 | */ |
812 | static void writeTarFile(int fileCount, char **fileTable) | 750 | static 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 | ||