summaryrefslogtreecommitdiff
path: root/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c')
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c175
1 files changed, 63 insertions, 112 deletions
diff --git a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
index 2dc2d92e8..0f0780a8e 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_windows.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2010 Tim Kientzle
- * Copyright (c) 2011 Michihiro NAKAJIMA
+ * Copyright (c) 2011-2012 Michihiro NAKAJIMA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,9 +33,6 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
#ifdef HAVE_SYS_UTIME_H
#include <sys/utime.h>
#endif
@@ -48,13 +45,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
-#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
#include <winioctl.h>
/* TODO: Support Mac OS 'quarantine' feature. This is really just a
@@ -89,7 +82,7 @@ static BOOL SetFilePointerEx_perso(HANDLE hFile,
if(lpNewFilePointer) {
lpNewFilePointer->QuadPart = li.QuadPart;
}
- return li.LowPart != -1 || GetLastError() == NO_ERROR;
+ return li.LowPart != (DWORD)-1 || GetLastError() == NO_ERROR;
}
struct fixup_entry {
@@ -144,8 +137,8 @@ struct archive_write_disk {
struct fixup_entry *current_fixup;
int64_t user_uid;
int skip_file_set;
- dev_t skip_file_dev;
- ino_t skip_file_ino;
+ int64_t skip_file_dev;
+ int64_t skip_file_ino;
time_t start_time;
int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid);
@@ -214,26 +207,24 @@ struct archive_write_disk {
static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(struct archive_write_disk *);
-static struct fixup_entry *current_fixup(struct archive_write_disk *, const wchar_t *pathname);
-#if defined(HAVE_FCHDIR) && defined(PATH_MAX)
-static void edit_deep_directories(struct archive_write_disk *ad);
-#endif
+static struct fixup_entry *current_fixup(struct archive_write_disk *,
+ const wchar_t *pathname);
static int cleanup_pathname(struct archive_write_disk *);
static int create_dir(struct archive_write_disk *, wchar_t *);
static int create_parent_dir(struct archive_write_disk *, wchar_t *);
+static int la_chmod(const wchar_t *, mode_t);
static int older(BY_HANDLE_FILE_INFORMATION *, struct archive_entry *);
+static int permissive_name_w(struct archive_write_disk *);
static int restore_entry(struct archive_write_disk *);
-#ifdef HAVE_POSIX_ACL
-static int set_acl(struct archive_write_disk *, int fd, const char *, struct archive_acl *,
- acl_type_t, int archive_entry_acl_type, const char *tn);
-#endif
-static int set_acls(struct archive_write_disk *, HANDLE h, const wchar_t *, struct archive_acl *);
+static int set_acls(struct archive_write_disk *, HANDLE h,
+ const wchar_t *, struct archive_acl *);
static int set_xattrs(struct archive_write_disk *);
static int set_fflags(struct archive_write_disk *);
static int set_ownership(struct archive_write_disk *);
static int set_mode(struct archive_write_disk *, int mode);
-static int set_times(struct archive_write_disk *, HANDLE, int, const wchar_t *,
- time_t, long, time_t, long, time_t, long, time_t, long);
+static int set_times(struct archive_write_disk *, HANDLE, int,
+ const wchar_t *, time_t, long, time_t, long, time_t,
+ long, time_t, long);
static int set_times_from_entry(struct archive_write_disk *);
static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
static ssize_t write_data_block(struct archive_write_disk *,
@@ -243,11 +234,14 @@ static struct archive_vtable *archive_write_disk_vtable(void);
static int _archive_write_disk_close(struct archive *);
static int _archive_write_disk_free(struct archive *);
-static int _archive_write_disk_header(struct archive *, struct archive_entry *);
+static int _archive_write_disk_header(struct archive *,
+ struct archive_entry *);
static int64_t _archive_write_disk_filter_bytes(struct archive *, int);
static int _archive_write_disk_finish_entry(struct archive *);
-static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t);
-static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t);
+static ssize_t _archive_write_disk_data(struct archive *, const void *,
+ size_t);
+static ssize_t _archive_write_disk_data_block(struct archive *, const void *,
+ size_t, int64_t);
#define bhfi_dev(bhfi) ((bhfi)->dwVolumeSerialNumber)
/* Treat FileIndex as i-node. We should remove a sequence number
@@ -361,7 +355,7 @@ file_information(struct archive_write_disk *a, wchar_t *path,
* So we have to make the full-pathname in another way, which does not
* break "../" path string.
*/
-int
+static int
permissive_name_w(struct archive_write_disk *a)
{
wchar_t *wn, *wnp;
@@ -424,10 +418,12 @@ permissive_name_w(struct archive_write_disk *a)
wn = _wcsdup(wnp);
if (wn == NULL)
return (-1);
- archive_wstring_ensure(&(a->_name_data), 8 + wcslen(wn) + 1);
+ archive_wstring_ensure(&(a->_name_data),
+ 8 + wcslen(wn) + 1);
a->name = a->_name_data.s;
/* Prepend "\\?\UNC\" */
- archive_wstrncpy(&(a->_name_data), L"\\\\?\\UNC\\", 8);
+ archive_wstrncpy(&(a->_name_data),
+ L"\\\\?\\UNC\\", 8);
archive_wstrcat(&(a->_name_data), wn+2);
free(wn);
return (0);
@@ -457,7 +453,8 @@ permissive_name_w(struct archive_write_disk *a)
wn = _wcsdup(wnp);
if (wn == NULL)
return (-1);
- archive_wstring_ensure(&(a->_name_data), 4 + 2 + wcslen(wn) + 1);
+ archive_wstring_ensure(&(a->_name_data),
+ 4 + 2 + wcslen(wn) + 1);
a->name = a->_name_data.s;
/* Prepend "\\?\" and drive name. */
archive_wstrncpy(&(a->_name_data), L"\\\\?\\", 4);
@@ -484,7 +481,7 @@ permissive_name_w(struct archive_write_disk *a)
return (0);
}
-int
+static int
la_chmod(const wchar_t *path, mode_t mode)
{
DWORD attr;
@@ -610,7 +607,7 @@ lazy_stat(struct archive_write_disk *a)
/*
* XXX At this point, symlinks should not be hit, otherwise
- * XXX a race occured. Do we want to check explicitly for that?
+ * XXX a race occurred. Do we want to check explicitly for that?
*/
if (file_information(a, a->name, &a->st, NULL, 1) == 0) {
a->pst = &a->st;
@@ -917,6 +914,7 @@ archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
static ssize_t
write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
{
+ OVERLAPPED ol;
uint64_t start_size = size;
DWORD bytes_written = 0;
ssize_t block_size = 0, bytes_to_write;
@@ -968,26 +966,13 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
* truncate it to the block boundary. */
bytes_to_write = size;
if (a->offset + bytes_to_write > block_end)
- bytes_to_write = block_end - a->offset;
+ bytes_to_write = (DWORD)(block_end - a->offset);
}
- /* Seek if necessary to the specified offset. */
- if (a->offset != a->fd_offset) {
- LARGE_INTEGER distance;
- distance.QuadPart = a->offset;
- if (SetFilePointerEx_perso(a->fh, distance, NULL, FILE_BEGIN) == 0) {
- DWORD lasterr = GetLastError();
- if (lasterr == ERROR_ACCESS_DENIED)
- errno = EBADF;
- else
- la_dosmaperr(lasterr);
- archive_set_error(&a->archive, errno,
- "Seek failed");
- return (ARCHIVE_FATAL);
- }
- a->fd_offset = a->offset;
- }
+ memset(&ol, 0, sizeof(ol));
+ ol.Offset = (DWORD)(a->offset & 0xFFFFFFFF);
+ ol.OffsetHigh = (DWORD)(a->offset >> 32);
if (!WriteFile(a->fh, buff, (uint32_t)bytes_to_write,
- &bytes_written, NULL)) {
+ &bytes_written, &ol)) {
DWORD lasterr;
lasterr = GetLastError();
@@ -1004,7 +989,7 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
a->offset += bytes_written;
a->fd_offset = a->offset;
}
- return (start_size - size);
+ return ((ssize_t)(start_size - size));
}
static ssize_t
@@ -1062,48 +1047,11 @@ _archive_write_disk_finish_entry(struct archive *_a)
/* Last write ended at exactly the filesize; we're done. */
/* Hopefully, this is the common case. */
} else {
- if (la_ftruncate(a->fh, a->filesize) == -1 &&
- a->filesize == 0) {
+ if (la_ftruncate(a->fh, a->filesize) == -1) {
archive_set_error(&a->archive, errno,
"File size could not be restored");
return (ARCHIVE_FAILED);
}
- /*
- * Not all platforms implement the XSI option to
- * extend files via ftruncate. Stat() the file again
- * to see what happened.
- */
- a->pst = NULL;
- if ((ret = lazy_stat(a)) != ARCHIVE_OK)
- return (ret);
- /* We can use lseek()/write() to extend the file if
- * ftruncate didn't work or isn't available. */
- if (bhfi_size(&(a->st)) < a->filesize) {
- const char nul = '\0';
- LARGE_INTEGER distance;
- distance.QuadPart = a->filesize - 1;
- if (!SetFilePointerEx_perso(a->fh, distance, NULL, FILE_BEGIN)) {
- DWORD lasterr = GetLastError();
- if (lasterr == ERROR_ACCESS_DENIED)
- errno = EBADF;
- else
- la_dosmaperr(lasterr);
- archive_set_error(&a->archive, errno,
- "Seek failed");
- return (ARCHIVE_FATAL);
- }
- if (!WriteFile(a->fh, &nul, 1, NULL, NULL)) {
- DWORD lasterr = GetLastError();
- if (lasterr == ERROR_ACCESS_DENIED)
- errno = EBADF;
- else
- la_dosmaperr(lasterr);
- archive_set_error(&a->archive, errno,
- "Write to restore size failed");
- return (ARCHIVE_FATAL);
- }
- a->pst = NULL;
- }
}
/* Restore metadata. */
@@ -1430,7 +1378,8 @@ restore_entry(struct archive_write_disk *a)
if (a->skip_file_set &&
bhfi_dev(&a->st) == a->skip_file_dev &&
bhfi_ino(&a->st) == a->skip_file_ino) {
- archive_set_error(&a->archive, 0, "Refusing to overwrite archive");
+ archive_set_error(&a->archive, 0,
+ "Refusing to overwrite archive");
return (ARCHIVE_FAILED);
}
@@ -1471,7 +1420,7 @@ restore_entry(struct archive_write_disk *a)
if (en) {
/* Everything failed; give up here. */
- archive_set_error(&a->archive, en, "Can't create '%s'",
+ archive_set_error(&a->archive, en, "Can't create '%ls'",
a->name);
return (ARCHIVE_FAILED);
}
@@ -1520,7 +1469,7 @@ create_filesystem_object(struct archive_write_disk *a)
*
* If the hardlink was successfully created and
* the archive doesn't have carry data for it,
- * consider it to be non-authoritive for meta data.
+ * consider it to be non-authoritative for meta data.
* This is consistent with GNU tar and BSD pax.
* If the hardlink does carry data, let the last
* archive entry decide ownership.
@@ -1562,7 +1511,7 @@ create_filesystem_object(struct archive_write_disk *a)
* that SUID, SGID, etc, require additional work to ensure
* security, so we never restore them at this point.
*/
- mode = final_mode & 0777 & a->user_umask;
+ mode = final_mode & 0777 & ~a->user_umask;
switch (a->mode & AE_IFMT) {
default:
@@ -1881,7 +1830,7 @@ check_symlinks(struct archive_write_disk *a)
*/
if (disk_unlink(a->name)) {
archive_set_error(&a->archive, errno,
- "Could not remove symlink %s",
+ "Could not remove symlink %ls",
a->name);
pn[0] = c;
return (ARCHIVE_FAILED);
@@ -1895,7 +1844,7 @@ check_symlinks(struct archive_write_disk *a)
*/
if (!S_ISLNK(a->mode)) {
archive_set_error(&a->archive, 0,
- "Removing symlink %s",
+ "Removing symlink %ls",
a->name);
}
/* Symlink gone. No more problem! */
@@ -1905,15 +1854,15 @@ check_symlinks(struct archive_write_disk *a)
/* User asked us to remove problems. */
if (disk_unlink(a->name) != 0) {
archive_set_error(&a->archive, 0,
- "Cannot remove intervening symlink %s",
- a->name);
+ "Cannot remove intervening "
+ "symlink %ls", a->name);
pn[0] = c;
return (ARCHIVE_FAILED);
}
a->pst = NULL;
} else {
archive_set_error(&a->archive, 0,
- "Cannot extract through symlink %s",
+ "Cannot extract through symlink %ls",
a->name);
pn[0] = c;
return (ARCHIVE_FAILED);
@@ -2184,19 +2133,20 @@ create_dir(struct archive_write_disk *a, wchar_t *path)
return (ARCHIVE_OK);
if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
archive_set_error(&a->archive, EEXIST,
- "Can't create directory '%s'", path);
+ "Can't create directory '%ls'", path);
return (ARCHIVE_FAILED);
}
if (disk_unlink(path) != 0) {
archive_set_error(&a->archive, errno,
- "Can't create directory '%s': "
+ "Can't create directory '%ls': "
"Conflicting file cannot be removed",
path);
return (ARCHIVE_FAILED);
}
} else if (errno != ENOENT && errno != ENOTDIR) {
/* Stat failed? */
- archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
+ archive_set_error(&a->archive, errno,
+ "Can't test directory '%ls'", path);
return (ARCHIVE_FAILED);
} else if (slash != NULL) {
*slash = '\0';
@@ -2245,10 +2195,11 @@ create_dir(struct archive_write_disk *a, wchar_t *path)
* don't add it to the fixup list here, as it's already been
* added.
*/
- if (file_information(a, path, &st, &st_mode, 0) == 0 && S_ISDIR(st_mode))
+ if (file_information(a, path, &st, &st_mode, 0) == 0 &&
+ S_ISDIR(st_mode))
return (ARCHIVE_OK);
- archive_set_error(&a->archive, errno, "Failed to create dir '%s'",
+ archive_set_error(&a->archive, errno, "Failed to create dir '%ls'",
path);
return (ARCHIVE_FAILED);
}
@@ -2277,7 +2228,7 @@ set_ownership(struct archive_write_disk *a)
}
archive_set_error(&a->archive, errno,
- "Can't set user=%jd/group=%jd for %s",
+ "Can't set user=%jd/group=%jd for %ls",
(intmax_t)a->uid, (intmax_t)a->gid, a->name);
return (ARCHIVE_WARN);
}
@@ -2288,7 +2239,7 @@ set_times(struct archive_write_disk *a,
time_t atime, long atime_nanos,
time_t birthtime, long birthtime_nanos,
time_t mtime, long mtime_nanos,
- time_t ctime, long ctime_nanos)
+ time_t ctime_sec, long ctime_nanos)
{
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
#define WINTIME(sec, nsec) ((Int32x32To64(sec, 10000000) + EPOC_TIME)\
@@ -2299,7 +2250,7 @@ set_times(struct archive_write_disk *a,
FILETIME *pfbtime;
FILETIME fatime, fbtime, fmtime;
- (void)ctime; /* UNUSED */
+ (void)ctime_sec; /* UNUSED */
(void)ctime_nanos; /* UNUSED */
if (h != INVALID_HANDLE_VALUE) {
@@ -2350,11 +2301,11 @@ settimes_failed:
static int
set_times_from_entry(struct archive_write_disk *a)
{
- time_t atime, birthtime, mtime, ctime;
+ time_t atime, birthtime, mtime, ctime_sec;
long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec;
/* Suitable defaults. */
- atime = birthtime = mtime = ctime = a->start_time;
+ atime = birthtime = mtime = ctime_sec = a->start_time;
atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0;
/* If no time was provided, we're done. */
@@ -2376,7 +2327,7 @@ set_times_from_entry(struct archive_write_disk *a)
mtime_nsec = archive_entry_mtime_nsec(a->entry);
}
if (archive_entry_ctime_is_set(a->entry)) {
- ctime = archive_entry_ctime(a->entry);
+ ctime_sec = archive_entry_ctime(a->entry);
ctime_nsec = archive_entry_ctime_nsec(a->entry);
}
@@ -2384,7 +2335,7 @@ set_times_from_entry(struct archive_write_disk *a)
atime, atime_nsec,
birthtime, birthtime_nsec,
mtime, mtime_nsec,
- ctime, ctime_nsec);
+ ctime_sec, ctime_nsec);
}
static int
@@ -2507,7 +2458,7 @@ set_xattrs(struct archive_write_disk *a)
}
static void
-fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
+fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
{
ULARGE_INTEGER utc;
@@ -2516,11 +2467,11 @@ fileTimeToUtc(const FILETIME *filetime, time_t *time, long *ns)
if (utc.QuadPart >= EPOC_TIME) {
utc.QuadPart -= EPOC_TIME;
/* milli seconds base */
- *time = (time_t)(utc.QuadPart / 10000000);
+ *t = (time_t)(utc.QuadPart / 10000000);
/* nano seconds base */
*ns = (long)(utc.QuadPart % 10000000) * 100;
} else {
- *time = 0;
+ *t = 0;
*ns = 0;
}
}