feat: pmm system-install mode (default) — /usr/bin, /etc/pmm, system lib, no env vars

Default (no -p) now installs like a system package manager:
- pmm config/db -> /etc/pmm, cache -> /var/cache/pmm, pmm binary -> /usr/bin.
- .pdm data routed by type: bin -> /usr/bin, lib -> /usr/lib/<pkg-subpath>,
  etc -> /etc/pmm/<pkg>, else -> /usr/share/pmm/<pkg>; then ldconfig.
- pmm_remove removes the recorded absolute system dests.
- pmm_add_to_path is a no-op in system mode (system paths are auto-found);
  the -p <path> local mode keeps the old ~/.pmm + PATH/LD_LIBRARY_PATH behavior.
Verified: routing moves (no double multiarch), and -p local mode still writes env.
这个提交包含在:
JGZYES
2026-09-06 17:00:45 +08:00
父节点 4b7c58560e
当前提交 06d7f2011a
修改 6 个文件,包含 79 行新增21 行删除
+2 -2
查看文件
文件差异因一行或多行过长而隐藏
+55 -15
查看文件
@@ -597,6 +597,34 @@ int pdm_install_file(const char *pdmfile) {
flatten_bin("."); /* cwd = the install address in flat mode */ flatten_bin("."); /* cwd = the install address in flat mode */
} }
/* system-install mode (default, no -p): route the staged files to system
* destinations (ELF->/usr/bin, .so->system lib dir, etc->/etc/pmm/<pkg>,
* else->/usr/share/pmm/<pkg>) and record the absolute dest paths for remove. */
int sys_mode = (!flat && pmm_system_mode());
char destfile[1500];
if (sys_mode) {
snprintf(destfile, sizeof(destfile), "%s/.pmm-dests.txt", home);
char cmd2[9000];
snprintf(cmd2, sizeof(cmd2),
"DESTFILE=\"%s\"; cd \"%s\" && : > \"$DESTFILE\" && "
"MULTI=$(uname -m | sed 's/x86_64/x86_64-linux-gnu/; s/aarch64/aarch64-linux-gnu/; s/armv7l/arm-linux-gnueabihf/'); "
"[ -n \"$MULTI\" ] || MULTI=x86_64-linux-gnu; "
"find . -type f | while IFS= read -r f; do "
"rel=${f#./}; "
"case \"$rel\" in "
"bin/*) d=\"/usr/bin/${rel#bin/}\"; mkdir -p \"$(dirname \"$d\")\"; mv -f \"$f\" \"$d\"; echo \"$d\" >> \"$DESTFILE\";; "
"lib/*) d=\"/usr/lib/${rel#lib/}\"; mkdir -p \"$(dirname \"$d\")\"; mv -f \"$f\" \"$d\"; echo \"$d\" >> \"$DESTFILE\";; "
"etc/*) d=\"/etc/pmm/%s/${rel#etc/}\"; mkdir -p \"$(dirname \"$d\")\"; mv -f \"$f\" \"$d\"; echo \"$d\" >> \"$DESTFILE\";; "
"usr/*) d=\"/usr/${rel#usr/}\"; mkdir -p \"$(dirname \"$d\")\"; mv -f \"$f\" \"$d\"; echo \"$d\" >> \"$DESTFILE\";; "
"*) d=\"/usr/share/pmm/%s/$rel\"; mkdir -p \"$(dirname \"$d\")\"; mv -f \"$f\" \"$d\"; echo \"$d\" >> \"$DESTFILE\";; "
"esac; done; ldconfig 2>/dev/null || true; "
"chmod -f +x /usr/bin/* >/dev/null 2>&1 || true",
destfile, root, pkg, pkg);
if (system(cmd2) != 0) {
pmm_warn("%s", pmm_tr_fmt("msg.warn.system-route", pkg));
}
}
/* record file list + control in db */ /* record file list + control in db */
snprintf(cmd, sizeof(cmd), "%s/%s.info", db, pkg); snprintf(cmd, sizeof(cmd), "%s/%s.info", db, pkg);
FILE *dbf = fopen(cmd, "wb"); /* binary: keep \n, avoid Windows CRLF translation */ FILE *dbf = fopen(cmd, "wb"); /* binary: keep \n, avoid Windows CRLF translation */
@@ -604,22 +632,33 @@ int pdm_install_file(const char *pdmfile) {
fprintf(dbf, "Package: %s\nVersion: %s\nSource: %s\n\n%s\n", fprintf(dbf, "Package: %s\nVersion: %s\nSource: %s\n\n%s\n",
pkg, ver ? ver : "0.0.0", base_name(pdmfile), ctl); pkg, ver ? ver : "0.0.0", base_name(pdmfile), ctl);
fprintf(dbf, "Files:\n"); fprintf(dbf, "Files:\n");
char ltcmd[2600]; if (sys_mode) {
snprintf(ltcmd, sizeof(ltcmd), "tar -tzf \"%s/data.tar.gz\"", stage); FILE *df = fopen(destfile, "r");
FILE *tf = PMM_POPEN_READ(ltcmd); if (df) {
if (tf) { char ln[2048];
char ln[2048]; while (fgets(ln, sizeof(ln), df)) fputs(ln, dbf);
while (fgets(ln, sizeof(ln), tf)) { fclose(df);
if (flat) { /* reflection of the flatten: strip a leading bin/ */ } else {
const char *q = ln; pmm_warn(pmm_tr("msg.warn.no-filelist"));
while (*q==' '||*q=='\t') q++;
if (q[0]=='.'&&q[1]=='/'&&strncasecmp(q+2,"bin/",4)==0) { ln[0]='\0'; continue; }
}
fputs(ln, dbf);
} }
PMM_PCLOSE_READ(tf);
} else { } else {
pmm_warn(pmm_tr("msg.warn.no-filelist")); char ltcmd[2600];
snprintf(ltcmd, sizeof(ltcmd), "tar -tzf \"%s/data.tar.gz\"", stage);
FILE *tf = PMM_POPEN_READ(ltcmd);
if (tf) {
char ln[2048];
while (fgets(ln, sizeof(ln), tf)) {
if (flat) { /* reflection of the flatten: strip a leading bin/ */
const char *q = ln;
while (*q==' '||*q=='\t') q++;
if (q[0]=='.'&&q[1]=='/'&&strncasecmp(q+2,"bin/",4)==0) { ln[0]='\0'; continue; }
}
fputs(ln, dbf);
}
PMM_PCLOSE_READ(tf);
} else {
pmm_warn(pmm_tr("msg.warn.no-filelist"));
}
} }
fclose(dbf); fclose(dbf);
} }
@@ -747,7 +786,8 @@ int pdm_remove(const char *name) {
char *p = path; char *p = path;
while (p[0] == '.' && p[1] == '/') p += 2; while (p[0] == '.' && p[1] == '/') p += 2;
char full[1200]; char full[1200];
snprintf(full, sizeof(full), "%s/%s", root, p); if (p[0] == '/') { snprintf(full, sizeof(full), "%s", p); } /* system-mode absolute dest */
else snprintf(full, sizeof(full), "%s/%s", root, p);
remove(full); remove(full);
n++; n++;
} }
+14 -2
查看文件
@@ -149,6 +149,16 @@ void pmm_set_install_path(const char *path) {
} }
int pmm_flat_mode(void) { return g_base_path[0] ? 1 : 0; } int pmm_flat_mode(void) { return g_base_path[0] ? 1 : 0; }
/* System-install mode: unix default (no -p <path>). Writes to /usr/bin, /etc/pmm,
* the system lib dir and /usr/share/pmm — no PATH/LD_LIBRARY_PATH needed. */
int pmm_system_mode(void) {
#ifdef _WIN32
return 0; /* Windows always uses local mode */
#else
return g_base_path[0] ? 0 : 1;
#endif
}
/* Resolve the .pmm base dir: explicit drive override > persisted drive > /* Resolve the .pmm base dir: explicit drive override > persisted drive >
* home/.pmm (when that drive is picked) > DEFAULT = D:\.pmm. * home/.pmm (when that drive is picked) > DEFAULT = D:\.pmm.
* Defaulting to D:\ spares the C: drive (user's primary diskspace concern); * Defaulting to D:\ spares the C: drive (user's primary diskspace concern);
@@ -188,7 +198,7 @@ static const char *pmm_base_dir(char *buf, size_t size) {
#ifdef _WIN32 #ifdef _WIN32
snprintf(buf, size, "D:\\.pmm"); /* Windows DEFAULT -> D: */ snprintf(buf, size, "D:\\.pmm"); /* Windows DEFAULT -> D: */
#else #else
snprintf(buf, size, "%s/.pmm", home_dir()); /* unix default -> ~/.pmm */ snprintf(buf, size, "/etc/pmm"); /* unix default -> system config dir */
#endif #endif
} }
return buf; return buf;
@@ -201,6 +211,7 @@ const char *pmm_config_dir(char *buf, size_t size) {
} }
const char *pmm_cache_dir(char *buf, size_t size) { const char *pmm_cache_dir(char *buf, size_t size) {
if (pmm_system_mode()) { snprintf(buf, size, "/var/cache/pmm"); mkdir_p(buf); return buf; }
char base[1024]; char base[1024];
pmm_base_dir(base, sizeof(base)); pmm_base_dir(base, sizeof(base));
snprintf(buf, size, "%s/cache", base); snprintf(buf, size, "%s/cache", base);
@@ -219,7 +230,7 @@ const char *pmm_install_dir(char *buf, size_t size) {
pmm_base_dir(base, sizeof(base)); pmm_base_dir(base, sizeof(base));
snprintf(buf, size, "%s/bin", base); /* Windows default -> <base>\bin */ snprintf(buf, size, "%s/bin", base); /* Windows default -> <base>\bin */
#else #else
snprintf(buf, size, "/usr/local/bin"); /* Linux/macOS default -> system-wide (on PATH) */ snprintf(buf, size, "/usr/bin"); /* Linux/macOS default -> system-wide (on PATH) */
#endif #endif
} }
mkdir_p(buf); mkdir_p(buf);
@@ -300,6 +311,7 @@ static void add_path_candidate(char list[][1200], int *n, int max, const char *d
} }
void pmm_add_to_path(void) { void pmm_add_to_path(void) {
if (pmm_system_mode()) return; /* system mode: /usr/bin & system libs are already found */
char home[1024]; char home[1024];
pmm_config_dir(home, sizeof(home)); pmm_config_dir(home, sizeof(home));
char base[1024]; char base[1024];
+4
查看文件
@@ -27,6 +27,10 @@ void pmm_set_install_path(const char *path);
* into that directory (files flattened), without a root/bin sub-folder. */ * into that directory (files flattened), without a root/bin sub-folder. */
int pmm_flat_mode(void); int pmm_flat_mode(void);
/* 1 if running in system-install mode (unix default, no -p): files go to
* /usr/bin, /etc/pmm, the system lib dir; no PATH/LD_LIBRARY_PATH is written. */
int pmm_system_mode(void);
/* File-association record written to the per-user registry on install. */ /* File-association record written to the per-user registry on install. */
typedef struct { typedef struct {
const char *progid; /* e.g. "Node.JSFile" */ const char *progid; /* e.g. "Node.JSFile" */
+2 -1
查看文件
@@ -137,5 +137,6 @@
"msg.err.not-cached": "%s not in cache (run pmm fetch)", "msg.err.not-cached": "%s not in cache (run pmm fetch)",
"msg.postinst-ok": "post-install script ran OK: %s", "msg.postinst-ok": "post-install script ran OK: %s",
"msg.warn.postinst": "post-install script returned non-zero: %s", "msg.warn.postinst": "post-install script returned non-zero: %s",
"msg.warn.postinst-missing": "post-install script missing: %s" "msg.warn.postinst-missing": "post-install script missing: %s",
"msg.warn.system-route": "some files failed to route to system paths: %s"
} }
+2 -1
查看文件
@@ -137,5 +137,6 @@
"msg.err.not-cached": "%s 未在缓存中(先运行 pmm fetch", "msg.err.not-cached": "%s 未在缓存中(先运行 pmm fetch",
"msg.postinst-ok": "安装后脚本执行成功: %s", "msg.postinst-ok": "安装后脚本执行成功: %s",
"msg.warn.postinst": "安装后脚本返回非 0: %s", "msg.warn.postinst": "安装后脚本返回非 0: %s",
"msg.warn.postinst-missing": "安装后脚本缺失: %s" "msg.warn.postinst-missing": "安装后脚本缺失: %s",
"msg.warn.system-route": "安装后路由到系统路径时部分失败: %s"
} }