fix: couldn't upload to drive's root https://github.com/rejetto/hfs/issues/87

Massimo Melina committed Jan 16, 2023 at 15:02 UTC ba628ccb6da3b0bf93470fce95dc1951e01e286a
3 files changed +20 -8
src/log.ts
+4 -4
@@ -5,11 +5,11 @@ import { Writable } from 'stream'
5 import { defineConfig } from './config'
6 import { createWriteStream, renameSync } from 'fs'
7 import * as util from 'util'
8 -import { mkdir, stat } from 'fs/promises'
8 +import { stat } from 'fs/promises'
9 import { DAY } from './const'
10 import events from './events'
11 import _ from 'lodash'
12 -import { dirname } from 'path'
12 +import { prepareFolder } from './util-files'
13 import { getCurrentUsername } from './perm'
14
15 class Logger {
@@ -31,8 +31,8 @@ class Logger {
31 this.last = stats.mtime || stats.ctime
32 }
33 catch {
34 - await mkdir(dirname(path), { recursive: true })
35 - .catch(() => console.log("cannot create folder for", path))
34 + if (await prepareFolder(path) === false)
35 + console.log("cannot create folder for", path)
36 }
37 this.reopen()
38 }
src/middlewares.ts
+3 -3
@@ -15,7 +15,7 @@ import {
15 } from './const'
16 import { FRONTEND_URI } from './const'
17 import { cantReadStatusCode, hasPermission, nodeIsDirectory, urlToNode, vfs, VfsNode } from './vfs'
18 -import { dirTraversal, objSameKeys, tryJson } from './misc'
18 +import { dirTraversal, objSameKeys, prepareFolder, tryJson } from './misc'
19 import { zipStreamFromFolder } from './zip'
20 import { serveFileNode } from './serveFile'
21 import { serveGuiFiles } from './serveGuiFiles'
@@ -28,7 +28,7 @@ import basicAuth from 'basic-auth'
28 import { SRPClientSession, SRPParameters, SRPRoutines } from 'tssrp6a'
29 import { srpStep1 } from './api.auth'
30 import { basename, dirname, join } from 'path'
31 -import { createWriteStream, mkdirSync } from 'fs'
31 +import { createWriteStream } from 'fs'
32 import { pipeline } from 'stream/promises'
33
34 export const gzipper = compress({
@@ -120,7 +120,7 @@ async function receiveUpload(base: VfsNode, path: string, stream: Readable, ctx:
120 if (!base.source || !hasPermission(base, 'can_upload', ctx))
121 return ctx.status = base.can_upload === false ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED
122 path = join(base.source, path)
123 - mkdirSync(dirname(path), { recursive: true })
123 + await prepareFolder(path)
124 const dest = createWriteStream(path)
125 await pipeline(stream, dest)
126 ctx.body = '{}'
src/util-files.ts
+13 -1
@@ -130,10 +130,22 @@ export async function unzip(stream: Readable, cb: (path: string) => false | stri
130 return entry.autodrain()
131 await pending // don't overlap writings
132 console.debug('unzip', dest)
133 - mkdirSync(dirname(dest), { recursive: true }) // easy way be sure to have the folder ready before proceeding
133 + await prepareFolder(dest)
134 const thisFile = entry.pipe(createWriteStream(dest))
135 pending = once(thisFile, 'finish')
136 })
137 )
138 }
139
140 +export async function prepareFolder(path: string, dirnameIt=true) {
141 + if (dirnameIt)
142 + path = dirname(path)
143 + if (isWindowsDrive(path)) return
144 + try {
145 + await fs.mkdir(path, { recursive: true })
146 + return true
147 + }
148 + catch {
149 + return false
150 + }
151 +}