From a48fa4eb218de63445bbaa9b8eb0b1db0a797057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thi=C3=AAn=20To=C3=A1n?= Date: Tue, 12 May 2026 09:35:28 +0700 Subject: [PATCH] fix: handle permission denied when creating DATA_DIR (#1005) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fallback to default user directory (~/.9router) when configured DATA_DIR is not writable (EACCES/EPERM). Other errors still throw. Co-authored-by: Thiên Toán Co-authored-by: Cursor --- src/lib/dataDir.js | 19 +++++++++++++++++-- src/mitm/paths.js | 26 +++++++++++++++++++++----- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/lib/dataDir.js b/src/lib/dataDir.js index 946a708..d4b0751 100644 --- a/src/lib/dataDir.js +++ b/src/lib/dataDir.js @@ -1,14 +1,29 @@ +import fs from "node:fs"; import path from "path"; import os from "os"; const APP_NAME = "9router"; -export function getDataDir() { - if (process.env.DATA_DIR) return process.env.DATA_DIR; +function defaultDir() { if (process.platform === "win32") { return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), APP_NAME); } return path.join(os.homedir(), `.${APP_NAME}`); } +export function getDataDir() { + const configured = process.env.DATA_DIR; + if (!configured) return defaultDir(); + try { + fs.mkdirSync(configured, { recursive: true }); + return configured; + } catch (e) { + if (e?.code === "EACCES" || e?.code === "EPERM") { + console.warn(`[DATA_DIR] '${configured}' not writable → fallback ~/.${APP_NAME}`); + return defaultDir(); + } + throw e; + } +} + export const DATA_DIR = getDataDir(); diff --git a/src/mitm/paths.js b/src/mitm/paths.js index 3c667f4..892c225 100644 --- a/src/mitm/paths.js +++ b/src/mitm/paths.js @@ -1,13 +1,29 @@ +const fs = require("fs"); const path = require("path"); const os = require("os"); -// Single source of truth for data directory — matches localDb.js logic -function getDataDir() { - if (process.env.DATA_DIR) return process.env.DATA_DIR; +const APP_NAME = "9router"; + +function defaultDir() { if (process.platform === "win32") { - return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), "9router"); + return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), APP_NAME); + } + return path.join(os.homedir(), `.${APP_NAME}`); +} + +function getDataDir() { + const configured = process.env.DATA_DIR; + if (!configured) return defaultDir(); + try { + fs.mkdirSync(configured, { recursive: true }); + return configured; + } catch (e) { + if (e?.code === "EACCES" || e?.code === "EPERM") { + console.warn(`[DATA_DIR] '${configured}' not writable → fallback ~/.${APP_NAME}`); + return defaultDir(); + } + throw e; } - return path.join(os.homedir(), ".9router"); } const DATA_DIR = getDataDir();