tar: mark bsdtar as long-path aware on Windows
bsdtar's -C/--directory option calls SetCurrentDirectoryW(), which is
limited to MAX_PATH (260) characters unless the process opts in to long
path support via an application manifest declaring longPathAware.
Extracting into (or changing into) a directory whose path exceeds 260
characters fails with "could not chdir".
Embed a longPathAware application manifest into bsdtar.exe so these
operations work for long destination paths. Both Windows build systems
(CMake and the autotools/Makefile.am build) embed it, using different
mechanisms per toolchain:
- MinGW/Clang (GNU ld) do not generate an application manifest, so it
is compiled from a resource script (bsdtar.rc) via windres. This
manifest replaces the toolchain default, so it also declares the
asInvoker execution level explicitly.
- MSVC's linker already embeds a manifest (resource id 1); a duplicate
RT_MANIFEST resource fails to link (CVT1100). Instead the manifest is
merged into the linker's default manifest (asInvoker) by adding it to
the target sources.
This commit is contained in:
1 parent
042501f89c
commit
6ef83d7a41
5 files changed
+64
No files matched your search
+13
@@ -74,6 +74,8 @@ distcheck-hook:
|
||||
#
|
||||
# Extra rules for cleanup
|
||||
#
|
||||
CLEANFILES=
|
||||
|
||||
DISTCLEANFILES= \
|
||||
libarchive/test/list.h \
|
||||
tar/test/list.h \
|
||||
@@ -1226,10 +1228,21 @@ bsdtar_LDADD= libarchive.la libarchive_fe.la $(LTLIBICONV)
|
||||
bsdtar_CPPFLAGS= -I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe $(bsdtar_ccstatic) $(PLATFORMCPPFLAGS)
|
||||
bsdtar_LDFLAGS= $(bsdtar_ldstatic) $(DEAD_CODE_REMOVAL)
|
||||
|
||||
if INC_WINDOWS_FILES
|
||||
# Embed an application manifest marking bsdtar as long-path aware.
|
||||
tar/bsdtar_rc.$(OBJEXT): $(top_srcdir)/tar/bsdtar.rc $(top_srcdir)/tar/bsdtar.exe.manifest
|
||||
$(AM_V_GEN)$(WINDRES) -I $(top_srcdir)/tar -i $(top_srcdir)/tar/bsdtar.rc -o $@
|
||||
bsdtar_LDADD += tar/bsdtar_rc.$(OBJEXT)
|
||||
bsdtar_DEPENDENCIES += tar/bsdtar_rc.$(OBJEXT)
|
||||
CLEANFILES += tar/bsdtar_rc.$(OBJEXT)
|
||||
endif
|
||||
|
||||
bsdtar_EXTRA_DIST= \
|
||||
tar/bsdtar.1 \
|
||||
tar/bsdtar_windows.h \
|
||||
tar/bsdtar_windows.c \
|
||||
tar/bsdtar.rc \
|
||||
tar/bsdtar.exe.manifest \
|
||||
tar/CMakeLists.txt \
|
||||
tar/config_freebsd.h
|
||||
|
||||
|
||||
@@ -101,6 +101,9 @@ esac
|
||||
AM_CONDITIONAL([INC_WINDOWS_FILES], [test $inc_windows_files = yes])
|
||||
AM_CONDITIONAL([INC_CYGWIN_FILES], [test $inc_cygwin_files = yes])
|
||||
|
||||
dnl On native Windows (MinGW), embedding the manifest needs windres
|
||||
AS_IF([test $inc_windows_files = yes], [AC_CHECK_TOOL([WINDRES], [windres])])
|
||||
|
||||
dnl Defines that are required for specific platforms (e.g. -D_POSIX_SOURCE, etc)
|
||||
PLATFORMCPPFLAGS=
|
||||
case "$host_os" in
|
||||
|
||||
@@ -30,6 +30,15 @@ IF(ENABLE_TAR)
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
LIST(APPEND bsdtar_SOURCES bsdtar_windows.c)
|
||||
LIST(APPEND bsdtar_SOURCES bsdtar_windows.h)
|
||||
IF(NOT MSVC)
|
||||
# The GNU toolchains (MinGW/Clang) do not generate an application
|
||||
# manifest, so we embed one through a resource script.
|
||||
ENABLE_LANGUAGE(RC)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
LIST(APPEND bsdtar_SOURCES bsdtar.rc)
|
||||
SET_SOURCE_FILES_PROPERTIES(bsdtar.rc PROPERTIES
|
||||
OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bsdtar.exe.manifest)
|
||||
ENDIF(NOT MSVC)
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
|
||||
# bsdtar documentation
|
||||
@@ -44,6 +53,10 @@ IF(ENABLE_TAR)
|
||||
SET_TARGET_PROPERTIES(bsdtar PROPERTIES COMPILE_DEFINITIONS
|
||||
LIBARCHIVE_STATIC)
|
||||
ENDIF(ENABLE_TAR_SHARED)
|
||||
IF(WIN32 AND NOT CYGWIN AND MSVC)
|
||||
# MSVC merges .manifest sources into the linker's default manifest
|
||||
TARGET_SOURCES(bsdtar PRIVATE bsdtar.exe.manifest)
|
||||
ENDIF(WIN32 AND NOT CYGWIN AND MSVC)
|
||||
|
||||
# Installation rules
|
||||
IF(ENABLE_INSTALL)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
|
||||
<ws2:longPathAware>true</ws2:longPathAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Embed an application manifest that marks bsdtar as long-path aware.
|
||||
*
|
||||
* bsdtar implements -C/--directory on Windows with SetCurrentDirectoryW(),
|
||||
* whose argument is limited to MAX_PATH (260) characters unless the process
|
||||
* opts in to long paths via a "longPathAware" manifest. A system-wide
|
||||
* LongPathsEnabled registry value is not sufficient on its own; the executable
|
||||
* must also carry this manifest. Without it, extracting into deeply nested
|
||||
* destination directories fails with "could not chdir to ...".
|
||||
*
|
||||
* See:
|
||||
* https://learn.microsoft.com/windows/win32/fileio/maximum-file-path-limitation
|
||||
*/
|
||||
|
||||
#define RT_MANIFEST 24
|
||||
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
|
||||
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "bsdtar.exe.manifest"
|
||||
Reference in new issue
Block a user