diff options
author | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2009-02-20 17:25:23 -0500 |
---|---|---|
committer | Michihiro NAKAJIMA <ggcueroad@gmail.com> | 2009-02-20 17:25:23 -0500 |
commit | fb9c740de3c99357d21fa627f2c4144e0c444eb8 (patch) | |
tree | b70393d5ba9639c89b0c02ba9dfa1296ae66a615 /tar/bsdtar_windows.c | |
parent | 0e5bc8159e481d9389bd075c536aa94d1b372e67 (diff) | |
download | libarchive-fb9c740de3c99357d21fa627f2c4144e0c444eb8.tar.gz |
Windows shell whose name is command.exe/cmd.exe does not
deal with wildcard characters '*' and '?'.
Windows application should handle those characters by
FindFirstFile() Win32 API for usability.
SVN-Revision: 678
Diffstat (limited to 'tar/bsdtar_windows.c')
-rw-r--r-- | tar/bsdtar_windows.c | 141 |
1 files changed, 130 insertions, 11 deletions
diff --git a/tar/bsdtar_windows.c b/tar/bsdtar_windows.c index a3cc1f2c..29ee9391 100644 --- a/tar/bsdtar_windows.c +++ b/tar/bsdtar_windows.c @@ -434,7 +434,7 @@ ftruncate(int fd, off_t length) } DIR * -opendir(const char *path) +__opendir(const char *path, int ff) { DIR *dir; wchar_t *wpath, *wfname; @@ -452,33 +452,49 @@ opendir(const char *path) free(dir); return (NULL); } - wlen = wcslen(wpath); - wfname = malloc((wlen + 3) * sizeof(wchar_t)); - if (wfname == NULL) { - errno = ENOMEM; - free(dir); + if (ff) { + wfname = wpath; + wpath = NULL; + } else { + wlen = wcslen(wpath); + wfname = malloc((wlen + 3) * sizeof(wchar_t)); + if (wfname == NULL) { + errno = ENOMEM; + free(dir); + free(wpath); + return (NULL); + } + wcscpy(wfname, wpath); + wcscat(wfname, L"\\*"); free(wpath); - return (NULL); } - wcscpy(wfname, wpath); - wcscat(wfname, L"\\*"); dir->handle = FindFirstFileW(wfname, &dir->fileData); if (dir->handle == INVALID_HANDLE_VALUE) { _dosmaperr(GetLastError()); free(dir); - free(wpath); free(wfname); return (NULL); } dir->first = 1; dir->finished = FALSE; - free(wpath); free(wfname); return (dir); } +static DIR * +opendir_findfile(const char *path) +{ + return (__opendir(path, 1)); +} + +DIR * +opendir(const char *path) +{ + return (__opendir(path, 0)); +} + struct dirent * readdir(DIR *dirp) { @@ -622,6 +638,20 @@ la_mkdir(const char *path, mode_t mode) return (0); } +/* Windows' mbstowcs is differrent error handling from other unix mbstowcs. + * That one is using MultiByteToWideChar function with MB_PRECOMPOSED and + * MB_ERR_INVALID_CHARS flags. + * This implements for only to pass libarchive_test. + */ +size_t +la_mbstowcs(wchar_t *wcstr, const char *mbstr, size_t nwchars) +{ + + return (MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, + mbstr, (int)strlen(mbstr), wcstr, + (int)nwchars)); +} + int la_open(const char *path, int flags, ...) { @@ -1047,6 +1077,95 @@ bsdtar_is_privileged(struct bsdtar *bsdtar) return (ret); } +/* + * Note: We should use wide-character for findng '\' character, + * a directory separator on Windows, because some character-set have + * been using the '\' character for a part of its multibyte character + * code. + */ +static size_t +dir_len_w(const char *path) +{ + const wchar_t *r; + wchar_t *wp; + const char *p; + size_t al, l; + + al = l = -1; + for (p = path; *p != '\0'; ++p) { + if (*p == '\\') + al = l = p - path; + else if (*p == '/') + al = p - path; + } + if (l == -1) + goto alen; + l = p - path; + if ((wp = malloc((l + 1) * sizeof(wchar_t))) == NULL) + goto alen; + if ((l = mbstowcs(wp, path, l)) == -1) { + free(wp); + goto alen; + } + wp[l] = L'\0'; + r = wp + l; + while (--r >= wp && *r != L'/' && *r != L'\\') + ; + l = wcstombs(NULL, ++r, 0); + free(wp); + if (l != -1) + return (p - path - l); +alen: + if (al == -1) + return (0); + return (al + 1); +} + +/* + * Find file names and call write_hierarchy function. + */ +void +write_hierarchy_win(struct bsdtar *bsdtar, struct archive *a, + const char *path, void (*write_hierarchy)(struct bsdtar *bsdtar, + struct archive *a, const char *path)) +{ + DIR *dir; + struct dirent *ent; + const char *r; + char *xpath; + size_t dl; + + r = path; + while (*r != '\0' && *r != '*' && *r != '?') + ++r; + if (*r == '\0') + /* There aren't meta-characters '*' and '?' in path */ + goto try_plain; + dir = opendir_findfile(path); + if (dir == NULL) + goto try_plain; + dl = dir_len_w(path); + xpath = malloc(dl + MAX_PATH); + if (xpath == NULL) + goto try_plain; + strncpy(xpath, path, dl); + while ((ent = readdir(dir)) != NULL) { + if (ent->d_name[0] == '.' && ent->d_name[1] == '\0') + continue; + if (ent->d_name[0] == '.' && ent->d_name[1] == '.' && + ent->d_name[2] == '\0') + continue; + strcpy(&xpath[dl], ent->d_name); + write_hierarchy(bsdtar, a, xpath); + } + free(xpath); + closedir(dir); + return; + +try_plain: + write_hierarchy(bsdtar, a, path); +} + #endif /* LIST_H */ #endif |