diff --git a/CHANGELOG.md b/CHANGELOG.md index a76cc7a1..0c506528 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - #973: Enables CORS and JWT configuration for WebApplications in module.xml - #1110: Add `iriscli` and `ipm` container utility scripts that are auto-installed to `~/.local/bin/` and `~/bin/` so they work both inside and outside of containers (Unix/Linux only) - #971: Adds structured test output formats (JSON, YAML, Toon). Use `-f ` for a one-shot override or `config set TestReportFormat ` for a persistent default. Without either, legacy output is shown. Also adds `-output-file` for writing results to a file (including JUnit XML via `.xml` extension) and improves `-quiet` to suppress build noise. +- #1053: Add file system permissions check before install/load. ### Fixed - #1130: Fix issue with ORAS repositories pointing to some OCI registries that require authentication (e.g. ghcr.io) not accepting credentials properly. `repo -list` now shows an `Authenticated?` status for ORAS repos with credentials configured. diff --git a/src/cls/IPM/Main.cls b/src/cls/IPM/Main.cls index 3871ecdb..b6b44129 100644 --- a/src/cls/IPM/Main.cls +++ b/src/cls/IPM/Main.cls @@ -2351,6 +2351,12 @@ ClassMethod LoadInternal( set extension = $$$lcase($piece(tDirectoryName,".",*)) if ##class(%File).Exists(tDirectoryName) && ((extension="tgz") || (extension="tar.gz")) { set tTargetDirectory = $$$FileTempDirSys + if tTargetDirectory = ("-" _ -tTargetDirectory) { + $$$ThrowStatus($$$ERROR($$$GeneralError, "Failed to create system temporary directory. Error code: " _ -tTargetDirectory)) + } + if '##class(%Library.File).Writeable(tTargetDirectory) { + $$$ThrowStatus($$$ERROR($$$GeneralError, $$$FormatText("Insufficient file system permissions to write to '%1'. Cannot load module from archive.", tTargetDirectory))) + } if $get(pCommandInfo("data", "Verbose")) { write !,"Extracting archive to ",tTargetDirectory } diff --git a/src/cls/IPM/Utils/Module.cls b/src/cls/IPM/Utils/Module.cls index 56bf4059..902a2dbc 100644 --- a/src/cls/IPM/Utils/Module.cls +++ b/src/cls/IPM/Utils/Module.cls @@ -226,6 +226,15 @@ ClassMethod LoadModuleFromArchive( try { set tVerbose = $get(pParams("Verbose")) + // Check base IPM install location + set ipmBaseDir = ##class(%Library.File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm") + set writeCheckDir = $select(##class(%File).DirectoryExists(ipmBaseDir): ipmBaseDir, 1: ##class(%SYSTEM.Util).DataDirectory()) + if '##class(%Library.File).Writeable(writeCheckDir) { + set msg = $$$FormatText("Insufficient file system permissions to write to '%1'. Cannot install module '%2'.", writeCheckDir, pModuleName) + set tSC = $$$ERROR($$$GeneralError, msg) + quit + } + // Modules have a well-defined location inside the archive set tTargetDirectory = ##class(%Library.File).NormalizeDirectory(##class(%SYSTEM.Util).DataDirectory() _ "ipm/" _ pModuleName _ "/" _ pModuleVersion) if ##class(%File).DirectoryExists(tTargetDirectory) {