(openclaw_path: &Path)
| 286 | } |
| 287 | |
| 288 | fn resolve_openclaw_owner_spec(openclaw_path: &Path) -> Result<Option<String>, Box<dyn Error>> { |
| 289 | use std::os::unix::fs::MetadataExt; |
| 290 | |
| 291 | let read_owner = |path: &Path| -> Result<(u32, u32), Box<dyn Error>> { |
| 292 | let metadata = std::fs::metadata(path)?; |
| 293 | Ok((metadata.uid(), metadata.gid())) |
| 294 | }; |
| 295 | |
| 296 | let file_owner = if openclaw_path.exists() { |
| 297 | Some(read_owner(openclaw_path)?) |
| 298 | } else { |
| 299 | None |
| 300 | }; |
| 301 | let parent_owner = openclaw_path |
| 302 | .parent() |
| 303 | .filter(|parent| parent.exists()) |
| 304 | .map(read_owner) |
| 305 | .transpose()?; |
| 306 | let root_entry_owner = { |
| 307 | let root = onboard::openclaw_config_root(openclaw_path); |
| 308 | if root.exists() { |
| 309 | let mut found = None; |
| 310 | for entry in std::fs::read_dir(root)? { |
| 311 | let entry = entry?; |
| 312 | found = Some(read_owner(&entry.path())?); |
| 313 | if let Some((uid, _)) = found |
| 314 | && uid != 0 |
| 315 | { |
| 316 | break; |
| 317 | } |
| 318 | } |
| 319 | found |
| 320 | } else { |
| 321 | None |
| 322 | } |
| 323 | }; |
| 324 | |
| 325 | let preferred = file_owner |
| 326 | .filter(|(uid, _)| *uid != 0) |
| 327 | .or_else(|| root_entry_owner.filter(|(uid, _)| *uid != 0)) |
| 328 | .or_else(|| parent_owner.filter(|(uid, _)| *uid != 0)) |
| 329 | .or(file_owner) |
| 330 | .or(root_entry_owner) |
| 331 | .or(parent_owner); |
| 332 | |
| 333 | Ok(preferred.map(|(uid, gid)| format!("{uid}:{gid}"))) |
| 334 | } |
| 335 | |
| 336 | fn chown_path(path: &Path, owner_spec: &str, recursive: bool) -> Result<(), Box<dyn Error>> { |
| 337 | let mut command = std::process::Command::new("chown"); |
no test coverage detected