firecracker_http_client/
validation.rs1use std::borrow::Cow;
2use std::path::Path;
3use validator::ValidationError;
4
5pub fn path_validation_error(message: impl Into<Cow<'static, str>>) -> ValidationError {
6 let mut err = ValidationError::new("invalid_path");
7 err.message = Some(message.into());
8 err
9}
10
11pub fn validate_unix_path(path: &str) -> Result<(), ValidationError> {
12 if path.is_empty() {
14 return Err(path_validation_error("Path cannot be empty"));
15 }
16
17 if !path.starts_with('/') {
19 return Err(path_validation_error("Path must be absolute"));
20 }
21
22 if path.contains('\0') || path.contains("..") {
24 return Err(path_validation_error(
25 "Path cannot contain parent directory references or null characters",
26 ));
27 }
28
29 if Path::new(path).components().count() == 0 {
31 return Err(ValidationError::new("path_invalid_format"));
32 }
33
34 Ok(())
35}
36
37pub fn validate_existing_path(path: &str) -> Result<(), ValidationError> {
39 validate_unix_path(path)?;
40
41 if !Path::new(path).exists() {
42 return Err(path_validation_error("Path does not exist"));
43 }
44
45 Ok(())
46}
47
48pub fn validate_writable_path(path: &str) -> Result<(), ValidationError> {
50 validate_unix_path(path)?;
51
52 let path = Path::new(path);
53
54 if path.exists() {
56 #[cfg(unix)]
57 {
58 use std::os::unix::fs::MetadataExt;
59 if let Ok(metadata) = path.metadata() {
60 let mode = metadata.mode();
61 if mode & 0o200 == 0 {
62 return Err(path_validation_error("Path is not writable"));
63 }
64 }
65 }
66 } else {
67 if let Some(parent) = path.parent() {
69 if !parent.exists() {
70 return Err(path_validation_error("Parent directory does not exist"));
71 }
72 #[cfg(unix)]
73 {
74 use std::os::unix::fs::MetadataExt;
75 if let Ok(metadata) = parent.metadata() {
76 let mode = metadata.mode();
77 if mode & 0o200 == 0 {
78 return Err(path_validation_error("Parent directory is not writable"));
79 }
80 }
81 }
82 }
83 }
84
85 Ok(())
86}
87
88#[macro_export]
90macro_rules! validate_path {
91 ($field:expr, $validator:expr) => {
92 if let Err(e) = $validator($field) {
93 let mut errors = ValidationErrors::new();
94 errors.add("path", e);
95 return Err(errors.into());
96 }
97 };
98}