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