From: Michihiro NAKAJIMA Date: Mon, 20 Feb 2012 07:51:40 +0000 (+0900) Subject: Properly remove leading slash letters and Windows drive letters in cpio. X-Git-Tag: v3.0.4~2^2~68 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43b15427b4e6879bfe3c0b7a673aa4f00b0b972e;p=thirdparty%2Flibarchive.git Properly remove leading slash letters and Windows drive letters in cpio. --- diff --git a/cpio/cpio.c b/cpio/cpio.c index 57f4e260d..627e9c019 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)