diff options
author | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2012-02-20 16:51:40 +0900 |
---|---|---|
committer | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2012-02-20 16:51:40 +0900 |
commit | 43b15427b4e6879bfe3c0b7a673aa4f00b0b972e (patch) | |
tree | 047a3f57c1cc48a07a6027988fa09739da3dc405 /cpio | |
parent | 6467e840cafb2e1f1b8f84dbc93cda4b0b6079d2 (diff) | |
download | libarchive-43b15427b4e6879bfe3c0b7a673aa4f00b0b972e.tar.gz |
Properly remove leading slash letters and Windows drive letters in cpio.
Diffstat (limited to 'cpio')
-rw-r--r-- | cpio/cpio.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/cpio/cpio.c b/cpio/cpio.c index 57f4e260..627e9c01 100644 --- a/cpio/cpio.c +++ b/cpio/cpio.c @@ -118,6 +118,7 @@ static void mode_in(struct cpio *); static void mode_list(struct cpio *); static void mode_out(struct cpio *); static void mode_pass(struct cpio *, const char *); +static const char *remove_leading_slash(const char *); static int restore_time(struct cpio *, struct archive_entry *, const char *, int fd); static void usage(void); @@ -587,6 +588,49 @@ mode_out(struct cpio *cpio) archive_write_free(cpio->archive); } +static const char * +remove_leading_slash(const char *p) +{ + const char *rp; + + /* Remove leading "//./" or "//?/" or "//?/UNC/" + * (absolute path prefixes used by Windows API) */ + if ((p[0] == '/' || p[0] == '\\') && + (p[1] == '/' || p[1] == '\\') && + (p[2] == '.' || p[2] == '?') && + (p[3] == '/' || p[3] == '\\')) + { + if (p[2] == '?' && + (p[4] == 'U' || p[4] == 'u') && + (p[5] == 'N' || p[5] == 'n') && + (p[6] == 'C' || p[6] == 'c') && + (p[7] == '/' || p[7] == '\\')) + p += 8; + else + p += 4; + } + do { + rp = p; + /* Remove leading drive letter from archives created + * on Windows. */ + if (((p[0] >= 'a' && p[0] <= 'z') || + (p[0] >= 'A' && p[0] <= 'Z')) && + p[1] == ':') { + p += 2; + } + /* Remove leading "/../", "//", etc. */ + while (p[0] == '/' || p[0] == '\\') { + if (p[1] == '.' && p[2] == '.' && + (p[3] == '/' || p[3] == '\\')) { + p += 3; /* Remove "/..", leave "/" + * for next pass. */ + } else + p += 1; /* Remove "/". */ + } + } while (rp != p); + return (p); +} + /* * This is used by both out mode (to copy objects from disk into * an archive) and pass mode (to copy objects from disk to @@ -598,7 +642,6 @@ file_to_archive(struct cpio *cpio, const char *srcpath) const char *destpath; struct archive_entry *entry, *spare; size_t len; - const char *p; int r; /* @@ -652,10 +695,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath) "Can't allocate path buffer"); } strcpy(cpio->pass_destpath, cpio->destdir); - p = srcpath; - while (p[0] == '/') - ++p; - strcat(cpio->pass_destpath, p); + strcat(cpio->pass_destpath, remove_leading_slash(srcpath)); destpath = cpio->pass_destpath; } if (cpio->option_rename) |