summaryrefslogtreecommitdiff
path: root/libarchive/archive_write_disk_windows.c
diff options
context:
space:
mode:
authorMartin Matuska <martin@matuska.org>2019-04-15 01:50:29 +0200
committerMartin Matuska <martin@matuska.org>2019-04-15 23:36:06 +0200
commitb0ed582e68fe6e474d321934d29b0f229c0feb9f (patch)
tree04d67b7fa3d5631736f850a1aead1dbe88e4f30a /libarchive/archive_write_disk_windows.c
parent19bd077987ff26a4cb108edde5eaf970837aa1f0 (diff)
downloadlibarchive-b0ed582e68fe6e474d321934d29b0f229c0feb9f.tar.gz
Windows symlinks: new functions and extended tar header
New functions: archive_entry_symlink_type() archive_entry_set_symlink_type() Suppoted value constants: AE_SYMLINK_TYPE_UNDEFINED AE_SYMLINK_TYPE_FILE AE_SYMLINK_TYPE_DIRECTORY New extended tar header: LIBARCHIVE.symlinktype The function archive_entry_symlink_type() retrieves and the function archive_entry_set_symlink_type() sets the symbolic link type of an archive entry. The information about the symbolic link type is required to properly restore symbolic links on Microsoft Windows. If the symlink type is set to AE_SYMLINK_TYPE_FILE or AE_SYMLINK_TYPE_DIRECTORY and a tar archive is written, an extended tar header LIBARCHIVE.symlinktype is stored with the value "file" or "dir". When reading symbolic links on Windows, the link type is automatically stored in the archive_entry structure. On unix systems, the symlink type has no effect when reading or writing symbolic links.
Diffstat (limited to 'libarchive/archive_write_disk_windows.c')
-rw-r--r--libarchive/archive_write_disk_windows.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c
index b29389c1..e3e65ba1 100644
--- a/libarchive/archive_write_disk_windows.c
+++ b/libarchive/archive_write_disk_windows.c
@@ -587,13 +587,14 @@ la_CreateHardLinkW(wchar_t *linkname, wchar_t *target)
}
/*
- * Create symolic link
+ * Create file or directory symolic link
*
- * Always creates a file symbolic link.
- * Directory symbolic links are currently not implemented.
+ * If linktype is AE_SYMLINK_TYPE_UNDEFINED (or unknown), guess linktype from
+ * the link target
*/
static int
-la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target) {
+la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target,
+ int linktype) {
static BOOLEAN (WINAPI *f)(LPCWSTR, LPCWSTR, DWORD);
static int set;
wchar_t *ttarget, *p;
@@ -636,14 +637,16 @@ la_CreateSymbolicLinkW(const wchar_t *linkname, const wchar_t *target) {
*p = L'\0';
/*
+ * In case of undefined symlink type we guess it from the target.
* If the target equals ".", "..", ends with a backslash or a
- * backslash followed by "." or ".." it always points to a directory.
- * In this case we can safely set the directory flag.
- * All other symlinks are created as file symlinks.
+ * backslash followed by "." or ".." we assume it is a directory
+ * symlink. In all other cases we assume a file symlink.
*/
- if (*(p - 1) == L'\\' || (*(p - 1) == L'.' && (
+ if (linktype != AE_SYMLINK_TYPE_FILE && (
+ linktype == AE_SYMLINK_TYPE_DIRECTORY ||
+ *(p - 1) == L'\\' || (*(p - 1) == L'.' && (
len == 1 || *(p - 2) == L'\\' || ( *(p - 2) == L'.' && (
- len == 2 || *(p - 3) == L'\\'))))) {
+ len == 2 || *(p - 3) == L'\\')))))) {
#if defined(SYMBOLIC_LINK_FLAG_DIRECTORY)
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
#else
@@ -1638,7 +1641,8 @@ create_filesystem_object(struct archive_write_disk *a)
return symlink(linkname, a->name) ? errno : 0;
#else
errno = 0;
- r = la_CreateSymbolicLinkW((const wchar_t *)a->name, linkname);
+ r = la_CreateSymbolicLinkW((const wchar_t *)a->name, linkname,
+ archive_entry_symlink_type(a->entry));
if (r == 0) {
if (errno == 0)
la_dosmaperr(GetLastError());