From 06d7f2011a56783be7bc08a6f2a820a01328d98d Mon Sep 17 00:00:00 2001 From: JGZYES Date: Sun, 6 Sep 2026 17:00:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20pmm=20system-install=20mode=20(default)?= =?UTF-8?q?=20=E2=80=94=20/usr/bin,=20/etc/pmm,=20system=20lib,=20no=20env?= =?UTF-8?q?=20vars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/, etc -> /etc/pmm/, else -> /usr/share/pmm/; 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 local mode keeps the old ~/.pmm + PATH/LD_LIBRARY_PATH behavior. Verified: routing moves (no double multiarch), and -p local mode still writes env. --- src/i18n.c | 4 +-- src/pdm.c | 70 +++++++++++++++++++++++++++++-------- src/pmm.c | 16 +++++++-- src/pmm.h | 4 +++ web/mirror/lang/en-US.pjson | 3 +- web/mirror/lang/zh-CN.pjson | 3 +- 6 files changed, 79 insertions(+), 21 deletions(-) diff --git a/src/i18n.c b/src/i18n.c index 935a071..1332cc8 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -54,7 +54,7 @@ static const char *kBuiltinZh = "\"msg.hash-sha256\":\"sha256: %s\",\"msg.hash-sha1\":\"sha1: %s\"," "\"msg.installing\":\"正在安装 %s ...\",\"msg.installed\":\"已安装 %s\"," "\"msg.checksum-ok\":\"%s 校验 OK: %s\",\"msg.checksum-mismatch\":\"校验不匹配 (%s)!\"," -"\"msg.resolving-dep\":\"正在解析依赖 %s%s%s\",\"msg.dep-satisfied\":\"依赖 %s%s%s 已装/被提供,跳过\",\"msg.registry-ok\":\"注册表 sha256 OK: %s\",\"msg.cache-cleared\":\"已清理缓存: %d 个文件,释放 %.1f KB\",\"msg.offline-using-cache\":\"离线: 使用缓存 %s\",\"msg.err.not-cached\":\"%s 未在缓存中(先运行 pmm fetch)\",\"msg.postinst-ok\":\"安装后脚本执行成功: %s\",\"msg.warn.postinst\":\"安装后脚本返回非 0: %s\",\"msg.warn.postinst-missing\":\"安装后脚本缺失: %s\",\"msg.doctor-issues\":\"doctor: 发现 %d 个问题\",\"msg.self-up-to-date\":\"当前 v%s 已是最新(v%s),跳过升级\"," +"\"msg.resolving-dep\":\"正在解析依赖 %s%s%s\",\"msg.dep-satisfied\":\"依赖 %s%s%s 已装/被提供,跳过\",\"msg.registry-ok\":\"注册表 sha256 OK: %s\",\"msg.cache-cleared\":\"已清理缓存: %d 个文件,释放 %.1f KB\",\"msg.offline-using-cache\":\"离线: 使用缓存 %s\",\"msg.err.not-cached\":\"%s 未在缓存中(先运行 pmm fetch)\",\"msg.postinst-ok\":\"安装后脚本执行成功: %s\",\"msg.warn.postinst\":\"安装后脚本返回非 0: %s\",\"msg.warn.postinst-missing\":\"安装后脚本缺失: %s\",\"msg.warn.system-route\":\"安装后路由到系统路径时部分失败: %s\",\"msg.doctor-issues\":\"doctor: 发现 %d 个问题\",\"msg.self-up-to-date\":\"当前 v%s 已是最新(v%s),跳过升级\"," "\"msg.path-exists\":\"PATH 已包含 PMM 目录\",\"msg.err.registry-not-found\":\"找不到软件包 '%s'\"," "\"msg.pmm-self-replaced\":\"pmm 已更新到 %s\",\"msg.pmm-self-hint\":\"无法覆盖 %s(需 root/管理员);新版本在 %s。请将其加入 PATH 并在当前 shell 运行 hash -r\"," "\"msg.err.usage\":\"用法\",\"msg.err.unknown-cmd\":\"未知命令 '%s' (试试 'pmm help')\"," @@ -69,7 +69,7 @@ static const char *kBuiltinZh = static const char *kBuiltinEn = -"{\"help.banner\":\"PMM %s (%s)\",\"help.usage\":\"usage:\",\"help.commands\":\"commands:\",\"help.options\":\"options:\",\"help.common\":\"common commands:\",\"cmd.list\":\"list\",\"cmd.info\":\"info\",\"cmd.search\":\"search\",\"cmd.install\":\"install\",\"cmd.remove\":\"remove\",\"cmd.update\":\"update\",\"cmd.upgrade\":\"upgrade\",\"cmd.mirror\":\"mirror\",\"cmd.self-update\":\"self-update\",\"cmd.version\":\"version\",\"cmd.help\":\"help\",\"desc.list\":\"list packages by name\",\"desc.info\":\"show detailed info for a package\",\"desc.search\":\"search packages by keyword\",\"desc.install\":\"install a package by name\",\"desc.remove\":\"uninstall a package by name\",\"desc.update\":\"refresh the registry index (apt-style)\",\"desc.upgrade\":\"upgrade all installed packages\",\"desc.mirror\":\"list / manage mirrors\",\"desc.self-update\":\"update the pmm tool itself\",\"desc.version\":\"show version\",\"desc.help\":\"show help\",\"opt.p-drive\":\"install under :\\\\\\\\.pmm\",\"opt.no-color\":\"omit ANSI colours on a terminal (PMM_NO_COLOR=1 too)\",\"opt.quiet\":\"only print errors/warnings (suppress info/success)\",\"opt.verbose\":\"print extra detail\",\"msg.looking-up\":\"looking up %s in mirror %s\",\"msg.selected\":\"selected %s@%s (os=%s arch=%s)\",\"msg.downloading\":\"downloading %s%s\",\"msg.downloaded\":\"downloaded %s\",\"msg.hash-sha256\":\"sha256: %s\",\"msg.hash-sha1\":\"sha1: %s\",\"msg.sha256\":\"sha256: %s %s\",\"msg.sha1\":\"sha1: %s %s\",\"msg.installing\":\"installing %s ...\",\"msg.installing-file\":\"installing local file %s\",\"msg.installed\":\"installed %s\",\"msg.removed\":\"removed %s (%d files)\",\"msg.packed\":\"packed %s (%s %s) -> %s\",\"msg.checksum-ok\":\"%s checksum OK: %s\",\"msg.checksum-mismatch\":\"CHECKSUM MISMATCH (%s)!\\n expected: %s\\n actual: %s\",\"msg.registry-ok\":\"registry sha256 OK: %s\",\"msg.registry-not-found\":\"package '%s' not found in any registry mirror\",\"msg.no-version\":\"no version of '%s' for os=%s arch=%s satisfying '%s'\",\"msg.up-to-date\":\"%s %s is up to date (latest %s)\",\"msg.upgrading\":\"%s: %s -> %s\",\"msg.upgraded\":\"upgraded %d package(s).\",\"msg.no-installed\":\"no installed packages.\",\"msg.registry-empty\":\"registry index is empty.\",\"msg.registry-updated\":\"updated registry index: %d/%d packages cached.\",\"msg.skipping-no-registry\":\"skipping %s: no registry entry\",\"msg.no-match\":\"no package matches '%s'\",\"msg.description\":\"description: %s\",\"msg.cleaning-cache\":\"cleaning cache %s\",\"msg.drive-set\":\"install drive set to %c:\",\"msg.path-set\":\"install path set to %s\",\"msg.path-adding\":\"adding to PATH: %s\",\"msg.path-exists\":\"PATH already contains PMM dirs\",\"msg.path-updated\":\"PATH updated for new shells (reopen a terminal or run: setx) (user-level)\",\"msg.path-reload\":\"updated %s (reload your shell)\",\"msg.registered\":\"registered '%s' %s in Installed Apps (uninstall via pmm remove %s)\",\"msg.unregistered\":\"removed '%s' from Installed Apps\",\"msg.mirror-added\":\"mirror '%s' added\",\"msg.mirror-active\":\"active mirror set to '%s'\",\"msg.mirror-removed\":\"mirror '%s' removed\",\"msg.lang-set\":\"language set to '%s'\",\"msg.setting-set\":\"set %s = %s\",\"msg.empty-path\":\"empty file path\",\"msg.verifying-native\":\"verifying %s is a native %s binary...\",\"msg.resolving-dep\":\"resolving dependency %s%s%s\",\"msg.err.usage\":\"usage:\",\"msg.err.not-found\":\"package '%s' not found\",\"msg.err.not-installed\":\"package '%s' is not installed\",\"msg.err.empty-path\":\"empty file path\",\"msg.err.registry-not-found\":\"package '%s' not found in any registry mirror\",\"msg.err.no-suitable-asset\":\"no suitable %s asset found in latest release of %s\",\"msg.err.unknown-cmd\":\"unknown command '%s' (try 'pmm help')\",\"msg.err.failed-install\":\"failed to install %s\",\"msg.err.cannot-write\":\"cannot write %s\",\"msg.err.cannot-read\":\"cannot read %s\",\"msg.err.cannot-open\":\"cannot open file: %s\",\"msg.err.invalid-locale\":\"invalid language pack: %s\",\"msg.err.download-failed\":\"failed to download %s\",\"msg.err.no-registry-mirror\":\"no registry mirror configured. Add to ~/.pmm/mirror.ini\",\"msg.err.no-mirror\":\"no mirrors configured (use: pmm mirror add)\",\"msg.err.no-mirror-file\":\"no mirror file\",\"msg.err.no-registry-index\":\"no registry index (packages.json) available\",\"msg.err.bad-registry-index\":\"bad registry index\",\"msg.err.bad-entry\":\"bad registry entry '%s'\",\"msg.err.bad-registry-entry\":\"bad registry entry for '%s' (%s)\",\"msg.err.checksum-mismatch-file\":\"checksum mismatch for %s in %s\",\"msg.err.no-control\":\"%s has no pdm-control file\",\"msg.err.no-package\":\"pdm-control missing 'Package:' field\",\"msg.err.tar-control\":\"tar (control) failed\",\"msg.err.tar-data\":\"tar (data) failed\",\"msg.err.not-pdm\":\"'%s' is not a .pdm file\",\"msg.err.no-tar\":\"cannot run tar\",\"msg.err.bad-archive\":\"not a valid .pdm archive: %s\",\"msg.err.no-control-tar\":\"missing control.tar.gz in %s\",\"msg.err.extract\":\"data extraction failed\",\"msg.err.oom\":\"out of memory\",\"msg.err.json-parse\":\"JSON parse error: %s\",\"msg.err.unknown-host\":\"unknown host '%s'\",\"msg.err.checksum-refuse\":\"refusing to install: checksum verification failed\",\"msg.err.registry-entry-no-url\":\"registry entry for '%s' has no url\",\"msg.err.rpm-stage\":\"cannot create rpm stage dir: %s\",\"msg.err.rpm-decompress\":\"rpm payload decompress/cpio failed (need %s)\",\"msg.err.rpm-copy\":\"failed to copy rpm payload into /\",\"msg.warn.parse-checksum\":\"warning: could not parse %s checksum file\",\"msg.warn.download-retry\":\"download failed, trying next source...\",\"msg.warn.not-usable\":\"%s is not a usable %s binary; will fall back\",\"msg.warn.no-checksum\":\"warning: no sha256sums member, skipping integrity check\",\"msg.warn.no-filelist\":\"warning: could not record file list\",\"msg.warn.no-register\":\"warning: could not register '%s' in Installed Apps\",\"msg.api-unreachable\":\"could not reach a known release API for %s\",\"msg.retrying-asset\":\"retrying with %s (%s)\",\"mirror.sources\":\"mirrors:\",\"mirror.checking\":\"checking registry mirrors...\",\"mirror.result\":\"result: %d/%d sources reachable\",\"lang.packs-in\":\"language packs in %s:\",\"desc.clean\":\"clean cache\",\"desc.cache\":\"manage download cache\",\"desc.fetch\":\"predownload to cache\",\"msg.dep-satisfied\":\"dependency %s%s%s already installed/provided, skipped\",\"msg.err.conflict\":\"cannot install %s: conflicts with installed %s\",\"msg.cache-cleared\":\"cache cleaned: %d files, freed %.1f KB\",\"msg.offline-using-cache\":\"offline: using cached %s\",\"msg.err.not-cached\":\"%s not in cache (run pmm fetch)\",\"msg.postinst-ok\":\"post-install script ran OK: %s\",\"msg.warn.postinst\":\"post-install script returned non-zero: %s\",\"msg.warn.postinst-missing\":\"post-install script missing: %s\",\"msg.self-up-to-date\":\"already up to date (v%s, latest v%s), skipping upgrade\",\"desc.doctor\":\"diagnose\",\"msg.doctor-issues\":\"doctor: found %d issue(s)\"}"; +"{\"help.banner\":\"PMM %s (%s)\",\"help.usage\":\"usage:\",\"help.commands\":\"commands:\",\"help.options\":\"options:\",\"help.common\":\"common commands:\",\"cmd.list\":\"list\",\"cmd.info\":\"info\",\"cmd.search\":\"search\",\"cmd.install\":\"install\",\"cmd.remove\":\"remove\",\"cmd.update\":\"update\",\"cmd.upgrade\":\"upgrade\",\"cmd.mirror\":\"mirror\",\"cmd.self-update\":\"self-update\",\"cmd.version\":\"version\",\"cmd.help\":\"help\",\"desc.list\":\"list packages by name\",\"desc.info\":\"show detailed info for a package\",\"desc.search\":\"search packages by keyword\",\"desc.install\":\"install a package by name\",\"desc.remove\":\"uninstall a package by name\",\"desc.update\":\"refresh the registry index (apt-style)\",\"desc.upgrade\":\"upgrade all installed packages\",\"desc.mirror\":\"list / manage mirrors\",\"desc.self-update\":\"update the pmm tool itself\",\"desc.version\":\"show version\",\"desc.help\":\"show help\",\"opt.p-drive\":\"install under :\\\\\\\\.pmm\",\"opt.no-color\":\"omit ANSI colours on a terminal (PMM_NO_COLOR=1 too)\",\"opt.quiet\":\"only print errors/warnings (suppress info/success)\",\"opt.verbose\":\"print extra detail\",\"msg.looking-up\":\"looking up %s in mirror %s\",\"msg.selected\":\"selected %s@%s (os=%s arch=%s)\",\"msg.downloading\":\"downloading %s%s\",\"msg.downloaded\":\"downloaded %s\",\"msg.hash-sha256\":\"sha256: %s\",\"msg.hash-sha1\":\"sha1: %s\",\"msg.sha256\":\"sha256: %s %s\",\"msg.sha1\":\"sha1: %s %s\",\"msg.installing\":\"installing %s ...\",\"msg.installing-file\":\"installing local file %s\",\"msg.installed\":\"installed %s\",\"msg.removed\":\"removed %s (%d files)\",\"msg.packed\":\"packed %s (%s %s) -> %s\",\"msg.checksum-ok\":\"%s checksum OK: %s\",\"msg.checksum-mismatch\":\"CHECKSUM MISMATCH (%s)!\\n expected: %s\\n actual: %s\",\"msg.registry-ok\":\"registry sha256 OK: %s\",\"msg.registry-not-found\":\"package '%s' not found in any registry mirror\",\"msg.no-version\":\"no version of '%s' for os=%s arch=%s satisfying '%s'\",\"msg.up-to-date\":\"%s %s is up to date (latest %s)\",\"msg.upgrading\":\"%s: %s -> %s\",\"msg.upgraded\":\"upgraded %d package(s).\",\"msg.no-installed\":\"no installed packages.\",\"msg.registry-empty\":\"registry index is empty.\",\"msg.registry-updated\":\"updated registry index: %d/%d packages cached.\",\"msg.skipping-no-registry\":\"skipping %s: no registry entry\",\"msg.no-match\":\"no package matches '%s'\",\"msg.description\":\"description: %s\",\"msg.cleaning-cache\":\"cleaning cache %s\",\"msg.drive-set\":\"install drive set to %c:\",\"msg.path-set\":\"install path set to %s\",\"msg.path-adding\":\"adding to PATH: %s\",\"msg.path-exists\":\"PATH already contains PMM dirs\",\"msg.path-updated\":\"PATH updated for new shells (reopen a terminal or run: setx) (user-level)\",\"msg.path-reload\":\"updated %s (reload your shell)\",\"msg.registered\":\"registered '%s' %s in Installed Apps (uninstall via pmm remove %s)\",\"msg.unregistered\":\"removed '%s' from Installed Apps\",\"msg.mirror-added\":\"mirror '%s' added\",\"msg.mirror-active\":\"active mirror set to '%s'\",\"msg.mirror-removed\":\"mirror '%s' removed\",\"msg.lang-set\":\"language set to '%s'\",\"msg.setting-set\":\"set %s = %s\",\"msg.empty-path\":\"empty file path\",\"msg.verifying-native\":\"verifying %s is a native %s binary...\",\"msg.resolving-dep\":\"resolving dependency %s%s%s\",\"msg.err.usage\":\"usage:\",\"msg.err.not-found\":\"package '%s' not found\",\"msg.err.not-installed\":\"package '%s' is not installed\",\"msg.err.empty-path\":\"empty file path\",\"msg.err.registry-not-found\":\"package '%s' not found in any registry mirror\",\"msg.err.no-suitable-asset\":\"no suitable %s asset found in latest release of %s\",\"msg.err.unknown-cmd\":\"unknown command '%s' (try 'pmm help')\",\"msg.err.failed-install\":\"failed to install %s\",\"msg.err.cannot-write\":\"cannot write %s\",\"msg.err.cannot-read\":\"cannot read %s\",\"msg.err.cannot-open\":\"cannot open file: %s\",\"msg.err.invalid-locale\":\"invalid language pack: %s\",\"msg.err.download-failed\":\"failed to download %s\",\"msg.err.no-registry-mirror\":\"no registry mirror configured. Add to ~/.pmm/mirror.ini\",\"msg.err.no-mirror\":\"no mirrors configured (use: pmm mirror add)\",\"msg.err.no-mirror-file\":\"no mirror file\",\"msg.err.no-registry-index\":\"no registry index (packages.json) available\",\"msg.err.bad-registry-index\":\"bad registry index\",\"msg.err.bad-entry\":\"bad registry entry '%s'\",\"msg.err.bad-registry-entry\":\"bad registry entry for '%s' (%s)\",\"msg.err.checksum-mismatch-file\":\"checksum mismatch for %s in %s\",\"msg.err.no-control\":\"%s has no pdm-control file\",\"msg.err.no-package\":\"pdm-control missing 'Package:' field\",\"msg.err.tar-control\":\"tar (control) failed\",\"msg.err.tar-data\":\"tar (data) failed\",\"msg.err.not-pdm\":\"'%s' is not a .pdm file\",\"msg.err.no-tar\":\"cannot run tar\",\"msg.err.bad-archive\":\"not a valid .pdm archive: %s\",\"msg.err.no-control-tar\":\"missing control.tar.gz in %s\",\"msg.err.extract\":\"data extraction failed\",\"msg.err.oom\":\"out of memory\",\"msg.err.json-parse\":\"JSON parse error: %s\",\"msg.err.unknown-host\":\"unknown host '%s'\",\"msg.err.checksum-refuse\":\"refusing to install: checksum verification failed\",\"msg.err.registry-entry-no-url\":\"registry entry for '%s' has no url\",\"msg.err.rpm-stage\":\"cannot create rpm stage dir: %s\",\"msg.err.rpm-decompress\":\"rpm payload decompress/cpio failed (need %s)\",\"msg.err.rpm-copy\":\"failed to copy rpm payload into /\",\"msg.warn.parse-checksum\":\"warning: could not parse %s checksum file\",\"msg.warn.download-retry\":\"download failed, trying next source...\",\"msg.warn.not-usable\":\"%s is not a usable %s binary; will fall back\",\"msg.warn.no-checksum\":\"warning: no sha256sums member, skipping integrity check\",\"msg.warn.no-filelist\":\"warning: could not record file list\",\"msg.warn.no-register\":\"warning: could not register '%s' in Installed Apps\",\"msg.api-unreachable\":\"could not reach a known release API for %s\",\"msg.retrying-asset\":\"retrying with %s (%s)\",\"mirror.sources\":\"mirrors:\",\"mirror.checking\":\"checking registry mirrors...\",\"mirror.result\":\"result: %d/%d sources reachable\",\"lang.packs-in\":\"language packs in %s:\",\"desc.clean\":\"clean cache\",\"desc.cache\":\"manage download cache\",\"desc.fetch\":\"predownload to cache\",\"msg.dep-satisfied\":\"dependency %s%s%s already installed/provided, skipped\",\"msg.err.conflict\":\"cannot install %s: conflicts with installed %s\",\"msg.cache-cleared\":\"cache cleaned: %d files, freed %.1f KB\",\"msg.offline-using-cache\":\"offline: using cached %s\",\"msg.err.not-cached\":\"%s not in cache (run pmm fetch)\",\"msg.postinst-ok\":\"post-install script ran OK: %s\",\"msg.warn.postinst\":\"post-install script returned non-zero: %s\",\"msg.warn.postinst-missing\":\"post-install script missing: %s\",\"msg.warn.system-route\":\"some files failed to route to system paths: %s\",\"msg.self-up-to-date\":\"already up to date (v%s, latest v%s), skipping upgrade\",\"desc.doctor\":\"diagnose\",\"msg.doctor-issues\":\"doctor: found %d issue(s)\"}"; /* Which built-in fallback matches the current locale? en -> en-US, else zh-CN. */ static const char *builtin_source(void) { diff --git a/src/pdm.c b/src/pdm.c index 678682d..c61d79f 100644 --- a/src/pdm.c +++ b/src/pdm.c @@ -597,6 +597,34 @@ int pdm_install_file(const char *pdmfile) { 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/, + * else->/usr/share/pmm/) 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 */ snprintf(cmd, sizeof(cmd), "%s/%s.info", db, pkg); 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", pkg, ver ? ver : "0.0.0", base_name(pdmfile), ctl); fprintf(dbf, "Files:\n"); - 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); + if (sys_mode) { + FILE *df = fopen(destfile, "r"); + if (df) { + char ln[2048]; + while (fgets(ln, sizeof(ln), df)) fputs(ln, dbf); + fclose(df); + } else { + pmm_warn(pmm_tr("msg.warn.no-filelist")); } - PMM_PCLOSE_READ(tf); } 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); } @@ -747,7 +786,8 @@ int pdm_remove(const char *name) { char *p = path; while (p[0] == '.' && p[1] == '/') p += 2; 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); n++; } diff --git a/src/pmm.c b/src/pmm.c index da64d5e..442b643 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -149,6 +149,16 @@ void pmm_set_install_path(const char *path) { } int pmm_flat_mode(void) { return g_base_path[0] ? 1 : 0; } +/* System-install mode: unix default (no -p ). 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 > * home/.pmm (when that drive is picked) > DEFAULT = D:\.pmm. * 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 snprintf(buf, size, "D:\\.pmm"); /* Windows DEFAULT -> D: */ #else - snprintf(buf, size, "%s/.pmm", home_dir()); /* unix default -> ~/.pmm */ + snprintf(buf, size, "/etc/pmm"); /* unix default -> system config dir */ #endif } 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) { + if (pmm_system_mode()) { snprintf(buf, size, "/var/cache/pmm"); mkdir_p(buf); return buf; } char base[1024]; pmm_base_dir(base, sizeof(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)); snprintf(buf, size, "%s/bin", base); /* Windows default -> \bin */ #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 } 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) { + if (pmm_system_mode()) return; /* system mode: /usr/bin & system libs are already found */ char home[1024]; pmm_config_dir(home, sizeof(home)); char base[1024]; diff --git a/src/pmm.h b/src/pmm.h index 42e2523..3d72f99 100644 --- a/src/pmm.h +++ b/src/pmm.h @@ -27,6 +27,10 @@ void pmm_set_install_path(const char *path); * into that directory (files flattened), without a root/bin sub-folder. */ 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. */ typedef struct { const char *progid; /* e.g. "Node.JSFile" */ diff --git a/web/mirror/lang/en-US.pjson b/web/mirror/lang/en-US.pjson index f1ccec1..6c9ece1 100644 --- a/web/mirror/lang/en-US.pjson +++ b/web/mirror/lang/en-US.pjson @@ -137,5 +137,6 @@ "msg.err.not-cached": "%s not in cache (run pmm fetch)", "msg.postinst-ok": "post-install script ran OK: %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" } diff --git a/web/mirror/lang/zh-CN.pjson b/web/mirror/lang/zh-CN.pjson index a9f9c04..fca8d1b 100644 --- a/web/mirror/lang/zh-CN.pjson +++ b/web/mirror/lang/zh-CN.pjson @@ -137,5 +137,6 @@ "msg.err.not-cached": "%s 未在缓存中(先运行 pmm fetch)", "msg.postinst-ok": "安装后脚本执行成功: %s", "msg.warn.postinst": "安装后脚本返回非 0: %s", - "msg.warn.postinst-missing": "安装后脚本缺失: %s" + "msg.warn.postinst-missing": "安装后脚本缺失: %s", + "msg.warn.system-route": "安装后路由到系统路径时部分失败: %s" }