Validate that a resource name is safe for URL path interpolation. Valid names start with an alphanumeric character and contain only alphanumerics, dots, underscores, and hyphens — matching Podman's own naming rules. Names longer than [`MAX_NAME_LEN`] are rejected.
(name: &str)
| 55 | /// alphanumerics, dots, underscores, and hyphens — matching Podman's |
| 56 | /// own naming rules. Names longer than [`MAX_NAME_LEN`] are rejected. |
| 57 | pub fn validate_name(name: &str) -> Result<(), PodmanApiError> { |
| 58 | // Regex-equivalent: ^[a-zA-Z0-9][a-zA-Z0-9._-]*$ |
| 59 | if name.is_empty() { |
| 60 | return Err(PodmanApiError::InvalidInput( |
| 61 | "name must not be empty".to_string(), |
| 62 | )); |
| 63 | } |
| 64 | if name.len() > MAX_NAME_LEN { |
| 65 | return Err(PodmanApiError::InvalidInput(format!( |
| 66 | "name exceeds maximum length of {MAX_NAME_LEN} characters (got {})", |
| 67 | name.len() |
| 68 | ))); |
| 69 | } |
| 70 | let bytes = name.as_bytes(); |
| 71 | if !bytes[0].is_ascii_alphanumeric() { |
| 72 | return Err(PodmanApiError::InvalidInput(format!( |
| 73 | "name must start with an alphanumeric character: {name:?}" |
| 74 | ))); |
| 75 | } |
| 76 | if !bytes |
| 77 | .iter() |
| 78 | .all(|&b| b.is_ascii_alphanumeric() || b == b'.' || b == b'_' || b == b'-') |
| 79 | { |
| 80 | return Err(PodmanApiError::InvalidInput(format!( |
| 81 | "name contains invalid characters: {name:?}" |
| 82 | ))); |
| 83 | } |
| 84 | Ok(()) |
| 85 | } |
| 86 | |
| 87 | /// A container state snapshot returned by inspect APIs. |
| 88 | #[derive(Debug, Clone, serde::Deserialize)] |
no test coverage detected