1#[cfg(any(fuchsia_api_level_at_least = "PLATFORM", not(fuchsia_api_level_at_least = "NEXT")))]
8use crate::common::stricter_or_same_rights;
9use crate::directory::entry::EntryInfo;
10
11use byteorder::{LittleEndian, WriteBytesExt as _};
12use fidl_fuchsia_io as fio;
13use static_assertions::assert_eq_size;
14use std::io::Write as _;
15use std::mem::size_of;
16#[cfg(any(fuchsia_api_level_at_least = "PLATFORM", not(fuchsia_api_level_at_least = "NEXT")))]
17use zx_status::Status;
18
19#[cfg(any(fuchsia_api_level_at_least = "PLATFORM", not(fuchsia_api_level_at_least = "NEXT")))]
24pub(crate) fn check_child_connection_flags(
25 parent_flags: fio::OpenFlags,
26 mut flags: fio::OpenFlags,
27) -> Result<fio::OpenFlags, Status> {
28 if flags & (fio::OpenFlags::NOT_DIRECTORY | fio::OpenFlags::DIRECTORY)
29 == fio::OpenFlags::NOT_DIRECTORY | fio::OpenFlags::DIRECTORY
30 {
31 return Err(Status::INVALID_ARGS);
32 }
33
34 if flags.intersects(fio::OpenFlags::CREATE_IF_ABSENT)
36 && !flags.intersects(fio::OpenFlags::CREATE)
37 {
38 return Err(Status::INVALID_ARGS);
39 }
40
41 if flags.intersects(fio::OpenFlags::CLONE_SAME_RIGHTS) {
43 return Err(Status::INVALID_ARGS);
44 }
45
46 if !parent_flags.intersects(fio::OpenFlags::RIGHT_EXECUTABLE) {
48 flags &= !fio::OpenFlags::POSIX_EXECUTABLE;
49 }
50 if !parent_flags.intersects(fio::OpenFlags::RIGHT_WRITABLE) {
51 flags &= !fio::OpenFlags::POSIX_WRITABLE;
52 }
53
54 if flags.intersects(fio::OpenFlags::CREATE)
56 && !parent_flags.intersects(fio::OpenFlags::RIGHT_WRITABLE)
57 {
58 return Err(Status::ACCESS_DENIED);
59 }
60
61 if stricter_or_same_rights(parent_flags, flags) {
62 Ok(flags)
63 } else {
64 Err(Status::ACCESS_DENIED)
65 }
66}
67
68pub(crate) fn encode_dirent(
73 buf: &mut Vec<u8>,
74 max_bytes: u64,
75 entry: &EntryInfo,
76 name: &str,
77) -> bool {
78 let header_size = size_of::<u64>() + size_of::<u8>() + size_of::<u8>();
79
80 assert_eq_size!(u64, usize);
81
82 if buf.len() + header_size + name.len() > max_bytes as usize {
83 return false;
84 }
85
86 assert!(
87 name.len() <= fio::MAX_NAME_LENGTH as usize,
88 "Entry names are expected to be no longer than MAX_FILENAME ({}) bytes.\n\
89 Got entry: '{}'\n\
90 Length: {} bytes",
91 fio::MAX_NAME_LENGTH,
92 name,
93 name.len()
94 );
95
96 assert!(
97 fio::MAX_NAME_LENGTH <= u8::max_value() as u64,
98 "Expecting to be able to store MAX_FILENAME ({}) in one byte.",
99 fio::MAX_NAME_LENGTH
100 );
101
102 buf.write_u64::<LittleEndian>(entry.inode())
103 .expect("out should be an in memory buffer that grows as needed");
104 buf.write_u8(name.len() as u8).expect("out should be an in memory buffer that grows as needed");
105 buf.write_u8(entry.type_().into_primitive())
106 .expect("out should be an in memory buffer that grows as needed");
107 buf.write_all(name.as_ref()).expect("out should be an in memory buffer that grows as needed");
108
109 true
110}