aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-09-09 12:49:03 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-09-09 12:49:03 +0000
commit76dd55083428109eb3bb5f81a64ba6ab215860fc (patch)
treee3a3377f46d5ee1e57db3cb775ad78ae746dbb91
parent6e9e480b223e6762ac6205a5d4b28514593d88dd (diff)
downloadbusybox-w32-76dd55083428109eb3bb5f81a64ba6ab215860fc.tar.gz
busybox-w32-76dd55083428109eb3bb5f81a64ba6ab215860fc.tar.bz2
busybox-w32-76dd55083428109eb3bb5f81a64ba6ab215860fc.zip
tar: fix "xopen with O_CREAT" warning, improve zero padding write
(was doing zillions of 1-byte write syscalls) git-svn-id: svn://busybox.net/trunk/busybox@16083 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--archival/tar.c118
-rw-r--r--libbb/recursive_action.c12
2 files changed, 71 insertions, 59 deletions
diff --git a/archival/tar.c b/archival/tar.c
index 0b5720f3b..91232bcf3 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -84,7 +84,6 @@ struct HardLinkInfo {
84 84
85/* Some info to be carried along when creating a new tarball */ 85/* Some info to be carried along when creating a new tarball */
86struct TarBallInfo { 86struct TarBallInfo {
87 char *fileName; /* File name of the tarball */
88 int tarFd; /* Open-for-write file descriptor 87 int tarFd; /* Open-for-write file descriptor
89 for the tarball */ 88 for the tarball */
90 struct stat statBuf; /* Stat info for the tarball, letting 89 struct stat statBuf; /* Stat info for the tarball, letting
@@ -117,18 +116,18 @@ typedef enum TarFileType TarFileType;
117/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ 116/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
118static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, 117static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr,
119 struct stat *statbuf, 118 struct stat *statbuf,
120 const char *name) 119 const char *fileName)
121{ 120{
122 /* Note: hlInfoHeadPtr can never be NULL! */ 121 /* Note: hlInfoHeadPtr can never be NULL! */
123 HardLinkInfo *hlInfo; 122 HardLinkInfo *hlInfo;
124 123
125 hlInfo = (HardLinkInfo *) xmalloc(sizeof(HardLinkInfo) + strlen(name)); 124 hlInfo = xmalloc(sizeof(HardLinkInfo) + strlen(fileName));
126 hlInfo->next = *hlInfoHeadPtr; 125 hlInfo->next = *hlInfoHeadPtr;
127 *hlInfoHeadPtr = hlInfo; 126 *hlInfoHeadPtr = hlInfo;
128 hlInfo->dev = statbuf->st_dev; 127 hlInfo->dev = statbuf->st_dev;
129 hlInfo->ino = statbuf->st_ino; 128 hlInfo->ino = statbuf->st_ino;
130 hlInfo->linkCount = statbuf->st_nlink; 129 hlInfo->linkCount = statbuf->st_nlink;
131 strcpy(hlInfo->name, name); 130 strcpy(hlInfo->name, fileName);
132} 131}
133 132
134static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) 133static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr)
@@ -156,7 +155,7 @@ static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbu
156 break; 155 break;
157 hlInfo = hlInfo->next; 156 hlInfo = hlInfo->next;
158 } 157 }
159 return (hlInfo); 158 return hlInfo;
160} 159}
161 160
162/* Put an octal string into the specified buffer. 161/* Put an octal string into the specified buffer.
@@ -193,9 +192,29 @@ static int putOctal(char *cp, int len, long value)
193 return TRUE; 192 return TRUE;
194} 193}
195 194
195/* Pad file to TAR_BLOCK_SIZE with zeros */
196static void block_write_zeroes(int fd, size_t size)
197{
198 char zerobuf[TAR_BLOCK_SIZE];
199 memset(zerobuf, 0, size);
200 /* No point in trying to continue on error */
201 if (full_write(fd, zerobuf, size) < 0)
202 bb_perror_msg_and_die("write");
203}
204
205static size_t pad_block_write(int fd, size_t size)
206{
207 size_t rem = (TAR_BLOCK_SIZE - size) & (TAR_BLOCK_SIZE-1);
208 if (rem) {
209 block_write_zeroes(fd, rem);
210 size += rem;
211 }
212 return size;
213}
214
196/* Write out a tar header for the specified file/directory/whatever */ 215/* Write out a tar header for the specified file/directory/whatever */
197static int writeTarHeader(struct TarBallInfo *tbInfo, 216static int writeTarHeader(struct TarBallInfo *tbInfo,
198 const char *header_name, const char *real_name, struct stat *statbuf) 217 const char *header_name, const char *fileName, struct stat *statbuf)
199{ 218{
200 long chksum = 0; 219 long chksum = 0;
201 struct TarHeader header; 220 struct TarHeader header;
@@ -225,10 +244,10 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
225 strncpy(header.linkname, tbInfo->hlInfo->name, 244 strncpy(header.linkname, tbInfo->hlInfo->name,
226 sizeof(header.linkname)); 245 sizeof(header.linkname));
227 } else if (S_ISLNK(statbuf->st_mode)) { 246 } else if (S_ISLNK(statbuf->st_mode)) {
228 char *lpath = xreadlink(real_name); 247 char *lpath = xreadlink(fileName);
229 248
230 if (!lpath) /* Already printed err msg inside xreadlink() */ 249 if (!lpath) /* Already printed err msg inside xreadlink() */
231 return (FALSE); 250 return FALSE;
232 header.typeflag = SYMTYPE; 251 header.typeflag = SYMTYPE;
233 strncpy(header.linkname, lpath, sizeof(header.linkname)); 252 strncpy(header.linkname, lpath, sizeof(header.linkname));
234 free(lpath); 253 free(lpath);
@@ -253,8 +272,8 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
253 header.typeflag = REGTYPE; 272 header.typeflag = REGTYPE;
254 putOctal(header.size, sizeof(header.size), statbuf->st_size); 273 putOctal(header.size, sizeof(header.size), statbuf->st_size);
255 } else { 274 } else {
256 bb_error_msg("%s: Unknown file type", real_name); 275 bb_error_msg("%s: unknown file type", fileName);
257 return (FALSE); 276 return FALSE;
258 } 277 }
259 278
260 /* Calculate and store the checksum (i.e., the sum of all of the bytes of 279 /* Calculate and store the checksum (i.e., the sum of all of the bytes of
@@ -269,16 +288,15 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
269 putOctal(header.chksum, 7, chksum); 288 putOctal(header.chksum, 7, chksum);
270 289
271 /* Now write the header out to disk */ 290 /* Now write the header out to disk */
272 if ((size = full_write(tbInfo->tarFd, (char *) &header, 291 size = full_write(tbInfo->tarFd, (char *) &header,
273 sizeof(struct TarHeader))) < 0) 292 sizeof(struct TarHeader));
274 { 293 if (size < 0) {
275 bb_error_msg(bb_msg_io_error, real_name); 294 bb_error_msg(bb_msg_io_error, fileName);
276 return (FALSE); 295 return FALSE;
277 } 296 }
278 /* Pad the header up to the tar block size */ 297 /* Pad the header up to the tar block size */
279 for (; size < TAR_BLOCK_SIZE; size++) { 298 size = pad_block_write(tbInfo->tarFd, size);
280 write(tbInfo->tarFd, "\0", 1); 299
281 }
282 /* Now do the verbose thing (or not) */ 300 /* Now do the verbose thing (or not) */
283 301
284 if (tbInfo->verboseFlag) { 302 if (tbInfo->verboseFlag) {
@@ -290,7 +308,7 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
290 fprintf(vbFd, "%s\n", header.name); 308 fprintf(vbFd, "%s\n", header.name);
291 } 309 }
292 310
293 return (TRUE); 311 return TRUE;
294} 312}
295 313
296# ifdef CONFIG_FEATURE_TAR_FROM 314# ifdef CONFIG_FEATURE_TAR_FROM
@@ -328,11 +346,11 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
328 int inputFileFd = -1; 346 int inputFileFd = -1;
329 347
330 /* 348 /*
331 ** Check to see if we are dealing with a hard link. 349 * Check to see if we are dealing with a hard link.
332 ** If so - 350 * If so -
333 ** Treat the first occurance of a given dev/inode as a file while 351 * Treat the first occurance of a given dev/inode as a file while
334 ** treating any additional occurances as hard links. This is done 352 * treating any additional occurances as hard links. This is done
335 ** by adding the file information to the HardLinkInfo linked list. 353 * by adding the file information to the HardLinkInfo linked list.
336 */ 354 */
337 tbInfo->hlInfo = NULL; 355 tbInfo->hlInfo = NULL;
338 if (statbuf->st_nlink > 1) { 356 if (statbuf->st_nlink > 1) {
@@ -344,7 +362,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
344 /* It is against the rules to archive a socket */ 362 /* It is against the rules to archive a socket */
345 if (S_ISSOCK(statbuf->st_mode)) { 363 if (S_ISSOCK(statbuf->st_mode)) {
346 bb_error_msg("%s: socket ignored", fileName); 364 bb_error_msg("%s: socket ignored", fileName);
347 return (TRUE); 365 return TRUE;
348 } 366 }
349 367
350 /* It is a bad idea to store the archive we are in the process of creating, 368 /* It is a bad idea to store the archive we are in the process of creating,
@@ -353,7 +371,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
353 if (tbInfo->statBuf.st_dev == statbuf->st_dev && 371 if (tbInfo->statBuf.st_dev == statbuf->st_dev &&
354 tbInfo->statBuf.st_ino == statbuf->st_ino) { 372 tbInfo->statBuf.st_ino == statbuf->st_ino) {
355 bb_error_msg("%s: file is the archive; skipping", fileName); 373 bb_error_msg("%s: file is the archive; skipping", fileName);
356 return (TRUE); 374 return TRUE;
357 } 375 }
358 376
359 header_name = fileName; 377 header_name = fileName;
@@ -361,7 +379,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
361 static int alreadyWarned = FALSE; 379 static int alreadyWarned = FALSE;
362 380
363 if (alreadyWarned == FALSE) { 381 if (alreadyWarned == FALSE) {
364 bb_error_msg("Removing leading '/' from member names"); 382 bb_error_msg("removing leading '/' from member names");
365 alreadyWarned = TRUE; 383 alreadyWarned = TRUE;
366 } 384 }
367 header_name++; 385 header_name++;
@@ -369,7 +387,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
369 387
370 if (strlen(fileName) >= NAME_SIZE) { 388 if (strlen(fileName) >= NAME_SIZE) {
371 bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE); 389 bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE);
372 return (TRUE); 390 return TRUE;
373 } 391 }
374 392
375 if (header_name[0] == '\0') 393 if (header_name[0] == '\0')
@@ -382,21 +400,20 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
382 400
383 /* Is this a regular file? */ 401 /* Is this a regular file? */
384 if ((tbInfo->hlInfo == NULL) && (S_ISREG(statbuf->st_mode))) { 402 if ((tbInfo->hlInfo == NULL) && (S_ISREG(statbuf->st_mode))) {
385
386 /* open the file we want to archive, and make sure all is well */ 403 /* open the file we want to archive, and make sure all is well */
387 if ((inputFileFd = open(fileName, O_RDONLY)) < 0) { 404 if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
388 bb_perror_msg("%s: Cannot open", fileName); 405 bb_perror_msg("%s: cannot open", fileName);
389 return (FALSE); 406 return FALSE;
390 } 407 }
391 } 408 }
392 409
393 /* Add an entry to the tarball */ 410 /* Add an entry to the tarball */
394 if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) { 411 if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) {
395 return (FALSE); 412 return FALSE;
396 } 413 }
397 414
398 /* If it was a regular file, write out the body */ 415 /* If it was a regular file, write out the body */
399 if (inputFileFd >= 0 ) { 416 if (inputFileFd >= 0) {
400 ssize_t readSize = 0; 417 ssize_t readSize = 0;
401 418
402 /* write the file to the archive */ 419 /* write the file to the archive */
@@ -404,11 +421,10 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
404 close(inputFileFd); 421 close(inputFileFd);
405 422
406 /* Pad the file up to the tar block size */ 423 /* Pad the file up to the tar block size */
407 for (; (readSize % TAR_BLOCK_SIZE) != 0; readSize++) 424 readSize = pad_block_write(tbInfo->tarFd, readSize);
408 write(tbInfo->tarFd, "\0", 1);
409 } 425 }
410 426
411 return (TRUE); 427 return TRUE;
412} 428}
413 429
414static int writeTarFile(const int tar_fd, const int verboseFlag, 430static int writeTarFile(const int tar_fd, const int verboseFlag,
@@ -416,9 +432,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
416 const llist_t *exclude, const int gzip) 432 const llist_t *exclude, const int gzip)
417{ 433{
418 pid_t gzipPid = 0; 434 pid_t gzipPid = 0;
419
420 int errorFlag = FALSE; 435 int errorFlag = FALSE;
421 ssize_t size;
422 struct TarBallInfo tbInfo; 436 struct TarBallInfo tbInfo;
423 437
424 tbInfo.hlInfoHead = NULL; 438 tbInfo.hlInfoHead = NULL;
@@ -430,7 +444,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
430 /* Store the stat info for the tarball's file, so 444 /* Store the stat info for the tarball's file, so
431 * can avoid including the tarball into itself.... */ 445 * can avoid including the tarball into itself.... */
432 if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) 446 if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)
433 bb_perror_msg_and_die("Couldnt stat tar file"); 447 bb_perror_msg_and_die("cannot stat tar file");
434 448
435 if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) { 449 if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) {
436 int gzipDataPipe[2] = { -1, -1 }; 450 int gzipDataPipe[2] = { -1, -1 };
@@ -440,7 +454,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
440 454
441 455
442 if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) 456 if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0)
443 bb_perror_msg_and_die("create pipe"); 457 bb_perror_msg_and_die("pipe");
444 458
445 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ 459 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
446 460
@@ -502,8 +516,8 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
502 include = include->link; 516 include = include->link;
503 } 517 }
504 /* Write two empty blocks to the end of the archive */ 518 /* Write two empty blocks to the end of the archive */
505 for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++) 519 block_write_zeroes(tbInfo.tarFd, TAR_BLOCK_SIZE);
506 write(tbInfo.tarFd, "\0", 1); 520 block_write_zeroes(tbInfo.tarFd, TAR_BLOCK_SIZE);
507 521
508 /* To be pedantically correct, we would check if the tarball 522 /* To be pedantically correct, we would check if the tarball
509 * is smaller than 20 tar blocks, and pad it if it was smaller, 523 * is smaller than 20 tar blocks, and pad it if it was smaller,
@@ -546,10 +560,10 @@ static llist_t *append_file_list_to_list(llist_t *list)
546 cur = cur->link; 560 cur = cur->link;
547 free(tmp); 561 free(tmp);
548 while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) { 562 while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) {
549 char *filename_ptr = last_char_is(line, '/'); 563 char *filename_ptr = last_char_is(line, '/');
550 if (filename_ptr > line) 564 if (filename_ptr > line)
551 *filename_ptr = '\0'; 565 *filename_ptr = '\0';
552 llist_add_to(&newlist, line); 566 llist_add_to(&newlist, line);
553 } 567 }
554 fclose(src_stream); 568 fclose(src_stream);
555 } 569 }
@@ -569,12 +583,13 @@ static char get_header_tar_Z(archive_handle_t *archive_handle)
569 if (xread_char(archive_handle->src_fd) != 0x1f || 583 if (xread_char(archive_handle->src_fd) != 0x1f ||
570 xread_char(archive_handle->src_fd) != 0x9d) 584 xread_char(archive_handle->src_fd) != 0x9d)
571 { 585 {
572 bb_error_msg_and_die("Invalid magic"); 586 bb_error_msg_and_die("invalid magic");
573 } 587 }
574 588
575 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress); 589 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress);
576 archive_handle->offset = 0; 590 archive_handle->offset = 0;
577 while (get_header_tar(archive_handle) == EXIT_SUCCESS); 591 while (get_header_tar(archive_handle) == EXIT_SUCCESS)
592 /* nothing */;
578 593
579 /* Can only do one file at a time */ 594 /* Can only do one file at a time */
580 return(EXIT_FAILURE); 595 return(EXIT_FAILURE);
@@ -828,7 +843,7 @@ int tar_main(int argc, char **argv)
828 tar_handle->src_fd = fileno(tar_stream); 843 tar_handle->src_fd = fileno(tar_stream);
829 tar_handle->seek = seek_by_char; 844 tar_handle->seek = seek_by_char;
830 } else { 845 } else {
831 tar_handle->src_fd = xopen(tar_filename, flags); 846 tar_handle->src_fd = xopen3(tar_filename, flags, 0666);
832 } 847 }
833 } 848 }
834 849
@@ -854,14 +869,15 @@ int tar_main(int argc, char **argv)
854 tar_handle->accept, 869 tar_handle->accept,
855 tar_handle->reject, zipMode); 870 tar_handle->reject, zipMode);
856 } else { 871 } else {
857 while (get_header_ptr(tar_handle) == EXIT_SUCCESS); 872 while (get_header_ptr(tar_handle) == EXIT_SUCCESS)
873 /* nothing */;
858 874
859 /* Check that every file that should have been extracted was */ 875 /* Check that every file that should have been extracted was */
860 while (tar_handle->accept) { 876 while (tar_handle->accept) {
861 if (!find_list_entry(tar_handle->reject, tar_handle->accept->data) 877 if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)
862 && !find_list_entry(tar_handle->passed, tar_handle->accept->data)) 878 && !find_list_entry(tar_handle->passed, tar_handle->accept->data))
863 { 879 {
864 bb_error_msg_and_die("%s: Not found in archive", tar_handle->accept->data); 880 bb_error_msg_and_die("%s: not found in archive", tar_handle->accept->data);
865 } 881 }
866 tar_handle->accept = tar_handle->accept->link; 882 tar_handle->accept = tar_handle->accept->link;
867 } 883 }
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c
index d491b781b..28a493403 100644
--- a/libbb/recursive_action.c
+++ b/libbb/recursive_action.c
@@ -23,14 +23,10 @@
23 * is so stinking huge. 23 * is so stinking huge.
24 */ 24 */
25int recursive_action(const char *fileName, 25int recursive_action(const char *fileName,
26 int recurse, int followLinks, int depthFirst, 26 int recurse, int followLinks, int depthFirst,
27 int (*fileAction) (const char *fileName, 27 int (*fileAction) (const char *fileName, struct stat * statbuf, void* userData),
28 struct stat * statbuf, 28 int (*dirAction) (const char *fileName, struct stat * statbuf, void* userData),
29 void* userData), 29 void* userData)
30 int (*dirAction) (const char *fileName,
31 struct stat * statbuf,
32 void* userData),
33 void* userData)
34{ 30{
35 int status; 31 int status;
36 struct stat statbuf; 32 struct stat statbuf;