]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - libarchive/archive_write_disk_windows.c
Update vendor/libarchive/dist to git 3c079320b23ddf5ef38c443569c25898ad79ddb9
[FreeBSD/FreeBSD.git] / libarchive / archive_write_disk_windows.c
1 /*-
2  * Copyright (c) 2003-2010 Tim Kientzle
3  * Copyright (c) 2011-2012 Michihiro NAKAJIMA
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer
11  *    in this position and unchanged.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "archive_platform.h"
29 __FBSDID("$FreeBSD$");
30
31 #if defined(_WIN32) && !defined(__CYGWIN__)
32
33 #ifdef HAVE_SYS_TYPES_H
34 #include <sys/types.h>
35 #endif
36 #ifdef HAVE_SYS_UTIME_H
37 #include <sys/utime.h>
38 #endif
39 #ifdef HAVE_ERRNO_H
40 #include <errno.h>
41 #endif
42 #ifdef HAVE_FCNTL_H
43 #include <fcntl.h>
44 #endif
45 #ifdef HAVE_LIMITS_H
46 #include <limits.h>
47 #endif
48 #ifdef HAVE_STDLIB_H
49 #include <stdlib.h>
50 #endif
51 #include <winioctl.h>
52
53 /* TODO: Support Mac OS 'quarantine' feature.  This is really just a
54  * standard tag to mark files that have been downloaded as "tainted".
55  * On Mac OS, we should mark the extracted files as tainted if the
56  * archive being read was tainted.  Windows has a similar feature; we
57  * should investigate ways to support this generically. */
58
59 #include "archive.h"
60 #include "archive_acl_private.h"
61 #include "archive_string.h"
62 #include "archive_entry.h"
63 #include "archive_private.h"
64
65 #ifndef O_BINARY
66 #define O_BINARY 0
67 #endif
68 #ifndef IO_REPARSE_TAG_SYMLINK
69 /* Old SDKs do not provide IO_REPARSE_TAG_SYMLINK */
70 #define IO_REPARSE_TAG_SYMLINK 0xA000000CL
71 #endif
72
73 static BOOL SetFilePointerEx_perso(HANDLE hFile,
74                              LARGE_INTEGER liDistanceToMove,
75                              PLARGE_INTEGER lpNewFilePointer,
76                              DWORD dwMoveMethod)
77 {
78         LARGE_INTEGER li;
79         li.QuadPart = liDistanceToMove.QuadPart;
80         li.LowPart = SetFilePointer(
81             hFile, li.LowPart, &li.HighPart, dwMoveMethod);
82         if(lpNewFilePointer) {
83                 lpNewFilePointer->QuadPart = li.QuadPart;
84         }
85         return li.LowPart != (DWORD)-1 || GetLastError() == NO_ERROR;
86 }
87
88 struct fixup_entry {
89         struct fixup_entry      *next;
90         struct archive_acl       acl;
91         mode_t                   mode;
92         int64_t                  atime;
93         int64_t                  birthtime;
94         int64_t                  mtime;
95         int64_t                  ctime;
96         unsigned long            atime_nanos;
97         unsigned long            birthtime_nanos;
98         unsigned long            mtime_nanos;
99         unsigned long            ctime_nanos;
100         unsigned long            fflags_set;
101         int                      fixup; /* bitmask of what needs fixing */
102         wchar_t                 *name;
103 };
104
105 /*
106  * We use a bitmask to track which operations remain to be done for
107  * this file.  In particular, this helps us avoid unnecessary
108  * operations when it's possible to take care of one step as a
109  * side-effect of another.  For example, mkdir() can specify the mode
110  * for the newly-created object but symlink() cannot.  This means we
111  * can skip chmod() if mkdir() succeeded, but we must explicitly
112  * chmod() if we're trying to create a directory that already exists
113  * (mkdir() failed) or if we're restoring a symlink.  Similarly, we
114  * need to verify UID/GID before trying to restore SUID/SGID bits;
115  * that verification can occur explicitly through a stat() call or
116  * implicitly because of a successful chown() call.
117  */
118 #define TODO_MODE_FORCE         0x40000000
119 #define TODO_MODE_BASE          0x20000000
120 #define TODO_SUID               0x10000000
121 #define TODO_SUID_CHECK         0x08000000
122 #define TODO_SGID               0x04000000
123 #define TODO_SGID_CHECK         0x02000000
124 #define TODO_MODE               (TODO_MODE_BASE|TODO_SUID|TODO_SGID)
125 #define TODO_TIMES              ARCHIVE_EXTRACT_TIME
126 #define TODO_OWNER              ARCHIVE_EXTRACT_OWNER
127 #define TODO_FFLAGS             ARCHIVE_EXTRACT_FFLAGS
128 #define TODO_ACLS               ARCHIVE_EXTRACT_ACL
129 #define TODO_XATTR              ARCHIVE_EXTRACT_XATTR
130 #define TODO_MAC_METADATA       ARCHIVE_EXTRACT_MAC_METADATA
131
132 struct archive_write_disk {
133         struct archive  archive;
134
135         mode_t                   user_umask;
136         struct fixup_entry      *fixup_list;
137         struct fixup_entry      *current_fixup;
138         int64_t                  user_uid;
139         int                      skip_file_set;
140         int64_t                  skip_file_dev;
141         int64_t                  skip_file_ino;
142         time_t                   start_time;
143
144         int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
145         void  (*cleanup_gid)(void *private);
146         void                    *lookup_gid_data;
147         int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid);
148         void  (*cleanup_uid)(void *private);
149         void                    *lookup_uid_data;
150
151         /*
152          * Full path of last file to satisfy symlink checks.
153          */
154         struct archive_wstring  path_safe;
155
156         /*
157          * Cached stat data from disk for the current entry.
158          * If this is valid, pst points to st.  Otherwise,
159          * pst is null.
160          */
161         BY_HANDLE_FILE_INFORMATION               st;
162         BY_HANDLE_FILE_INFORMATION              *pst;
163
164         /* Information about the object being restored right now. */
165         struct archive_entry    *entry; /* Entry being extracted. */
166         wchar_t                 *name; /* Name of entry, possibly edited. */
167         struct archive_wstring   _name_data; /* backing store for 'name' */
168         /* Tasks remaining for this object. */
169         int                      todo;
170         /* Tasks deferred until end-of-archive. */
171         int                      deferred;
172         /* Options requested by the client. */
173         int                      flags;
174         /* Handle for the file we're restoring. */
175         HANDLE           fh;
176         /* Current offset for writing data to the file. */
177         int64_t                  offset;
178         /* Last offset actually written to disk. */
179         int64_t                  fd_offset;
180         /* Total bytes actually written to files. */
181         int64_t                  total_bytes_written;
182         /* Maximum size of file, -1 if unknown. */
183         int64_t                  filesize;
184         /* Dir we were in before this restore; only for deep paths. */
185         int                      restore_pwd;
186         /* Mode we should use for this entry; affected by _PERM and umask. */
187         mode_t                   mode;
188         /* UID/GID to use in restoring this entry. */
189         int64_t                  uid;
190         int64_t                  gid;
191 };
192
193 /*
194  * Default mode for dirs created automatically (will be modified by umask).
195  * Note that POSIX specifies 0777 for implicitly-created dirs, "modified
196  * by the process' file creation mask."
197  */
198 #define DEFAULT_DIR_MODE 0777
199 /*
200  * Dir modes are restored in two steps:  During the extraction, the permissions
201  * in the archive are modified to match the following limits.  During
202  * the post-extract fixup pass, the permissions from the archive are
203  * applied.
204  */
205 #define MINIMUM_DIR_MODE 0700
206 #define MAXIMUM_DIR_MODE 0775
207
208 static int      check_symlinks(struct archive_write_disk *);
209 static int      create_filesystem_object(struct archive_write_disk *);
210 static struct fixup_entry *current_fixup(struct archive_write_disk *,
211                     const wchar_t *pathname);
212 static int      cleanup_pathname(struct archive_write_disk *);
213 static int      create_dir(struct archive_write_disk *, wchar_t *);
214 static int      create_parent_dir(struct archive_write_disk *, wchar_t *);
215 static int      la_chmod(const wchar_t *, mode_t);
216 static int      older(BY_HANDLE_FILE_INFORMATION *, struct archive_entry *);
217 static int      permissive_name_w(struct archive_write_disk *);
218 static int      restore_entry(struct archive_write_disk *);
219 static int      set_acls(struct archive_write_disk *, HANDLE h,
220                     const wchar_t *, struct archive_acl *);
221 static int      set_xattrs(struct archive_write_disk *);
222 static int      set_fflags(struct archive_write_disk *);
223 static int      set_ownership(struct archive_write_disk *);
224 static int      set_mode(struct archive_write_disk *, int mode);
225 static int      set_times(struct archive_write_disk *, HANDLE, int,
226                     const wchar_t *, time_t, long, time_t, long, time_t,
227                     long, time_t, long);
228 static int      set_times_from_entry(struct archive_write_disk *);
229 static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
230 static ssize_t  write_data_block(struct archive_write_disk *,
231                     const char *, size_t);
232
233 static struct archive_vtable *archive_write_disk_vtable(void);
234
235 static int      _archive_write_disk_close(struct archive *);
236 static int      _archive_write_disk_free(struct archive *);
237 static int      _archive_write_disk_header(struct archive *,
238                     struct archive_entry *);
239 static int64_t  _archive_write_disk_filter_bytes(struct archive *, int);
240 static int      _archive_write_disk_finish_entry(struct archive *);
241 static ssize_t  _archive_write_disk_data(struct archive *, const void *,
242                     size_t);
243 static ssize_t  _archive_write_disk_data_block(struct archive *, const void *,
244                     size_t, int64_t);
245
246 #define bhfi_dev(bhfi)  ((bhfi)->dwVolumeSerialNumber)
247 /* Treat FileIndex as i-node. We should remove a sequence number
248  * which is high-16-bits of nFileIndexHigh. */
249 #define bhfi_ino(bhfi)  \
250         ((((int64_t)((bhfi)->nFileIndexHigh & 0x0000FFFFUL)) << 32) \
251     + (bhfi)->nFileIndexLow)
252 #define bhfi_size(bhfi) \
253     ((((int64_t)(bhfi)->nFileSizeHigh) << 32) + (bhfi)->nFileSizeLow)
254
255 static int
256 file_information(struct archive_write_disk *a, wchar_t *path,
257     BY_HANDLE_FILE_INFORMATION *st, mode_t *mode, int sim_lstat)
258 {
259         HANDLE h;
260         int r;
261         DWORD flag = FILE_FLAG_BACKUP_SEMANTICS;
262         WIN32_FIND_DATAW        findData;
263
264         if (sim_lstat || mode != NULL) {
265                 h = FindFirstFileW(path, &findData);
266                 if (h == INVALID_HANDLE_VALUE &&
267                     GetLastError() == ERROR_INVALID_NAME) {
268                         wchar_t *full;
269                         full = __la_win_permissive_name_w(path);
270                         h = FindFirstFileW(full, &findData);
271                         free(full);
272                 }
273                 if (h == INVALID_HANDLE_VALUE) {
274                         la_dosmaperr(GetLastError());
275                         return (-1);
276                 }
277                 FindClose(h);
278         }
279
280         /* Is symlink file ? */
281         if (sim_lstat && 
282             ((findData.dwFileAttributes
283                         & FILE_ATTRIBUTE_REPARSE_POINT) &&
284                 (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)))
285                 flag |= FILE_FLAG_OPEN_REPARSE_POINT;
286
287         h = CreateFileW(a->name, 0, 0, NULL,
288             OPEN_EXISTING, flag, NULL);
289         if (h == INVALID_HANDLE_VALUE &&
290             GetLastError() == ERROR_INVALID_NAME) {
291                 wchar_t *full;
292                 full = __la_win_permissive_name_w(path);
293                 h = CreateFileW(full, 0, 0, NULL,
294                     OPEN_EXISTING, flag, NULL);
295                 free(full);
296         }
297         if (h == INVALID_HANDLE_VALUE) {
298                 la_dosmaperr(GetLastError());
299                 return (-1);
300         }
301         r = GetFileInformationByHandle(h, st);
302         CloseHandle(h);
303         if (r == 0) {
304                 la_dosmaperr(GetLastError());
305                 return (-1);
306         }
307
308         if (mode == NULL)
309                 return (0);
310
311         *mode = S_IRUSR | S_IRGRP | S_IROTH;
312         if ((st->dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
313                 *mode |= S_IWUSR | S_IWGRP | S_IWOTH;
314         if ((st->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
315             findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)
316                 *mode |= S_IFLNK;
317         else if (st->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
318                 *mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
319         else {
320                 const wchar_t *p;
321
322                 *mode |= S_IFREG;
323                 p = wcsrchr(path, L'.');
324                 if (p != NULL && wcslen(p) == 4) {
325                         switch (p[1]) {
326                         case L'B': case L'b':
327                                 if ((p[2] == L'A' || p[2] == L'a' ) &&
328                                     (p[3] == L'T' || p[3] == L't' ))
329                                         *mode |= S_IXUSR | S_IXGRP | S_IXOTH;
330                                 break;
331                         case L'C': case L'c':
332                                 if (((p[2] == L'M' || p[2] == L'm' ) &&
333                                     (p[3] == L'D' || p[3] == L'd' )))
334                                         *mode |= S_IXUSR | S_IXGRP | S_IXOTH;
335                                 break;
336                         case L'E': case L'e':
337                                 if ((p[2] == L'X' || p[2] == L'x' ) &&
338                                     (p[3] == L'E' || p[3] == L'e' ))
339                                         *mode |= S_IXUSR | S_IXGRP | S_IXOTH;
340                                 break;
341                         default:
342                                 break;
343                         }
344                 }
345         }
346         return (0);
347 }
348
349 /* 
350  * Note: The path, for example, "aa/a/../b../c" will be converted to "aa/c"
351  * by GetFullPathNameW() W32 API, which __la_win_permissive_name_w uses.
352  * It means we cannot handle multiple dirs in one archive_entry.
353  * So we have to make the full-pathname in another way, which does not
354  * break "../" path string.
355  */
356 static int
357 permissive_name_w(struct archive_write_disk *a)
358 {
359         wchar_t *wn, *wnp;
360         wchar_t *ws, *wsp;
361         DWORD l;
362
363         wnp = a->name;
364         if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
365             wnp[2] == L'?' && wnp[3] == L'\\')
366                 /* We have already a permissive name. */
367                 return (0);
368
369         if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
370                 wnp[2] == L'.' && wnp[3] == L'\\') {
371                 /* This is a device name */
372                 if (((wnp[4] >= L'a' && wnp[4] <= L'z') ||
373                      (wnp[4] >= L'A' && wnp[4] <= L'Z')) &&
374                          wnp[5] == L':' && wnp[6] == L'\\') {
375                         wnp[2] = L'?';/* Not device name. */
376                         return (0);
377                 }
378         }
379
380         /*
381          * A full-pathname starting with a drive name like "C:\abc".
382          */
383         if (((wnp[0] >= L'a' && wnp[0] <= L'z') ||
384              (wnp[0] >= L'A' && wnp[0] <= L'Z')) &&
385                  wnp[1] == L':' && wnp[2] == L'\\') {
386                 wn = _wcsdup(wnp);
387                 if (wn == NULL)
388                         return (-1);
389                 archive_wstring_ensure(&(a->_name_data), 4 + wcslen(wn) + 1);
390                 a->name = a->_name_data.s;
391                 /* Prepend "\\?\" */
392                 archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
393                 archive_wstrcat(&(a->_name_data), wn);
394                 free(wn);
395                 return (0);
396         }
397
398         /*
399          * A full-pathname pointing to a network drive
400          * like "\\<server-name>\<share-name>\file". 
401          */
402         if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
403                 const wchar_t *p = &wnp[2];
404
405                 /* Skip server-name letters. */
406                 while (*p != L'\\' && *p != L'\0')
407                         ++p;
408                 if (*p == L'\\') {
409                         const wchar_t *rp = ++p;
410                         /* Skip share-name letters. */
411                         while (*p != L'\\' && *p != L'\0')
412                                 ++p;
413                         if (*p == L'\\' && p != rp) {
414                                 /* Now, match patterns such as
415                                  * "\\server-name\share-name\" */
416                                 wn = _wcsdup(wnp);
417                                 if (wn == NULL)
418                                         return (-1);
419                                 archive_wstring_ensure(&(a->_name_data),
420                                         8 + wcslen(wn) + 1);
421                                 a->name = a->_name_data.s;
422                                 /* Prepend "\\?\UNC\" */
423                                 archive_wstrncpy(&(a->_name_data),
424                                         L"\\\\?\\UNC\\", 8);
425                                 archive_wstrcat(&(a->_name_data), wn+2);
426                                 free(wn);
427                                 return (0);
428                         }
429                 }
430                 return (0);
431         }
432
433         /*
434          * Get current working directory.
435          */
436         l = GetCurrentDirectoryW(0, NULL);
437         if (l == 0)
438                 return (-1);
439         ws = malloc(l * sizeof(wchar_t));
440         l = GetCurrentDirectoryW(l, ws);
441         if (l == 0) {
442                 free(ws);
443                 return (-1);
444         }
445         wsp = ws;
446
447         /*
448          * A full-pathname starting without a drive name like "\abc".
449          */
450         if (wnp[0] == L'\\') {
451                 wn = _wcsdup(wnp);
452                 if (wn == NULL)
453                         return (-1);
454                 archive_wstring_ensure(&(a->_name_data),
455                         4 + 2 + wcslen(wn) + 1);
456                 a->name = a->_name_data.s;
457                 /* Prepend "\\?\" and drive name. */
458                 archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
459                 archive_wstrncat(&(a->_name_data), wsp, 2);
460                 archive_wstrcat(&(a->_name_data), wn);
461                 free(wsp);
462                 free(wn);
463                 return (0);
464         }
465
466         wn = _wcsdup(wnp);
467         if (wn == NULL)
468                 return (-1);
469         archive_wstring_ensure(&(a->_name_data), 4 + l + 1 + wcslen(wn) + 1);
470         a->name = a->_name_data.s;
471         /* Prepend "\\?\" and drive name if not already added. */
472         if (l > 3 && wsp[0] == L'\\' && wsp[1] == L'\\' &&
473                 wsp[2] == L'?' && wsp[3] == L'\\')
474         {
475                 archive_wstrncpy(&(a->_name_data), wsp, l);
476         }
477         else if (l > 2 && wsp[0] == L'\\' && wsp[1] == L'\\' && wsp[2] != L'\\')
478         {
479                 archive_wstrncpy(&(a->_name_data), L"\\\\?\\UNC\\", 8);
480                 archive_wstrncat(&(a->_name_data), wsp+2, l-2);
481         }
482         else
483         {
484                 archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
485                 archive_wstrncat(&(a->_name_data), wsp, l);
486         }
487         archive_wstrncat(&(a->_name_data), L"\\", 1);
488         archive_wstrcat(&(a->_name_data), wn);
489         a->name = a->_name_data.s;
490         free(wsp);
491         free(wn);
492         return (0);
493 }
494
495 static int
496 la_chmod(const wchar_t *path, mode_t mode)
497 {
498         DWORD attr;
499         BOOL r;
500         wchar_t *fullname;
501         int ret = 0;
502
503         fullname = NULL;
504         attr = GetFileAttributesW(path);
505         if (attr == (DWORD)-1 &&
506             GetLastError() == ERROR_INVALID_NAME) {
507                 fullname = __la_win_permissive_name_w(path);
508                 attr = GetFileAttributesW(fullname);
509         }
510         if (attr == (DWORD)-1) {
511                 la_dosmaperr(GetLastError());
512                 ret = -1;
513                 goto exit_chmode;
514         }
515         if (mode & _S_IWRITE)
516                 attr &= ~FILE_ATTRIBUTE_READONLY;
517         else
518                 attr |= FILE_ATTRIBUTE_READONLY;
519         if (fullname != NULL)
520                 r = SetFileAttributesW(fullname, attr);
521         else
522                 r = SetFileAttributesW(path, attr);
523         if (r == 0) {
524                 la_dosmaperr(GetLastError());
525                 ret = -1;
526         }
527 exit_chmode:
528         free(fullname);
529         return (ret);
530 }
531
532 static void *
533 la_GetFunctionKernel32(const char *name)
534 {
535         static HINSTANCE lib;
536         static int set;
537         if (!set) {
538                 set = 1;
539                 lib = LoadLibrary(TEXT("kernel32.dll"));
540         }
541         if (lib == NULL) {
542                 fprintf(stderr, "Can't load kernel32.dll?!\n");
543                 exit(1);
544         }
545         return (void *)GetProcAddress(lib, name);
546 }
547
548 static int
549 la_CreateHardLinkW(wchar_t *linkname, wchar_t *target)
550 {
551         static BOOLEAN (WINAPI *f)(LPWSTR, LPWSTR, LPSECURITY_ATTRIBUTES);
552         static int set;
553         BOOL ret;
554
555         if (!set) {
556                 set = 1;
557                 f = la_GetFunctionKernel32("CreateHardLinkW");
558         }
559         if (!f)
560                 return (0);
561         ret = (*f)(linkname, target, NULL);
562         if (!ret) {
563                 /* Under windows 2000, it is necessary to remove
564                  * the "\\?\" prefix. */
565 #define IS_UNC(name)    ((name[0] == L'U' || name[0] == L'u') &&        \
566                          (name[1] == L'N' || name[1] == L'n') &&        \
567                          (name[2] == L'C' || name[2] == L'c') &&        \
568                          name[3] == L'\\')
569                 if (!wcsncmp(linkname,L"\\\\?\\", 4)) {
570                         linkname += 4;
571                         if (IS_UNC(linkname))
572                                 linkname += 4;
573                 }
574                 if (!wcsncmp(target,L"\\\\?\\", 4)) {
575                         target += 4;
576                         if (IS_UNC(target))
577                                 target += 4;
578                 }
579 #undef IS_UNC
580                 ret = (*f)(linkname, target, NULL);
581         }
582         return (ret);
583 }
584
585 static int
586 la_ftruncate(HANDLE handle, int64_t length)
587 {
588         LARGE_INTEGER distance;
589
590         if (GetFileType(handle) != FILE_TYPE_DISK) {
591                 errno = EBADF;
592                 return (-1);
593         }
594         distance.QuadPart = length;
595         if (!SetFilePointerEx_perso(handle, distance, NULL, FILE_BEGIN)) {
596                 la_dosmaperr(GetLastError());
597                 return (-1);
598         }
599         if (!SetEndOfFile(handle)) {
600                 la_dosmaperr(GetLastError());
601                 return (-1);
602         }
603         return (0);
604 }
605
606 static int
607 lazy_stat(struct archive_write_disk *a)
608 {
609         if (a->pst != NULL) {
610                 /* Already have stat() data available. */
611                 return (ARCHIVE_OK);
612         }
613         if (a->fh != INVALID_HANDLE_VALUE &&
614             GetFileInformationByHandle(a->fh, &a->st) == 0) {
615                 a->pst = &a->st;
616                 return (ARCHIVE_OK);
617         }
618
619         /*
620          * XXX At this point, symlinks should not be hit, otherwise
621          * XXX a race occurred.  Do we want to check explicitly for that?
622          */
623         if (file_information(a, a->name, &a->st, NULL, 1) == 0) {
624                 a->pst = &a->st;
625                 return (ARCHIVE_OK);
626         }
627         archive_set_error(&a->archive, errno, "Couldn't stat file");
628         return (ARCHIVE_WARN);
629 }
630
631 static struct archive_vtable *
632 archive_write_disk_vtable(void)
633 {
634         static struct archive_vtable av;
635         static int inited = 0;
636
637         if (!inited) {
638                 av.archive_close = _archive_write_disk_close;
639                 av.archive_filter_bytes = _archive_write_disk_filter_bytes;
640                 av.archive_free = _archive_write_disk_free;
641                 av.archive_write_header = _archive_write_disk_header;
642                 av.archive_write_finish_entry
643                     = _archive_write_disk_finish_entry;
644                 av.archive_write_data = _archive_write_disk_data;
645                 av.archive_write_data_block = _archive_write_disk_data_block;
646                 inited = 1;
647         }
648         return (&av);
649 }
650
651 static int64_t
652 _archive_write_disk_filter_bytes(struct archive *_a, int n)
653 {
654         struct archive_write_disk *a = (struct archive_write_disk *)_a;
655         (void)n; /* UNUSED */
656         if (n == -1 || n == 0)
657                 return (a->total_bytes_written);
658         return (-1);
659 }
660
661
662 int
663 archive_write_disk_set_options(struct archive *_a, int flags)
664 {
665         struct archive_write_disk *a = (struct archive_write_disk *)_a;
666
667         a->flags = flags;
668         return (ARCHIVE_OK);
669 }
670
671
672 /*
673  * Extract this entry to disk.
674  *
675  * TODO: Validate hardlinks.  According to the standards, we're
676  * supposed to check each extracted hardlink and squawk if it refers
677  * to a file that we didn't restore.  I'm not entirely convinced this
678  * is a good idea, but more importantly: Is there any way to validate
679  * hardlinks without keeping a complete list of filenames from the
680  * entire archive?? Ugh.
681  *
682  */
683 static int
684 _archive_write_disk_header(struct archive *_a, struct archive_entry *entry)
685 {
686         struct archive_write_disk *a = (struct archive_write_disk *)_a;
687         struct fixup_entry *fe;
688         int ret, r;
689
690         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
691             ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
692             "archive_write_disk_header");
693         archive_clear_error(&a->archive);
694         if (a->archive.state & ARCHIVE_STATE_DATA) {
695                 r = _archive_write_disk_finish_entry(&a->archive);
696                 if (r == ARCHIVE_FATAL)
697                         return (r);
698         }
699
700         /* Set up for this particular entry. */
701         a->pst = NULL;
702         a->current_fixup = NULL;
703         a->deferred = 0;
704         archive_entry_free(a->entry);
705         a->entry = NULL;
706         a->entry = archive_entry_clone(entry);
707         a->fh = INVALID_HANDLE_VALUE;
708         a->fd_offset = 0;
709         a->offset = 0;
710         a->restore_pwd = -1;
711         a->uid = a->user_uid;
712         a->mode = archive_entry_mode(a->entry);
713         if (archive_entry_size_is_set(a->entry))
714                 a->filesize = archive_entry_size(a->entry);
715         else
716                 a->filesize = -1;
717         archive_wstrcpy(&(a->_name_data), archive_entry_pathname_w(a->entry));
718         a->name = a->_name_data.s;
719         archive_clear_error(&a->archive);
720
721         /*
722          * Clean up the requested path.  This is necessary for correct
723          * dir restores; the dir restore logic otherwise gets messed
724          * up by nonsense like "dir/.".
725          */
726         ret = cleanup_pathname(a);
727         if (ret != ARCHIVE_OK)
728                 return (ret);
729
730         /*
731          * Generate a full-pathname and use it from here.
732          */
733         if (permissive_name_w(a) < 0) {
734                 errno = EINVAL;
735                 return (ARCHIVE_FAILED);
736         }
737
738         /*
739          * Query the umask so we get predictable mode settings.
740          * This gets done on every call to _write_header in case the
741          * user edits their umask during the extraction for some
742          * reason.
743          */
744         umask(a->user_umask = umask(0));
745
746         /* Figure out what we need to do for this entry. */
747         a->todo = TODO_MODE_BASE;
748         if (a->flags & ARCHIVE_EXTRACT_PERM) {
749                 a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */
750                 /*
751                  * SGID requires an extra "check" step because we
752                  * cannot easily predict the GID that the system will
753                  * assign.  (Different systems assign GIDs to files
754                  * based on a variety of criteria, including process
755                  * credentials and the gid of the enclosing
756                  * directory.)  We can only restore the SGID bit if
757                  * the file has the right GID, and we only know the
758                  * GID if we either set it (see set_ownership) or if
759                  * we've actually called stat() on the file after it
760                  * was restored.  Since there are several places at
761                  * which we might verify the GID, we need a TODO bit
762                  * to keep track.
763                  */
764                 if (a->mode & S_ISGID)
765                         a->todo |= TODO_SGID | TODO_SGID_CHECK;
766                 /*
767                  * Verifying the SUID is simpler, but can still be
768                  * done in multiple ways, hence the separate "check" bit.
769                  */
770                 if (a->mode & S_ISUID)
771                         a->todo |= TODO_SUID | TODO_SUID_CHECK;
772         } else {
773                 /*
774                  * User didn't request full permissions, so don't
775                  * restore SUID, SGID bits and obey umask.
776                  */
777                 a->mode &= ~S_ISUID;
778                 a->mode &= ~S_ISGID;
779                 a->mode &= ~S_ISVTX;
780                 a->mode &= ~a->user_umask;
781         }
782 #if 0
783         if (a->flags & ARCHIVE_EXTRACT_OWNER)
784                 a->todo |= TODO_OWNER;
785 #endif
786         if (a->flags & ARCHIVE_EXTRACT_TIME)
787                 a->todo |= TODO_TIMES;
788         if (a->flags & ARCHIVE_EXTRACT_ACL) {
789                 if (archive_entry_filetype(a->entry) == AE_IFDIR)
790                         a->deferred |= TODO_ACLS;
791                 else
792                         a->todo |= TODO_ACLS;
793         }
794         if (a->flags & ARCHIVE_EXTRACT_XATTR)
795                 a->todo |= TODO_XATTR;
796         if (a->flags & ARCHIVE_EXTRACT_FFLAGS)
797                 a->todo |= TODO_FFLAGS;
798         if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) {
799                 ret = check_symlinks(a);
800                 if (ret != ARCHIVE_OK)
801                         return (ret);
802         }
803
804         ret = restore_entry(a);
805
806         /*
807          * TODO: There are rumours that some extended attributes must
808          * be restored before file data is written.  If this is true,
809          * then we either need to write all extended attributes both
810          * before and after restoring the data, or find some rule for
811          * determining which must go first and which last.  Due to the
812          * many ways people are using xattrs, this may prove to be an
813          * intractable problem.
814          */
815
816         /*
817          * Fixup uses the unedited pathname from archive_entry_pathname(),
818          * because it is relative to the base dir and the edited path
819          * might be relative to some intermediate dir as a result of the
820          * deep restore logic.
821          */
822         if (a->deferred & TODO_MODE) {
823                 fe = current_fixup(a, archive_entry_pathname_w(entry));
824                 fe->fixup |= TODO_MODE_BASE;
825                 fe->mode = a->mode;
826         }
827
828         if ((a->deferred & TODO_TIMES)
829                 && (archive_entry_mtime_is_set(entry)
830                     || archive_entry_atime_is_set(entry))) {
831                 fe = current_fixup(a, archive_entry_pathname_w(entry));
832                 fe->mode = a->mode;
833                 fe->fixup |= TODO_TIMES;
834                 if (archive_entry_atime_is_set(entry)) {
835                         fe->atime = archive_entry_atime(entry);
836                         fe->atime_nanos = archive_entry_atime_nsec(entry);
837                 } else {
838                         /* If atime is unset, use start time. */
839                         fe->atime = a->start_time;
840                         fe->atime_nanos = 0;
841                 }
842                 if (archive_entry_mtime_is_set(entry)) {
843                         fe->mtime = archive_entry_mtime(entry);
844                         fe->mtime_nanos = archive_entry_mtime_nsec(entry);
845                 } else {
846                         /* If mtime is unset, use start time. */
847                         fe->mtime = a->start_time;
848                         fe->mtime_nanos = 0;
849                 }
850                 if (archive_entry_birthtime_is_set(entry)) {
851                         fe->birthtime = archive_entry_birthtime(entry);
852                         fe->birthtime_nanos = archive_entry_birthtime_nsec(entry);
853                 } else {
854                         /* If birthtime is unset, use mtime. */
855                         fe->birthtime = fe->mtime;
856                         fe->birthtime_nanos = fe->mtime_nanos;
857                 }
858         }
859
860         if (a->deferred & TODO_ACLS) {
861                 fe = current_fixup(a, archive_entry_pathname_w(entry));
862                 archive_acl_copy(&fe->acl, archive_entry_acl(entry));
863         }
864
865         if (a->deferred & TODO_FFLAGS) {
866                 fe = current_fixup(a, archive_entry_pathname_w(entry));
867                 fe->fixup |= TODO_FFLAGS;
868                 /* TODO: Complete this.. defer fflags from below. */
869         }
870
871         /*
872          * On Windows, A creating sparse file requires a special mark.
873          */
874         if (a->fh != INVALID_HANDLE_VALUE &&
875             archive_entry_sparse_count(entry) > 0) {
876                 int64_t base = 0, offset, length;
877                 int i, cnt = archive_entry_sparse_reset(entry);
878                 int sparse = 0;
879
880                 for (i = 0; i < cnt; i++) {
881                         archive_entry_sparse_next(entry, &offset, &length);
882                         if (offset - base >= 4096) {
883                                 sparse = 1;/* we have a hole. */
884                                 break;
885                         }
886                         base = offset + length;
887                 }
888                 if (sparse) {
889                         DWORD dmy;
890                         /* Mark this file as sparse. */
891                         DeviceIoControl(a->fh, FSCTL_SET_SPARSE,
892                             NULL, 0, NULL, 0, &dmy, NULL);
893                 }
894         }
895
896         /* We've created the object and are ready to pour data into it. */
897         if (ret >= ARCHIVE_WARN)
898                 a->archive.state = ARCHIVE_STATE_DATA;
899         /*
900          * If it's not open, tell our client not to try writing.
901          * In particular, dirs, links, etc, don't get written to.
902          */
903         if (a->fh == INVALID_HANDLE_VALUE) {
904                 archive_entry_set_size(entry, 0);
905                 a->filesize = 0;
906         }
907
908         return (ret);
909 }
910
911 int
912 archive_write_disk_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
913 {
914         struct archive_write_disk *a = (struct archive_write_disk *)_a;
915         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
916             ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
917         a->skip_file_set = 1;
918         a->skip_file_dev = d;
919         a->skip_file_ino = i;
920         return (ARCHIVE_OK);
921 }
922
923 static ssize_t
924 write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
925 {
926         OVERLAPPED ol;
927         uint64_t start_size = size;
928         DWORD bytes_written = 0;
929         ssize_t block_size = 0, bytes_to_write;
930
931         if (size == 0)
932                 return (ARCHIVE_OK);
933
934         if (a->filesize == 0 || a->fh == INVALID_HANDLE_VALUE) {
935                 archive_set_error(&a->archive, 0,
936                     "Attempt to write to an empty file");
937                 return (ARCHIVE_WARN);
938         }
939
940         if (a->flags & ARCHIVE_EXTRACT_SPARSE) {
941                 /* XXX TODO XXX Is there a more appropriate choice here ? */
942                 /* This needn't match the filesystem allocation size. */
943                 block_size = 16*1024;
944         }
945
946         /* If this write would run beyond the file size, truncate it. */
947         if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize)
948                 start_size = size = (size_t)(a->filesize - a->offset);
949
950         /* Write the data. */
951         while (size > 0) {
952                 if (block_size == 0) {
953                         bytes_to_write = size;
954                 } else {
955                         /* We're sparsifying the file. */
956                         const char *p, *end;
957                         int64_t block_end;
958
959                         /* Skip leading zero bytes. */
960                         for (p = buff, end = buff + size; p < end; ++p) {
961                                 if (*p != '\0')
962                                         break;
963                         }
964                         a->offset += p - buff;
965                         size -= p - buff;
966                         buff = p;
967                         if (size == 0)
968                                 break;
969
970                         /* Calculate next block boundary after offset. */
971                         block_end
972                             = (a->offset / block_size + 1) * block_size;
973
974                         /* If the adjusted write would cross block boundary,
975                          * truncate it to the block boundary. */
976                         bytes_to_write = size;
977                         if (a->offset + bytes_to_write > block_end)
978                                 bytes_to_write = (DWORD)(block_end - a->offset);
979                 }
980                 memset(&ol, 0, sizeof(ol));
981                 ol.Offset = (DWORD)(a->offset & 0xFFFFFFFF);
982                 ol.OffsetHigh = (DWORD)(a->offset >> 32);
983                 if (!WriteFile(a->fh, buff, (uint32_t)bytes_to_write,
984                     &bytes_written, &ol)) {
985                         DWORD lasterr;
986
987                         lasterr = GetLastError();
988                         if (lasterr == ERROR_ACCESS_DENIED)
989                                 errno = EBADF;
990                         else
991                                 la_dosmaperr(lasterr);
992                         archive_set_error(&a->archive, errno, "Write failed");
993                         return (ARCHIVE_WARN);
994                 }
995                 buff += bytes_written;
996                 size -= bytes_written;
997                 a->total_bytes_written += bytes_written;
998                 a->offset += bytes_written;
999                 a->fd_offset = a->offset;
1000         }
1001         return ((ssize_t)(start_size - size));
1002 }
1003
1004 static ssize_t
1005 _archive_write_disk_data_block(struct archive *_a,
1006     const void *buff, size_t size, int64_t offset)
1007 {
1008         struct archive_write_disk *a = (struct archive_write_disk *)_a;
1009         ssize_t r;
1010
1011         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1012             ARCHIVE_STATE_DATA, "archive_write_data_block");
1013
1014         a->offset = offset;
1015         r = write_data_block(a, buff, size);
1016         if (r < ARCHIVE_OK)
1017                 return (r);
1018         if ((size_t)r < size) {
1019                 archive_set_error(&a->archive, 0,
1020                     "Write request too large");
1021                 return (ARCHIVE_WARN);
1022         }
1023 #if ARCHIVE_VERSION_NUMBER < 3999000
1024         return (ARCHIVE_OK);
1025 #else
1026         return (size);
1027 #endif
1028 }
1029
1030 static ssize_t
1031 _archive_write_disk_data(struct archive *_a, const void *buff, size_t size)
1032 {
1033         struct archive_write_disk *a = (struct archive_write_disk *)_a;
1034
1035         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1036             ARCHIVE_STATE_DATA, "archive_write_data");
1037
1038         return (write_data_block(a, buff, size));
1039 }
1040
1041 static int
1042 _archive_write_disk_finish_entry(struct archive *_a)
1043 {
1044         struct archive_write_disk *a = (struct archive_write_disk *)_a;
1045         int ret = ARCHIVE_OK;
1046
1047         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1048             ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1049             "archive_write_finish_entry");
1050         if (a->archive.state & ARCHIVE_STATE_HEADER)
1051                 return (ARCHIVE_OK);
1052         archive_clear_error(&a->archive);
1053
1054         /* Pad or truncate file to the right size. */
1055         if (a->fh == INVALID_HANDLE_VALUE) {
1056                 /* There's no file. */
1057         } else if (a->filesize < 0) {
1058                 /* File size is unknown, so we can't set the size. */
1059         } else if (a->fd_offset == a->filesize) {
1060                 /* Last write ended at exactly the filesize; we're done. */
1061                 /* Hopefully, this is the common case. */
1062         } else {
1063                 if (la_ftruncate(a->fh, a->filesize) == -1) {
1064                         archive_set_error(&a->archive, errno,
1065                             "File size could not be restored");
1066                         return (ARCHIVE_FAILED);
1067                 }
1068         }
1069
1070         /* Restore metadata. */
1071
1072         /*
1073          * Look up the "real" UID only if we're going to need it.
1074          * TODO: the TODO_SGID condition can be dropped here, can't it?
1075          */
1076         if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) {
1077                 a->uid = archive_write_disk_uid(&a->archive,
1078                     archive_entry_uname(a->entry),
1079                     archive_entry_uid(a->entry));
1080         }
1081         /* Look up the "real" GID only if we're going to need it. */
1082         /* TODO: the TODO_SUID condition can be dropped here, can't it? */
1083         if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) {
1084                 a->gid = archive_write_disk_gid(&a->archive,
1085                     archive_entry_gname(a->entry),
1086                     archive_entry_gid(a->entry));
1087          }
1088
1089         /*
1090          * Restore ownership before set_mode tries to restore suid/sgid
1091          * bits.  If we set the owner, we know what it is and can skip
1092          * a stat() call to examine the ownership of the file on disk.
1093          */
1094         if (a->todo & TODO_OWNER)
1095                 ret = set_ownership(a);
1096
1097         /*
1098          * set_mode must precede ACLs on systems such as Solaris and
1099          * FreeBSD where setting the mode implicitly clears extended ACLs
1100          */
1101         if (a->todo & TODO_MODE) {
1102                 int r2 = set_mode(a, a->mode);
1103                 if (r2 < ret) ret = r2;
1104         }
1105
1106         /*
1107          * Security-related extended attributes (such as
1108          * security.capability on Linux) have to be restored last,
1109          * since they're implicitly removed by other file changes.
1110          */
1111         if (a->todo & TODO_XATTR) {
1112                 int r2 = set_xattrs(a);
1113                 if (r2 < ret) ret = r2;
1114         }
1115
1116         /*
1117          * Some flags prevent file modification; they must be restored after
1118          * file contents are written.
1119          */
1120         if (a->todo & TODO_FFLAGS) {
1121                 int r2 = set_fflags(a);
1122                 if (r2 < ret) ret = r2;
1123         }
1124
1125         /*
1126          * Time must follow most other metadata;
1127          * otherwise atime will get changed.
1128          */
1129         if (a->todo & TODO_TIMES) {
1130                 int r2 = set_times_from_entry(a);
1131                 if (r2 < ret) ret = r2;
1132         }
1133
1134         /*
1135          * ACLs must be restored after timestamps because there are
1136          * ACLs that prevent attribute changes (including time).
1137          */
1138         if (a->todo & TODO_ACLS) {
1139                 int r2 = set_acls(a, a->fh,
1140                                   archive_entry_pathname_w(a->entry),
1141                                   archive_entry_acl(a->entry));
1142                 if (r2 < ret) ret = r2;
1143         }
1144
1145         /* If there's an fd, we can close it now. */
1146         if (a->fh != INVALID_HANDLE_VALUE) {
1147                 CloseHandle(a->fh);
1148                 a->fh = INVALID_HANDLE_VALUE;
1149         }
1150         /* If there's an entry, we can release it now. */
1151         archive_entry_free(a->entry);
1152         a->entry = NULL;
1153         a->archive.state = ARCHIVE_STATE_HEADER;
1154         return (ret);
1155 }
1156
1157 int
1158 archive_write_disk_set_group_lookup(struct archive *_a,
1159     void *private_data,
1160     la_int64_t (*lookup_gid)(void *private, const char *gname, la_int64_t gid),
1161     void (*cleanup_gid)(void *private))
1162 {
1163         struct archive_write_disk *a = (struct archive_write_disk *)_a;
1164         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1165             ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup");
1166
1167         if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL)
1168                 (a->cleanup_gid)(a->lookup_gid_data);
1169
1170         a->lookup_gid = lookup_gid;
1171         a->cleanup_gid = cleanup_gid;
1172         a->lookup_gid_data = private_data;
1173         return (ARCHIVE_OK);
1174 }
1175
1176 int
1177 archive_write_disk_set_user_lookup(struct archive *_a,
1178     void *private_data,
1179     int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid),
1180     void (*cleanup_uid)(void *private))
1181 {
1182         struct archive_write_disk *a = (struct archive_write_disk *)_a;
1183         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1184             ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup");
1185
1186         if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL)
1187                 (a->cleanup_uid)(a->lookup_uid_data);
1188
1189         a->lookup_uid = lookup_uid;
1190         a->cleanup_uid = cleanup_uid;
1191         a->lookup_uid_data = private_data;
1192         return (ARCHIVE_OK);
1193 }
1194
1195 int64_t
1196 archive_write_disk_gid(struct archive *_a, const char *name, la_int64_t id)
1197 {
1198        struct archive_write_disk *a = (struct archive_write_disk *)_a;
1199        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1200            ARCHIVE_STATE_ANY, "archive_write_disk_gid");
1201        if (a->lookup_gid)
1202                return (a->lookup_gid)(a->lookup_gid_data, name, id);
1203        return (id);
1204 }
1205  
1206 int64_t
1207 archive_write_disk_uid(struct archive *_a, const char *name, la_int64_t id)
1208 {
1209        struct archive_write_disk *a = (struct archive_write_disk *)_a;
1210        archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1211            ARCHIVE_STATE_ANY, "archive_write_disk_uid");
1212        if (a->lookup_uid)
1213                return (a->lookup_uid)(a->lookup_uid_data, name, id);
1214        return (id);
1215 }
1216
1217 /*
1218  * Create a new archive_write_disk object and initialize it with global state.
1219  */
1220 struct archive *
1221 archive_write_disk_new(void)
1222 {
1223         struct archive_write_disk *a;
1224
1225         a = (struct archive_write_disk *)calloc(1, sizeof(*a));
1226         if (a == NULL)
1227                 return (NULL);
1228         a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC;
1229         /* We're ready to write a header immediately. */
1230         a->archive.state = ARCHIVE_STATE_HEADER;
1231         a->archive.vtable = archive_write_disk_vtable();
1232         a->start_time = time(NULL);
1233         /* Query and restore the umask. */
1234         umask(a->user_umask = umask(0));
1235         if (archive_wstring_ensure(&a->path_safe, 512) == NULL) {
1236                 free(a);
1237                 return (NULL);
1238         }
1239         return (&a->archive);
1240 }
1241
1242 static int
1243 disk_unlink(wchar_t *path)
1244 {
1245         wchar_t *fullname;
1246         int r;
1247
1248         r = _wunlink(path);
1249         if (r != 0 && GetLastError() == ERROR_INVALID_NAME) {
1250                 fullname = __la_win_permissive_name_w(path);
1251                 r = _wunlink(fullname);
1252                 free(fullname);
1253         }
1254         return (r);
1255 }
1256
1257 static int
1258 disk_rmdir(wchar_t *path)
1259 {
1260         wchar_t *fullname;
1261         int r;
1262
1263         r = _wrmdir(path);
1264         if (r != 0 && GetLastError() == ERROR_INVALID_NAME) {
1265                 fullname = __la_win_permissive_name_w(path);
1266                 r = _wrmdir(fullname);
1267                 free(fullname);
1268         }
1269         return (r);
1270 }
1271
1272 /*
1273  * The main restore function.
1274  */
1275 static int
1276 restore_entry(struct archive_write_disk *a)
1277 {
1278         int ret = ARCHIVE_OK, en;
1279
1280         if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) {
1281                 /*
1282                  * TODO: Fix this.  Apparently, there are platforms
1283                  * that still allow root to hose the entire filesystem
1284                  * by unlinking a dir.  The S_ISDIR() test above
1285                  * prevents us from using unlink() here if the new
1286                  * object is a dir, but that doesn't mean the old
1287                  * object isn't a dir.
1288                  */
1289                 if (disk_unlink(a->name) == 0) {
1290                         /* We removed it, reset cached stat. */
1291                         a->pst = NULL;
1292                 } else if (errno == ENOENT) {
1293                         /* File didn't exist, that's just as good. */
1294                 } else if (disk_rmdir(a->name) == 0) {
1295                         /* It was a dir, but now it's gone. */
1296                         a->pst = NULL;
1297                 } else {
1298                         /* We tried, but couldn't get rid of it. */
1299                         archive_set_error(&a->archive, errno,
1300                             "Could not unlink");
1301                         return(ARCHIVE_FAILED);
1302                 }
1303         }
1304
1305         /* Try creating it first; if this fails, we'll try to recover. */
1306         en = create_filesystem_object(a);
1307
1308         if ((en == ENOTDIR || en == ENOENT)
1309             && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) {
1310                 wchar_t *full;
1311                 /* If the parent dir doesn't exist, try creating it. */
1312                 create_parent_dir(a, a->name);
1313                 /* Now try to create the object again. */
1314                 full = __la_win_permissive_name_w(a->name);
1315                 if (full == NULL) {
1316                         en = EINVAL;
1317                 } else {
1318                         /* Remove multiple directories such as "a/../b../c" */
1319                         archive_wstrcpy(&(a->_name_data), full);
1320                         a->name = a->_name_data.s;
1321                         free(full);
1322                         en = create_filesystem_object(a);
1323                 }
1324         }
1325
1326         if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) {
1327                 archive_set_error(&a->archive, en,
1328                         "Hard-link target '%s' does not exist.",
1329                         archive_entry_hardlink(a->entry));
1330                 return (ARCHIVE_FAILED);
1331         }
1332
1333         if ((en == EISDIR || en == EEXIST)
1334             && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
1335                 /* If we're not overwriting, we're done. */
1336                 if (S_ISDIR(a->mode)) {
1337                         /* Don't overwrite any settings on existing directories. */
1338                         a->todo = 0;
1339                 }
1340                 archive_entry_unset_size(a->entry);
1341                 return (ARCHIVE_OK);
1342         }
1343
1344         /*
1345          * Some platforms return EISDIR if you call
1346          * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some
1347          * return EEXIST.  POSIX is ambiguous, requiring EISDIR
1348          * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT)
1349          * on an existing item.
1350          */
1351         if (en == EISDIR) {
1352                 /* A dir is in the way of a non-dir, rmdir it. */
1353                 if (disk_rmdir(a->name) != 0) {
1354                         archive_set_error(&a->archive, errno,
1355                             "Can't remove already-existing dir");
1356                         return (ARCHIVE_FAILED);
1357                 }
1358                 a->pst = NULL;
1359                 /* Try again. */
1360                 en = create_filesystem_object(a);
1361         } else if (en == EEXIST) {
1362                 mode_t st_mode;
1363                 /*
1364                  * We know something is in the way, but we don't know what;
1365                  * we need to find out before we go any further.
1366                  */
1367                 int r = 0;
1368                 /*
1369                  * The SECURE_SYMLINK logic has already removed a
1370                  * symlink to a dir if the client wants that.  So
1371                  * follow the symlink if we're creating a dir.
1372                  */
1373                 if (S_ISDIR(a->mode))
1374                         r = file_information(a, a->name, &a->st, &st_mode, 0);
1375                 /*
1376                  * If it's not a dir (or it's a broken symlink),
1377                  * then don't follow it.
1378                  */
1379                 if (r != 0 || !S_ISDIR(a->mode))
1380                         r = file_information(a, a->name, &a->st, &st_mode, 1);
1381                 if (r != 0) {
1382                         archive_set_error(&a->archive, errno,
1383                             "Can't stat existing object");
1384                         return (ARCHIVE_FAILED);
1385                 }
1386
1387                 /*
1388                  * NO_OVERWRITE_NEWER doesn't apply to directories.
1389                  */
1390                 if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
1391                     &&  !S_ISDIR(st_mode)) {
1392                         if (!older(&(a->st), a->entry)) {
1393                                 archive_entry_unset_size(a->entry);
1394                                 return (ARCHIVE_OK);
1395                         }
1396                 }
1397
1398                 /* If it's our archive, we're done. */
1399                 if (a->skip_file_set &&
1400                     bhfi_dev(&a->st) == a->skip_file_dev &&
1401                     bhfi_ino(&a->st) == a->skip_file_ino) {
1402                         archive_set_error(&a->archive, 0,
1403                             "Refusing to overwrite archive");
1404                         return (ARCHIVE_FAILED);
1405                 }
1406
1407                 if (!S_ISDIR(st_mode)) {
1408                         /* A non-dir is in the way, unlink it. */
1409                         if (disk_unlink(a->name) != 0) {
1410                                 archive_set_error(&a->archive, errno,
1411                                     "Can't unlink already-existing object");
1412                                 return (ARCHIVE_FAILED);
1413                         }
1414                         a->pst = NULL;
1415                         /* Try again. */
1416                         en = create_filesystem_object(a);
1417                 } else if (!S_ISDIR(a->mode)) {
1418                         /* A dir is in the way of a non-dir, rmdir it. */
1419                         if (disk_rmdir(a->name) != 0) {
1420                                 archive_set_error(&a->archive, errno,
1421                                     "Can't remove already-existing dir");
1422                                 return (ARCHIVE_FAILED);
1423                         }
1424                         /* Try again. */
1425                         en = create_filesystem_object(a);
1426                 } else {
1427                         /*
1428                          * There's a dir in the way of a dir.  Don't
1429                          * waste time with rmdir()/mkdir(), just fix
1430                          * up the permissions on the existing dir.
1431                          * Note that we don't change perms on existing
1432                          * dirs unless _EXTRACT_PERM is specified.
1433                          */
1434                         if ((a->mode != st_mode)
1435                             && (a->todo & TODO_MODE_FORCE))
1436                                 a->deferred |= (a->todo & TODO_MODE);
1437                         /* Ownership doesn't need deferred fixup. */
1438                         en = 0; /* Forget the EEXIST. */
1439                 }
1440         }
1441
1442         if (en) {
1443                 /* Everything failed; give up here. */
1444                 archive_set_error(&a->archive, en, "Can't create '%ls'",
1445                     a->name);
1446                 return (ARCHIVE_FAILED);
1447         }
1448
1449         a->pst = NULL; /* Cached stat data no longer valid. */
1450         return (ret);
1451 }
1452
1453 /*
1454  * Returns 0 if creation succeeds, or else returns errno value from
1455  * the failed system call.   Note:  This function should only ever perform
1456  * a single system call.
1457  */
1458 static int
1459 create_filesystem_object(struct archive_write_disk *a)
1460 {
1461         /* Create the entry. */
1462         const wchar_t *linkname;
1463         wchar_t *fullname;
1464         mode_t final_mode, mode;
1465         int r;
1466
1467         /* We identify hard/symlinks according to the link names. */
1468         /* Since link(2) and symlink(2) don't handle modes, we're done here. */
1469         linkname = archive_entry_hardlink_w(a->entry);
1470         if (linkname != NULL) {
1471                 wchar_t *linkfull, *namefull;
1472
1473                 linkfull = __la_win_permissive_name_w(linkname);
1474                 namefull = __la_win_permissive_name_w(a->name);
1475                 if (linkfull == NULL || namefull == NULL) {
1476                         errno = EINVAL;
1477                         r = -1;
1478                 } else {
1479                         r = la_CreateHardLinkW(namefull, linkfull);
1480                         if (r == 0) {
1481                                 la_dosmaperr(GetLastError());
1482                                 r = errno;
1483                         } else
1484                                 r = 0;
1485                 }
1486                 /*
1487                  * New cpio and pax formats allow hardlink entries
1488                  * to carry data, so we may have to open the file
1489                  * for hardlink entries.
1490                  *
1491                  * If the hardlink was successfully created and
1492                  * the archive doesn't have carry data for it,
1493                  * consider it to be non-authoritative for meta data.
1494                  * This is consistent with GNU tar and BSD pax.
1495                  * If the hardlink does carry data, let the last
1496                  * archive entry decide ownership.
1497                  */
1498                 if (r == 0 && a->filesize <= 0) {
1499                         a->todo = 0;
1500                         a->deferred = 0;
1501                 } else if (r == 0 && a->filesize > 0) {
1502                         a->fh = CreateFileW(namefull, GENERIC_WRITE, 0, NULL,
1503                             TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1504                         if (a->fh == INVALID_HANDLE_VALUE) {
1505                                 la_dosmaperr(GetLastError());
1506                                 r = errno;
1507                         }
1508                 }
1509                 free(linkfull);
1510                 free(namefull);
1511                 return (r);
1512         }
1513         linkname = archive_entry_symlink_w(a->entry);
1514         if (linkname != NULL) {
1515 #if HAVE_SYMLINK
1516                 return symlink(linkname, a->name) ? errno : 0;
1517 #else
1518                 return (EPERM);
1519 #endif
1520         }
1521
1522         /*
1523          * The remaining system calls all set permissions, so let's
1524          * try to take advantage of that to avoid an extra chmod()
1525          * call.  (Recall that umask is set to zero right now!)
1526          */
1527
1528         /* Mode we want for the final restored object (w/o file type bits). */
1529         final_mode = a->mode & 07777;
1530         /*
1531          * The mode that will actually be restored in this step.  Note
1532          * that SUID, SGID, etc, require additional work to ensure
1533          * security, so we never restore them at this point.
1534          */
1535         mode = final_mode & 0777 & ~a->user_umask;
1536
1537         switch (a->mode & AE_IFMT) {
1538         default:
1539                 /* POSIX requires that we fall through here. */
1540                 /* FALLTHROUGH */
1541         case AE_IFREG:
1542                 fullname = a->name;
1543                 /* O_WRONLY | O_CREAT | O_EXCL */
1544                 a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL,
1545                     CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
1546                 if (a->fh == INVALID_HANDLE_VALUE &&
1547                     GetLastError() == ERROR_INVALID_NAME &&
1548                     fullname == a->name) {
1549                         fullname = __la_win_permissive_name_w(a->name);
1550                         a->fh = CreateFileW(fullname, GENERIC_WRITE, 0, NULL,
1551                             CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
1552                 }
1553                 if (a->fh == INVALID_HANDLE_VALUE) {
1554                         if (GetLastError() == ERROR_ACCESS_DENIED) {
1555                                 DWORD attr;
1556                                 /* Simulate an errno of POSIX system. */
1557                                 attr = GetFileAttributesW(fullname);
1558                                 if (attr == (DWORD)-1)
1559                                         la_dosmaperr(GetLastError());
1560                                 else if (attr & FILE_ATTRIBUTE_DIRECTORY)
1561                                         errno = EISDIR;
1562                                 else
1563                                         errno = EACCES;
1564                         } else
1565                                 la_dosmaperr(GetLastError());
1566                         r = 1;
1567                 } else
1568                         r = 0;
1569                 if (fullname != a->name)
1570                         free(fullname);
1571                 break;
1572         case AE_IFCHR:
1573         case AE_IFBLK:
1574                 /* TODO: Find a better way to warn about our inability
1575                  * to restore a block device node. */
1576                 return (EINVAL);
1577         case AE_IFDIR:
1578                 mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE;
1579                 fullname = a->name;
1580                 r = CreateDirectoryW(fullname, NULL);
1581                 if (r == 0 && GetLastError() == ERROR_INVALID_NAME &&
1582                         fullname == a->name) {
1583                         fullname = __la_win_permissive_name_w(a->name);
1584                         r = CreateDirectoryW(fullname, NULL);
1585                 }
1586                 if (r != 0) {
1587                         r = 0;
1588                         /* Defer setting dir times. */
1589                         a->deferred |= (a->todo & TODO_TIMES);
1590                         a->todo &= ~TODO_TIMES;
1591                         /* Never use an immediate chmod(). */
1592                         /* We can't avoid the chmod() entirely if EXTRACT_PERM
1593                          * because of SysV SGID inheritance. */
1594                         if ((mode != final_mode)
1595                             || (a->flags & ARCHIVE_EXTRACT_PERM))
1596                                 a->deferred |= (a->todo & TODO_MODE);
1597                         a->todo &= ~TODO_MODE;
1598                 } else {
1599                         la_dosmaperr(GetLastError());
1600                         r = -1;
1601                 }
1602                 if (fullname != a->name)
1603                         free(fullname);
1604                 break;
1605         case AE_IFIFO:
1606                 /* TODO: Find a better way to warn about our inability
1607                  * to restore a fifo. */
1608                 return (EINVAL);
1609         }
1610
1611         /* All the system calls above set errno on failure. */
1612         if (r)
1613                 return (errno);
1614
1615         /* If we managed to set the final mode, we've avoided a chmod(). */
1616         if (mode == final_mode)
1617                 a->todo &= ~TODO_MODE;
1618         return (0);
1619 }
1620
1621 /*
1622  * Cleanup function for archive_extract.  Mostly, this involves processing
1623  * the fixup list, which is used to address a number of problems:
1624  *   * Dir permissions might prevent us from restoring a file in that
1625  *     dir, so we restore the dir with minimum 0700 permissions first,
1626  *     then correct the mode at the end.
1627  *   * Similarly, the act of restoring a file touches the directory
1628  *     and changes the timestamp on the dir, so we have to touch-up dir
1629  *     timestamps at the end as well.
1630  *   * Some file flags can interfere with the restore by, for example,
1631  *     preventing the creation of hardlinks to those files.
1632  *   * Mac OS extended metadata includes ACLs, so must be deferred on dirs.
1633  *
1634  * Note that tar/cpio do not require that archives be in a particular
1635  * order; there is no way to know when the last file has been restored
1636  * within a directory, so there's no way to optimize the memory usage
1637  * here by fixing up the directory any earlier than the
1638  * end-of-archive.
1639  *
1640  * XXX TODO: Directory ACLs should be restored here, for the same
1641  * reason we set directory perms here. XXX
1642  */
1643 static int
1644 _archive_write_disk_close(struct archive *_a)
1645 {
1646         struct archive_write_disk *a = (struct archive_write_disk *)_a;
1647         struct fixup_entry *next, *p;
1648         int ret;
1649
1650         archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
1651             ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA,
1652             "archive_write_disk_close");
1653         ret = _archive_write_disk_finish_entry(&a->archive);
1654
1655         /* Sort dir list so directories are fixed up in depth-first order. */
1656         p = sort_dir_list(a->fixup_list);
1657
1658         while (p != NULL) {
1659                 a->pst = NULL; /* Mark stat cache as out-of-date. */
1660                 if (p->fixup & TODO_TIMES) {
1661                         set_times(a, INVALID_HANDLE_VALUE, p->mode, p->name,
1662                             p->atime, p->atime_nanos,
1663                             p->birthtime, p->birthtime_nanos,
1664                             p->mtime, p->mtime_nanos,
1665                             p->ctime, p->ctime_nanos);
1666                 }
1667                 if (p->fixup & TODO_MODE_BASE)
1668                         la_chmod(p->name, p->mode);
1669                 if (p->fixup & TODO_ACLS)
1670                         set_acls(a, INVALID_HANDLE_VALUE, p->name, &p->acl);
1671                 next = p->next;
1672                 archive_acl_clear(&p->acl);
1673                 free(p->name);
1674                 free(p);
1675                 p = next;
1676         }
1677         a->fixup_list = NULL;
1678         return (ret);
1679 }
1680
1681 static int
1682 _archive_write_disk_free(struct archive *_a)
1683 {
1684         struct archive_write_disk *a;
1685         int ret;
1686         if (_a == NULL)
1687                 return (ARCHIVE_OK);
1688         archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC,
1689             ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free");
1690         a = (struct archive_write_disk *)_a;
1691         ret = _archive_write_disk_close(&a->archive);
1692         archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL);
1693         archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL);
1694         archive_entry_free(a->entry);
1695         archive_wstring_free(&a->_name_data);
1696         archive_string_free(&a->archive.error_string);
1697         archive_wstring_free(&a->path_safe);
1698         a->archive.magic = 0;
1699         __archive_clean(&a->archive);
1700         free(a);
1701         return (ret);
1702 }
1703
1704 /*
1705  * Simple O(n log n) merge sort to order the fixup list.  In
1706  * particular, we want to restore dir timestamps depth-first.
1707  */
1708 static struct fixup_entry *
1709 sort_dir_list(struct fixup_entry *p)
1710 {
1711         struct fixup_entry *a, *b, *t;
1712
1713         if (p == NULL)
1714                 return (NULL);
1715         /* A one-item list is already sorted. */
1716         if (p->next == NULL)
1717                 return (p);
1718
1719         /* Step 1: split the list. */
1720         t = p;
1721         a = p->next->next;
1722         while (a != NULL) {
1723                 /* Step a twice, t once. */
1724                 a = a->next;
1725                 if (a != NULL)
1726                         a = a->next;
1727                 t = t->next;
1728         }
1729         /* Now, t is at the mid-point, so break the list here. */
1730         b = t->next;
1731         t->next = NULL;
1732         a = p;
1733
1734         /* Step 2: Recursively sort the two sub-lists. */
1735         a = sort_dir_list(a);
1736         b = sort_dir_list(b);
1737
1738         /* Step 3: Merge the returned lists. */
1739         /* Pick the first element for the merged list. */
1740         if (wcscmp(a->name, b->name) > 0) {
1741                 t = p = a;
1742                 a = a->next;
1743         } else {
1744                 t = p = b;
1745                 b = b->next;
1746         }
1747
1748         /* Always put the later element on the list first. */
1749         while (a != NULL && b != NULL) {
1750                 if (wcscmp(a->name, b->name) > 0) {
1751                         t->next = a;
1752                         a = a->next;
1753                 } else {
1754                         t->next = b;
1755                         b = b->next;
1756                 }
1757                 t = t->next;
1758         }
1759
1760         /* Only one list is non-empty, so just splice it on. */
1761         if (a != NULL)
1762                 t->next = a;
1763         if (b != NULL)
1764                 t->next = b;
1765
1766         return (p);
1767 }
1768
1769 /*
1770  * Returns a new, initialized fixup entry.
1771  *
1772  * TODO: Reduce the memory requirements for this list by using a tree
1773  * structure rather than a simple list of names.
1774  */
1775 static struct fixup_entry *
1776 new_fixup(struct archive_write_disk *a, const wchar_t *pathname)
1777 {
1778         struct fixup_entry *fe;
1779
1780         fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry));
1781         if (fe == NULL)
1782                 return (NULL);
1783         fe->next = a->fixup_list;
1784         a->fixup_list = fe;
1785         fe->fixup = 0;
1786         fe->name = _wcsdup(pathname);
1787         return (fe);
1788 }
1789
1790 /*
1791  * Returns a fixup structure for the current entry.
1792  */
1793 static struct fixup_entry *
1794 current_fixup(struct archive_write_disk *a, const wchar_t *pathname)
1795 {
1796         if (a->current_fixup == NULL)
1797                 a->current_fixup = new_fixup(a, pathname);
1798         return (a->current_fixup);
1799 }
1800
1801 /* TODO: Make this work. */
1802 /*
1803  * TODO: The deep-directory support bypasses this; disable deep directory
1804  * support if we're doing symlink checks.
1805  */
1806 /*
1807  * TODO: Someday, integrate this with the deep dir support; they both
1808  * scan the path and both can be optimized by comparing against other
1809  * recent paths.
1810  */
1811 /* TODO: Extend this to support symlinks on Windows Vista and later. */
1812 static int
1813 check_symlinks(struct archive_write_disk *a)
1814 {
1815         wchar_t *pn, *p;
1816         wchar_t c;
1817         int r;
1818         BY_HANDLE_FILE_INFORMATION st;
1819         mode_t st_mode;
1820
1821         /*
1822          * Guard against symlink tricks.  Reject any archive entry whose
1823          * destination would be altered by a symlink.
1824          */
1825         /* Whatever we checked last time doesn't need to be re-checked. */
1826         pn = a->name;
1827         p = a->path_safe.s;
1828         while ((*pn != '\0') && (*p == *pn))
1829                 ++p, ++pn;
1830         c = pn[0];
1831         /* Keep going until we've checked the entire name. */
1832         while (pn[0] != '\0' && (pn[0] != '\\' || pn[1] != '\0')) {
1833                 /* Skip the next path element. */
1834                 while (*pn != '\0' && *pn != '\\')
1835                         ++pn;
1836                 c = pn[0];
1837                 pn[0] = '\0';
1838                 /* Check that we haven't hit a symlink. */
1839                 r = file_information(a, a->name, &st, &st_mode, 1);
1840                 if (r != 0) {
1841                         /* We've hit a dir that doesn't exist; stop now. */
1842                         if (errno == ENOENT)
1843                                 break;
1844                 } else if (S_ISLNK(st_mode)) {
1845                         if (c == '\0') {
1846                                 /*
1847                                  * Last element is symlink; remove it
1848                                  * so we can overwrite it with the
1849                                  * item being extracted.
1850                                  */
1851                                 if (disk_unlink(a->name)) {
1852                                         archive_set_error(&a->archive, errno,
1853                                             "Could not remove symlink %ls",
1854                                             a->name);
1855                                         pn[0] = c;
1856                                         return (ARCHIVE_FAILED);
1857                                 }
1858                                 a->pst = NULL;
1859                                 /*
1860                                  * Even if we did remove it, a warning
1861                                  * is in order.  The warning is silly,
1862                                  * though, if we're just replacing one
1863                                  * symlink with another symlink.
1864                                  */
1865                                 if (!S_ISLNK(a->mode)) {
1866                                         archive_set_error(&a->archive, 0,
1867                                             "Removing symlink %ls",
1868                                             a->name);
1869                                 }
1870                                 /* Symlink gone.  No more problem! */
1871                                 pn[0] = c;
1872                                 return (0);
1873                         } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) {
1874                                 /* User asked us to remove problems. */
1875                                 if (disk_unlink(a->name) != 0) {
1876                                         archive_set_error(&a->archive, 0,
1877                                             "Cannot remove intervening "
1878                                             "symlink %ls", a->name);
1879                                         pn[0] = c;
1880                                         return (ARCHIVE_FAILED);
1881                                 }
1882                                 a->pst = NULL;
1883                         } else {
1884                                 archive_set_error(&a->archive, 0,
1885                                     "Cannot extract through symlink %ls",
1886                                     a->name);
1887                                 pn[0] = c;
1888                                 return (ARCHIVE_FAILED);
1889                         }
1890                 }
1891         }
1892         pn[0] = c;
1893         /* We've checked and/or cleaned the whole path, so remember it. */
1894         archive_wstrcpy(&a->path_safe, a->name);
1895         return (ARCHIVE_OK);
1896 }
1897
1898 static int
1899 guidword(wchar_t *p, int n)
1900 {
1901         int i;
1902
1903         for (i = 0; i < n; i++) {
1904                 if ((*p >= L'0' && *p <= L'9') ||
1905                     (*p >= L'a' && *p <= L'f') ||
1906                     (*p >= L'A' && *p <= L'F'))
1907                         p++;
1908                 else
1909                         return (-1);
1910         }
1911         return (0);
1912 }
1913
1914 /*
1915  * Canonicalize the pathname.  In particular, this strips duplicate
1916  * '\' characters, '.' elements, and trailing '\'.  It also raises an
1917  * error for an empty path, a trailing '..' or (if _SECURE_NODOTDOT is
1918  * set) any '..' in the path.
1919  */
1920 static int
1921 cleanup_pathname(struct archive_write_disk *a)
1922 {
1923         wchar_t *dest, *src, *p, *top;
1924         wchar_t separator = L'\0';
1925
1926         p = a->name;
1927         if (*p == L'\0') {
1928                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1929                     "Invalid empty pathname");
1930                 return (ARCHIVE_FAILED);
1931         }
1932
1933         /* Replace '/' by '\' */
1934         for (; *p != L'\0'; p++) {
1935                 if (*p == L'/')
1936                         *p = L'\\';
1937         }
1938         p = a->name;
1939
1940         /* Skip leading "\\.\" or "\\?\" or "\\?\UNC\" or
1941          * "\\?\Volume{GUID}\"
1942          * (absolute path prefixes used by Windows API) */
1943         if (p[0] == L'\\' && p[1] == L'\\' &&
1944             (p[2] == L'.' || p[2] == L'?') && p[3] ==  L'\\')
1945         {
1946                 /* A path begin with "\\?\UNC\" */
1947                 if (p[2] == L'?' &&
1948                     (p[4] == L'U' || p[4] == L'u') &&
1949                     (p[5] == L'N' || p[5] == L'n') &&
1950                     (p[6] == L'C' || p[6] == L'c') &&
1951                     p[7] == L'\\')
1952                         p += 8;
1953                 /* A path begin with "\\?\Volume{GUID}\" */
1954                 else if (p[2] == L'?' &&
1955                     (p[4] == L'V' || p[4] == L'v') &&
1956                     (p[5] == L'O' || p[5] == L'o') &&
1957                     (p[6] == L'L' || p[6] == L'l') &&
1958                     (p[7] == L'U' || p[7] == L'u') &&
1959                     (p[8] == L'M' || p[8] == L'm') &&
1960                     (p[9] == L'E' || p[9] == L'e') &&
1961                     p[10] == L'{') {
1962                         if (guidword(p+11, 8) == 0 && p[19] == L'-' &&
1963                             guidword(p+20, 4) == 0 && p[24] == L'-' &&
1964                             guidword(p+25, 4) == 0 && p[29] == L'-' &&
1965                             guidword(p+30, 4) == 0 && p[34] == L'-' &&
1966                             guidword(p+35, 12) == 0 && p[47] == L'}' &&
1967                             p[48] == L'\\')
1968                                 p += 49;
1969                         else
1970                                 p += 4;
1971                 /* A path begin with "\\.\PhysicalDriveX" */
1972                 } else if (p[2] == L'.' &&
1973                     (p[4] == L'P' || p[4] == L'p') &&
1974                     (p[5] == L'H' || p[5] == L'h') &&
1975                     (p[6] == L'Y' || p[6] == L'y') &&
1976                     (p[7] == L'S' || p[7] == L's') &&
1977                     (p[8] == L'I' || p[8] == L'i') &&
1978                     (p[9] == L'C' || p[9] == L'c') &&
1979                     (p[9] == L'A' || p[9] == L'a') &&
1980                     (p[9] == L'L' || p[9] == L'l') &&
1981                     (p[9] == L'D' || p[9] == L'd') &&
1982                     (p[9] == L'R' || p[9] == L'r') &&
1983                     (p[9] == L'I' || p[9] == L'i') &&
1984                     (p[9] == L'V' || p[9] == L'v') &&
1985                     (p[9] == L'E' || p[9] == L'e') &&
1986                     (p[10] >= L'0' && p[10] <= L'9') &&
1987                     p[11] == L'\0') {
1988                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1989                             "Path is a physical drive name");
1990                         return (ARCHIVE_FAILED);
1991                 } else
1992                         p += 4;
1993         }
1994
1995         /* Skip leading drive letter from archives created
1996          * on Windows. */
1997         if (((p[0] >= L'a' && p[0] <= L'z') ||
1998              (p[0] >= L'A' && p[0] <= L'Z')) &&
1999                  p[1] == L':') {
2000                 if (p[2] == L'\0') {
2001                         archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2002                             "Path is a drive name");
2003                         return (ARCHIVE_FAILED);
2004                 }
2005                 if (p[2] == L'\\')
2006                         p += 2;
2007         }
2008
2009         top = dest = src = p;
2010         /* Rewrite the path name if its character is a unusable. */
2011         for (; *p != L'\0'; p++) {
2012                 if (*p == L':' || *p == L'*' || *p == L'?' || *p == L'"' ||
2013                     *p == L'<' || *p == L'>' || *p == L'|')
2014                         *p = L'_';
2015         }
2016         /* Skip leading '\'. */
2017         if (*src == L'\\')
2018                 separator = *src++;
2019
2020         /* Scan the pathname one element at a time. */
2021         for (;;) {
2022                 /* src points to first char after '\' */
2023                 if (src[0] == L'\0') {
2024                         break;
2025                 } else if (src[0] == L'\\') {
2026                         /* Found '\\'('//'), ignore second one. */
2027                         src++;
2028                         continue;
2029                 } else if (src[0] == L'.') {
2030                         if (src[1] == L'\0') {
2031                                 /* Ignore trailing '.' */
2032                                 break;
2033                         } else if (src[1] == L'\\') {
2034                                 /* Skip '.\'. */
2035                                 src += 2;
2036                                 continue;
2037                         } else if (src[1] == L'.') {
2038                                 if (src[2] == L'\\' || src[2] == L'\0') {
2039                                         /* Conditionally warn about '..' */
2040                                         if (a->flags &
2041                                             ARCHIVE_EXTRACT_SECURE_NODOTDOT) {
2042                                                 archive_set_error(&a->archive,
2043                                                     ARCHIVE_ERRNO_MISC,
2044                                                     "Path contains '..'");
2045                                                 return (ARCHIVE_FAILED);
2046                                         }
2047                                 }
2048                                 /*
2049                                  * Note: Under no circumstances do we
2050                                  * remove '..' elements.  In
2051                                  * particular, restoring
2052                                  * '\foo\..\bar\' should create the
2053                                  * 'foo' dir as a side-effect.
2054                                  */
2055                         }
2056                 }
2057
2058                 /* Copy current element, including leading '\'. */
2059                 if (separator)
2060                         *dest++ = L'\\';
2061                 while (*src != L'\0' && *src != L'\\') {
2062                         *dest++ = *src++;
2063                 }
2064
2065                 if (*src == L'\0')
2066                         break;
2067
2068                 /* Skip '\' separator. */
2069                 separator = *src++;
2070         }
2071         /*
2072          * We've just copied zero or more path elements, not including the
2073          * final '\'.
2074          */
2075         if (dest == top) {
2076                 /*
2077                  * Nothing got copied.  The path must have been something
2078                  * like '.' or '\' or './' or '/././././/./'.
2079                  */
2080                 if (separator)
2081                         *dest++ = L'\\';
2082                 else
2083                         *dest++ = L'.';
2084         }
2085         /* Terminate the result. */
2086         *dest = L'\0';
2087         return (ARCHIVE_OK);
2088 }
2089
2090 /*
2091  * Create the parent directory of the specified path, assuming path
2092  * is already in mutable storage.
2093  */
2094 static int
2095 create_parent_dir(struct archive_write_disk *a, wchar_t *path)
2096 {
2097         wchar_t *slash;
2098         int r;
2099
2100         /* Remove tail element to obtain parent name. */
2101         slash = wcsrchr(path, L'\\');
2102         if (slash == NULL)
2103                 return (ARCHIVE_OK);
2104         *slash = L'\0';
2105         r = create_dir(a, path);
2106         *slash = L'\\';
2107         return (r);
2108 }
2109
2110 /*
2111  * Create the specified dir, recursing to create parents as necessary.
2112  *
2113  * Returns ARCHIVE_OK if the path exists when we're done here.
2114  * Otherwise, returns ARCHIVE_FAILED.
2115  * Assumes path is in mutable storage; path is unchanged on exit.
2116  */
2117 static int
2118 create_dir(struct archive_write_disk *a, wchar_t *path)
2119 {
2120         BY_HANDLE_FILE_INFORMATION st;
2121         struct fixup_entry *le;
2122         wchar_t *slash, *base, *full;
2123         mode_t mode_final, mode, st_mode;
2124         int r;
2125
2126         /* Check for special names and just skip them. */
2127         slash = wcsrchr(path, L'\\');
2128         if (slash == NULL)
2129                 base = path;
2130         else
2131                 base = slash + 1;
2132
2133         if (base[0] == L'\0' ||
2134             (base[0] == L'.' && base[1] == L'\0') ||
2135             (base[0] == L'.' && base[1] == L'.' && base[2] == L'\0')) {
2136                 /* Don't bother trying to create null path, '.', or '..'. */
2137                 if (slash != NULL) {
2138                         *slash = L'\0';
2139                         r = create_dir(a, path);
2140                         *slash = L'\\';
2141                         return (r);
2142                 }
2143                 return (ARCHIVE_OK);
2144         }
2145
2146         /*
2147          * Yes, this should be stat() and not lstat().  Using lstat()
2148          * here loses the ability to extract through symlinks.  Also note
2149          * that this should not use the a->st cache.
2150          */
2151         if (file_information(a, path, &st, &st_mode, 0) == 0) {
2152                 if (S_ISDIR(st_mode))
2153                         return (ARCHIVE_OK);
2154                 if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
2155                         archive_set_error(&a->archive, EEXIST,
2156                             "Can't create directory '%ls'", path);
2157                         return (ARCHIVE_FAILED);
2158                 }
2159                 if (disk_unlink(path) != 0) {
2160                         archive_set_error(&a->archive, errno,
2161                             "Can't create directory '%ls': "
2162                             "Conflicting file cannot be removed",
2163                             path);
2164                         return (ARCHIVE_FAILED);
2165                 }
2166         } else if (errno != ENOENT && errno != ENOTDIR) {
2167                 /* Stat failed? */
2168                 archive_set_error(&a->archive, errno,
2169                     "Can't test directory '%ls'", path);
2170                 return (ARCHIVE_FAILED);
2171         } else if (slash != NULL) {
2172                 *slash = '\0';
2173                 r = create_dir(a, path);
2174                 *slash = '\\';
2175                 if (r != ARCHIVE_OK)
2176                         return (r);
2177         }
2178
2179         /*
2180          * Mode we want for the final restored directory.  Per POSIX,
2181          * implicitly-created dirs must be created obeying the umask.
2182          * There's no mention whether this is different for privileged
2183          * restores (which the rest of this code handles by pretending
2184          * umask=0).  I've chosen here to always obey the user's umask for
2185          * implicit dirs, even if _EXTRACT_PERM was specified.
2186          */
2187         mode_final = DEFAULT_DIR_MODE & ~a->user_umask;
2188         /* Mode we want on disk during the restore process. */
2189         mode = mode_final;
2190         mode |= MINIMUM_DIR_MODE;
2191         mode &= MAXIMUM_DIR_MODE;
2192         /*
2193          * Apply __la_win_permissive_name_w to path in order to
2194          * remove '../' path string.
2195          */
2196         full = __la_win_permissive_name_w(path);
2197         if (full == NULL)
2198                 errno = EINVAL;
2199         else if (CreateDirectoryW(full, NULL) != 0) {
2200                 if (mode != mode_final) {
2201                         le = new_fixup(a, path);
2202                         le->fixup |=TODO_MODE_BASE;
2203                         le->mode = mode_final;
2204                 }
2205                 free(full);
2206                 return (ARCHIVE_OK);
2207         } else {
2208                 la_dosmaperr(GetLastError());
2209         }
2210         free(full);
2211
2212         /*
2213          * Without the following check, a/b/../b/c/d fails at the
2214          * second visit to 'b', so 'd' can't be created.  Note that we
2215          * don't add it to the fixup list here, as it's already been
2216          * added.
2217          */
2218         if (file_information(a, path, &st, &st_mode, 0) == 0 &&
2219             S_ISDIR(st_mode))
2220                 return (ARCHIVE_OK);
2221
2222         archive_set_error(&a->archive, errno, "Failed to create dir '%ls'",
2223             path);
2224         return (ARCHIVE_FAILED);
2225 }
2226
2227 /*
2228  * Note: Although we can skip setting the user id if the desired user
2229  * id matches the current user, we cannot skip setting the group, as
2230  * many systems set the gid based on the containing directory.  So
2231  * we have to perform a chown syscall if we want to set the SGID
2232  * bit.  (The alternative is to stat() and then possibly chown(); it's
2233  * more efficient to skip the stat() and just always chown().)  Note
2234  * that a successful chown() here clears the TODO_SGID_CHECK bit, which
2235  * allows set_mode to skip the stat() check for the GID.
2236  */
2237 static int
2238 set_ownership(struct archive_write_disk *a)
2239 {
2240 /* unfortunately, on win32 there is no 'root' user with uid 0,
2241    so we just have to try the chown and see if it works */
2242
2243         /* If we know we can't change it, don't bother trying. */
2244         if (a->user_uid != 0  &&  a->user_uid != a->uid) {
2245                 archive_set_error(&a->archive, errno,
2246                     "Can't set UID=%jd", (intmax_t)a->uid);
2247                 return (ARCHIVE_WARN);
2248         }
2249
2250         archive_set_error(&a->archive, errno,
2251             "Can't set user=%jd/group=%jd for %ls",
2252             (intmax_t)a->uid, (intmax_t)a->gid, a->name);
2253         return (ARCHIVE_WARN);
2254 }
2255
2256 static int
2257 set_times(struct archive_write_disk *a,
2258     HANDLE h, int mode, const wchar_t *name,
2259     time_t atime, long atime_nanos,
2260     time_t birthtime, long birthtime_nanos,
2261     time_t mtime, long mtime_nanos,
2262     time_t ctime_sec, long ctime_nanos)
2263 {
2264 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
2265 #define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
2266          + (((nsec)/1000)*10))
2267
2268         HANDLE hw = 0;
2269         ULARGE_INTEGER wintm;
2270         FILETIME *pfbtime;
2271         FILETIME fatime, fbtime, fmtime;
2272
2273         (void)ctime_sec; /* UNUSED */
2274         (void)ctime_nanos; /* UNUSED */
2275
2276         if (h != INVALID_HANDLE_VALUE) {
2277                 hw = NULL;
2278         } else {
2279                 wchar_t *ws;
2280
2281                 if (S_ISLNK(mode))
2282                         return (ARCHIVE_OK);
2283                 ws = __la_win_permissive_name_w(name);
2284                 if (ws == NULL)
2285                         goto settimes_failed;
2286                 hw = CreateFileW(ws, FILE_WRITE_ATTRIBUTES,
2287                     0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2288                 free(ws);
2289                 if (hw == INVALID_HANDLE_VALUE)
2290                         goto settimes_failed;
2291                 h = hw;
2292         }
2293
2294         wintm.QuadPart = WINTIME(atime, atime_nanos);
2295         fatime.dwLowDateTime = wintm.LowPart;
2296         fatime.dwHighDateTime = wintm.HighPart;
2297         wintm.QuadPart = WINTIME(mtime, mtime_nanos);
2298         fmtime.dwLowDateTime = wintm.LowPart;
2299         fmtime.dwHighDateTime = wintm.HighPart;
2300         /*
2301          * SetFileTime() supports birthtime.
2302          */
2303         if (birthtime > 0 || birthtime_nanos > 0) {
2304                 wintm.QuadPart = WINTIME(birthtime, birthtime_nanos);
2305                 fbtime.dwLowDateTime = wintm.LowPart;
2306                 fbtime.dwHighDateTime = wintm.HighPart;
2307                 pfbtime = &fbtime;
2308         } else
2309                 pfbtime = NULL;
2310         if (SetFileTime(h, pfbtime, &fatime, &fmtime) == 0)
2311                 goto settimes_failed;
2312         CloseHandle(hw);
2313         return (ARCHIVE_OK);
2314
2315 settimes_failed:
2316         CloseHandle(hw);
2317         archive_set_error(&a->archive, EINVAL, "Can't restore time");
2318         return (ARCHIVE_WARN);
2319 }
2320
2321 static int
2322 set_times_from_entry(struct archive_write_disk *a)
2323 {
2324         time_t atime, birthtime, mtime, ctime_sec;
2325         long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
2326
2327         /* Suitable defaults. */
2328         atime = birthtime = mtime = ctime_sec = a->start_time;
2329         atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
2330
2331         /* If no time was provided, we're done. */
2332         if (!archive_entry_atime_is_set(a->entry)
2333             && !archive_entry_birthtime_is_set(a->entry)
2334             && !archive_entry_mtime_is_set(a->entry))
2335                 return (ARCHIVE_OK);
2336
2337         if (archive_entry_atime_is_set(a->entry)) {
2338                 atime = archive_entry_atime(a->entry);
2339                 atime_nsec = archive_entry_atime_nsec(a->entry);
2340         }
2341         if (archive_entry_birthtime_is_set(a->entry)) {
2342                 birthtime = archive_entry_birthtime(a->entry);
2343                 birthtime_nsec = archive_entry_birthtime_nsec(a->entry);
2344         }
2345         if (archive_entry_mtime_is_set(a->entry)) {
2346                 mtime = archive_entry_mtime(a->entry);
2347                 mtime_nsec = archive_entry_mtime_nsec(a->entry);
2348         }
2349         if (archive_entry_ctime_is_set(a->entry)) {
2350                 ctime_sec = archive_entry_ctime(a->entry);
2351                 ctime_nsec = archive_entry_ctime_nsec(a->entry);
2352         }
2353
2354         return set_times(a, a->fh, a->mode, a->name,
2355                          atime, atime_nsec,
2356                          birthtime, birthtime_nsec,
2357                          mtime, mtime_nsec,
2358                          ctime_sec, ctime_nsec);
2359 }
2360
2361 static int
2362 set_mode(struct archive_write_disk *a, int mode)
2363 {
2364         int r = ARCHIVE_OK;
2365         mode &= 07777; /* Strip off file type bits. */
2366
2367         if (a->todo & TODO_SGID_CHECK) {
2368                 /*
2369                  * If we don't know the GID is right, we must stat()
2370                  * to verify it.  We can't just check the GID of this
2371                  * process, since systems sometimes set GID from
2372                  * the enclosing dir or based on ACLs.
2373                  */
2374                 if ((r = lazy_stat(a)) != ARCHIVE_OK)
2375                         return (r);
2376                 if (0 != a->gid) {
2377                         mode &= ~ S_ISGID;
2378                 }
2379                 /* While we're here, double-check the UID. */
2380                 if (0 != a->uid
2381                     && (a->todo & TODO_SUID)) {
2382                         mode &= ~ S_ISUID;
2383                 }
2384                 a->todo &= ~TODO_SGID_CHECK;
2385                 a->todo &= ~TODO_SUID_CHECK;
2386         } else if (a->todo & TODO_SUID_CHECK) {
2387                 /*
2388                  * If we don't know the UID is right, we can just check
2389                  * the user, since all systems set the file UID from
2390                  * the process UID.
2391                  */
2392                 if (a->user_uid != a->uid) {
2393                         mode &= ~ S_ISUID;
2394                 }
2395                 a->todo &= ~TODO_SUID_CHECK;
2396         }
2397
2398         if (S_ISLNK(a->mode)) {
2399 #ifdef HAVE_LCHMOD
2400                 /*
2401                  * If this is a symlink, use lchmod().  If the
2402                  * platform doesn't support lchmod(), just skip it.  A
2403                  * platform that doesn't provide a way to set
2404                  * permissions on symlinks probably ignores
2405                  * permissions on symlinks, so a failure here has no
2406                  * impact.
2407                  */
2408                 if (lchmod(a->name, mode) != 0) {
2409                         archive_set_error(&a->archive, errno,
2410                             "Can't set permissions to 0%o", (int)mode);
2411                         r = ARCHIVE_WARN;
2412                 }
2413 #endif
2414         } else if (!S_ISDIR(a->mode)) {
2415                 /*
2416                  * If it's not a symlink and not a dir, then use
2417                  * fchmod() or chmod(), depending on whether we have
2418                  * an fd.  Dirs get their perms set during the
2419                  * post-extract fixup, which is handled elsewhere.
2420                  */
2421 #ifdef HAVE_FCHMOD
2422                 if (a->fd >= 0) {
2423                         if (fchmod(a->fd, mode) != 0) {
2424                                 archive_set_error(&a->archive, errno,
2425                                     "Can't set permissions to 0%o", (int)mode);
2426                                 r = ARCHIVE_WARN;
2427                         }
2428                 } else
2429 #endif
2430                         /* If this platform lacks fchmod(), then
2431                          * we'll just use chmod(). */
2432                         if (la_chmod(a->name, mode) != 0) {
2433                                 archive_set_error(&a->archive, errno,
2434                                     "Can't set permissions to 0%o", (int)mode);
2435                                 r = ARCHIVE_WARN;
2436                         }
2437         }
2438         return (r);
2439 }
2440
2441 static int
2442 set_fflags(struct archive_write_disk *a)
2443 {
2444         (void)a; /* UNUSED */
2445         return (ARCHIVE_OK);
2446 }
2447
2448 /* Default empty function body to satisfy mainline code. */
2449 static int
2450 set_acls(struct archive_write_disk *a, HANDLE h, const wchar_t *name,
2451          struct archive_acl *acl)
2452 {
2453         (void)a; /* UNUSED */
2454         (void)h; /* UNUSED */
2455         (void)name; /* UNUSED */
2456         (void)acl; /* UNUSED */
2457         return (ARCHIVE_OK);
2458 }
2459
2460 /*
2461  * Restore extended attributes - stub implementation for unsupported systems
2462  */
2463 static int
2464 set_xattrs(struct archive_write_disk *a)
2465 {
2466         static int warning_done = 0;
2467
2468         /* If there aren't any extended attributes, then it's okay not
2469          * to extract them, otherwise, issue a single warning. */
2470         if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) {
2471                 warning_done = 1;
2472                 archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2473                     "Cannot restore extended attributes on this system");
2474                 return (ARCHIVE_WARN);
2475         }
2476         /* Warning was already emitted; suppress further warnings. */
2477         return (ARCHIVE_OK);
2478 }
2479
2480 static void
2481 fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
2482 {
2483         ULARGE_INTEGER utc;
2484
2485         utc.HighPart = filetime->dwHighDateTime;
2486         utc.LowPart  = filetime->dwLowDateTime;
2487         if (utc.QuadPart >= EPOC_TIME) {
2488                 utc.QuadPart -= EPOC_TIME;
2489                 /* milli seconds base */
2490                 *t = (time_t)(utc.QuadPart / 10000000);
2491                 /* nano seconds base */
2492                 *ns = (long)(utc.QuadPart % 10000000) * 100;
2493         } else {
2494                 *t = 0;
2495                 *ns = 0;
2496         }
2497 }
2498 /*
2499  * Test if file on disk is older than entry.
2500  */
2501 static int
2502 older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry)
2503 {
2504         time_t sec;
2505         long nsec;
2506
2507         fileTimeToUtc(&st->ftLastWriteTime, &sec, &nsec);
2508         /* First, test the seconds and return if we have a definite answer. */
2509         /* Definitely older. */
2510         if (sec < archive_entry_mtime(entry))
2511                 return (1);
2512         /* Definitely younger. */
2513         if (sec > archive_entry_mtime(entry))
2514                 return (0);
2515         if (nsec < archive_entry_mtime_nsec(entry))
2516                 return (1);
2517         /* Same age or newer, so not older. */
2518         return (0);
2519 }
2520
2521 #endif /* _WIN32 && !__CYGWIN__ */
2522