summaryrefslogtreecommitdiff
path: root/tar/bsdtar_windows.c
diff options
context:
space:
mode:
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>2009-02-20 17:25:23 -0500
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>2009-02-20 17:25:23 -0500
commitfb9c740de3c99357d21fa627f2c4144e0c444eb8 (patch)
treeb70393d5ba9639c89b0c02ba9dfa1296ae66a615 /tar/bsdtar_windows.c
parent0e5bc8159e481d9389bd075c536aa94d1b372e67 (diff)
downloadlibarchive-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.c141
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