Skip to content

Commit

Permalink
Fix zip files created on Windows being unusable on Linux/MacOS
Browse files Browse the repository at this point in the history
  • Loading branch information
Jimbly committed May 10, 2020
1 parent 36b2a6a commit 9e2e73f
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 2 deletions.
11 changes: 10 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ function Entry(metadataPath, isDirectory, options) {
if (options.mode != null) {
this.setFileAttributesMode(options.mode);
} else {
this.setFileAttributesMode(isDirectory ? 0o40775 : 0o100664);
this.setFileAttributesMode(0o664);
}
if (isDirectory) {
this.crcAndFileSizeKnown = true;
Expand Down Expand Up @@ -435,6 +435,15 @@ Entry.prototype.setLastModDate = function(date) {
Entry.prototype.setFileAttributesMode = function(mode) {
if ((mode & 0xffff) !== mode) throw new Error("invalid mode. expected: 0 <= " + mode + " <= " + 0xffff);
// http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute/14727#14727
if (this.isDirectory) {
// 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)) & 0o111;
mode |= 0o040000; // S_IFDIR
} else {
mode |= 0o100000; // S_IFREG
}

this.externalFileAttributes = (mode << 16) >>> 0;
};
// doFileDataPump() should not call pumpEntries() directly. see issue #9.
Expand Down
10 changes: 9 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ var BufferList = require("bl");
zipfile.addBuffer(bufferFrom("buffer"), "b.txt");
zipfile.addReadStream(new BufferList().append("stream"), "c.txt");
zipfile.addEmptyDirectory("d/");
zipfile.addEmptyDirectory("e");
zipfile.addEmptyDirectory("e", { mode: 0o644 });
zipfile.end(function(finalSize) {
if (finalSize !== -1) throw new Error("finalSize should be unknown");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
Expand All @@ -92,6 +92,14 @@ var BufferList = require("bl");
if (entry.fileName !== expectedName) {
throw new Error("unexpected entry fileName: " + entry.fileName + ", expected: " + expectedName);
}
var mode = entry.externalFileAttributes >>> 16;
if (/\/$/.test(entry.fileName)) {
// Directory file names end with '/'.
if (!(mode & 0o040000)) throw new Error("directory expected to have S_IFDIR, found " + mode.toString(8));
if (!(mode & 0o111)) throw new Error("directory expected to have executable flags, found " + mode.toString(8));
} else {
if (!(mode & 0o100000)) throw new Error("file expected to have S_IFREG, found " + mode.toString(8));
}
});
zipfile.on("end", function() {
if (entryNames.length === 0) console.log("optional parameters and directories: pass");
Expand Down

0 comments on commit 9e2e73f

Please sign in to comment.