diff options
author | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2009-02-25 02:06:17 -0500 |
---|---|---|
committer | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2009-02-25 02:06:17 -0500 |
commit | 80b77b326a75ae684f2bbfa37982ec1c476ba142 (patch) | |
tree | bc5e4035d9fe2b07a9b5f7d1e2be83da098962e7 /tar/util.c | |
parent | 45dc32d5c0fbd235bf24fb86f8d97cebdab56053 (diff) | |
download | libarchive-80b77b326a75ae684f2bbfa37982ec1c476ba142.tar.gz |
Improve stripping Windows drive letters.
SVN-Revision: 709
Diffstat (limited to 'tar/util.c')
-rw-r--r-- | tar/util.c | 89 |
1 files changed, 58 insertions, 31 deletions
@@ -513,45 +513,72 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry) } } - /* Strip redundant leading '/' characters. */ - while (name[0] == '/' && name[1] == '/') - name++; - /* By default, don't write or restore absolute pathnames. */ if (!bsdtar->option_absolute_paths) { - /* Strip Windows drive letters. */ - if (((name[0] >= 'A' && name[0] <= 'Z') - || (name[0] >= 'a' && name[0] <= 'z')) - && name[1] == ':' - && (name[2] == '/' || name[2] == '\\')) + const char *rp, *p = name; + int slashonly = 1; + + /* 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] == '\\')) { - /* Generate a warning the first time this happens. */ - if (!bsdtar->warned_lead_slash) { - bsdtar_warnc(bsdtar, 0, - "Removing leading drive letter from member names"); - bsdtar->warned_lead_slash = 1; - } - name += 3; - while (*name == '/' || *name == '\\') - ++name; - /* Special case: Stripping everything yields ".". */ - if (*name == '\0') - name = "."; + 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; + slashonly = 0; } + 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; + slashonly = 0; + } + /* Remove leading "/../", "//", etc. */ + while (p[0] == '/' || p[0] == '\\') { + if (p[1] == '.' && p[2] == '.' && + (p[3] == '/' || p[3] == '\\')) { + p += 3; /* Remove "/..", leave "/" + * for next pass. */ + slashonly = 0; + } else + p += 1; /* Remove "/". */ + } + } while (rp != p); - /* Strip leading '/'. */ - if (name[0] == '/') { + if (p != name && !bsdtar->warned_lead_slash) { /* Generate a warning the first time this happens. */ - if (!bsdtar->warned_lead_slash) { + if (slashonly) bsdtar_warnc(bsdtar, 0, - "Removing leading '/' from member names"); - bsdtar->warned_lead_slash = 1; - } - name++; - /* Special case: Stripping everything yields ".". */ - if (*name == '\0') - name = "."; + "Removing leading '%c' from member names", + name[0]); + else + bsdtar_warnc(bsdtar, 0, + "Removing leading drive letter from " + "member names"); + bsdtar->warned_lead_slash = 1; } + + /* Special case: Stripping everything yields ".". */ + if (*p == '\0') + name = "."; + else + name = p; + } else { + /* Strip redundant leading '/' characters. */ + while (name[0] == '/' && name[1] == '/') + name++; } /* Safely replace name in archive_entry. */ |