From 29c97fcbb06b7c2463141c437afb95076e08baf2 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 7 Nov 2025 11:20:13 -0700 Subject: [PATCH] sdk fixes --- core/startos/src/service/mod.rs | 45 +++++++++++++-------- sdk/package/lib/mainFn/CommandController.ts | 4 ++ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/core/startos/src/service/mod.rs b/core/startos/src/service/mod.rs index b4c895ee0..701d5655a 100644 --- a/core/startos/src/service/mod.rs +++ b/core/startos/src/service/mod.rs @@ -725,6 +725,8 @@ pub struct AttachParams { name: Option, #[ts(type = "string | null")] image_id: Option, + #[ts(type = "string | null")] + user: Option, } pub async fn attach( ctx: RpcContext, @@ -738,6 +740,7 @@ pub async fn attach( subcontainer, image_id, name, + user, }: AttachParams, ) -> Result { let (container_id, subcontainer_id, image_id, workdir, root_command) = { @@ -814,9 +817,26 @@ pub async fn attach( .join("etc") .join("passwd"); - let root_command = get_passwd_root_command(passwd).await; + let image_meta = serde_json::from_str::( + &tokio::fs::read_to_string( + root_dir + .join("media/startos/images/") + .join(&image_id) + .with_extension("json"), + ) + .await?, + ) + .with_kind(ErrorKind::Deserialization)?; - let workdir = attach_workdir(&image_id, &root_dir).await?; + let root_command = get_passwd_command( + passwd, + user.as_deref() + .or_else(|| image_meta["user"].as_str()) + .unwrap_or("root"), + ) + .await; + + let workdir = image_meta["workdir"].as_str().map(|s| s.to_owned()); if subcontainer_ids.len() > 1 { let subcontainer_ids = subcontainer_ids @@ -1051,19 +1071,7 @@ pub async fn attach( Ok(guid) } -async fn attach_workdir(image_id: &ImageId, root_dir: &Path) -> Result, Error> { - let path_str = root_dir.join("media/startos/images/"); - - let mut subcontainer_json = - tokio::fs::File::open(path_str.join(image_id).with_extension("json")).await?; - let mut contents = vec![]; - subcontainer_json.read_to_end(&mut contents).await?; - let subcontainer_json: serde_json::Value = - serde_json::from_slice(&contents).with_kind(ErrorKind::Filesystem)?; - Ok(subcontainer_json["workdir"].as_str().map(|x| x.to_string())) -} - -async fn get_passwd_root_command(etc_passwd_path: PathBuf) -> RootCommand { +async fn get_passwd_command(etc_passwd_path: PathBuf, user: &str) -> RootCommand { async { let mut file = tokio::fs::File::open(etc_passwd_path).await?; @@ -1074,8 +1082,8 @@ async fn get_passwd_root_command(etc_passwd_path: PathBuf) -> RootCommand { for line in contents.split('\n') { let line_information = line.split(':').collect::>(); - if let (Some(&"root"), Some(shell)) = - (line_information.first(), line_information.last()) + if let (Some(&u), Some(shell)) = (line_information.first(), line_information.last()) + && u == user { return Ok(shell.to_string()); } @@ -1106,6 +1114,8 @@ pub struct CliAttachParams { #[arg(long, short)] name: Option, #[arg(long, short)] + user: Option, + #[arg(long, short)] image_id: Option, } #[instrument[skip_all]] @@ -1147,6 +1157,7 @@ pub async fn cli_attach( "subcontainer": params.subcontainer, "imageId": params.image_id, "name": params.name, + "user": params.user, }), ) .await?, diff --git a/sdk/package/lib/mainFn/CommandController.ts b/sdk/package/lib/mainFn/CommandController.ts index 156792dcf..b325ac585 100644 --- a/sdk/package/lib/mainFn/CommandController.ts +++ b/sdk/package/lib/mainFn/CommandController.ts @@ -77,10 +77,14 @@ export class CommandController< if (exec.runAsInit) { childProcess = await subcontainer!.launch(commands, { env: exec.env, + user: exec.user, + cwd: exec.cwd, }) } else { childProcess = await subcontainer!.spawn(commands, { env: exec.env, + user: exec.user, + cwd: exec.cwd, stdio: exec.onStdout || exec.onStderr ? "pipe" : "inherit", }) }