]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Properly restore birthtime on Windows; use W32API directly in
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 25 Jan 2011 22:36:17 +0000 (17:36 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 25 Jan 2011 22:36:17 +0000 (17:36 -0500)
archive_write_disk.c and remove __la_futimes()/__la_utimes()
functions and related definitions, which were used in
archive_write_disk.c only.

SVN-Revision: 2948

libarchive/archive_read_disk_windows.c
libarchive/archive_windows.c
libarchive/archive_windows.h
libarchive/archive_write_disk.c

index 30218d95c49e66cafc179aee2a849f8d57a6afb5..6f5d07b81295d4fb73ba38f612db72d58d1750e0 100644 (file)
@@ -1180,89 +1180,6 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path,
        }
 }
 
-/*
- * 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.
  */
@@ -1353,7 +1270,7 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
        }
        base = pathname;
 
-       p = permissive_name(base);
+       p = __la_win_permissive_name(path);
        if (p == NULL) {
                free(pathname);
                goto failed;
@@ -1761,14 +1678,6 @@ tree_target_is_same_as_parent(struct tree *t,
 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);
 }
 
index 5c724bb47d07dfe386a12cf1e99aacb563a6915c..f613b174647225fc5ba58fab57f0aae6c8837948 100644 (file)
@@ -122,8 +122,8 @@ getino(struct ustat *ub)
  * 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;
@@ -230,7 +230,7 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
                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,
@@ -282,8 +282,8 @@ __link(const char *src, const char *dst)
                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);
@@ -396,51 +396,6 @@ __la_ftruncate(int fd, int64_t length)
        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)
 {
@@ -455,7 +410,7 @@ __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);
@@ -483,7 +438,7 @@ __la_chmod(const char *path, mode_t mode)
                        la_dosmaperr(GetLastError());
                        return (-1);
                }
-               ws = permissive_name(path);
+               ws = __la_win_permissive_name(path);
                if (ws == NULL) {
                        errno = EINVAL;
                        return (-1);
@@ -582,7 +537,7 @@ __la_mkdir(const char *path, mode_t mode)
                }
        } else
                return (0);
-       ws = permissive_name(path);
+       ws = __la_win_permissive_name(path);
        if (ws == NULL) {
                errno = EINVAL;
                return (-1);
@@ -629,7 +584,7 @@ __la_open(const char *path, int flags, ...)
                 */
                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);
@@ -686,7 +641,7 @@ __la_open(const char *path, int flags, ...)
                }
                if (r >= 0 || errno != ENOENT)
                        return (r);
-               ws = permissive_name(path);
+               ws = __la_win_permissive_name(path);
                if (ws == NULL) {
                        errno = EINVAL;
                        return (-1);
@@ -768,7 +723,7 @@ __la_rmdir(const char *path)
        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);
@@ -987,7 +942,7 @@ __la_unlink(const char *path)
        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);
@@ -1300,7 +1255,7 @@ __archive_mktemp(const char *tmpdir)
                        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;
@@ -1344,7 +1299,7 @@ __archive_mktemp(const char *tmpdir)
                        *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;
index b3f4f97819d1e179c6592ea1622dc121e657d5c5..068cdaa5e456f5ccc59ec28c1a7e068153940af5 100644 (file)
@@ -98,7 +98,6 @@
 #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
@@ -313,7 +294,6 @@ extern int   __la_chmod(const char *path, mode_t mode);
 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);
@@ -325,7 +305,6 @@ extern ssize_t       __la_read(int fd, void *buf, size_t nbytes);
 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);
 
@@ -335,4 +314,6 @@ 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 */
index 7115a4a669c88c3992388199f885ec3f9dab7c6f..8bc7c7d7384d11fc3416406c746717cf8a302707 100644 (file)
@@ -278,7 +278,9 @@ static int  set_fflags_platform(struct archive_write_disk *, int fd,
                    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 *);
@@ -1976,6 +1978,73 @@ set_ownership(struct archive_write_disk *a)
        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.
  */
@@ -2007,11 +2076,7 @@ set_time(int fd, int mode, const char *name,
         * 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;
@@ -2094,6 +2159,8 @@ set_times(struct archive_write_disk *a,
        return (ARCHIVE_OK);
 }
 
+#endif /* defined(_WIN32) && !defined(__CYGWIN__) */
+
 static int
 set_times_from_entry(struct archive_write_disk *a)
 {