summaryrefslogtreecommitdiff
path: root/cpio/cpio.c
diff options
context:
space:
mode:
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>2012-02-20 16:51:40 +0900
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>2012-02-20 16:51:40 +0900
commit43b15427b4e6879bfe3c0b7a673aa4f00b0b972e (patch)
tree047a3f57c1cc48a07a6027988fa09739da3dc405 /cpio/cpio.c
parent6467e840cafb2e1f1b8f84dbc93cda4b0b6079d2 (diff)
downloadlibarchive-43b15427b4e6879bfe3c0b7a673aa4f00b0b972e.tar.gz
Properly remove leading slash letters and Windows drive letters in cpio.
Diffstat (limited to 'cpio/cpio.c')
-rw-r--r--cpio/cpio.c50
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)