}
}
-/*
- * Prepend "\\?\" to the path name and convert it to unicode to permit
- * an extended-length path for a maximum total path length of 32767
- * characters.
- * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx
- */
-static wchar_t *
-permissive_name(const wchar_t *name)
-{
- wchar_t *wn, *wnp;
- wchar_t *ws, *wsp;
- DWORD l, len, slen;
- int unc;
-
- /* Get a full path names */
- l = GetFullPathNameW(name, 0, NULL, NULL);
- if (l == 0)
- return (NULL);
- wnp = malloc(l * sizeof(wchar_t));
- if (wnp == NULL)
- return (NULL);
- len = GetFullPathNameW(name, l, wnp, NULL);
- wn = wnp;
-
- if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
- wnp[2] == L'?' && wnp[3] == L'\\')
- /* We have already permissive names. */
- return (wn);
-
- if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
- wnp[2] == L'.' && wnp[3] == L'\\') {
- /* Device names */
- if (((wnp[4] >= L'a' && wnp[4] <= L'z') ||
- (wnp[4] >= L'A' && wnp[4] <= L'Z')) &&
- wnp[5] == L':' && wnp[6] == L'\\')
- wnp[2] = L'?';/* Not device names. */
- return (wn);
- }
-
- unc = 0;
- if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
- wchar_t *p = &wnp[2];
-
- /* Skip server-name letters. */
- while (*p != L'\\' && *p != L'\0')
- ++p;
- if (*p == L'\\') {
- wchar_t *rp = ++p;
- /* Skip share-name letters. */
- while (*p != L'\\' && *p != L'\0')
- ++p;
- if (*p == L'\\' && p != rp) {
- /* Now, match patterns such as
- * "\\server-name\share-name\" */
- wnp += 2;
- len -= 2;
- unc = 1;
- }
- }
- }
-
- slen = 4 + (unc * 4) + len + 1;
- ws = wsp = malloc(slen * sizeof(wchar_t));
- if (ws == NULL) {
- free(wn);
- return (NULL);
- }
- /* prepend "\\?\" */
- wcsncpy(wsp, L"\\\\?\\", 4);
- wsp += 4;
- slen -= 4;
- if (unc) {
- /* append "UNC\" ---> "\\?\UNC\" */
- wcsncpy(wsp, L"UNC\\", 4);
- wsp += 4;
- slen -= 4;
- }
- wcsncpy(wsp, wnp, slen);
- wsp[slen - 1] = L'\0'; /* Ensure null termination. */
- free(wn);
- return (ws);
-}
-
/*
* Append a name to the current dir path.
*/
}
base = pathname;
- p = permissive_name(base);
+ p = __la_win_permissive_name(path);
if (p == NULL) {
free(pathname);
goto failed;
static const wchar_t *
tree_current_access_path(struct tree *t)
{
-#if defined(_DEBUG)
- wchar_t *wp;
-
- wp = permissive_name(t->path.s);
- if (wcscmp(wp, t->full_path.s) != 0)
- DebugBreak();
- free(wp);
-#endif
return (t->full_path.s);
}
* characters.
* see also http://msdn.microsoft.com/en-us/library/aa365247.aspx
*/
-static wchar_t *
-permissive_name(const char *name)
+wchar_t *
+__la_win_permissive_name(const char *name)
{
wchar_t *wn, *wnp;
wchar_t *ws, *wsp;
return (handle);
if (GetLastError() != ERROR_PATH_NOT_FOUND)
return (handle);
- wpath = permissive_name(path);
+ wpath = __la_win_permissive_name(path);
if (wpath == NULL)
return (handle);
handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode,
return -1;
}
- wsrc = permissive_name(src);
- wdst = permissive_name(dst);
+ wsrc = __la_win_permissive_name(src);
+ wdst = __la_win_permissive_name(dst);
if (wsrc == NULL || wdst == NULL) {
free(wsrc);
free(wdst);
return (0);
}
-#define WINTIME(sec, usec) ((Int32x32To64(sec, 10000000) + EPOC_TIME) + (usec * 10))
-static int
-__hutimes(HANDLE handle, const struct __timeval *times)
-{
- ULARGE_INTEGER wintm;
- FILETIME fatime, fmtime;
-
- wintm.QuadPart = WINTIME(times[0].tv_sec, times[0].tv_usec);
- fatime.dwLowDateTime = wintm.LowPart;
- fatime.dwHighDateTime = wintm.HighPart;
- wintm.QuadPart = WINTIME(times[1].tv_sec, times[1].tv_usec);
- fmtime.dwLowDateTime = wintm.LowPart;
- fmtime.dwHighDateTime = wintm.HighPart;
- if (SetFileTime(handle, NULL, &fatime, &fmtime) == 0) {
- errno = EINVAL;
- return (-1);
- }
- return (0);
-}
-
-int
-__la_futimes(int fd, const struct __timeval *times)
-{
-
- return (__hutimes((HANDLE)_get_osfhandle(fd), times));
-}
-
-int
-__la_utimes(const char *name, const struct __timeval *times)
-{
- int ret;
- HANDLE handle;
-
- handle = la_CreateFile(name, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (handle == INVALID_HANDLE_VALUE) {
- la_dosmaperr(GetLastError());
- return (-1);
- }
- ret = __hutimes(handle, times);
- CloseHandle(handle);
- return (ret);
-}
-
int
__la_chdir(const char *path)
{
}
} else
return (0);
- ws = permissive_name(path);
+ ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
return (-1);
la_dosmaperr(GetLastError());
return (-1);
}
- ws = permissive_name(path);
+ ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
return (-1);
}
} else
return (0);
- ws = permissive_name(path);
+ ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
return (-1);
*/
attr = GetFileAttributesA(path);
if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND) {
- ws = permissive_name(path);
+ ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
return (-1);
}
if (r >= 0 || errno != ENOENT)
return (r);
- ws = permissive_name(path);
+ ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
return (-1);
r = _rmdir(path);
if (r >= 0 || errno != ENOENT)
return (r);
- ws = permissive_name(path);
+ ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
return (-1);
r = _unlink(path);
if (r >= 0 || errno != ENOENT)
return (r);
- ws = permissive_name(path);
+ ws = __la_win_permissive_name(path);
if (ws == NULL) {
errno = EINVAL;
return (-1);
la_dosmaperr(GetLastError());
goto exit_tmpfile;
}
- ws = permissive_name(temp_name.s);
+ ws = __la_win_permissive_name(temp_name.s);
if (ws == NULL) {
errno = EINVAL;
goto exit_tmpfile;
*p = num[*p % sizeof(num)];
free(ws);
- ws = permissive_name(temp_name.s);
+ ws = __la_win_permissive_name(temp_name.s);
if (ws == NULL) {
errno = EINVAL;
goto exit_tmpfile;
#endif
#define fstat __la_fstat
#define ftruncate __la_ftruncate
-#define futimes __la_futimes
#define link __la_link
#define lseek __la_lseek
#define lstat __la_stat
#define umask _umask
#endif
#define unlink __la_unlink
-#define utimes __la_utimes
#define waitpid __la_waitpid
#define write __la_write
#endif /* __MINGW32__ */
#endif /* LARGE_FILES */
-#ifdef USE_WINSOCK_TIMEVAL
-/* Winsock timeval has long size tv_sec. */
-#define __timeval timeval
-#else
-struct _timeval64i32 {
- time_t tv_sec;
- long tv_usec;
-};
-#define __timeval _timeval64i32
-#endif
-
/* End of Win32 definitions. */
/* Tell libarchive code that we have simulations for these. */
#ifndef HAVE_FTRUNCATE
#define HAVE_FTRUNCATE 1
#endif
-#ifndef HAVE_FUTIMES
-#define HAVE_FUTIMES 1
-#endif
-#ifndef HAVE_UTIMES
-#define HAVE_UTIMES 1
-#endif
#ifndef HAVE_LINK
#define HAVE_LINK 1
#endif
extern int __la_fcntl(int fd, int cmd, int val);
extern int __la_fstat(int fd, struct stat *st);
extern int __la_ftruncate(int fd, int64_t length);
-extern int __la_futimes(int fd, const struct __timeval *times);
extern int __la_link(const char *src, const char *dst);
extern __int64 __la_lseek(int fd, __int64 offset, int whence);
extern int __la_lstat(const char *path, struct stat *st);
extern int __la_rmdir(const char *path);
extern int __la_stat(const char *path, struct stat *st);
extern int __la_unlink(const char *path);
-extern int __la_utimes(const char *name, const struct __timeval *times);
extern pid_t __la_waitpid(pid_t wpid, int *status, int option);
extern ssize_t __la_write(int fd, const void *buf, size_t nbytes);
#define WIFEXITED(sts) ((sts & 0x100) == 0)
#define WEXITSTATUS(sts) (sts & 0x0FF)
+extern wchar_t *__la_win_permissive_name(const char *name);
+
#endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */
unsigned long fflags_set, unsigned long fflags_clear);
static int set_ownership(struct archive_write_disk *);
static int set_mode(struct archive_write_disk *, int mode);
+#if !defined(_WIN32) || defined(__CYGWIN__)
static int set_time(int, int, const char *, time_t, long, time_t, long);
+#endif
static int set_times(struct archive_write_disk *, int, int, const char *,
time_t, long, time_t, long, time_t, long);
static int set_times_from_entry(struct archive_write_disk *);
return (ARCHIVE_WARN);
}
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
+static int
+set_times(struct archive_write_disk *a,
+ int fd, int mode, const char *name,
+ time_t atime, long atime_nanos,
+ time_t birthtime, long birthtime_nanos,
+ time_t mtime, long mtime_nanos)
+{
+#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
+#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
+ + (((nsec)/1000)*10))
+
+ HANDLE h, hw;
+ ULARGE_INTEGER wintm;
+ wchar_t *ws;
+ FILETIME *pfbtime;
+ FILETIME fatime, fbtime, fmtime;
+
+ if (fd >= 0) {
+ h = (HANDLE)_get_osfhandle(fd);
+ hw = NULL;
+ ws = NULL;
+ } else {
+ if (S_ISLNK(mode))
+ return (ARCHIVE_OK);
+ ws = __la_win_permissive_name(name);
+ if (ws == NULL)
+ goto settimes_failed;
+ hw = CreateFileW(ws, FILE_WRITE_ATTRIBUTES,
+ 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (hw == INVALID_HANDLE_VALUE)
+ goto settimes_failed;
+ h = hw;
+ }
+
+ wintm.QuadPart = WINTIME(atime, atime_nanos);
+ fatime.dwLowDateTime = wintm.LowPart;
+ fatime.dwHighDateTime = wintm.HighPart;
+ wintm.QuadPart = WINTIME(mtime, mtime_nanos);
+ fmtime.dwLowDateTime = wintm.LowPart;
+ fmtime.dwHighDateTime = wintm.HighPart;
+ /*
+ * SetFileTime() supports birthtime.
+ */
+ if (birthtime > 0 || birthtime_nanos > 0) {
+ wintm.QuadPart = WINTIME(birthtime, birthtime_nanos);
+ fbtime.dwLowDateTime = wintm.LowPart;
+ fbtime.dwHighDateTime = wintm.HighPart;
+ pfbtime = &fbtime;
+ } else
+ pfbtime = NULL;
+ if (SetFileTime(h, pfbtime, &fatime, &fmtime) == 0)
+ goto settimes_failed;
+ free(ws);
+ CloseHandle(hw);
+ return (ARCHIVE_OK);
+
+settimes_failed:
+ free(ws);
+ CloseHandle(hw);
+ archive_set_error(&a->archive, EINVAL, "Can't restore time");
+ return (ARCHIVE_WARN);
+}
+
+#else /* defined(_WIN32) && !defined(__CYGWIN__) */
+
/*
* Note: Returns 0 on success, non-zero on failure.
*/
* LEGACY by POSIX, futimes() and lutimes() are not described
* in POSIX.
*/
-#if defined(_WIN32) && !defined(__CYGWIN__)
- struct __timeval times[2];
-#else
struct timeval times[2];
-#endif
times[0].tv_sec = atime;
times[0].tv_usec = atime_nsec / 1000;
return (ARCHIVE_OK);
}
+#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
+
static int
set_times_from_entry(struct archive_write_disk *a)
{