From cef7d8dbe67bc344a4a84166b823909ca828ee3c Mon Sep 17 00:00:00 2001 From: ijisol Date: Thu, 17 Oct 2024 21:29:31 +0900 Subject: [PATCH 1/2] Fix zip files created on Windows being unusable on Linux/MacOS (missing executable bits on directories) from https://github.com/thejoshwolfe/yazl/pull/59 --- index.js | 15 ++++++++++++--- test/test.js | 18 +++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index c54eaf1..5580a8e 100644 --- a/index.js +++ b/index.js @@ -83,7 +83,7 @@ class Entry { this.isDirectory = isDirectory; this.state = Entry.WAITING_FOR_METADATA; this.setLastModDate(options.mtime ?? new Date()); - this.setFileAttributesMode(options.mode ?? (isDirectory ? 0o40775 : 0o100664)); + this.setFileAttributesMode(options.mode ?? 0o000664, isDirectory); if (isDirectory) { this.crcAndFileSizeKnown = true; this.crc32 = 0; @@ -139,10 +139,19 @@ class Entry { /** * @param {number} mode */ - setFileAttributesMode(mode) { + setFileAttributesMode(mode, isDirectory) { if ((mode & 0xffff) !== mode) { throw new Error(`invalid mode. expected: 0 <= ${mode} <= 65535`); } + if (isDirectory) { + // https://github.com/thejoshwolfe/yazl/pull/59 + // Set executable bit on directories if any other bits are set for that user/group/all + // Fixes creating unusable zip files on platforms that do not use an executable bit + mode |= ((mode >> 1) | (mode >> 2)) & 0o000111; + mode |= 0o040000; // S_IFDIR + } else { + mode |= 0o100000; // S_IFREG + } // http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute/14727#14727 this.externalFileAttributes = (mode << 16) >>> 0; } @@ -381,7 +390,7 @@ class ZipFile extends EventEmitter { } entry.uncompressedSize = stats.size; if (options.mtime == null) entry.setLastModDate(stats.mtime); - if (options.mode == null) entry.setFileAttributesMode(stats.mode); + if (options.mode == null) entry.setFileAttributesMode(stats.mode, false); entry.setFileDataPumpFunction(() => { const readStream = createReadStream(realPath); entry.state = Entry.FILE_DATA_IN_PROGRESS; diff --git a/test/test.js b/test/test.js index 61bb68f..99b6f99 100644 --- a/test/test.js +++ b/test/test.js @@ -87,7 +87,7 @@ const filename = fileURLToPath(import.meta.url); zipfile.addBuffer(Buffer.from('buffer'), 'b.txt'); zipfile.addReadStream(new BufferListStream().append('stream'), 'c.txt'); zipfile.addEmptyDirectory('d/'); - zipfile.addEmptyDirectory('e'); + zipfile.addEmptyDirectory('e', { mode: 0o000644 }); zipfile.end(function (finalSize) { if (finalSize !== -1) throw new Error('finalSize should be unknown'); zipfile.outputStream.pipe(new BufferListStream(function (err, data) { @@ -96,9 +96,21 @@ const filename = fileURLToPath(import.meta.url); if (err) throw err; const entryNames = ['a.txt', 'b.txt', 'c.txt', 'd/', 'e/']; zipfile.on('entry', function (entry) { + const { fileName } = entry; const expectedName = entryNames.shift(); - if (entry.fileName !== expectedName) { - throw new Error(`unexpected entry fileName: ${entry.fileName}, expected: ${expectedName}`); + if (fileName !== expectedName) { + throw new Error(`unexpected entry fileName: ${fileName}, expected: ${expectedName}`); + } + const mode = entry.externalFileAttributes >>> 16; + if (fileName.endsWith('/')) { + if ((mode & 0o040000) === 0) { + throw new Error(`directory expected to have S_IFDIR, found ${mode.toString(8)}`); + } + if ((mode & 0o000111) === 0) { + throw new Error(`directory expected to have executable flags, found ${mode.toString(8)}`); + } + } else if ((mode & 0o100000) === 0) { + throw new Error(`file expected to have S_IFREG, found ${mode.toString(8)}`); } }); zipfile.on('end', function () { From 92fd0e7626223a21a9a9c440cd6ecebb689f7c83 Mon Sep 17 00:00:00 2001 From: ijisol Date: Thu, 17 Oct 2024 22:15:39 +0900 Subject: [PATCH 2/2] Add the author's name of the original code See https://github.com/thejoshwolfe/yazl/pull/59#issuecomment-2419496648 --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 1fe9271..e79e722 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ MIT License Copyright (c) 2014 Josh Wolfe -Copyright (c) 2024 Lee Jisol +Copyright (c) 2024 Lee Jisol and Jimb Esser Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal