include file's mode in zip
Massimo Melina committed
Apr 20, 2022 at 22:54 UTC
f21854d5f62732d79a92132da9195e5e516837d0
2 files changed
+8
-5
server/src/QuickZipStream.ts
+7
-5
@@ -16,12 +16,13 @@ interface ZipSource {
16
getData: () => Readable // deferred stream, so that we don't keep many open files because of calculateSize()
17
size: number
18
ts: Date
19
+ mode?: number
20
}
21
export class QuickZipStream extends Readable {
22
private workingFile = false
23
private numberOfFiles: number = 0
24
private finished = false
24
- private readonly centralDir: ({ size:number, crc:number, ts:Date, pathAsBuffer:Buffer, offset:number, version:number })[] = []
25
+ private readonly centralDir: ({ size:number, crc:number, ts:Date, pathAsBuffer:Buffer, offset:number, version:number, extAttr: number })[] = []
26
private dataWritten = 0
27
private prewalk?: ZipSource[]
28
@@ -69,7 +70,7 @@ export class QuickZipStream extends Readable {
70
if (!file)
71
return this.closeArchive()
72
++this.numberOfFiles
72
- let { path, getData, size, ts } = file
73
+ let { path, getData, size, ts, mode } = file
74
const data = getData()
75
const pathAsBuffer = Buffer.from(path, 'utf8')
76
const crc32 = await crc32provider
@@ -102,7 +103,8 @@ export class QuickZipStream extends Readable {
103
this.workingFile = true
104
data.on('end', ()=>{
105
this.workingFile = false
105
- this.centralDir.push({ size, crc:crc!, pathAsBuffer, ts, offset, version })
106
+ const extAttr = !mode ? 0 : (mode | 0x8000) * 0x10000 // it's like <<16 but doesn't overflow so easily
107
+ this.centralDir.push({ size, crc:crc!, pathAsBuffer, ts, offset, version, extAttr })
108
const sizeSize = size > ZIP64_LIMIT ? 8 : 4
109
this._push([
110
4, 0x08074b50,
@@ -116,7 +118,7 @@ export class QuickZipStream extends Readable {
118
closeArchive() {
119
this.finished = true
120
let centralOffset = this.dataWritten
119
- for (let { size, ts, crc, offset, pathAsBuffer, version } of this.centralDir) {
121
+ for (let { size, ts, crc, offset, pathAsBuffer, version, extAttr } of this.centralDir) {
122
const extra = []
123
if (size > ZIP64_LIMIT) {
124
extra.push(size, size)
@@ -145,7 +147,7 @@ export class QuickZipStream extends Readable {
147
2, 0, //comment length
148
2, 0, // disk
149
2, 0, // attr
148
- 4, 0, // ext.attr
150
+ 4, extAttr,
151
4, offset,
152
])
153
this._push(pathAsBuffer)
server/src/zip.ts
+1
@@ -41,6 +41,7 @@ export async function zipStreamFromFolder(node: VfsNode, ctx: Koa.Context) {
41
path: name,
42
size: st.size,
43
ts: st.mtime || st.ctime,
44
+ mode: st.mode,
45
getData: () => createReadStream(source)
46
}
47
}