Pithos on Linux desktops: per-user s3d paths
s3d's Linux defaults (/etc/s3d/s3d.yml, /var/lib/s3d) are for a system service; a desktop user cannot write them, so the desktop app could never create its config. When no system config exists and those places are not writable, Pithos uses ~/.config/s3d/s3d.yml and ~/.local/share/s3d (XDG), and writes the directory into the new config so s3d itself, started with S3D_CONFIG_FILE, uses the same place.
This commit is contained in:
parent
cb622aa5af
commit
3d863b5fe6
2 changed files with 29 additions and 3 deletions
|
|
@ -5,7 +5,7 @@ import fs from 'node:fs';
|
|||
import path from 'node:path';
|
||||
import crypto from 'node:crypto';
|
||||
import YAML from 'yaml';
|
||||
import { defaultDataDir } from './paths.js';
|
||||
import { defaultDataDir, linuxUserMode } from './paths.js';
|
||||
|
||||
// Fields the settings form exposes, as dotted yaml paths. Anything else in the
|
||||
// file is left untouched.
|
||||
|
|
@ -71,6 +71,8 @@ export function ensureConfig(file) {
|
|||
apiAddress: DEFAULTS.apiAddress,
|
||||
adminAddress: DEFAULTS.adminAddress,
|
||||
adminPassword: randomPassword(),
|
||||
// s3d itself would fall back to /var/lib/s3d, which this user cannot write
|
||||
...(linuxUserMode() ? { directory: defaultDataDir() } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,33 @@ import fs from 'node:fs';
|
|||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
// s3d's Linux defaults (/etc/s3d, /var/lib/s3d) suit a system service. A
|
||||
// desktop user who cannot write there, and has no system config, gets the
|
||||
// XDG per-user places instead; new configs then name that directory
|
||||
// explicitly, so a hand-run s3d with S3D_CONFIG_FILE agrees.
|
||||
const xdg = (envName, fallback) => process.env[envName] || path.join(os.homedir(), ...fallback);
|
||||
const userConfigFile = () => path.join(xdg('XDG_CONFIG_HOME', ['.config']), 's3d', 's3d.yml');
|
||||
const userDataDir = () => path.join(xdg('XDG_DATA_HOME', ['.local', 'share']), 's3d');
|
||||
|
||||
function writable(p) {
|
||||
// the nearest existing folder decides whether p could be created
|
||||
for (let d = p; ; d = path.dirname(d)) {
|
||||
if (fs.existsSync(d)) { try { fs.accessSync(d, fs.constants.W_OK); return true; } catch { return false; } }
|
||||
if (path.dirname(d) === d) return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function linuxUserMode() {
|
||||
if (process.platform === 'win32' || process.platform === 'darwin') return false;
|
||||
if (['/etc/s3d/s3d.yml', '/var/lib/s3d/s3d.yml'].some((p) => fs.existsSync(p))) return false;
|
||||
return !(writable('/etc/s3d') && writable('/var/lib/s3d'));
|
||||
}
|
||||
|
||||
export function defaultDataDir() {
|
||||
switch (process.platform) {
|
||||
case 'win32': return path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 's3d');
|
||||
case 'darwin': return path.join(os.homedir(), 'Library', 'Application Support', 's3d');
|
||||
default: return '/var/lib/s3d';
|
||||
default: return linuxUserMode() ? userDataDir() : '/var/lib/s3d';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -20,7 +42,9 @@ export function configSearchPaths() {
|
|||
switch (process.platform) {
|
||||
case 'win32': paths.push(path.join(defaultDataDir(), 's3d.yml')); break;
|
||||
case 'darwin': paths.push(path.join(defaultDataDir(), 's3d.yml')); break;
|
||||
default: paths.push('/etc/s3d/s3d.yml', '/var/lib/s3d/s3d.yml');
|
||||
default:
|
||||
if (linuxUserMode()) paths.push(userConfigFile());
|
||||
paths.push('/etc/s3d/s3d.yml', '/var/lib/s3d/s3d.yml');
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue