diff options
author | Matt Kraai <kraai@debian.org> | 2001-01-03 17:22:10 +0000 |
---|---|---|
committer | Matt Kraai <kraai@debian.org> | 2001-01-03 17:22:10 +0000 |
commit | be7499c83c45a5953580f24189fb3473e5ec01e4 (patch) | |
tree | e8256ba6a8372be48d9c5f37d8641ec41f206cfb | |
parent | a9711a59695d0c0591e8786a2ea811940ef8735a (diff) | |
download | busybox-w32-be7499c83c45a5953580f24189fb3473e5ec01e4.tar.gz busybox-w32-be7499c83c45a5953580f24189fb3473e5ec01e4.tar.bz2 busybox-w32-be7499c83c45a5953580f24189fb3473e5ec01e4.zip |
Behave like GNU tar when matching excluded files.
-rw-r--r-- | archival/tar.c | 81 | ||||
-rw-r--r-- | tar.c | 81 |
2 files changed, 78 insertions, 84 deletions
diff --git a/archival/tar.c b/archival/tar.c index 4971e4775..9a3cff361 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <sys/types.h> | 51 | #include <sys/types.h> |
52 | #include <sys/sysmacros.h> | 52 | #include <sys/sysmacros.h> |
53 | #include <getopt.h> | 53 | #include <getopt.h> |
54 | #include <fnmatch.h> | ||
54 | 55 | ||
55 | #ifdef BB_FEATURE_TAR_GZIP | 56 | #ifdef BB_FEATURE_TAR_GZIP |
56 | extern int unzip(int in, int out); | 57 | extern int unzip(int in, int out); |
@@ -251,9 +252,6 @@ extern int tar_main(int argc, char **argv) | |||
251 | excludeList[excludeListSize] = *(++argv); | 252 | excludeList[excludeListSize] = *(++argv); |
252 | if (excludeList[excludeListSize] == NULL) | 253 | if (excludeList[excludeListSize] == NULL) |
253 | error_msg_and_die( "Option requires an argument: No file specified\n"); | 254 | error_msg_and_die( "Option requires an argument: No file specified\n"); |
254 | /* Remove leading "/"s */ | ||
255 | while (*excludeList[excludeListSize] =='/') | ||
256 | excludeList[excludeListSize]++; | ||
257 | /* Tack a NULL onto the end of the list */ | 255 | /* Tack a NULL onto the end of the list */ |
258 | excludeList[++excludeListSize] = NULL; | 256 | excludeList[++excludeListSize] = NULL; |
259 | stopIt=TRUE; | 257 | stopIt=TRUE; |
@@ -274,9 +272,6 @@ extern int tar_main(int argc, char **argv) | |||
274 | if (file[strlen(file)-1] == '\n') | 272 | if (file[strlen(file)-1] == '\n') |
275 | file[strlen(file)-1] = '\0'; | 273 | file[strlen(file)-1] = '\0'; |
276 | excludeList[excludeListSize] = xstrdup(file); | 274 | excludeList[excludeListSize] = xstrdup(file); |
277 | /* Remove leading "/"s */ | ||
278 | while (*excludeList[excludeListSize] == '/') | ||
279 | excludeList[excludeListSize]++; | ||
280 | /* Tack a NULL onto the end of the list */ | 275 | /* Tack a NULL onto the end of the list */ |
281 | excludeList[++excludeListSize] = NULL; | 276 | excludeList[++excludeListSize] = NULL; |
282 | } | 277 | } |
@@ -576,6 +571,32 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) | |||
576 | return( FALSE); | 571 | return( FALSE); |
577 | } | 572 | } |
578 | 573 | ||
574 | int exclude_file(char **excluded_files, const char *file) | ||
575 | { | ||
576 | int i; | ||
577 | |||
578 | if (excluded_files == NULL) | ||
579 | return 0; | ||
580 | |||
581 | for (i = 0; excluded_files[i] != NULL; i++) { | ||
582 | if (excluded_files[i][0] == '/') { | ||
583 | if (fnmatch(excluded_files[i], file, | ||
584 | FNM_PATHNAME | FNM_LEADING_DIR) == 0) | ||
585 | return 1; | ||
586 | } else { | ||
587 | const char *p; | ||
588 | |||
589 | for (p = file; p[0] != '\0'; p++) { | ||
590 | if ((p == file || p[-1] == '/') && p[0] != '/' && | ||
591 | fnmatch(excluded_files[i], p, | ||
592 | FNM_PATHNAME | FNM_LEADING_DIR) == 0) | ||
593 | return 1; | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | |||
598 | return 0; | ||
599 | } | ||
579 | 600 | ||
580 | /* | 601 | /* |
581 | * Read a tar file and extract or list the specified files within it. | 602 | * Read a tar file and extract or list the specified files within it. |
@@ -629,32 +650,19 @@ extern int readTarFile(int tarFd, int extractFlag, int listFlag, | |||
629 | } | 650 | } |
630 | 651 | ||
631 | #if defined BB_FEATURE_TAR_EXCLUDE | 652 | #if defined BB_FEATURE_TAR_EXCLUDE |
632 | { | 653 | if (exclude_file(excludeList, header.name)) { |
633 | int skipFlag=FALSE; | ||
634 | /* Check for excluded files.... */ | ||
635 | for (tmpList=excludeList; tmpList && *tmpList; tmpList++) { | ||
636 | /* Do some extra hoop jumping for when directory names | ||
637 | * end in '/' but the entry in tmpList doesn't */ | ||
638 | if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || ( | ||
639 | header.name[strlen(header.name)-1]=='/' | ||
640 | && strncmp( *tmpList, header.name, | ||
641 | MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) { | ||
642 | /* If it is a regular file, pretend to extract it with | ||
643 | * the extractFlag set to FALSE, so the junk in the tarball | ||
644 | * is properly skipped over */ | ||
645 | if ( header.type==REGTYPE || header.type==REGTYPE0 ) { | ||
646 | if (tarExtractRegularFile(&header, FALSE, FALSE) == FALSE) | ||
647 | errorFlag = TRUE; | ||
648 | } | ||
649 | skipFlag=TRUE; | ||
650 | break; | ||
651 | } | ||
652 | } | ||
653 | /* There are not the droids you're looking for, move along */ | 654 | /* There are not the droids you're looking for, move along */ |
654 | if (skipFlag==TRUE) | 655 | /* If it is a regular file, pretend to extract it with |
655 | continue; | 656 | * the extractFlag set to FALSE, so the junk in the tarball |
657 | * is properly skipped over */ | ||
658 | if ( header.type==REGTYPE || header.type==REGTYPE0 ) { | ||
659 | if (tarExtractRegularFile(&header, FALSE, FALSE) == FALSE) | ||
660 | errorFlag = TRUE; | ||
661 | } | ||
662 | continue; | ||
656 | } | 663 | } |
657 | #endif | 664 | #endif |
665 | |||
658 | if (extractList != NULL) { | 666 | if (extractList != NULL) { |
659 | int skipFlag = TRUE; | 667 | int skipFlag = TRUE; |
660 | for (tmpList = extractList; *tmpList != NULL; tmpList++) { | 668 | for (tmpList = extractList; *tmpList != NULL; tmpList++) { |
@@ -1036,9 +1044,6 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* | |||
1036 | { | 1044 | { |
1037 | struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; | 1045 | struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; |
1038 | const char *header_name; | 1046 | const char *header_name; |
1039 | #if defined BB_FEATURE_TAR_EXCLUDE | ||
1040 | char** tmpList; | ||
1041 | #endif | ||
1042 | 1047 | ||
1043 | /* | 1048 | /* |
1044 | ** Check to see if we are dealing with a hard link. | 1049 | ** Check to see if we are dealing with a hard link. |
@@ -1090,16 +1095,8 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* | |||
1090 | return TRUE; | 1095 | return TRUE; |
1091 | 1096 | ||
1092 | #if defined BB_FEATURE_TAR_EXCLUDE | 1097 | #if defined BB_FEATURE_TAR_EXCLUDE |
1093 | /* Check for excluded files.... */ | 1098 | if (exclude_file(tbInfo->excludeList, header_name)) { |
1094 | for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { | 1099 | return SKIP; |
1095 | /* Do some extra hoop jumping for when directory names | ||
1096 | * end in '/' but the entry in tmpList doesn't */ | ||
1097 | if (strncmp( *tmpList, header_name, strlen(*tmpList))==0 || ( | ||
1098 | fileName[strlen(fileName)-1]=='/' | ||
1099 | && strncmp( *tmpList, fileName, | ||
1100 | MIN(strlen(fileName)-1, strlen(*tmpList)))==0)) { | ||
1101 | return SKIP; | ||
1102 | } | ||
1103 | } | 1100 | } |
1104 | #endif | 1101 | #endif |
1105 | 1102 | ||
@@ -51,6 +51,7 @@ | |||
51 | #include <sys/types.h> | 51 | #include <sys/types.h> |
52 | #include <sys/sysmacros.h> | 52 | #include <sys/sysmacros.h> |
53 | #include <getopt.h> | 53 | #include <getopt.h> |
54 | #include <fnmatch.h> | ||
54 | 55 | ||
55 | #ifdef BB_FEATURE_TAR_GZIP | 56 | #ifdef BB_FEATURE_TAR_GZIP |
56 | extern int unzip(int in, int out); | 57 | extern int unzip(int in, int out); |
@@ -251,9 +252,6 @@ extern int tar_main(int argc, char **argv) | |||
251 | excludeList[excludeListSize] = *(++argv); | 252 | excludeList[excludeListSize] = *(++argv); |
252 | if (excludeList[excludeListSize] == NULL) | 253 | if (excludeList[excludeListSize] == NULL) |
253 | error_msg_and_die( "Option requires an argument: No file specified\n"); | 254 | error_msg_and_die( "Option requires an argument: No file specified\n"); |
254 | /* Remove leading "/"s */ | ||
255 | while (*excludeList[excludeListSize] =='/') | ||
256 | excludeList[excludeListSize]++; | ||
257 | /* Tack a NULL onto the end of the list */ | 255 | /* Tack a NULL onto the end of the list */ |
258 | excludeList[++excludeListSize] = NULL; | 256 | excludeList[++excludeListSize] = NULL; |
259 | stopIt=TRUE; | 257 | stopIt=TRUE; |
@@ -274,9 +272,6 @@ extern int tar_main(int argc, char **argv) | |||
274 | if (file[strlen(file)-1] == '\n') | 272 | if (file[strlen(file)-1] == '\n') |
275 | file[strlen(file)-1] = '\0'; | 273 | file[strlen(file)-1] = '\0'; |
276 | excludeList[excludeListSize] = xstrdup(file); | 274 | excludeList[excludeListSize] = xstrdup(file); |
277 | /* Remove leading "/"s */ | ||
278 | while (*excludeList[excludeListSize] == '/') | ||
279 | excludeList[excludeListSize]++; | ||
280 | /* Tack a NULL onto the end of the list */ | 275 | /* Tack a NULL onto the end of the list */ |
281 | excludeList[++excludeListSize] = NULL; | 276 | excludeList[++excludeListSize] = NULL; |
282 | } | 277 | } |
@@ -576,6 +571,32 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) | |||
576 | return( FALSE); | 571 | return( FALSE); |
577 | } | 572 | } |
578 | 573 | ||
574 | int exclude_file(char **excluded_files, const char *file) | ||
575 | { | ||
576 | int i; | ||
577 | |||
578 | if (excluded_files == NULL) | ||
579 | return 0; | ||
580 | |||
581 | for (i = 0; excluded_files[i] != NULL; i++) { | ||
582 | if (excluded_files[i][0] == '/') { | ||
583 | if (fnmatch(excluded_files[i], file, | ||
584 | FNM_PATHNAME | FNM_LEADING_DIR) == 0) | ||
585 | return 1; | ||
586 | } else { | ||
587 | const char *p; | ||
588 | |||
589 | for (p = file; p[0] != '\0'; p++) { | ||
590 | if ((p == file || p[-1] == '/') && p[0] != '/' && | ||
591 | fnmatch(excluded_files[i], p, | ||
592 | FNM_PATHNAME | FNM_LEADING_DIR) == 0) | ||
593 | return 1; | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | |||
598 | return 0; | ||
599 | } | ||
579 | 600 | ||
580 | /* | 601 | /* |
581 | * Read a tar file and extract or list the specified files within it. | 602 | * Read a tar file and extract or list the specified files within it. |
@@ -629,32 +650,19 @@ extern int readTarFile(int tarFd, int extractFlag, int listFlag, | |||
629 | } | 650 | } |
630 | 651 | ||
631 | #if defined BB_FEATURE_TAR_EXCLUDE | 652 | #if defined BB_FEATURE_TAR_EXCLUDE |
632 | { | 653 | if (exclude_file(excludeList, header.name)) { |
633 | int skipFlag=FALSE; | ||
634 | /* Check for excluded files.... */ | ||
635 | for (tmpList=excludeList; tmpList && *tmpList; tmpList++) { | ||
636 | /* Do some extra hoop jumping for when directory names | ||
637 | * end in '/' but the entry in tmpList doesn't */ | ||
638 | if (strncmp( *tmpList, header.name, strlen(*tmpList))==0 || ( | ||
639 | header.name[strlen(header.name)-1]=='/' | ||
640 | && strncmp( *tmpList, header.name, | ||
641 | MIN(strlen(header.name)-1, strlen(*tmpList)))==0)) { | ||
642 | /* If it is a regular file, pretend to extract it with | ||
643 | * the extractFlag set to FALSE, so the junk in the tarball | ||
644 | * is properly skipped over */ | ||
645 | if ( header.type==REGTYPE || header.type==REGTYPE0 ) { | ||
646 | if (tarExtractRegularFile(&header, FALSE, FALSE) == FALSE) | ||
647 | errorFlag = TRUE; | ||
648 | } | ||
649 | skipFlag=TRUE; | ||
650 | break; | ||
651 | } | ||
652 | } | ||
653 | /* There are not the droids you're looking for, move along */ | 654 | /* There are not the droids you're looking for, move along */ |
654 | if (skipFlag==TRUE) | 655 | /* If it is a regular file, pretend to extract it with |
655 | continue; | 656 | * the extractFlag set to FALSE, so the junk in the tarball |
657 | * is properly skipped over */ | ||
658 | if ( header.type==REGTYPE || header.type==REGTYPE0 ) { | ||
659 | if (tarExtractRegularFile(&header, FALSE, FALSE) == FALSE) | ||
660 | errorFlag = TRUE; | ||
661 | } | ||
662 | continue; | ||
656 | } | 663 | } |
657 | #endif | 664 | #endif |
665 | |||
658 | if (extractList != NULL) { | 666 | if (extractList != NULL) { |
659 | int skipFlag = TRUE; | 667 | int skipFlag = TRUE; |
660 | for (tmpList = extractList; *tmpList != NULL; tmpList++) { | 668 | for (tmpList = extractList; *tmpList != NULL; tmpList++) { |
@@ -1036,9 +1044,6 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* | |||
1036 | { | 1044 | { |
1037 | struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; | 1045 | struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; |
1038 | const char *header_name; | 1046 | const char *header_name; |
1039 | #if defined BB_FEATURE_TAR_EXCLUDE | ||
1040 | char** tmpList; | ||
1041 | #endif | ||
1042 | 1047 | ||
1043 | /* | 1048 | /* |
1044 | ** Check to see if we are dealing with a hard link. | 1049 | ** Check to see if we are dealing with a hard link. |
@@ -1090,16 +1095,8 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* | |||
1090 | return TRUE; | 1095 | return TRUE; |
1091 | 1096 | ||
1092 | #if defined BB_FEATURE_TAR_EXCLUDE | 1097 | #if defined BB_FEATURE_TAR_EXCLUDE |
1093 | /* Check for excluded files.... */ | 1098 | if (exclude_file(tbInfo->excludeList, header_name)) { |
1094 | for (tmpList=tbInfo->excludeList; tmpList && *tmpList; tmpList++) { | 1099 | return SKIP; |
1095 | /* Do some extra hoop jumping for when directory names | ||
1096 | * end in '/' but the entry in tmpList doesn't */ | ||
1097 | if (strncmp( *tmpList, header_name, strlen(*tmpList))==0 || ( | ||
1098 | fileName[strlen(fileName)-1]=='/' | ||
1099 | && strncmp( *tmpList, fileName, | ||
1100 | MIN(strlen(fileName)-1, strlen(*tmpList)))==0)) { | ||
1101 | return SKIP; | ||
1102 | } | ||
1103 | } | 1100 | } |
1104 | #endif | 1101 | #endif |
1105 | 1102 | ||