From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2201) id D570F3858039; Sun, 18 Jul 2021 13:41:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D570F3858039 To: cygwin-apps-cvs@sourceware.org Subject: [setup - the official Cygwin setup program] branch master, updated. release_2.909-2-g274b400f X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 77e4675a9603cdd5757152a744f9ff7e53bdbafc X-Git-Newrev: 274b400f42c9314e835a3520cec0e15b87e466a2 Message-Id: <20210718134112.D570F3858039@sourceware.org> Date: Sun, 18 Jul 2021 13:41:12 +0000 (GMT) From: Jon TURNEY X-BeenThere: cygwin-apps-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin-apps git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Jul 2021 13:41:12 -0000 https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=274b400f42c9314e835a3520cec0e15b87e466a2 commit 274b400f42c9314e835a3520cec0e15b87e466a2 Author: Jon Turney Date: Sat Jul 17 13:56:31 2021 +0100 Only build for x86_64 in github workflow Only build for x86_64 in github workflow, since the requirements for i686 are now impossible to obtain (Fedora <=31 for non-DW2 EH compiler, but coprs for EOL'ed Fedoras have been expired) https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=b6dab3ea3ae98d9de63bc0c5775be38e4fe08d68 commit b6dab3ea3ae98d9de63bc0c5775be38e4fe08d68 Author: Christian Franke Date: Fri May 14 09:50:12 2021 +0200 Add new option '--compact-os ALGORITHM'. If specified, selected Compact OS compression algorithm is applied to files below /bin, /sbin and /usr. Most DLL files are excluded because rebase will open these files again for writing. Diff: --- .github/workflows/fedora.yml | 4 +- Makefile.am | 2 + compactos.cc | 63 +++++++++++++++++++++++++++++++ compactos.h | 25 +++++++++++++ io_stream_cygfile.cc | 89 +++++++++++++++++++++++++++++++++++++++++++- io_stream_cygfile.h | 2 + packaging-scripts/conf.sh | 3 +- 7 files changed, 183 insertions(+), 5 deletions(-) diff --git a/.github/workflows/fedora.yml b/.github/workflows/fedora.yml index e070d305..2bd76e57 100644 --- a/.github/workflows/fedora.yml +++ b/.github/workflows/fedora.yml @@ -6,7 +6,7 @@ jobs: fedora-build: name: Fedora runs-on: ubuntu-latest - container: fedora:31 + container: fedora:latest steps: # install git, so checkout uses git to fetch repository, so 'git describe' works - name: Install git @@ -21,4 +21,4 @@ jobs: run: packaging-scripts/fedora-prereqs-install.sh - name: Build - run: packaging-scripts/conf.sh upx + run: packaging-scripts/conf.sh upx x86_64 diff --git a/Makefile.am b/Makefile.am index d10ad6b1..63e96dae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -108,6 +108,8 @@ inilint_SOURCES = \ archive_tar_file.cc \ choose.cc \ choose.h \ + compactos.cc \ + compactos.h \ compress.cc \ compress.h \ compress_bz.cc \ diff --git a/compactos.cc b/compactos.cc new file mode 100644 index 00000000..9ed2a731 --- /dev/null +++ b/compactos.cc @@ -0,0 +1,63 @@ +// +// compactos.cc +// +// Copyright (C) 2021 Christian Franke +// +// SPDX-License-Identifier: MIT +// + +#include "compactos.h" + +/* Not yet provided by w32api headers. */ +#ifndef FSCTL_SET_EXTERNAL_BACKING +#define FSCTL_SET_EXTERNAL_BACKING \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 195, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#endif + +#ifndef WOF_CURRENT_VERSION +#define WOF_CURRENT_VERSION 1 + +typedef struct _WOF_EXTERNAL_INFO { + DWORD Version; + DWORD Provider; +} WOF_EXTERNAL_INFO; + +#endif + +#ifndef WOF_PROVIDER_FILE +#define WOF_PROVIDER_FILE 2 +#define FILE_PROVIDER_CURRENT_VERSION 1 + +typedef struct _FILE_PROVIDER_EXTERNAL_INFO_V1 { + DWORD Version; + DWORD Algorithm; + DWORD Flags; +} FILE_PROVIDER_EXTERNAL_INFO_V1; + +#endif + +#ifndef ERROR_COMPRESSION_NOT_BENEFICIAL +#define ERROR_COMPRESSION_NOT_BENEFICIAL 344 +#endif + +int CompactOsCompressFile(HANDLE h, DWORD algorithm) +{ + struct { + WOF_EXTERNAL_INFO Wof; + FILE_PROVIDER_EXTERNAL_INFO_V1 FileProvider; + } wfp; + wfp.Wof.Version = WOF_CURRENT_VERSION; + wfp.Wof.Provider = WOF_PROVIDER_FILE; + wfp.FileProvider.Version = FILE_PROVIDER_CURRENT_VERSION; + wfp.FileProvider.Algorithm = algorithm; + wfp.FileProvider.Flags = 0; + + if (!DeviceIoControl(h, FSCTL_SET_EXTERNAL_BACKING, &wfp, sizeof(wfp), 0, 0, 0, 0)) + { + if (GetLastError() != ERROR_COMPRESSION_NOT_BENEFICIAL) + return -1; + return 0; + } + + return 1; +} diff --git a/compactos.h b/compactos.h new file mode 100644 index 00000000..f1877189 --- /dev/null +++ b/compactos.h @@ -0,0 +1,25 @@ +// +// compactos.h +// +// Copyright (C) 2021 Christian Franke +// +// SPDX-License-Identifier: MIT +// + +#ifndef COMPACTOS_H +#define COMPACTOS_H + +#include + +/* Not yet provided by w32api headers. */ +#ifndef FILE_PROVIDER_COMPRESSION_XPRESS4K +#define FILE_PROVIDER_COMPRESSION_XPRESS4K 0 +#define FILE_PROVIDER_COMPRESSION_LZX 1 +#define FILE_PROVIDER_COMPRESSION_XPRESS8K 2 +#define FILE_PROVIDER_COMPRESSION_XPRESS16K 3 +#endif + +// Returns: 1=compressed, 0=not compressed, -1=error +int CompactOsCompressFile(HANDLE h, DWORD algorithm); + +#endif // COMPACTOS_H diff --git a/io_stream_cygfile.cc b/io_stream_cygfile.cc index 2d0716ff..a9150e7e 100644 --- a/io_stream_cygfile.cc +++ b/io_stream_cygfile.cc @@ -18,6 +18,9 @@ #include "filemanip.h" #include "mkdir.h" #include "mount.h" +#include "compactos.h" + +#include "getopt++/StringOption.h" #include #include @@ -27,6 +30,45 @@ #include "IOStreamProvider.h" #include "LogSingleton.h" +/* Option '--compact-os ALGORITHM' */ +class CompactOsStringOption : public StringOption +{ +public: + CompactOsStringOption (); + virtual Result Process (char const *optarg, int prefixIndex) /* override */; + operator int () const { return intval; } +private: + int intval; +}; + +CompactOsStringOption::CompactOsStringOption () +: StringOption ("", '\0', "compact-os", + "Compress installed files with Compact OS " + "(xpress4k, xpress8k, xpress16k, lzx)", false), + intval (-1) +{ +} + +Option::Result CompactOsStringOption::Process (char const *optarg, int prefixIndex) +{ + Result res = StringOption::Process (optarg, prefixIndex); + if (res != Ok) + return res; + const std::string& strval = *this; + if (strval == "xpress4k") + intval = FILE_PROVIDER_COMPRESSION_XPRESS4K; + else if (strval == "xpress8k") + intval = FILE_PROVIDER_COMPRESSION_XPRESS8K; + else if (strval == "xpress16k") + intval = FILE_PROVIDER_COMPRESSION_XPRESS16K; + else if (strval == "lzx") + intval = FILE_PROVIDER_COMPRESSION_LZX; + else + return Failed; + return Ok; +} + +static CompactOsStringOption CompactOsOption; /* completely private iostream registration class */ class CygFileProvider : public IOStreamProvider @@ -59,7 +101,8 @@ CygFileProvider CygFileProvider::theInstance = CygFileProvider(); std::string io_stream_cygfile::cwd("/"); - +bool io_stream_cygfile::compact_os_is_available = (OSMajorVersion () >= 10); + // Normalise a unix style path relative to // cwd. std::string @@ -120,7 +163,27 @@ get_root_dir_now () read_mounts (std::string ()); } -io_stream_cygfile::io_stream_cygfile (const std::string& name, const std::string& mode, mode_t perms) : fp(), lasterr (0), fname(), wname (NULL) +static bool +compactos_is_useless (const std::string& name) +{ + const char * const p = name.c_str(); + if (!(!strncmp (p, "/bin/", 5) || !strncmp (p, "/sbin/", 6) || !strncmp (p, "/usr/", 5))) + return true; /* File is not in R/O tree. */ + const size_t len = name.size(); /* >= 5 */ + if (!strcmp (p + (len - 4), ".dll") || !strcmp (p + (len - 3), ".so")) { + if ((len >= 5 + 11 && !strcmp (p + (len - 11), "cygwin1.dll")) + || strstr (p + 5, "/sys-root/mingw/")) + return false; /* Ignored by rebase. */ + return true; /* Rebase will open file for writing which uncompresses the file. */ + } + if (!strcmp (p + (len - 4), ".bz2") || !strcmp (p + (len - 3), ".gz") + || !strcmp (p + (len - 3), ".xz")) + return true; /* File is already compressed. */ + return false; +} + +io_stream_cygfile::io_stream_cygfile (const std::string& name, const std::string& mode, mode_t perms) +: fp(), lasterr (0), fname(), wname (NULL), compact_os_algorithm(-1) { errno = 0; if (!name.size()) @@ -153,6 +216,10 @@ io_stream_cygfile::io_stream_cygfile (const std::string& name, const std::string Log (LOG_TIMESTAMP) << "io_stream_cygfile: fopen(" << name << ") failed " << errno << " " << strerror(errno) << endLog; } + + if (mode[0] == 'w' && compact_os_is_available && CompactOsOption >= 0 + && !compactos_is_useless (name)) + compact_os_algorithm = CompactOsOption; } } @@ -367,6 +434,24 @@ io_stream_cygfile::set_mtime (time_t mtime) FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0); if (h == INVALID_HANDLE_VALUE) return 1; + + if (compact_os_algorithm >= 0) + { + /* Compact OS must be applied after last WriteFile() + and before SetFileTime(). */ + int rc = CompactOsCompressFile (h, compact_os_algorithm); + if (rc < 0) + { + DWORD err = GetLastError(); + Log (LOG_TIMESTAMP) << "Compact OS disabled after error " << err + << " on " << fname << endLog; + compact_os_is_available = false; + } + else + Log (LOG_BABBLE) << "Compact OS algorithm " << compact_os_algorithm + << (rc == 0 ? " not" : "") << " applied to " << fname << endLog; + } + SetFileTime (h, 0, 0, &ftime); CloseHandle (h); return 0; diff --git a/io_stream_cygfile.h b/io_stream_cygfile.h index 1ece2428..b9779094 100644 --- a/io_stream_cygfile.h +++ b/io_stream_cygfile.h @@ -61,7 +61,9 @@ private: std::string fname; wchar_t *wname; wchar_t *w_str (); + int compact_os_algorithm; static std::string cwd; + static bool compact_os_is_available; }; #endif /* SETUP_IO_STREAM_CYGFILE_H */ diff --git a/packaging-scripts/conf.sh b/packaging-scripts/conf.sh index 10d78b46..f01b1990 100755 --- a/packaging-scripts/conf.sh +++ b/packaging-scripts/conf.sh @@ -1,6 +1,7 @@ #!/bin/bash -e TARGET=${1:-upx} +ARCHES=${2:-i686 x86_64} function arch() { cpu=$1 @@ -16,6 +17,6 @@ make ${TARGET} cd .. } -for ARCH in i686 x86_64 ; do +for ARCH in ${ARCHES} ; do arch ${ARCH} done