xref: /aosp_15_r20/external/crosvm/fuse/src/server.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2019 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::max;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::min;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryInto;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::CStr;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::MaybeUninit;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::AsRawFd;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
16*bb4ee6a4SAndroid Build Coastguard Worker use base::pagesize;
17*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
18*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
19*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
20*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
21*bb4ee6a4SAndroid Build Coastguard Worker 
22*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::Context;
23*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::DirEntry;
24*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::DirectoryIterator;
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::Entry;
26*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::FileSystem;
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::GetxattrReply;
28*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::IoctlReply;
29*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::ListxattrReply;
30*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::ZeroCopyReader;
31*bb4ee6a4SAndroid Build Coastguard Worker use crate::filesystem::ZeroCopyWriter;
32*bb4ee6a4SAndroid Build Coastguard Worker use crate::sys::*;
33*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error;
34*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result;
35*bb4ee6a4SAndroid Build Coastguard Worker 
36*bb4ee6a4SAndroid Build Coastguard Worker const DIRENT_PADDING: [u8; 8] = [0; 8];
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker const SELINUX_XATTR_CSTR: &[u8] = b"security.selinux\0";
39*bb4ee6a4SAndroid Build Coastguard Worker 
40*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for reading from the underlying FUSE endpoint.
41*bb4ee6a4SAndroid Build Coastguard Worker pub trait Reader: io::Read {
read_struct<T: AsBytes + FromBytes + FromZeroes>(&mut self) -> Result<T>42*bb4ee6a4SAndroid Build Coastguard Worker     fn read_struct<T: AsBytes + FromBytes + FromZeroes>(&mut self) -> Result<T> {
43*bb4ee6a4SAndroid Build Coastguard Worker         let mut out = T::new_zeroed();
44*bb4ee6a4SAndroid Build Coastguard Worker         self.read_exact(out.as_bytes_mut())
45*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(Error::DecodeMessage)?;
46*bb4ee6a4SAndroid Build Coastguard Worker         Ok(out)
47*bb4ee6a4SAndroid Build Coastguard Worker     }
48*bb4ee6a4SAndroid Build Coastguard Worker }
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker impl<R: Reader> Reader for &'_ mut R {}
51*bb4ee6a4SAndroid Build Coastguard Worker 
52*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for writing to the underlying FUSE endpoint. The FUSE device expects the write
53*bb4ee6a4SAndroid Build Coastguard Worker /// operation to happen in one write transaction. Since there are cases when data needs to be
54*bb4ee6a4SAndroid Build Coastguard Worker /// generated earlier than the header, it implies the writer implementation to keep an internal
55*bb4ee6a4SAndroid Build Coastguard Worker /// buffer. The buffer then can be flushed once header and data are both prepared.
56*bb4ee6a4SAndroid Build Coastguard Worker pub trait Writer: io::Write {
57*bb4ee6a4SAndroid Build Coastguard Worker     /// The type passed in to the closure in `write_at`. For most implementations, this should be
58*bb4ee6a4SAndroid Build Coastguard Worker     /// `Self`.
59*bb4ee6a4SAndroid Build Coastguard Worker     type ClosureWriter: Writer + ZeroCopyWriter;
60*bb4ee6a4SAndroid Build Coastguard Worker 
61*bb4ee6a4SAndroid Build Coastguard Worker     /// Allows a closure to generate and write data at the current writer's offset. The current
62*bb4ee6a4SAndroid Build Coastguard Worker     /// writer is passed as a mutable reference to the closure. As an example, this provides an
63*bb4ee6a4SAndroid Build Coastguard Worker     /// adapter for the read implementation of a filesystem to write directly to the final buffer
64*bb4ee6a4SAndroid Build Coastguard Worker     /// without generating the FUSE header first.
65*bb4ee6a4SAndroid Build Coastguard Worker     ///
66*bb4ee6a4SAndroid Build Coastguard Worker     /// Notes: An alternative implementation would be to return a slightly different writer for the
67*bb4ee6a4SAndroid Build Coastguard Worker     /// API client to write to the offset. Since the API needs to be called for more than one time,
68*bb4ee6a4SAndroid Build Coastguard Worker     /// it imposes some complexity to deal with borrowing and mutability. The current approach
69*bb4ee6a4SAndroid Build Coastguard Worker     /// simply does not need to create a different writer, thus no need to deal with the mentioned
70*bb4ee6a4SAndroid Build Coastguard Worker     /// complexity.
write_at<F>(&mut self, offset: usize, f: F) -> io::Result<usize> where F: Fn(&mut Self::ClosureWriter) -> io::Result<usize>71*bb4ee6a4SAndroid Build Coastguard Worker     fn write_at<F>(&mut self, offset: usize, f: F) -> io::Result<usize>
72*bb4ee6a4SAndroid Build Coastguard Worker     where
73*bb4ee6a4SAndroid Build Coastguard Worker         F: Fn(&mut Self::ClosureWriter) -> io::Result<usize>;
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker     /// Checks if the writer can still accept certain amount of data.
has_sufficient_buffer(&self, size: u32) -> bool76*bb4ee6a4SAndroid Build Coastguard Worker     fn has_sufficient_buffer(&self, size: u32) -> bool;
77*bb4ee6a4SAndroid Build Coastguard Worker }
78*bb4ee6a4SAndroid Build Coastguard Worker 
79*bb4ee6a4SAndroid Build Coastguard Worker impl<W: Writer> Writer for &'_ mut W {
80*bb4ee6a4SAndroid Build Coastguard Worker     type ClosureWriter = W::ClosureWriter;
81*bb4ee6a4SAndroid Build Coastguard Worker 
write_at<F>(&mut self, offset: usize, f: F) -> io::Result<usize> where F: Fn(&mut Self::ClosureWriter) -> io::Result<usize>,82*bb4ee6a4SAndroid Build Coastguard Worker     fn write_at<F>(&mut self, offset: usize, f: F) -> io::Result<usize>
83*bb4ee6a4SAndroid Build Coastguard Worker     where
84*bb4ee6a4SAndroid Build Coastguard Worker         F: Fn(&mut Self::ClosureWriter) -> io::Result<usize>,
85*bb4ee6a4SAndroid Build Coastguard Worker     {
86*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_at(offset, f)
87*bb4ee6a4SAndroid Build Coastguard Worker     }
88*bb4ee6a4SAndroid Build Coastguard Worker 
has_sufficient_buffer(&self, size: u32) -> bool89*bb4ee6a4SAndroid Build Coastguard Worker     fn has_sufficient_buffer(&self, size: u32) -> bool {
90*bb4ee6a4SAndroid Build Coastguard Worker         (**self).has_sufficient_buffer(size)
91*bb4ee6a4SAndroid Build Coastguard Worker     }
92*bb4ee6a4SAndroid Build Coastguard Worker }
93*bb4ee6a4SAndroid Build Coastguard Worker 
94*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for memory mapping for DAX.
95*bb4ee6a4SAndroid Build Coastguard Worker ///
96*bb4ee6a4SAndroid Build Coastguard Worker /// For some transports (like virtio) it may be possible to share a region of memory with the
97*bb4ee6a4SAndroid Build Coastguard Worker /// FUSE kernel driver so that it can access file contents directly without issuing read or
98*bb4ee6a4SAndroid Build Coastguard Worker /// write requests.  In this case the driver will instead send requests to map a section of a
99*bb4ee6a4SAndroid Build Coastguard Worker /// file into the shared memory region.
100*bb4ee6a4SAndroid Build Coastguard Worker pub trait Mapper {
101*bb4ee6a4SAndroid Build Coastguard Worker     /// Maps `size` bytes starting at `file_offset` bytes from within the given `fd` at `mem_offset`
102*bb4ee6a4SAndroid Build Coastguard Worker     /// bytes from the start of the memory region with `prot` protections. `mem_offset` must be
103*bb4ee6a4SAndroid Build Coastguard Worker     /// page aligned.
104*bb4ee6a4SAndroid Build Coastguard Worker     ///
105*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
106*bb4ee6a4SAndroid Build Coastguard Worker     /// * `mem_offset` - Page aligned offset into the memory region in bytes.
107*bb4ee6a4SAndroid Build Coastguard Worker     /// * `size` - Size of memory region in bytes.
108*bb4ee6a4SAndroid Build Coastguard Worker     /// * `fd` - File descriptor to mmap from.
109*bb4ee6a4SAndroid Build Coastguard Worker     /// * `file_offset` - Offset in bytes from the beginning of `fd` to start the mmap.
110*bb4ee6a4SAndroid Build Coastguard Worker     /// * `prot` - Protection of the memory region.
map( &self, mem_offset: u64, size: usize, fd: &dyn AsRawFd, file_offset: u64, prot: Protection, ) -> io::Result<()>111*bb4ee6a4SAndroid Build Coastguard Worker     fn map(
112*bb4ee6a4SAndroid Build Coastguard Worker         &self,
113*bb4ee6a4SAndroid Build Coastguard Worker         mem_offset: u64,
114*bb4ee6a4SAndroid Build Coastguard Worker         size: usize,
115*bb4ee6a4SAndroid Build Coastguard Worker         fd: &dyn AsRawFd,
116*bb4ee6a4SAndroid Build Coastguard Worker         file_offset: u64,
117*bb4ee6a4SAndroid Build Coastguard Worker         prot: Protection,
118*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()>;
119*bb4ee6a4SAndroid Build Coastguard Worker 
120*bb4ee6a4SAndroid Build Coastguard Worker     /// Unmaps `size` bytes at `offset` bytes from the start of the memory region. `offset` must be
121*bb4ee6a4SAndroid Build Coastguard Worker     /// page aligned.
122*bb4ee6a4SAndroid Build Coastguard Worker     ///
123*bb4ee6a4SAndroid Build Coastguard Worker     /// # Arguments
124*bb4ee6a4SAndroid Build Coastguard Worker     /// * `offset` - Page aligned offset into the arena in bytes.
125*bb4ee6a4SAndroid Build Coastguard Worker     /// * `size` - Size of memory region in bytes.
unmap(&self, offset: u64, size: u64) -> io::Result<()>126*bb4ee6a4SAndroid Build Coastguard Worker     fn unmap(&self, offset: u64, size: u64) -> io::Result<()>;
127*bb4ee6a4SAndroid Build Coastguard Worker }
128*bb4ee6a4SAndroid Build Coastguard Worker 
129*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, M: Mapper> Mapper for &'a M {
map( &self, mem_offset: u64, size: usize, fd: &dyn AsRawFd, file_offset: u64, prot: Protection, ) -> io::Result<()>130*bb4ee6a4SAndroid Build Coastguard Worker     fn map(
131*bb4ee6a4SAndroid Build Coastguard Worker         &self,
132*bb4ee6a4SAndroid Build Coastguard Worker         mem_offset: u64,
133*bb4ee6a4SAndroid Build Coastguard Worker         size: usize,
134*bb4ee6a4SAndroid Build Coastguard Worker         fd: &dyn AsRawFd,
135*bb4ee6a4SAndroid Build Coastguard Worker         file_offset: u64,
136*bb4ee6a4SAndroid Build Coastguard Worker         prot: Protection,
137*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<()> {
138*bb4ee6a4SAndroid Build Coastguard Worker         (**self).map(mem_offset, size, fd, file_offset, prot)
139*bb4ee6a4SAndroid Build Coastguard Worker     }
140*bb4ee6a4SAndroid Build Coastguard Worker 
unmap(&self, offset: u64, size: u64) -> io::Result<()>141*bb4ee6a4SAndroid Build Coastguard Worker     fn unmap(&self, offset: u64, size: u64) -> io::Result<()> {
142*bb4ee6a4SAndroid Build Coastguard Worker         (**self).unmap(offset, size)
143*bb4ee6a4SAndroid Build Coastguard Worker     }
144*bb4ee6a4SAndroid Build Coastguard Worker }
145*bb4ee6a4SAndroid Build Coastguard Worker 
146*bb4ee6a4SAndroid Build Coastguard Worker pub struct Server<F: FileSystem + Sync> {
147*bb4ee6a4SAndroid Build Coastguard Worker     fs: F,
148*bb4ee6a4SAndroid Build Coastguard Worker }
149*bb4ee6a4SAndroid Build Coastguard Worker 
150*bb4ee6a4SAndroid Build Coastguard Worker impl<F: FileSystem + Sync> Server<F> {
new(fs: F) -> Server<F>151*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(fs: F) -> Server<F> {
152*bb4ee6a4SAndroid Build Coastguard Worker         Server { fs }
153*bb4ee6a4SAndroid Build Coastguard Worker     }
154*bb4ee6a4SAndroid Build Coastguard Worker 
handle_message<R: Reader + ZeroCopyReader, W: Writer + ZeroCopyWriter, M: Mapper>( &self, mut r: R, w: W, mapper: M, ) -> Result<usize>155*bb4ee6a4SAndroid Build Coastguard Worker     pub fn handle_message<R: Reader + ZeroCopyReader, W: Writer + ZeroCopyWriter, M: Mapper>(
156*bb4ee6a4SAndroid Build Coastguard Worker         &self,
157*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
158*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
159*bb4ee6a4SAndroid Build Coastguard Worker         mapper: M,
160*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
161*bb4ee6a4SAndroid Build Coastguard Worker         let in_header: InHeader = r.read_struct()?;
162*bb4ee6a4SAndroid Build Coastguard Worker         cros_tracing::trace_simple_print!("fuse server: handle_message: in_header={:?}", in_header);
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker         if in_header.len
165*bb4ee6a4SAndroid Build Coastguard Worker             > size_of::<InHeader>() as u32 + size_of::<WriteIn>() as u32 + self.fs.max_buffer_size()
166*bb4ee6a4SAndroid Build Coastguard Worker         {
167*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
168*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
169*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
170*bb4ee6a4SAndroid Build Coastguard Worker                 w,
171*bb4ee6a4SAndroid Build Coastguard Worker             );
172*bb4ee6a4SAndroid Build Coastguard Worker         }
173*bb4ee6a4SAndroid Build Coastguard Worker         match Opcode::n(in_header.opcode) {
174*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Lookup) => self.lookup(in_header, r, w),
175*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Forget) => self.forget(in_header, r), // No reply.
176*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Getattr) => self.getattr(in_header, r, w),
177*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Setattr) => self.setattr(in_header, r, w),
178*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Readlink) => self.readlink(in_header, w),
179*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Symlink) => self.symlink(in_header, r, w),
180*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Mknod) => self.mknod(in_header, r, w),
181*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Mkdir) => self.mkdir(in_header, r, w),
182*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Unlink) => self.unlink(in_header, r, w),
183*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Rmdir) => self.rmdir(in_header, r, w),
184*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Rename) => self.rename(in_header, r, w),
185*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Link) => self.link(in_header, r, w),
186*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Open) => self.open(in_header, r, w),
187*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Read) => self.read(in_header, r, w),
188*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Write) => self.write(in_header, r, w),
189*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Statfs) => self.statfs(in_header, w),
190*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Release) => self.release(in_header, r, w),
191*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Fsync) => self.fsync(in_header, r, w),
192*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Setxattr) => self.setxattr(in_header, r, w),
193*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Getxattr) => self.getxattr(in_header, r, w),
194*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Listxattr) => self.listxattr(in_header, r, w),
195*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Removexattr) => self.removexattr(in_header, r, w),
196*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Flush) => self.flush(in_header, r, w),
197*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Init) => self.init(in_header, r, w),
198*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Opendir) => self.opendir(in_header, r, w),
199*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Readdir) => self.readdir(in_header, r, w),
200*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Releasedir) => self.releasedir(in_header, r, w),
201*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Fsyncdir) => self.fsyncdir(in_header, r, w),
202*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Getlk) => self.getlk(in_header, r, w),
203*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Setlk) => self.setlk(in_header, r, w),
204*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Setlkw) => self.setlkw(in_header, r, w),
205*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Access) => self.access(in_header, r, w),
206*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Create) => self.create(in_header, r, w),
207*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Interrupt) => self.interrupt(in_header),
208*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Bmap) => self.bmap(in_header, r, w),
209*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Destroy) => self.destroy(),
210*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Ioctl) => self.ioctl(in_header, r, w),
211*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Poll) => self.poll(in_header, r, w),
212*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::NotifyReply) => self.notify_reply(in_header, r, w),
213*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::BatchForget) => self.batch_forget(in_header, r, w),
214*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Fallocate) => self.fallocate(in_header, r, w),
215*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Readdirplus) => self.readdirplus(in_header, r, w),
216*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Rename2) => self.rename2(in_header, r, w),
217*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::Lseek) => self.lseek(in_header, r, w),
218*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::CopyFileRange) => self.copy_file_range(in_header, r, w),
219*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::ChromeOsTmpfile) => self.chromeos_tmpfile(in_header, r, w),
220*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::SetUpMapping) => self.set_up_mapping(in_header, r, w, mapper),
221*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::RemoveMapping) => self.remove_mapping(in_header, r, w, mapper),
222*bb4ee6a4SAndroid Build Coastguard Worker             Some(Opcode::OpenAtomic) => self.open_atomic(in_header, r, w),
223*bb4ee6a4SAndroid Build Coastguard Worker             None => reply_error(
224*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOSYS),
225*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
226*bb4ee6a4SAndroid Build Coastguard Worker                 w,
227*bb4ee6a4SAndroid Build Coastguard Worker             ),
228*bb4ee6a4SAndroid Build Coastguard Worker         }
229*bb4ee6a4SAndroid Build Coastguard Worker     }
230*bb4ee6a4SAndroid Build Coastguard Worker 
lookup<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>231*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
232*bb4ee6a4SAndroid Build Coastguard Worker         let namelen = (in_header.len as usize)
233*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
234*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
235*bb4ee6a4SAndroid Build Coastguard Worker 
236*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; namelen];
237*bb4ee6a4SAndroid Build Coastguard Worker 
238*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
239*bb4ee6a4SAndroid Build Coastguard Worker 
240*bb4ee6a4SAndroid Build Coastguard Worker         let name = bytes_to_cstr(&buf)?;
241*bb4ee6a4SAndroid Build Coastguard Worker 
242*bb4ee6a4SAndroid Build Coastguard Worker         match self
243*bb4ee6a4SAndroid Build Coastguard Worker             .fs
244*bb4ee6a4SAndroid Build Coastguard Worker             .lookup(Context::from(in_header), in_header.nodeid.into(), name)
245*bb4ee6a4SAndroid Build Coastguard Worker         {
246*bb4ee6a4SAndroid Build Coastguard Worker             Ok(entry) => {
247*bb4ee6a4SAndroid Build Coastguard Worker                 let out = EntryOut::from(entry);
248*bb4ee6a4SAndroid Build Coastguard Worker 
249*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
250*bb4ee6a4SAndroid Build Coastguard Worker             }
251*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
252*bb4ee6a4SAndroid Build Coastguard Worker         }
253*bb4ee6a4SAndroid Build Coastguard Worker     }
254*bb4ee6a4SAndroid Build Coastguard Worker 
forget<R: Reader>(&self, in_header: InHeader, mut r: R) -> Result<usize>255*bb4ee6a4SAndroid Build Coastguard Worker     fn forget<R: Reader>(&self, in_header: InHeader, mut r: R) -> Result<usize> {
256*bb4ee6a4SAndroid Build Coastguard Worker         let ForgetIn { nlookup } = r.read_struct()?;
257*bb4ee6a4SAndroid Build Coastguard Worker 
258*bb4ee6a4SAndroid Build Coastguard Worker         self.fs
259*bb4ee6a4SAndroid Build Coastguard Worker             .forget(Context::from(in_header), in_header.nodeid.into(), nlookup);
260*bb4ee6a4SAndroid Build Coastguard Worker 
261*bb4ee6a4SAndroid Build Coastguard Worker         // There is no reply for forget messages.
262*bb4ee6a4SAndroid Build Coastguard Worker         Ok(0)
263*bb4ee6a4SAndroid Build Coastguard Worker     }
264*bb4ee6a4SAndroid Build Coastguard Worker 
getattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>265*bb4ee6a4SAndroid Build Coastguard Worker     fn getattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
266*bb4ee6a4SAndroid Build Coastguard Worker         let GetattrIn {
267*bb4ee6a4SAndroid Build Coastguard Worker             flags,
268*bb4ee6a4SAndroid Build Coastguard Worker             dummy: _,
269*bb4ee6a4SAndroid Build Coastguard Worker             fh,
270*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
271*bb4ee6a4SAndroid Build Coastguard Worker 
272*bb4ee6a4SAndroid Build Coastguard Worker         let handle = if (flags & GETATTR_FH) != 0 {
273*bb4ee6a4SAndroid Build Coastguard Worker             Some(fh.into())
274*bb4ee6a4SAndroid Build Coastguard Worker         } else {
275*bb4ee6a4SAndroid Build Coastguard Worker             None
276*bb4ee6a4SAndroid Build Coastguard Worker         };
277*bb4ee6a4SAndroid Build Coastguard Worker 
278*bb4ee6a4SAndroid Build Coastguard Worker         match self
279*bb4ee6a4SAndroid Build Coastguard Worker             .fs
280*bb4ee6a4SAndroid Build Coastguard Worker             .getattr(Context::from(in_header), in_header.nodeid.into(), handle)
281*bb4ee6a4SAndroid Build Coastguard Worker         {
282*bb4ee6a4SAndroid Build Coastguard Worker             Ok((st, timeout)) => {
283*bb4ee6a4SAndroid Build Coastguard Worker                 let out = AttrOut {
284*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid: timeout.as_secs(),
285*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid_nsec: timeout.subsec_nanos(),
286*bb4ee6a4SAndroid Build Coastguard Worker                     dummy: 0,
287*bb4ee6a4SAndroid Build Coastguard Worker                     attr: st.into(),
288*bb4ee6a4SAndroid Build Coastguard Worker                 };
289*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
290*bb4ee6a4SAndroid Build Coastguard Worker             }
291*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
292*bb4ee6a4SAndroid Build Coastguard Worker         }
293*bb4ee6a4SAndroid Build Coastguard Worker     }
294*bb4ee6a4SAndroid Build Coastguard Worker 
setattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>295*bb4ee6a4SAndroid Build Coastguard Worker     fn setattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
296*bb4ee6a4SAndroid Build Coastguard Worker         let setattr_in: SetattrIn = r.read_struct()?;
297*bb4ee6a4SAndroid Build Coastguard Worker 
298*bb4ee6a4SAndroid Build Coastguard Worker         let handle = if setattr_in.valid & FATTR_FH != 0 {
299*bb4ee6a4SAndroid Build Coastguard Worker             Some(setattr_in.fh.into())
300*bb4ee6a4SAndroid Build Coastguard Worker         } else {
301*bb4ee6a4SAndroid Build Coastguard Worker             None
302*bb4ee6a4SAndroid Build Coastguard Worker         };
303*bb4ee6a4SAndroid Build Coastguard Worker 
304*bb4ee6a4SAndroid Build Coastguard Worker         let valid = SetattrValid::from_bits_truncate(setattr_in.valid);
305*bb4ee6a4SAndroid Build Coastguard Worker 
306*bb4ee6a4SAndroid Build Coastguard Worker         let st: libc::stat64 = setattr_in.into();
307*bb4ee6a4SAndroid Build Coastguard Worker 
308*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.setattr(
309*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
310*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
311*bb4ee6a4SAndroid Build Coastguard Worker             st,
312*bb4ee6a4SAndroid Build Coastguard Worker             handle,
313*bb4ee6a4SAndroid Build Coastguard Worker             valid,
314*bb4ee6a4SAndroid Build Coastguard Worker         ) {
315*bb4ee6a4SAndroid Build Coastguard Worker             Ok((st, timeout)) => {
316*bb4ee6a4SAndroid Build Coastguard Worker                 let out = AttrOut {
317*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid: timeout.as_secs(),
318*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid_nsec: timeout.subsec_nanos(),
319*bb4ee6a4SAndroid Build Coastguard Worker                     dummy: 0,
320*bb4ee6a4SAndroid Build Coastguard Worker                     attr: st.into(),
321*bb4ee6a4SAndroid Build Coastguard Worker                 };
322*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
323*bb4ee6a4SAndroid Build Coastguard Worker             }
324*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
325*bb4ee6a4SAndroid Build Coastguard Worker         }
326*bb4ee6a4SAndroid Build Coastguard Worker     }
327*bb4ee6a4SAndroid Build Coastguard Worker 
readlink<W: Writer>(&self, in_header: InHeader, w: W) -> Result<usize>328*bb4ee6a4SAndroid Build Coastguard Worker     fn readlink<W: Writer>(&self, in_header: InHeader, w: W) -> Result<usize> {
329*bb4ee6a4SAndroid Build Coastguard Worker         match self
330*bb4ee6a4SAndroid Build Coastguard Worker             .fs
331*bb4ee6a4SAndroid Build Coastguard Worker             .readlink(Context::from(in_header), in_header.nodeid.into())
332*bb4ee6a4SAndroid Build Coastguard Worker         {
333*bb4ee6a4SAndroid Build Coastguard Worker             Ok(linkname) => {
334*bb4ee6a4SAndroid Build Coastguard Worker                 // We need to disambiguate the option type here even though it is `None`.
335*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(None::<u8>, Some(&linkname), in_header.unique, w)
336*bb4ee6a4SAndroid Build Coastguard Worker             }
337*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
338*bb4ee6a4SAndroid Build Coastguard Worker         }
339*bb4ee6a4SAndroid Build Coastguard Worker     }
340*bb4ee6a4SAndroid Build Coastguard Worker 
symlink<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>341*bb4ee6a4SAndroid Build Coastguard Worker     fn symlink<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
342*bb4ee6a4SAndroid Build Coastguard Worker         // Unfortunately the name and linkname are encoded one after another and
343*bb4ee6a4SAndroid Build Coastguard Worker         // separated by a nul character.
344*bb4ee6a4SAndroid Build Coastguard Worker         let len = (in_header.len as usize)
345*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
346*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
347*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; len];
348*bb4ee6a4SAndroid Build Coastguard Worker 
349*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
350*bb4ee6a4SAndroid Build Coastguard Worker 
351*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = buf.split_inclusive(|&c| c == b'\0');
352*bb4ee6a4SAndroid Build Coastguard Worker         let name = iter
353*bb4ee6a4SAndroid Build Coastguard Worker             .next()
354*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)
355*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(bytes_to_cstr)?;
356*bb4ee6a4SAndroid Build Coastguard Worker         let linkname = iter
357*bb4ee6a4SAndroid Build Coastguard Worker             .next()
358*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)
359*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(bytes_to_cstr)?;
360*bb4ee6a4SAndroid Build Coastguard Worker 
361*bb4ee6a4SAndroid Build Coastguard Worker         let split_pos = name.to_bytes_with_nul().len() + linkname.to_bytes_with_nul().len();
362*bb4ee6a4SAndroid Build Coastguard Worker         let security_ctx = parse_selinux_xattr(&buf[split_pos..])?;
363*bb4ee6a4SAndroid Build Coastguard Worker 
364*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.symlink(
365*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
366*bb4ee6a4SAndroid Build Coastguard Worker             linkname,
367*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
368*bb4ee6a4SAndroid Build Coastguard Worker             name,
369*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx,
370*bb4ee6a4SAndroid Build Coastguard Worker         ) {
371*bb4ee6a4SAndroid Build Coastguard Worker             Ok(entry) => {
372*bb4ee6a4SAndroid Build Coastguard Worker                 let out = EntryOut::from(entry);
373*bb4ee6a4SAndroid Build Coastguard Worker 
374*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
375*bb4ee6a4SAndroid Build Coastguard Worker             }
376*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
377*bb4ee6a4SAndroid Build Coastguard Worker         }
378*bb4ee6a4SAndroid Build Coastguard Worker     }
379*bb4ee6a4SAndroid Build Coastguard Worker 
mknod<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>380*bb4ee6a4SAndroid Build Coastguard Worker     fn mknod<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
381*bb4ee6a4SAndroid Build Coastguard Worker         let MknodIn {
382*bb4ee6a4SAndroid Build Coastguard Worker             mode, rdev, umask, ..
383*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
384*bb4ee6a4SAndroid Build Coastguard Worker 
385*bb4ee6a4SAndroid Build Coastguard Worker         let buflen = (in_header.len as usize)
386*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
387*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<MknodIn>()))
388*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
389*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; buflen];
390*bb4ee6a4SAndroid Build Coastguard Worker 
391*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
392*bb4ee6a4SAndroid Build Coastguard Worker 
393*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = buf.split_inclusive(|&c| c == b'\0');
394*bb4ee6a4SAndroid Build Coastguard Worker         let name = iter
395*bb4ee6a4SAndroid Build Coastguard Worker             .next()
396*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)
397*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(bytes_to_cstr)?;
398*bb4ee6a4SAndroid Build Coastguard Worker 
399*bb4ee6a4SAndroid Build Coastguard Worker         let split_pos = name.to_bytes_with_nul().len();
400*bb4ee6a4SAndroid Build Coastguard Worker         let security_ctx = parse_selinux_xattr(&buf[split_pos..])?;
401*bb4ee6a4SAndroid Build Coastguard Worker 
402*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.mknod(
403*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
404*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
405*bb4ee6a4SAndroid Build Coastguard Worker             name,
406*bb4ee6a4SAndroid Build Coastguard Worker             mode,
407*bb4ee6a4SAndroid Build Coastguard Worker             rdev,
408*bb4ee6a4SAndroid Build Coastguard Worker             umask,
409*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx,
410*bb4ee6a4SAndroid Build Coastguard Worker         ) {
411*bb4ee6a4SAndroid Build Coastguard Worker             Ok(entry) => {
412*bb4ee6a4SAndroid Build Coastguard Worker                 let out = EntryOut::from(entry);
413*bb4ee6a4SAndroid Build Coastguard Worker 
414*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
415*bb4ee6a4SAndroid Build Coastguard Worker             }
416*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
417*bb4ee6a4SAndroid Build Coastguard Worker         }
418*bb4ee6a4SAndroid Build Coastguard Worker     }
419*bb4ee6a4SAndroid Build Coastguard Worker 
mkdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>420*bb4ee6a4SAndroid Build Coastguard Worker     fn mkdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
421*bb4ee6a4SAndroid Build Coastguard Worker         let MkdirIn { mode, umask } = r.read_struct()?;
422*bb4ee6a4SAndroid Build Coastguard Worker 
423*bb4ee6a4SAndroid Build Coastguard Worker         let buflen = (in_header.len as usize)
424*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
425*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<MkdirIn>()))
426*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
427*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; buflen];
428*bb4ee6a4SAndroid Build Coastguard Worker 
429*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
430*bb4ee6a4SAndroid Build Coastguard Worker 
431*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = buf.split_inclusive(|&c| c == b'\0');
432*bb4ee6a4SAndroid Build Coastguard Worker         let name = iter
433*bb4ee6a4SAndroid Build Coastguard Worker             .next()
434*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)
435*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(bytes_to_cstr)?;
436*bb4ee6a4SAndroid Build Coastguard Worker 
437*bb4ee6a4SAndroid Build Coastguard Worker         let split_pos = name.to_bytes_with_nul().len();
438*bb4ee6a4SAndroid Build Coastguard Worker         let security_ctx = parse_selinux_xattr(&buf[split_pos..])?;
439*bb4ee6a4SAndroid Build Coastguard Worker 
440*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.mkdir(
441*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
442*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
443*bb4ee6a4SAndroid Build Coastguard Worker             name,
444*bb4ee6a4SAndroid Build Coastguard Worker             mode,
445*bb4ee6a4SAndroid Build Coastguard Worker             umask,
446*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx,
447*bb4ee6a4SAndroid Build Coastguard Worker         ) {
448*bb4ee6a4SAndroid Build Coastguard Worker             Ok(entry) => {
449*bb4ee6a4SAndroid Build Coastguard Worker                 let out = EntryOut::from(entry);
450*bb4ee6a4SAndroid Build Coastguard Worker 
451*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
452*bb4ee6a4SAndroid Build Coastguard Worker             }
453*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
454*bb4ee6a4SAndroid Build Coastguard Worker         }
455*bb4ee6a4SAndroid Build Coastguard Worker     }
456*bb4ee6a4SAndroid Build Coastguard Worker 
chromeos_tmpfile<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>457*bb4ee6a4SAndroid Build Coastguard Worker     fn chromeos_tmpfile<R: Reader, W: Writer>(
458*bb4ee6a4SAndroid Build Coastguard Worker         &self,
459*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
460*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
461*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
462*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
463*bb4ee6a4SAndroid Build Coastguard Worker         let ChromeOsTmpfileIn { mode, umask } = r.read_struct()?;
464*bb4ee6a4SAndroid Build Coastguard Worker 
465*bb4ee6a4SAndroid Build Coastguard Worker         let len = (in_header.len as usize)
466*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
467*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<ChromeOsTmpfileIn>()))
468*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
469*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; len];
470*bb4ee6a4SAndroid Build Coastguard Worker 
471*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
472*bb4ee6a4SAndroid Build Coastguard Worker 
473*bb4ee6a4SAndroid Build Coastguard Worker         let security_ctx = parse_selinux_xattr(&buf)?;
474*bb4ee6a4SAndroid Build Coastguard Worker 
475*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.chromeos_tmpfile(
476*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
477*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
478*bb4ee6a4SAndroid Build Coastguard Worker             mode,
479*bb4ee6a4SAndroid Build Coastguard Worker             umask,
480*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx,
481*bb4ee6a4SAndroid Build Coastguard Worker         ) {
482*bb4ee6a4SAndroid Build Coastguard Worker             Ok(entry) => {
483*bb4ee6a4SAndroid Build Coastguard Worker                 let out = EntryOut::from(entry);
484*bb4ee6a4SAndroid Build Coastguard Worker 
485*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
486*bb4ee6a4SAndroid Build Coastguard Worker             }
487*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
488*bb4ee6a4SAndroid Build Coastguard Worker         }
489*bb4ee6a4SAndroid Build Coastguard Worker     }
490*bb4ee6a4SAndroid Build Coastguard Worker 
unlink<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>491*bb4ee6a4SAndroid Build Coastguard Worker     fn unlink<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
492*bb4ee6a4SAndroid Build Coastguard Worker         let namelen = (in_header.len as usize)
493*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
494*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
495*bb4ee6a4SAndroid Build Coastguard Worker         let mut name = vec![0; namelen];
496*bb4ee6a4SAndroid Build Coastguard Worker 
497*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut name).map_err(Error::DecodeMessage)?;
498*bb4ee6a4SAndroid Build Coastguard Worker 
499*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.unlink(
500*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
501*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
502*bb4ee6a4SAndroid Build Coastguard Worker             bytes_to_cstr(&name)?,
503*bb4ee6a4SAndroid Build Coastguard Worker         ) {
504*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
505*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
506*bb4ee6a4SAndroid Build Coastguard Worker         }
507*bb4ee6a4SAndroid Build Coastguard Worker     }
508*bb4ee6a4SAndroid Build Coastguard Worker 
rmdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>509*bb4ee6a4SAndroid Build Coastguard Worker     fn rmdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
510*bb4ee6a4SAndroid Build Coastguard Worker         let namelen = (in_header.len as usize)
511*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
512*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
513*bb4ee6a4SAndroid Build Coastguard Worker         let mut name = vec![0; namelen];
514*bb4ee6a4SAndroid Build Coastguard Worker 
515*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut name).map_err(Error::DecodeMessage)?;
516*bb4ee6a4SAndroid Build Coastguard Worker 
517*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.rmdir(
518*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
519*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
520*bb4ee6a4SAndroid Build Coastguard Worker             bytes_to_cstr(&name)?,
521*bb4ee6a4SAndroid Build Coastguard Worker         ) {
522*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
523*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
524*bb4ee6a4SAndroid Build Coastguard Worker         }
525*bb4ee6a4SAndroid Build Coastguard Worker     }
526*bb4ee6a4SAndroid Build Coastguard Worker 
do_rename<R: Reader, W: Writer>( &self, in_header: InHeader, msg_size: usize, newdir: u64, flags: u32, mut r: R, w: W, ) -> Result<usize>527*bb4ee6a4SAndroid Build Coastguard Worker     fn do_rename<R: Reader, W: Writer>(
528*bb4ee6a4SAndroid Build Coastguard Worker         &self,
529*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
530*bb4ee6a4SAndroid Build Coastguard Worker         msg_size: usize,
531*bb4ee6a4SAndroid Build Coastguard Worker         newdir: u64,
532*bb4ee6a4SAndroid Build Coastguard Worker         flags: u32,
533*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
534*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
535*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
536*bb4ee6a4SAndroid Build Coastguard Worker         let buflen = (in_header.len as usize)
537*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
538*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(msg_size))
539*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
540*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; buflen];
541*bb4ee6a4SAndroid Build Coastguard Worker 
542*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
543*bb4ee6a4SAndroid Build Coastguard Worker 
544*bb4ee6a4SAndroid Build Coastguard Worker         // We want to include the '\0' byte in the first slice.
545*bb4ee6a4SAndroid Build Coastguard Worker         let split_pos = buf
546*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
547*bb4ee6a4SAndroid Build Coastguard Worker             .position(|c| *c == b'\0')
548*bb4ee6a4SAndroid Build Coastguard Worker             .map(|p| p + 1)
549*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)?;
550*bb4ee6a4SAndroid Build Coastguard Worker 
551*bb4ee6a4SAndroid Build Coastguard Worker         let (oldname, newname) = buf.split_at(split_pos);
552*bb4ee6a4SAndroid Build Coastguard Worker 
553*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.rename(
554*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
555*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
556*bb4ee6a4SAndroid Build Coastguard Worker             bytes_to_cstr(oldname)?,
557*bb4ee6a4SAndroid Build Coastguard Worker             newdir.into(),
558*bb4ee6a4SAndroid Build Coastguard Worker             bytes_to_cstr(newname)?,
559*bb4ee6a4SAndroid Build Coastguard Worker             flags,
560*bb4ee6a4SAndroid Build Coastguard Worker         ) {
561*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
562*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
563*bb4ee6a4SAndroid Build Coastguard Worker         }
564*bb4ee6a4SAndroid Build Coastguard Worker     }
565*bb4ee6a4SAndroid Build Coastguard Worker 
rename<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>566*bb4ee6a4SAndroid Build Coastguard Worker     fn rename<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
567*bb4ee6a4SAndroid Build Coastguard Worker         let RenameIn { newdir } = r.read_struct()?;
568*bb4ee6a4SAndroid Build Coastguard Worker 
569*bb4ee6a4SAndroid Build Coastguard Worker         self.do_rename(in_header, size_of::<RenameIn>(), newdir, 0, r, w)
570*bb4ee6a4SAndroid Build Coastguard Worker     }
571*bb4ee6a4SAndroid Build Coastguard Worker 
rename2<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>572*bb4ee6a4SAndroid Build Coastguard Worker     fn rename2<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
573*bb4ee6a4SAndroid Build Coastguard Worker         let Rename2In { newdir, flags, .. } = r.read_struct()?;
574*bb4ee6a4SAndroid Build Coastguard Worker 
575*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::unnecessary_cast)]
576*bb4ee6a4SAndroid Build Coastguard Worker         let flags = flags & (libc::RENAME_EXCHANGE | libc::RENAME_NOREPLACE) as u32;
577*bb4ee6a4SAndroid Build Coastguard Worker 
578*bb4ee6a4SAndroid Build Coastguard Worker         self.do_rename(in_header, size_of::<Rename2In>(), newdir, flags, r, w)
579*bb4ee6a4SAndroid Build Coastguard Worker     }
580*bb4ee6a4SAndroid Build Coastguard Worker 
link<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>581*bb4ee6a4SAndroid Build Coastguard Worker     fn link<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
582*bb4ee6a4SAndroid Build Coastguard Worker         let LinkIn { oldnodeid } = r.read_struct()?;
583*bb4ee6a4SAndroid Build Coastguard Worker 
584*bb4ee6a4SAndroid Build Coastguard Worker         let namelen = (in_header.len as usize)
585*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
586*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<LinkIn>()))
587*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
588*bb4ee6a4SAndroid Build Coastguard Worker         let mut name = vec![0; namelen];
589*bb4ee6a4SAndroid Build Coastguard Worker 
590*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut name).map_err(Error::DecodeMessage)?;
591*bb4ee6a4SAndroid Build Coastguard Worker 
592*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.link(
593*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
594*bb4ee6a4SAndroid Build Coastguard Worker             oldnodeid.into(),
595*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
596*bb4ee6a4SAndroid Build Coastguard Worker             bytes_to_cstr(&name)?,
597*bb4ee6a4SAndroid Build Coastguard Worker         ) {
598*bb4ee6a4SAndroid Build Coastguard Worker             Ok(entry) => {
599*bb4ee6a4SAndroid Build Coastguard Worker                 let out = EntryOut::from(entry);
600*bb4ee6a4SAndroid Build Coastguard Worker 
601*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
602*bb4ee6a4SAndroid Build Coastguard Worker             }
603*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
604*bb4ee6a4SAndroid Build Coastguard Worker         }
605*bb4ee6a4SAndroid Build Coastguard Worker     }
606*bb4ee6a4SAndroid Build Coastguard Worker 
open<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>607*bb4ee6a4SAndroid Build Coastguard Worker     fn open<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
608*bb4ee6a4SAndroid Build Coastguard Worker         let OpenIn { flags, .. } = r.read_struct()?;
609*bb4ee6a4SAndroid Build Coastguard Worker 
610*bb4ee6a4SAndroid Build Coastguard Worker         match self
611*bb4ee6a4SAndroid Build Coastguard Worker             .fs
612*bb4ee6a4SAndroid Build Coastguard Worker             .open(Context::from(in_header), in_header.nodeid.into(), flags)
613*bb4ee6a4SAndroid Build Coastguard Worker         {
614*bb4ee6a4SAndroid Build Coastguard Worker             Ok((handle, opts)) => {
615*bb4ee6a4SAndroid Build Coastguard Worker                 let out = OpenOut {
616*bb4ee6a4SAndroid Build Coastguard Worker                     fh: handle.map(Into::into).unwrap_or(0),
617*bb4ee6a4SAndroid Build Coastguard Worker                     open_flags: opts.bits(),
618*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
619*bb4ee6a4SAndroid Build Coastguard Worker                 };
620*bb4ee6a4SAndroid Build Coastguard Worker 
621*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
622*bb4ee6a4SAndroid Build Coastguard Worker             }
623*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
624*bb4ee6a4SAndroid Build Coastguard Worker         }
625*bb4ee6a4SAndroid Build Coastguard Worker     }
626*bb4ee6a4SAndroid Build Coastguard Worker 
read<R: Reader, W: ZeroCopyWriter + Writer>( &self, in_header: InHeader, mut r: R, mut w: W, ) -> Result<usize>627*bb4ee6a4SAndroid Build Coastguard Worker     fn read<R: Reader, W: ZeroCopyWriter + Writer>(
628*bb4ee6a4SAndroid Build Coastguard Worker         &self,
629*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
630*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
631*bb4ee6a4SAndroid Build Coastguard Worker         mut w: W,
632*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
633*bb4ee6a4SAndroid Build Coastguard Worker         let ReadIn {
634*bb4ee6a4SAndroid Build Coastguard Worker             fh,
635*bb4ee6a4SAndroid Build Coastguard Worker             offset,
636*bb4ee6a4SAndroid Build Coastguard Worker             size,
637*bb4ee6a4SAndroid Build Coastguard Worker             read_flags,
638*bb4ee6a4SAndroid Build Coastguard Worker             lock_owner,
639*bb4ee6a4SAndroid Build Coastguard Worker             flags,
640*bb4ee6a4SAndroid Build Coastguard Worker             ..
641*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
642*bb4ee6a4SAndroid Build Coastguard Worker 
643*bb4ee6a4SAndroid Build Coastguard Worker         if size > self.fs.max_buffer_size() {
644*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
645*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
646*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
647*bb4ee6a4SAndroid Build Coastguard Worker                 w,
648*bb4ee6a4SAndroid Build Coastguard Worker             );
649*bb4ee6a4SAndroid Build Coastguard Worker         }
650*bb4ee6a4SAndroid Build Coastguard Worker 
651*bb4ee6a4SAndroid Build Coastguard Worker         let owner = if read_flags & READ_LOCKOWNER != 0 {
652*bb4ee6a4SAndroid Build Coastguard Worker             Some(lock_owner)
653*bb4ee6a4SAndroid Build Coastguard Worker         } else {
654*bb4ee6a4SAndroid Build Coastguard Worker             None
655*bb4ee6a4SAndroid Build Coastguard Worker         };
656*bb4ee6a4SAndroid Build Coastguard Worker 
657*bb4ee6a4SAndroid Build Coastguard Worker         // Skip for the header size to write the data first.
658*bb4ee6a4SAndroid Build Coastguard Worker         match w.write_at(size_of::<OutHeader>(), |writer| {
659*bb4ee6a4SAndroid Build Coastguard Worker             self.fs.read(
660*bb4ee6a4SAndroid Build Coastguard Worker                 Context::from(in_header),
661*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.nodeid.into(),
662*bb4ee6a4SAndroid Build Coastguard Worker                 fh.into(),
663*bb4ee6a4SAndroid Build Coastguard Worker                 writer,
664*bb4ee6a4SAndroid Build Coastguard Worker                 size,
665*bb4ee6a4SAndroid Build Coastguard Worker                 offset,
666*bb4ee6a4SAndroid Build Coastguard Worker                 owner,
667*bb4ee6a4SAndroid Build Coastguard Worker                 flags,
668*bb4ee6a4SAndroid Build Coastguard Worker             )
669*bb4ee6a4SAndroid Build Coastguard Worker         }) {
670*bb4ee6a4SAndroid Build Coastguard Worker             Ok(count) => {
671*bb4ee6a4SAndroid Build Coastguard Worker                 // Don't use `reply_ok` because we need to set a custom size length for the
672*bb4ee6a4SAndroid Build Coastguard Worker                 // header.
673*bb4ee6a4SAndroid Build Coastguard Worker                 let out = OutHeader {
674*bb4ee6a4SAndroid Build Coastguard Worker                     len: (size_of::<OutHeader>() + count) as u32,
675*bb4ee6a4SAndroid Build Coastguard Worker                     error: 0,
676*bb4ee6a4SAndroid Build Coastguard Worker                     unique: in_header.unique,
677*bb4ee6a4SAndroid Build Coastguard Worker                 };
678*bb4ee6a4SAndroid Build Coastguard Worker 
679*bb4ee6a4SAndroid Build Coastguard Worker                 w.write_all(out.as_bytes()).map_err(Error::EncodeMessage)?;
680*bb4ee6a4SAndroid Build Coastguard Worker                 w.flush().map_err(Error::FlushMessage)?;
681*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(out.len as usize)
682*bb4ee6a4SAndroid Build Coastguard Worker             }
683*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
684*bb4ee6a4SAndroid Build Coastguard Worker         }
685*bb4ee6a4SAndroid Build Coastguard Worker     }
686*bb4ee6a4SAndroid Build Coastguard Worker 
write<R: Reader + ZeroCopyReader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>687*bb4ee6a4SAndroid Build Coastguard Worker     fn write<R: Reader + ZeroCopyReader, W: Writer>(
688*bb4ee6a4SAndroid Build Coastguard Worker         &self,
689*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
690*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
691*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
692*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
693*bb4ee6a4SAndroid Build Coastguard Worker         let WriteIn {
694*bb4ee6a4SAndroid Build Coastguard Worker             fh,
695*bb4ee6a4SAndroid Build Coastguard Worker             offset,
696*bb4ee6a4SAndroid Build Coastguard Worker             size,
697*bb4ee6a4SAndroid Build Coastguard Worker             write_flags,
698*bb4ee6a4SAndroid Build Coastguard Worker             lock_owner,
699*bb4ee6a4SAndroid Build Coastguard Worker             flags,
700*bb4ee6a4SAndroid Build Coastguard Worker             ..
701*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
702*bb4ee6a4SAndroid Build Coastguard Worker 
703*bb4ee6a4SAndroid Build Coastguard Worker         if size > self.fs.max_buffer_size() {
704*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
705*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
706*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
707*bb4ee6a4SAndroid Build Coastguard Worker                 w,
708*bb4ee6a4SAndroid Build Coastguard Worker             );
709*bb4ee6a4SAndroid Build Coastguard Worker         }
710*bb4ee6a4SAndroid Build Coastguard Worker 
711*bb4ee6a4SAndroid Build Coastguard Worker         let owner = if write_flags & WRITE_LOCKOWNER != 0 {
712*bb4ee6a4SAndroid Build Coastguard Worker             Some(lock_owner)
713*bb4ee6a4SAndroid Build Coastguard Worker         } else {
714*bb4ee6a4SAndroid Build Coastguard Worker             None
715*bb4ee6a4SAndroid Build Coastguard Worker         };
716*bb4ee6a4SAndroid Build Coastguard Worker 
717*bb4ee6a4SAndroid Build Coastguard Worker         let delayed_write = write_flags & WRITE_CACHE != 0;
718*bb4ee6a4SAndroid Build Coastguard Worker 
719*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.write(
720*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
721*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
722*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
723*bb4ee6a4SAndroid Build Coastguard Worker             r,
724*bb4ee6a4SAndroid Build Coastguard Worker             size,
725*bb4ee6a4SAndroid Build Coastguard Worker             offset,
726*bb4ee6a4SAndroid Build Coastguard Worker             owner,
727*bb4ee6a4SAndroid Build Coastguard Worker             delayed_write,
728*bb4ee6a4SAndroid Build Coastguard Worker             flags,
729*bb4ee6a4SAndroid Build Coastguard Worker         ) {
730*bb4ee6a4SAndroid Build Coastguard Worker             Ok(count) => {
731*bb4ee6a4SAndroid Build Coastguard Worker                 let out = WriteOut {
732*bb4ee6a4SAndroid Build Coastguard Worker                     size: count as u32,
733*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
734*bb4ee6a4SAndroid Build Coastguard Worker                 };
735*bb4ee6a4SAndroid Build Coastguard Worker 
736*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
737*bb4ee6a4SAndroid Build Coastguard Worker             }
738*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
739*bb4ee6a4SAndroid Build Coastguard Worker         }
740*bb4ee6a4SAndroid Build Coastguard Worker     }
741*bb4ee6a4SAndroid Build Coastguard Worker 
statfs<W: Writer>(&self, in_header: InHeader, w: W) -> Result<usize>742*bb4ee6a4SAndroid Build Coastguard Worker     fn statfs<W: Writer>(&self, in_header: InHeader, w: W) -> Result<usize> {
743*bb4ee6a4SAndroid Build Coastguard Worker         match self
744*bb4ee6a4SAndroid Build Coastguard Worker             .fs
745*bb4ee6a4SAndroid Build Coastguard Worker             .statfs(Context::from(in_header), in_header.nodeid.into())
746*bb4ee6a4SAndroid Build Coastguard Worker         {
747*bb4ee6a4SAndroid Build Coastguard Worker             Ok(st) => reply_ok(Some(Kstatfs::from(st)), None, in_header.unique, w),
748*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
749*bb4ee6a4SAndroid Build Coastguard Worker         }
750*bb4ee6a4SAndroid Build Coastguard Worker     }
751*bb4ee6a4SAndroid Build Coastguard Worker 
release<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>752*bb4ee6a4SAndroid Build Coastguard Worker     fn release<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
753*bb4ee6a4SAndroid Build Coastguard Worker         let ReleaseIn {
754*bb4ee6a4SAndroid Build Coastguard Worker             fh,
755*bb4ee6a4SAndroid Build Coastguard Worker             flags,
756*bb4ee6a4SAndroid Build Coastguard Worker             release_flags,
757*bb4ee6a4SAndroid Build Coastguard Worker             lock_owner,
758*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
759*bb4ee6a4SAndroid Build Coastguard Worker 
760*bb4ee6a4SAndroid Build Coastguard Worker         let flush = release_flags & RELEASE_FLUSH != 0;
761*bb4ee6a4SAndroid Build Coastguard Worker         let flock_release = release_flags & RELEASE_FLOCK_UNLOCK != 0;
762*bb4ee6a4SAndroid Build Coastguard Worker         let lock_owner = if flush || flock_release {
763*bb4ee6a4SAndroid Build Coastguard Worker             Some(lock_owner)
764*bb4ee6a4SAndroid Build Coastguard Worker         } else {
765*bb4ee6a4SAndroid Build Coastguard Worker             None
766*bb4ee6a4SAndroid Build Coastguard Worker         };
767*bb4ee6a4SAndroid Build Coastguard Worker 
768*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.release(
769*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
770*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
771*bb4ee6a4SAndroid Build Coastguard Worker             flags,
772*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
773*bb4ee6a4SAndroid Build Coastguard Worker             flush,
774*bb4ee6a4SAndroid Build Coastguard Worker             flock_release,
775*bb4ee6a4SAndroid Build Coastguard Worker             lock_owner,
776*bb4ee6a4SAndroid Build Coastguard Worker         ) {
777*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
778*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
779*bb4ee6a4SAndroid Build Coastguard Worker         }
780*bb4ee6a4SAndroid Build Coastguard Worker     }
781*bb4ee6a4SAndroid Build Coastguard Worker 
fsync<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>782*bb4ee6a4SAndroid Build Coastguard Worker     fn fsync<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
783*bb4ee6a4SAndroid Build Coastguard Worker         let FsyncIn {
784*bb4ee6a4SAndroid Build Coastguard Worker             fh, fsync_flags, ..
785*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
786*bb4ee6a4SAndroid Build Coastguard Worker         let datasync = fsync_flags & 0x1 != 0;
787*bb4ee6a4SAndroid Build Coastguard Worker 
788*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.fsync(
789*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
790*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
791*bb4ee6a4SAndroid Build Coastguard Worker             datasync,
792*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
793*bb4ee6a4SAndroid Build Coastguard Worker         ) {
794*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
795*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
796*bb4ee6a4SAndroid Build Coastguard Worker         }
797*bb4ee6a4SAndroid Build Coastguard Worker     }
798*bb4ee6a4SAndroid Build Coastguard Worker 
setxattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>799*bb4ee6a4SAndroid Build Coastguard Worker     fn setxattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
800*bb4ee6a4SAndroid Build Coastguard Worker         let SetxattrIn { size, flags } = r.read_struct()?;
801*bb4ee6a4SAndroid Build Coastguard Worker 
802*bb4ee6a4SAndroid Build Coastguard Worker         // The name and value and encoded one after another and separated by a '\0' character.
803*bb4ee6a4SAndroid Build Coastguard Worker         let len = (in_header.len as usize)
804*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
805*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<SetxattrIn>()))
806*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
807*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; len];
808*bb4ee6a4SAndroid Build Coastguard Worker 
809*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
810*bb4ee6a4SAndroid Build Coastguard Worker 
811*bb4ee6a4SAndroid Build Coastguard Worker         // We want to include the '\0' byte in the first slice.
812*bb4ee6a4SAndroid Build Coastguard Worker         let split_pos = buf
813*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
814*bb4ee6a4SAndroid Build Coastguard Worker             .position(|c| *c == b'\0')
815*bb4ee6a4SAndroid Build Coastguard Worker             .map(|p| p + 1)
816*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)?;
817*bb4ee6a4SAndroid Build Coastguard Worker 
818*bb4ee6a4SAndroid Build Coastguard Worker         let (name, value) = buf.split_at(split_pos);
819*bb4ee6a4SAndroid Build Coastguard Worker 
820*bb4ee6a4SAndroid Build Coastguard Worker         if size != value.len() as u32 {
821*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::InvalidXattrSize(size, value.len()));
822*bb4ee6a4SAndroid Build Coastguard Worker         }
823*bb4ee6a4SAndroid Build Coastguard Worker 
824*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.setxattr(
825*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
826*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
827*bb4ee6a4SAndroid Build Coastguard Worker             bytes_to_cstr(name)?,
828*bb4ee6a4SAndroid Build Coastguard Worker             value,
829*bb4ee6a4SAndroid Build Coastguard Worker             flags,
830*bb4ee6a4SAndroid Build Coastguard Worker         ) {
831*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
832*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
833*bb4ee6a4SAndroid Build Coastguard Worker         }
834*bb4ee6a4SAndroid Build Coastguard Worker     }
835*bb4ee6a4SAndroid Build Coastguard Worker 
getxattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>836*bb4ee6a4SAndroid Build Coastguard Worker     fn getxattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
837*bb4ee6a4SAndroid Build Coastguard Worker         let GetxattrIn { size, .. } = r.read_struct()?;
838*bb4ee6a4SAndroid Build Coastguard Worker 
839*bb4ee6a4SAndroid Build Coastguard Worker         let namelen = (in_header.len as usize)
840*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
841*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<GetxattrIn>()))
842*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
843*bb4ee6a4SAndroid Build Coastguard Worker         let mut name = vec![0; namelen];
844*bb4ee6a4SAndroid Build Coastguard Worker 
845*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut name).map_err(Error::DecodeMessage)?;
846*bb4ee6a4SAndroid Build Coastguard Worker 
847*bb4ee6a4SAndroid Build Coastguard Worker         if size > self.fs.max_buffer_size() {
848*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
849*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
850*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
851*bb4ee6a4SAndroid Build Coastguard Worker                 w,
852*bb4ee6a4SAndroid Build Coastguard Worker             );
853*bb4ee6a4SAndroid Build Coastguard Worker         }
854*bb4ee6a4SAndroid Build Coastguard Worker 
855*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.getxattr(
856*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
857*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
858*bb4ee6a4SAndroid Build Coastguard Worker             bytes_to_cstr(&name)?,
859*bb4ee6a4SAndroid Build Coastguard Worker             size,
860*bb4ee6a4SAndroid Build Coastguard Worker         ) {
861*bb4ee6a4SAndroid Build Coastguard Worker             Ok(GetxattrReply::Value(val)) => reply_ok(None::<u8>, Some(&val), in_header.unique, w),
862*bb4ee6a4SAndroid Build Coastguard Worker             Ok(GetxattrReply::Count(count)) => {
863*bb4ee6a4SAndroid Build Coastguard Worker                 let out = GetxattrOut {
864*bb4ee6a4SAndroid Build Coastguard Worker                     size: count,
865*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
866*bb4ee6a4SAndroid Build Coastguard Worker                 };
867*bb4ee6a4SAndroid Build Coastguard Worker 
868*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
869*bb4ee6a4SAndroid Build Coastguard Worker             }
870*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
871*bb4ee6a4SAndroid Build Coastguard Worker         }
872*bb4ee6a4SAndroid Build Coastguard Worker     }
873*bb4ee6a4SAndroid Build Coastguard Worker 
listxattr<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>874*bb4ee6a4SAndroid Build Coastguard Worker     fn listxattr<R: Reader, W: Writer>(
875*bb4ee6a4SAndroid Build Coastguard Worker         &self,
876*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
877*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
878*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
879*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
880*bb4ee6a4SAndroid Build Coastguard Worker         let GetxattrIn { size, .. } = r.read_struct()?;
881*bb4ee6a4SAndroid Build Coastguard Worker 
882*bb4ee6a4SAndroid Build Coastguard Worker         if size > self.fs.max_buffer_size() {
883*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
884*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
885*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
886*bb4ee6a4SAndroid Build Coastguard Worker                 w,
887*bb4ee6a4SAndroid Build Coastguard Worker             );
888*bb4ee6a4SAndroid Build Coastguard Worker         }
889*bb4ee6a4SAndroid Build Coastguard Worker 
890*bb4ee6a4SAndroid Build Coastguard Worker         match self
891*bb4ee6a4SAndroid Build Coastguard Worker             .fs
892*bb4ee6a4SAndroid Build Coastguard Worker             .listxattr(Context::from(in_header), in_header.nodeid.into(), size)
893*bb4ee6a4SAndroid Build Coastguard Worker         {
894*bb4ee6a4SAndroid Build Coastguard Worker             Ok(ListxattrReply::Names(val)) => reply_ok(None::<u8>, Some(&val), in_header.unique, w),
895*bb4ee6a4SAndroid Build Coastguard Worker             Ok(ListxattrReply::Count(count)) => {
896*bb4ee6a4SAndroid Build Coastguard Worker                 let out = GetxattrOut {
897*bb4ee6a4SAndroid Build Coastguard Worker                     size: count,
898*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
899*bb4ee6a4SAndroid Build Coastguard Worker                 };
900*bb4ee6a4SAndroid Build Coastguard Worker 
901*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
902*bb4ee6a4SAndroid Build Coastguard Worker             }
903*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
904*bb4ee6a4SAndroid Build Coastguard Worker         }
905*bb4ee6a4SAndroid Build Coastguard Worker     }
906*bb4ee6a4SAndroid Build Coastguard Worker 
removexattr<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>907*bb4ee6a4SAndroid Build Coastguard Worker     fn removexattr<R: Reader, W: Writer>(
908*bb4ee6a4SAndroid Build Coastguard Worker         &self,
909*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
910*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
911*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
912*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
913*bb4ee6a4SAndroid Build Coastguard Worker         let namelen = (in_header.len as usize)
914*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
915*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
916*bb4ee6a4SAndroid Build Coastguard Worker 
917*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; namelen];
918*bb4ee6a4SAndroid Build Coastguard Worker 
919*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
920*bb4ee6a4SAndroid Build Coastguard Worker 
921*bb4ee6a4SAndroid Build Coastguard Worker         let name = bytes_to_cstr(&buf)?;
922*bb4ee6a4SAndroid Build Coastguard Worker 
923*bb4ee6a4SAndroid Build Coastguard Worker         match self
924*bb4ee6a4SAndroid Build Coastguard Worker             .fs
925*bb4ee6a4SAndroid Build Coastguard Worker             .removexattr(Context::from(in_header), in_header.nodeid.into(), name)
926*bb4ee6a4SAndroid Build Coastguard Worker         {
927*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
928*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
929*bb4ee6a4SAndroid Build Coastguard Worker         }
930*bb4ee6a4SAndroid Build Coastguard Worker     }
931*bb4ee6a4SAndroid Build Coastguard Worker 
flush<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>932*bb4ee6a4SAndroid Build Coastguard Worker     fn flush<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
933*bb4ee6a4SAndroid Build Coastguard Worker         let FlushIn {
934*bb4ee6a4SAndroid Build Coastguard Worker             fh,
935*bb4ee6a4SAndroid Build Coastguard Worker             unused: _,
936*bb4ee6a4SAndroid Build Coastguard Worker             padding: _,
937*bb4ee6a4SAndroid Build Coastguard Worker             lock_owner,
938*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
939*bb4ee6a4SAndroid Build Coastguard Worker 
940*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.flush(
941*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
942*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
943*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
944*bb4ee6a4SAndroid Build Coastguard Worker             lock_owner,
945*bb4ee6a4SAndroid Build Coastguard Worker         ) {
946*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
947*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
948*bb4ee6a4SAndroid Build Coastguard Worker         }
949*bb4ee6a4SAndroid Build Coastguard Worker     }
950*bb4ee6a4SAndroid Build Coastguard Worker 
init<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>951*bb4ee6a4SAndroid Build Coastguard Worker     fn init<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
952*bb4ee6a4SAndroid Build Coastguard Worker         cros_tracing::trace_simple_print!("fuse server: init: in_header={:?}", in_header);
953*bb4ee6a4SAndroid Build Coastguard Worker         let InitIn {
954*bb4ee6a4SAndroid Build Coastguard Worker             major,
955*bb4ee6a4SAndroid Build Coastguard Worker             minor,
956*bb4ee6a4SAndroid Build Coastguard Worker             max_readahead,
957*bb4ee6a4SAndroid Build Coastguard Worker             flags,
958*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
959*bb4ee6a4SAndroid Build Coastguard Worker 
960*bb4ee6a4SAndroid Build Coastguard Worker         if major < KERNEL_VERSION {
961*bb4ee6a4SAndroid Build Coastguard Worker             error!("Unsupported fuse protocol version: {}.{}", major, minor);
962*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
963*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::EPROTO),
964*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
965*bb4ee6a4SAndroid Build Coastguard Worker                 w,
966*bb4ee6a4SAndroid Build Coastguard Worker             );
967*bb4ee6a4SAndroid Build Coastguard Worker         }
968*bb4ee6a4SAndroid Build Coastguard Worker 
969*bb4ee6a4SAndroid Build Coastguard Worker         if major > KERNEL_VERSION {
970*bb4ee6a4SAndroid Build Coastguard Worker             // Wait for the kernel to reply back with a 7.X version.
971*bb4ee6a4SAndroid Build Coastguard Worker             let out = InitOut {
972*bb4ee6a4SAndroid Build Coastguard Worker                 major: KERNEL_VERSION,
973*bb4ee6a4SAndroid Build Coastguard Worker                 minor: KERNEL_MINOR_VERSION,
974*bb4ee6a4SAndroid Build Coastguard Worker                 ..Default::default()
975*bb4ee6a4SAndroid Build Coastguard Worker             };
976*bb4ee6a4SAndroid Build Coastguard Worker 
977*bb4ee6a4SAndroid Build Coastguard Worker             return reply_ok(Some(out), None, in_header.unique, w);
978*bb4ee6a4SAndroid Build Coastguard Worker         }
979*bb4ee6a4SAndroid Build Coastguard Worker 
980*bb4ee6a4SAndroid Build Coastguard Worker         if minor < OLDEST_SUPPORTED_KERNEL_MINOR_VERSION {
981*bb4ee6a4SAndroid Build Coastguard Worker             error!(
982*bb4ee6a4SAndroid Build Coastguard Worker                 "Unsupported fuse protocol minor version: {}.{}",
983*bb4ee6a4SAndroid Build Coastguard Worker                 major, minor
984*bb4ee6a4SAndroid Build Coastguard Worker             );
985*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
986*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::EPROTO),
987*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
988*bb4ee6a4SAndroid Build Coastguard Worker                 w,
989*bb4ee6a4SAndroid Build Coastguard Worker             );
990*bb4ee6a4SAndroid Build Coastguard Worker         }
991*bb4ee6a4SAndroid Build Coastguard Worker 
992*bb4ee6a4SAndroid Build Coastguard Worker         let InitInExt { flags2, .. } =
993*bb4ee6a4SAndroid Build Coastguard Worker             if (FsOptions::from_bits_truncate(u64::from(flags)) & FsOptions::INIT_EXT).is_empty() {
994*bb4ee6a4SAndroid Build Coastguard Worker                 InitInExt::default()
995*bb4ee6a4SAndroid Build Coastguard Worker             } else {
996*bb4ee6a4SAndroid Build Coastguard Worker                 r.read_struct()?
997*bb4ee6a4SAndroid Build Coastguard Worker             };
998*bb4ee6a4SAndroid Build Coastguard Worker 
999*bb4ee6a4SAndroid Build Coastguard Worker         // These fuse features are supported by this server by default.
1000*bb4ee6a4SAndroid Build Coastguard Worker         let supported = FsOptions::ASYNC_READ
1001*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::PARALLEL_DIROPS
1002*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::BIG_WRITES
1003*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::AUTO_INVAL_DATA
1004*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::HANDLE_KILLPRIV
1005*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::ASYNC_DIO
1006*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::HAS_IOCTL_DIR
1007*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::DO_READDIRPLUS
1008*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::READDIRPLUS_AUTO
1009*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::ATOMIC_O_TRUNC
1010*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::MAX_PAGES
1011*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::MAP_ALIGNMENT
1012*bb4ee6a4SAndroid Build Coastguard Worker             | FsOptions::INIT_EXT;
1013*bb4ee6a4SAndroid Build Coastguard Worker 
1014*bb4ee6a4SAndroid Build Coastguard Worker         let capable = FsOptions::from_bits_truncate(u64::from(flags) | u64::from(flags2) << 32);
1015*bb4ee6a4SAndroid Build Coastguard Worker 
1016*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.init(capable) {
1017*bb4ee6a4SAndroid Build Coastguard Worker             Ok(want) => {
1018*bb4ee6a4SAndroid Build Coastguard Worker                 let mut enabled = capable & (want | supported);
1019*bb4ee6a4SAndroid Build Coastguard Worker 
1020*bb4ee6a4SAndroid Build Coastguard Worker                 // HANDLE_KILLPRIV doesn't work correctly when writeback caching is enabled so turn
1021*bb4ee6a4SAndroid Build Coastguard Worker                 // it off.
1022*bb4ee6a4SAndroid Build Coastguard Worker                 if enabled.contains(FsOptions::WRITEBACK_CACHE) {
1023*bb4ee6a4SAndroid Build Coastguard Worker                     enabled.remove(FsOptions::HANDLE_KILLPRIV);
1024*bb4ee6a4SAndroid Build Coastguard Worker                 }
1025*bb4ee6a4SAndroid Build Coastguard Worker 
1026*bb4ee6a4SAndroid Build Coastguard Worker                 // ATOMIC_O_TRUNC doesn't work with ZERO_MESSAGE_OPEN.
1027*bb4ee6a4SAndroid Build Coastguard Worker                 if enabled.contains(FsOptions::ZERO_MESSAGE_OPEN) {
1028*bb4ee6a4SAndroid Build Coastguard Worker                     enabled.remove(FsOptions::ATOMIC_O_TRUNC);
1029*bb4ee6a4SAndroid Build Coastguard Worker                 }
1030*bb4ee6a4SAndroid Build Coastguard Worker 
1031*bb4ee6a4SAndroid Build Coastguard Worker                 let max_write = self.fs.max_buffer_size();
1032*bb4ee6a4SAndroid Build Coastguard Worker                 let max_pages = min(
1033*bb4ee6a4SAndroid Build Coastguard Worker                     max(max_readahead, max_write) / pagesize() as u32,
1034*bb4ee6a4SAndroid Build Coastguard Worker                     u16::MAX as u32,
1035*bb4ee6a4SAndroid Build Coastguard Worker                 ) as u16;
1036*bb4ee6a4SAndroid Build Coastguard Worker                 let out = InitOut {
1037*bb4ee6a4SAndroid Build Coastguard Worker                     major: KERNEL_VERSION,
1038*bb4ee6a4SAndroid Build Coastguard Worker                     minor: KERNEL_MINOR_VERSION,
1039*bb4ee6a4SAndroid Build Coastguard Worker                     max_readahead,
1040*bb4ee6a4SAndroid Build Coastguard Worker                     flags: enabled.bits() as u32,
1041*bb4ee6a4SAndroid Build Coastguard Worker                     max_background: u16::MAX,
1042*bb4ee6a4SAndroid Build Coastguard Worker                     congestion_threshold: (u16::MAX / 4) * 3,
1043*bb4ee6a4SAndroid Build Coastguard Worker                     max_write,
1044*bb4ee6a4SAndroid Build Coastguard Worker                     time_gran: 1, // nanoseconds
1045*bb4ee6a4SAndroid Build Coastguard Worker                     max_pages,
1046*bb4ee6a4SAndroid Build Coastguard Worker                     map_alignment: pagesize().trailing_zeros() as u16,
1047*bb4ee6a4SAndroid Build Coastguard Worker                     flags2: (enabled.bits() >> 32) as u32,
1048*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
1049*bb4ee6a4SAndroid Build Coastguard Worker                 };
1050*bb4ee6a4SAndroid Build Coastguard Worker 
1051*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
1052*bb4ee6a4SAndroid Build Coastguard Worker             }
1053*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1054*bb4ee6a4SAndroid Build Coastguard Worker         }
1055*bb4ee6a4SAndroid Build Coastguard Worker     }
1056*bb4ee6a4SAndroid Build Coastguard Worker 
opendir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>1057*bb4ee6a4SAndroid Build Coastguard Worker     fn opendir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
1058*bb4ee6a4SAndroid Build Coastguard Worker         let OpenIn { flags, .. } = r.read_struct()?;
1059*bb4ee6a4SAndroid Build Coastguard Worker 
1060*bb4ee6a4SAndroid Build Coastguard Worker         match self
1061*bb4ee6a4SAndroid Build Coastguard Worker             .fs
1062*bb4ee6a4SAndroid Build Coastguard Worker             .opendir(Context::from(in_header), in_header.nodeid.into(), flags)
1063*bb4ee6a4SAndroid Build Coastguard Worker         {
1064*bb4ee6a4SAndroid Build Coastguard Worker             Ok((handle, opts)) => {
1065*bb4ee6a4SAndroid Build Coastguard Worker                 let out = OpenOut {
1066*bb4ee6a4SAndroid Build Coastguard Worker                     fh: handle.map(Into::into).unwrap_or(0),
1067*bb4ee6a4SAndroid Build Coastguard Worker                     open_flags: opts.bits(),
1068*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
1069*bb4ee6a4SAndroid Build Coastguard Worker                 };
1070*bb4ee6a4SAndroid Build Coastguard Worker 
1071*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
1072*bb4ee6a4SAndroid Build Coastguard Worker             }
1073*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1074*bb4ee6a4SAndroid Build Coastguard Worker         }
1075*bb4ee6a4SAndroid Build Coastguard Worker     }
1076*bb4ee6a4SAndroid Build Coastguard Worker 
readdir<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, mut w: W, ) -> Result<usize>1077*bb4ee6a4SAndroid Build Coastguard Worker     fn readdir<R: Reader, W: Writer>(
1078*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1079*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1080*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1081*bb4ee6a4SAndroid Build Coastguard Worker         mut w: W,
1082*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1083*bb4ee6a4SAndroid Build Coastguard Worker         let ReadIn {
1084*bb4ee6a4SAndroid Build Coastguard Worker             fh, offset, size, ..
1085*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1086*bb4ee6a4SAndroid Build Coastguard Worker 
1087*bb4ee6a4SAndroid Build Coastguard Worker         if size > self.fs.max_buffer_size() {
1088*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
1089*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
1090*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
1091*bb4ee6a4SAndroid Build Coastguard Worker                 w,
1092*bb4ee6a4SAndroid Build Coastguard Worker             );
1093*bb4ee6a4SAndroid Build Coastguard Worker         }
1094*bb4ee6a4SAndroid Build Coastguard Worker 
1095*bb4ee6a4SAndroid Build Coastguard Worker         if !w.has_sufficient_buffer(size) {
1096*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
1097*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
1098*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
1099*bb4ee6a4SAndroid Build Coastguard Worker                 w,
1100*bb4ee6a4SAndroid Build Coastguard Worker             );
1101*bb4ee6a4SAndroid Build Coastguard Worker         }
1102*bb4ee6a4SAndroid Build Coastguard Worker 
1103*bb4ee6a4SAndroid Build Coastguard Worker         // Skip over enough bytes for the header.
1104*bb4ee6a4SAndroid Build Coastguard Worker         let unique = in_header.unique;
1105*bb4ee6a4SAndroid Build Coastguard Worker         let result = w.write_at(size_of::<OutHeader>(), |cursor| {
1106*bb4ee6a4SAndroid Build Coastguard Worker             match self.fs.readdir(
1107*bb4ee6a4SAndroid Build Coastguard Worker                 Context::from(in_header),
1108*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.nodeid.into(),
1109*bb4ee6a4SAndroid Build Coastguard Worker                 fh.into(),
1110*bb4ee6a4SAndroid Build Coastguard Worker                 size,
1111*bb4ee6a4SAndroid Build Coastguard Worker                 offset,
1112*bb4ee6a4SAndroid Build Coastguard Worker             ) {
1113*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(mut entries) => {
1114*bb4ee6a4SAndroid Build Coastguard Worker                     let mut total_written = 0;
1115*bb4ee6a4SAndroid Build Coastguard Worker                     while let Some(dirent) = entries.next() {
1116*bb4ee6a4SAndroid Build Coastguard Worker                         let remaining = (size as usize).saturating_sub(total_written);
1117*bb4ee6a4SAndroid Build Coastguard Worker                         match add_dirent(cursor, remaining, &dirent, None) {
1118*bb4ee6a4SAndroid Build Coastguard Worker                             // No more space left in the buffer.
1119*bb4ee6a4SAndroid Build Coastguard Worker                             Ok(0) => break,
1120*bb4ee6a4SAndroid Build Coastguard Worker                             Ok(bytes_written) => {
1121*bb4ee6a4SAndroid Build Coastguard Worker                                 total_written += bytes_written;
1122*bb4ee6a4SAndroid Build Coastguard Worker                             }
1123*bb4ee6a4SAndroid Build Coastguard Worker                             Err(e) => return Err(e),
1124*bb4ee6a4SAndroid Build Coastguard Worker                         }
1125*bb4ee6a4SAndroid Build Coastguard Worker                     }
1126*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(total_written)
1127*bb4ee6a4SAndroid Build Coastguard Worker                 }
1128*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => Err(e),
1129*bb4ee6a4SAndroid Build Coastguard Worker             }
1130*bb4ee6a4SAndroid Build Coastguard Worker         });
1131*bb4ee6a4SAndroid Build Coastguard Worker 
1132*bb4ee6a4SAndroid Build Coastguard Worker         match result {
1133*bb4ee6a4SAndroid Build Coastguard Worker             Ok(total_written) => reply_readdir(total_written, unique, w),
1134*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, unique, w),
1135*bb4ee6a4SAndroid Build Coastguard Worker         }
1136*bb4ee6a4SAndroid Build Coastguard Worker     }
1137*bb4ee6a4SAndroid Build Coastguard Worker 
lookup_dirent_attribute( &self, in_header: &InHeader, dir_entry: &DirEntry, ) -> io::Result<Entry>1138*bb4ee6a4SAndroid Build Coastguard Worker     fn lookup_dirent_attribute(
1139*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1140*bb4ee6a4SAndroid Build Coastguard Worker         in_header: &InHeader,
1141*bb4ee6a4SAndroid Build Coastguard Worker         dir_entry: &DirEntry,
1142*bb4ee6a4SAndroid Build Coastguard Worker     ) -> io::Result<Entry> {
1143*bb4ee6a4SAndroid Build Coastguard Worker         let parent = in_header.nodeid.into();
1144*bb4ee6a4SAndroid Build Coastguard Worker         let name = dir_entry.name.to_bytes();
1145*bb4ee6a4SAndroid Build Coastguard Worker         let entry = if name == b"." || name == b".." {
1146*bb4ee6a4SAndroid Build Coastguard Worker             // Don't do lookups on the current directory or the parent directory.
1147*bb4ee6a4SAndroid Build Coastguard Worker             // SAFETY: struct only contains integer fields and any value is valid.
1148*bb4ee6a4SAndroid Build Coastguard Worker             let mut attr = unsafe { MaybeUninit::<libc::stat64>::zeroed().assume_init() };
1149*bb4ee6a4SAndroid Build Coastguard Worker             attr.st_ino = dir_entry.ino;
1150*bb4ee6a4SAndroid Build Coastguard Worker             attr.st_mode = dir_entry.type_;
1151*bb4ee6a4SAndroid Build Coastguard Worker 
1152*bb4ee6a4SAndroid Build Coastguard Worker             // We use 0 for the inode value to indicate a negative entry.
1153*bb4ee6a4SAndroid Build Coastguard Worker             Entry {
1154*bb4ee6a4SAndroid Build Coastguard Worker                 inode: 0,
1155*bb4ee6a4SAndroid Build Coastguard Worker                 generation: 0,
1156*bb4ee6a4SAndroid Build Coastguard Worker                 attr,
1157*bb4ee6a4SAndroid Build Coastguard Worker                 attr_timeout: Duration::from_secs(0),
1158*bb4ee6a4SAndroid Build Coastguard Worker                 entry_timeout: Duration::from_secs(0),
1159*bb4ee6a4SAndroid Build Coastguard Worker             }
1160*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1161*bb4ee6a4SAndroid Build Coastguard Worker             self.fs
1162*bb4ee6a4SAndroid Build Coastguard Worker                 .lookup(Context::from(*in_header), parent, dir_entry.name)?
1163*bb4ee6a4SAndroid Build Coastguard Worker         };
1164*bb4ee6a4SAndroid Build Coastguard Worker 
1165*bb4ee6a4SAndroid Build Coastguard Worker         Ok(entry)
1166*bb4ee6a4SAndroid Build Coastguard Worker     }
1167*bb4ee6a4SAndroid Build Coastguard Worker 
readdirplus<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, mut w: W, ) -> Result<usize>1168*bb4ee6a4SAndroid Build Coastguard Worker     fn readdirplus<R: Reader, W: Writer>(
1169*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1170*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1171*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1172*bb4ee6a4SAndroid Build Coastguard Worker         mut w: W,
1173*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1174*bb4ee6a4SAndroid Build Coastguard Worker         cros_tracing::trace_simple_print!("fuse server: readdirplus: in_header={:?}", in_header);
1175*bb4ee6a4SAndroid Build Coastguard Worker         let ReadIn {
1176*bb4ee6a4SAndroid Build Coastguard Worker             fh, offset, size, ..
1177*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1178*bb4ee6a4SAndroid Build Coastguard Worker 
1179*bb4ee6a4SAndroid Build Coastguard Worker         if size > self.fs.max_buffer_size() {
1180*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
1181*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
1182*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
1183*bb4ee6a4SAndroid Build Coastguard Worker                 w,
1184*bb4ee6a4SAndroid Build Coastguard Worker             );
1185*bb4ee6a4SAndroid Build Coastguard Worker         }
1186*bb4ee6a4SAndroid Build Coastguard Worker 
1187*bb4ee6a4SAndroid Build Coastguard Worker         if !w.has_sufficient_buffer(size) {
1188*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
1189*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::ENOMEM),
1190*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
1191*bb4ee6a4SAndroid Build Coastguard Worker                 w,
1192*bb4ee6a4SAndroid Build Coastguard Worker             );
1193*bb4ee6a4SAndroid Build Coastguard Worker         }
1194*bb4ee6a4SAndroid Build Coastguard Worker 
1195*bb4ee6a4SAndroid Build Coastguard Worker         // Skip over enough bytes for the header.
1196*bb4ee6a4SAndroid Build Coastguard Worker         let unique = in_header.unique;
1197*bb4ee6a4SAndroid Build Coastguard Worker         let result = w.write_at(size_of::<OutHeader>(), |cursor| {
1198*bb4ee6a4SAndroid Build Coastguard Worker             match self.fs.readdir(
1199*bb4ee6a4SAndroid Build Coastguard Worker                 Context::from(in_header),
1200*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.nodeid.into(),
1201*bb4ee6a4SAndroid Build Coastguard Worker                 fh.into(),
1202*bb4ee6a4SAndroid Build Coastguard Worker                 size,
1203*bb4ee6a4SAndroid Build Coastguard Worker                 offset,
1204*bb4ee6a4SAndroid Build Coastguard Worker             ) {
1205*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(mut entries) => {
1206*bb4ee6a4SAndroid Build Coastguard Worker                     let mut total_written = 0;
1207*bb4ee6a4SAndroid Build Coastguard Worker                     while let Some(dirent) = entries.next() {
1208*bb4ee6a4SAndroid Build Coastguard Worker                         let mut entry_inode = None;
1209*bb4ee6a4SAndroid Build Coastguard Worker                         let dirent_result = self
1210*bb4ee6a4SAndroid Build Coastguard Worker                             .lookup_dirent_attribute(&in_header, &dirent)
1211*bb4ee6a4SAndroid Build Coastguard Worker                             .and_then(|e| {
1212*bb4ee6a4SAndroid Build Coastguard Worker                                 entry_inode = Some(e.inode);
1213*bb4ee6a4SAndroid Build Coastguard Worker                                 let remaining = (size as usize).saturating_sub(total_written);
1214*bb4ee6a4SAndroid Build Coastguard Worker                                 add_dirent(cursor, remaining, &dirent, Some(e))
1215*bb4ee6a4SAndroid Build Coastguard Worker                             });
1216*bb4ee6a4SAndroid Build Coastguard Worker 
1217*bb4ee6a4SAndroid Build Coastguard Worker                         match dirent_result {
1218*bb4ee6a4SAndroid Build Coastguard Worker                             Ok(0) => {
1219*bb4ee6a4SAndroid Build Coastguard Worker                                 // No more space left in the buffer but we need to undo the lookup
1220*bb4ee6a4SAndroid Build Coastguard Worker                                 // that created the Entry or we will end up with mismatched lookup
1221*bb4ee6a4SAndroid Build Coastguard Worker                                 // counts.
1222*bb4ee6a4SAndroid Build Coastguard Worker                                 if let Some(inode) = entry_inode {
1223*bb4ee6a4SAndroid Build Coastguard Worker                                     self.fs.forget(Context::from(in_header), inode.into(), 1);
1224*bb4ee6a4SAndroid Build Coastguard Worker                                 }
1225*bb4ee6a4SAndroid Build Coastguard Worker                                 break;
1226*bb4ee6a4SAndroid Build Coastguard Worker                             }
1227*bb4ee6a4SAndroid Build Coastguard Worker                             Ok(bytes_written) => {
1228*bb4ee6a4SAndroid Build Coastguard Worker                                 total_written += bytes_written;
1229*bb4ee6a4SAndroid Build Coastguard Worker                             }
1230*bb4ee6a4SAndroid Build Coastguard Worker                             Err(e) => {
1231*bb4ee6a4SAndroid Build Coastguard Worker                                 if let Some(inode) = entry_inode {
1232*bb4ee6a4SAndroid Build Coastguard Worker                                     self.fs.forget(Context::from(in_header), inode.into(), 1);
1233*bb4ee6a4SAndroid Build Coastguard Worker                                 }
1234*bb4ee6a4SAndroid Build Coastguard Worker 
1235*bb4ee6a4SAndroid Build Coastguard Worker                                 if total_written == 0 {
1236*bb4ee6a4SAndroid Build Coastguard Worker                                     // We haven't filled any entries yet so we can just propagate
1237*bb4ee6a4SAndroid Build Coastguard Worker                                     // the error.
1238*bb4ee6a4SAndroid Build Coastguard Worker                                     return Err(e);
1239*bb4ee6a4SAndroid Build Coastguard Worker                                 }
1240*bb4ee6a4SAndroid Build Coastguard Worker 
1241*bb4ee6a4SAndroid Build Coastguard Worker                                 // We already filled in some entries. Returning an error now will
1242*bb4ee6a4SAndroid Build Coastguard Worker                                 // cause lookup count mismatches for those entries so just return
1243*bb4ee6a4SAndroid Build Coastguard Worker                                 // whatever we already have.
1244*bb4ee6a4SAndroid Build Coastguard Worker                                 break;
1245*bb4ee6a4SAndroid Build Coastguard Worker                             }
1246*bb4ee6a4SAndroid Build Coastguard Worker                         }
1247*bb4ee6a4SAndroid Build Coastguard Worker                     }
1248*bb4ee6a4SAndroid Build Coastguard Worker                     Ok(total_written)
1249*bb4ee6a4SAndroid Build Coastguard Worker                 }
1250*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => Err(e),
1251*bb4ee6a4SAndroid Build Coastguard Worker             }
1252*bb4ee6a4SAndroid Build Coastguard Worker         });
1253*bb4ee6a4SAndroid Build Coastguard Worker 
1254*bb4ee6a4SAndroid Build Coastguard Worker         match result {
1255*bb4ee6a4SAndroid Build Coastguard Worker             Ok(total_written) => reply_readdir(total_written, unique, w),
1256*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, unique, w),
1257*bb4ee6a4SAndroid Build Coastguard Worker         }
1258*bb4ee6a4SAndroid Build Coastguard Worker     }
1259*bb4ee6a4SAndroid Build Coastguard Worker 
releasedir<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>1260*bb4ee6a4SAndroid Build Coastguard Worker     fn releasedir<R: Reader, W: Writer>(
1261*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1262*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1263*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1264*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1265*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1266*bb4ee6a4SAndroid Build Coastguard Worker         let ReleaseIn { fh, flags, .. } = r.read_struct()?;
1267*bb4ee6a4SAndroid Build Coastguard Worker 
1268*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.releasedir(
1269*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
1270*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1271*bb4ee6a4SAndroid Build Coastguard Worker             flags,
1272*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
1273*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1274*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
1275*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1276*bb4ee6a4SAndroid Build Coastguard Worker         }
1277*bb4ee6a4SAndroid Build Coastguard Worker     }
1278*bb4ee6a4SAndroid Build Coastguard Worker 
fsyncdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>1279*bb4ee6a4SAndroid Build Coastguard Worker     fn fsyncdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
1280*bb4ee6a4SAndroid Build Coastguard Worker         let FsyncIn {
1281*bb4ee6a4SAndroid Build Coastguard Worker             fh, fsync_flags, ..
1282*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1283*bb4ee6a4SAndroid Build Coastguard Worker         let datasync = fsync_flags & 0x1 != 0;
1284*bb4ee6a4SAndroid Build Coastguard Worker 
1285*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.fsyncdir(
1286*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
1287*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1288*bb4ee6a4SAndroid Build Coastguard Worker             datasync,
1289*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
1290*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1291*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
1292*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1293*bb4ee6a4SAndroid Build Coastguard Worker         }
1294*bb4ee6a4SAndroid Build Coastguard Worker     }
1295*bb4ee6a4SAndroid Build Coastguard Worker 
getlk<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize>1296*bb4ee6a4SAndroid Build Coastguard Worker     fn getlk<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize> {
1297*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.fs.getlk() {
1298*bb4ee6a4SAndroid Build Coastguard Worker             reply_error(e, in_header.unique, w)
1299*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1300*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
1301*bb4ee6a4SAndroid Build Coastguard Worker         }
1302*bb4ee6a4SAndroid Build Coastguard Worker     }
1303*bb4ee6a4SAndroid Build Coastguard Worker 
setlk<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize>1304*bb4ee6a4SAndroid Build Coastguard Worker     fn setlk<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize> {
1305*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.fs.setlk() {
1306*bb4ee6a4SAndroid Build Coastguard Worker             reply_error(e, in_header.unique, w)
1307*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1308*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
1309*bb4ee6a4SAndroid Build Coastguard Worker         }
1310*bb4ee6a4SAndroid Build Coastguard Worker     }
1311*bb4ee6a4SAndroid Build Coastguard Worker 
setlkw<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize>1312*bb4ee6a4SAndroid Build Coastguard Worker     fn setlkw<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize> {
1313*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.fs.setlkw() {
1314*bb4ee6a4SAndroid Build Coastguard Worker             reply_error(e, in_header.unique, w)
1315*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1316*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
1317*bb4ee6a4SAndroid Build Coastguard Worker         }
1318*bb4ee6a4SAndroid Build Coastguard Worker     }
1319*bb4ee6a4SAndroid Build Coastguard Worker 
access<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>1320*bb4ee6a4SAndroid Build Coastguard Worker     fn access<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
1321*bb4ee6a4SAndroid Build Coastguard Worker         let AccessIn { mask, .. } = r.read_struct()?;
1322*bb4ee6a4SAndroid Build Coastguard Worker 
1323*bb4ee6a4SAndroid Build Coastguard Worker         match self
1324*bb4ee6a4SAndroid Build Coastguard Worker             .fs
1325*bb4ee6a4SAndroid Build Coastguard Worker             .access(Context::from(in_header), in_header.nodeid.into(), mask)
1326*bb4ee6a4SAndroid Build Coastguard Worker         {
1327*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
1328*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1329*bb4ee6a4SAndroid Build Coastguard Worker         }
1330*bb4ee6a4SAndroid Build Coastguard Worker     }
1331*bb4ee6a4SAndroid Build Coastguard Worker 
create<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>1332*bb4ee6a4SAndroid Build Coastguard Worker     fn create<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
1333*bb4ee6a4SAndroid Build Coastguard Worker         let CreateIn {
1334*bb4ee6a4SAndroid Build Coastguard Worker             flags, mode, umask, ..
1335*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1336*bb4ee6a4SAndroid Build Coastguard Worker 
1337*bb4ee6a4SAndroid Build Coastguard Worker         let buflen = (in_header.len as usize)
1338*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
1339*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<CreateIn>()))
1340*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
1341*bb4ee6a4SAndroid Build Coastguard Worker 
1342*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; buflen];
1343*bb4ee6a4SAndroid Build Coastguard Worker 
1344*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
1345*bb4ee6a4SAndroid Build Coastguard Worker 
1346*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = buf.split_inclusive(|&c| c == b'\0');
1347*bb4ee6a4SAndroid Build Coastguard Worker         let name = iter
1348*bb4ee6a4SAndroid Build Coastguard Worker             .next()
1349*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)
1350*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(bytes_to_cstr)?;
1351*bb4ee6a4SAndroid Build Coastguard Worker 
1352*bb4ee6a4SAndroid Build Coastguard Worker         let split_pos = name.to_bytes_with_nul().len();
1353*bb4ee6a4SAndroid Build Coastguard Worker         let security_ctx = parse_selinux_xattr(&buf[split_pos..])?;
1354*bb4ee6a4SAndroid Build Coastguard Worker 
1355*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.create(
1356*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
1357*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1358*bb4ee6a4SAndroid Build Coastguard Worker             name,
1359*bb4ee6a4SAndroid Build Coastguard Worker             mode,
1360*bb4ee6a4SAndroid Build Coastguard Worker             flags,
1361*bb4ee6a4SAndroid Build Coastguard Worker             umask,
1362*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx,
1363*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1364*bb4ee6a4SAndroid Build Coastguard Worker             Ok((entry, handle, opts)) => {
1365*bb4ee6a4SAndroid Build Coastguard Worker                 let entry_out = EntryOut {
1366*bb4ee6a4SAndroid Build Coastguard Worker                     nodeid: entry.inode,
1367*bb4ee6a4SAndroid Build Coastguard Worker                     generation: entry.generation,
1368*bb4ee6a4SAndroid Build Coastguard Worker                     entry_valid: entry.entry_timeout.as_secs(),
1369*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid: entry.attr_timeout.as_secs(),
1370*bb4ee6a4SAndroid Build Coastguard Worker                     entry_valid_nsec: entry.entry_timeout.subsec_nanos(),
1371*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid_nsec: entry.attr_timeout.subsec_nanos(),
1372*bb4ee6a4SAndroid Build Coastguard Worker                     attr: entry.attr.into(),
1373*bb4ee6a4SAndroid Build Coastguard Worker                 };
1374*bb4ee6a4SAndroid Build Coastguard Worker                 let open_out = OpenOut {
1375*bb4ee6a4SAndroid Build Coastguard Worker                     fh: handle.map(Into::into).unwrap_or(0),
1376*bb4ee6a4SAndroid Build Coastguard Worker                     open_flags: opts.bits(),
1377*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
1378*bb4ee6a4SAndroid Build Coastguard Worker                 };
1379*bb4ee6a4SAndroid Build Coastguard Worker 
1380*bb4ee6a4SAndroid Build Coastguard Worker                 // Kind of a hack to write both structs.
1381*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(
1382*bb4ee6a4SAndroid Build Coastguard Worker                     Some(entry_out),
1383*bb4ee6a4SAndroid Build Coastguard Worker                     Some(open_out.as_bytes()),
1384*bb4ee6a4SAndroid Build Coastguard Worker                     in_header.unique,
1385*bb4ee6a4SAndroid Build Coastguard Worker                     w,
1386*bb4ee6a4SAndroid Build Coastguard Worker                 )
1387*bb4ee6a4SAndroid Build Coastguard Worker             }
1388*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1389*bb4ee6a4SAndroid Build Coastguard Worker         }
1390*bb4ee6a4SAndroid Build Coastguard Worker     }
1391*bb4ee6a4SAndroid Build Coastguard Worker 
1392*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(clippy::unnecessary_wraps)]
interrupt(&self, _in_header: InHeader) -> Result<usize>1393*bb4ee6a4SAndroid Build Coastguard Worker     fn interrupt(&self, _in_header: InHeader) -> Result<usize> {
1394*bb4ee6a4SAndroid Build Coastguard Worker         Ok(0)
1395*bb4ee6a4SAndroid Build Coastguard Worker     }
1396*bb4ee6a4SAndroid Build Coastguard Worker 
bmap<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize>1397*bb4ee6a4SAndroid Build Coastguard Worker     fn bmap<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize> {
1398*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.fs.bmap() {
1399*bb4ee6a4SAndroid Build Coastguard Worker             reply_error(e, in_header.unique, w)
1400*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1401*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
1402*bb4ee6a4SAndroid Build Coastguard Worker         }
1403*bb4ee6a4SAndroid Build Coastguard Worker     }
1404*bb4ee6a4SAndroid Build Coastguard Worker 
1405*bb4ee6a4SAndroid Build Coastguard Worker     #[allow(clippy::unnecessary_wraps)]
destroy(&self) -> Result<usize>1406*bb4ee6a4SAndroid Build Coastguard Worker     fn destroy(&self) -> Result<usize> {
1407*bb4ee6a4SAndroid Build Coastguard Worker         // No reply to this function.
1408*bb4ee6a4SAndroid Build Coastguard Worker         self.fs.destroy();
1409*bb4ee6a4SAndroid Build Coastguard Worker 
1410*bb4ee6a4SAndroid Build Coastguard Worker         Ok(0)
1411*bb4ee6a4SAndroid Build Coastguard Worker     }
1412*bb4ee6a4SAndroid Build Coastguard Worker 
ioctl<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize>1413*bb4ee6a4SAndroid Build Coastguard Worker     fn ioctl<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
1414*bb4ee6a4SAndroid Build Coastguard Worker         let IoctlIn {
1415*bb4ee6a4SAndroid Build Coastguard Worker             fh,
1416*bb4ee6a4SAndroid Build Coastguard Worker             flags,
1417*bb4ee6a4SAndroid Build Coastguard Worker             cmd,
1418*bb4ee6a4SAndroid Build Coastguard Worker             arg,
1419*bb4ee6a4SAndroid Build Coastguard Worker             in_size,
1420*bb4ee6a4SAndroid Build Coastguard Worker             out_size,
1421*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1422*bb4ee6a4SAndroid Build Coastguard Worker 
1423*bb4ee6a4SAndroid Build Coastguard Worker         let res = self.fs.ioctl(
1424*bb4ee6a4SAndroid Build Coastguard Worker             in_header.into(),
1425*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1426*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
1427*bb4ee6a4SAndroid Build Coastguard Worker             IoctlFlags::from_bits_truncate(flags),
1428*bb4ee6a4SAndroid Build Coastguard Worker             cmd,
1429*bb4ee6a4SAndroid Build Coastguard Worker             arg,
1430*bb4ee6a4SAndroid Build Coastguard Worker             in_size,
1431*bb4ee6a4SAndroid Build Coastguard Worker             out_size,
1432*bb4ee6a4SAndroid Build Coastguard Worker             r,
1433*bb4ee6a4SAndroid Build Coastguard Worker         );
1434*bb4ee6a4SAndroid Build Coastguard Worker 
1435*bb4ee6a4SAndroid Build Coastguard Worker         match res {
1436*bb4ee6a4SAndroid Build Coastguard Worker             Ok(reply) => match reply {
1437*bb4ee6a4SAndroid Build Coastguard Worker                 IoctlReply::Retry { input, output } => {
1438*bb4ee6a4SAndroid Build Coastguard Worker                     retry_ioctl(in_header.unique, input, output, w)
1439*bb4ee6a4SAndroid Build Coastguard Worker                 }
1440*bb4ee6a4SAndroid Build Coastguard Worker                 IoctlReply::Done(res) => finish_ioctl(in_header.unique, res, w),
1441*bb4ee6a4SAndroid Build Coastguard Worker             },
1442*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1443*bb4ee6a4SAndroid Build Coastguard Worker         }
1444*bb4ee6a4SAndroid Build Coastguard Worker     }
1445*bb4ee6a4SAndroid Build Coastguard Worker 
poll<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize>1446*bb4ee6a4SAndroid Build Coastguard Worker     fn poll<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize> {
1447*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.fs.poll() {
1448*bb4ee6a4SAndroid Build Coastguard Worker             reply_error(e, in_header.unique, w)
1449*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1450*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
1451*bb4ee6a4SAndroid Build Coastguard Worker         }
1452*bb4ee6a4SAndroid Build Coastguard Worker     }
1453*bb4ee6a4SAndroid Build Coastguard Worker 
notify_reply<R: Reader, W: Writer>( &self, in_header: InHeader, mut _r: R, w: W, ) -> Result<usize>1454*bb4ee6a4SAndroid Build Coastguard Worker     fn notify_reply<R: Reader, W: Writer>(
1455*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1456*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1457*bb4ee6a4SAndroid Build Coastguard Worker         mut _r: R,
1458*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1459*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1460*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.fs.notify_reply() {
1461*bb4ee6a4SAndroid Build Coastguard Worker             reply_error(e, in_header.unique, w)
1462*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1463*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
1464*bb4ee6a4SAndroid Build Coastguard Worker         }
1465*bb4ee6a4SAndroid Build Coastguard Worker     }
1466*bb4ee6a4SAndroid Build Coastguard Worker 
batch_forget<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>1467*bb4ee6a4SAndroid Build Coastguard Worker     fn batch_forget<R: Reader, W: Writer>(
1468*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1469*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1470*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1471*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1472*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1473*bb4ee6a4SAndroid Build Coastguard Worker         let BatchForgetIn { count, .. } = r.read_struct()?;
1474*bb4ee6a4SAndroid Build Coastguard Worker 
1475*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(size) = (count as usize).checked_mul(size_of::<ForgetOne>()) {
1476*bb4ee6a4SAndroid Build Coastguard Worker             if size > self.fs.max_buffer_size() as usize {
1477*bb4ee6a4SAndroid Build Coastguard Worker                 return reply_error(
1478*bb4ee6a4SAndroid Build Coastguard Worker                     io::Error::from_raw_os_error(libc::ENOMEM),
1479*bb4ee6a4SAndroid Build Coastguard Worker                     in_header.unique,
1480*bb4ee6a4SAndroid Build Coastguard Worker                     w,
1481*bb4ee6a4SAndroid Build Coastguard Worker                 );
1482*bb4ee6a4SAndroid Build Coastguard Worker             }
1483*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1484*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
1485*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::EOVERFLOW),
1486*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
1487*bb4ee6a4SAndroid Build Coastguard Worker                 w,
1488*bb4ee6a4SAndroid Build Coastguard Worker             );
1489*bb4ee6a4SAndroid Build Coastguard Worker         }
1490*bb4ee6a4SAndroid Build Coastguard Worker 
1491*bb4ee6a4SAndroid Build Coastguard Worker         let mut requests = Vec::with_capacity(count as usize);
1492*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..count {
1493*bb4ee6a4SAndroid Build Coastguard Worker             let f: ForgetOne = r.read_struct()?;
1494*bb4ee6a4SAndroid Build Coastguard Worker             requests.push((f.nodeid.into(), f.nlookup));
1495*bb4ee6a4SAndroid Build Coastguard Worker         }
1496*bb4ee6a4SAndroid Build Coastguard Worker 
1497*bb4ee6a4SAndroid Build Coastguard Worker         self.fs.batch_forget(Context::from(in_header), requests);
1498*bb4ee6a4SAndroid Build Coastguard Worker 
1499*bb4ee6a4SAndroid Build Coastguard Worker         // No reply for forget messages.
1500*bb4ee6a4SAndroid Build Coastguard Worker         Ok(0)
1501*bb4ee6a4SAndroid Build Coastguard Worker     }
1502*bb4ee6a4SAndroid Build Coastguard Worker 
fallocate<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>1503*bb4ee6a4SAndroid Build Coastguard Worker     fn fallocate<R: Reader, W: Writer>(
1504*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1505*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1506*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1507*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1508*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1509*bb4ee6a4SAndroid Build Coastguard Worker         let FallocateIn {
1510*bb4ee6a4SAndroid Build Coastguard Worker             fh,
1511*bb4ee6a4SAndroid Build Coastguard Worker             offset,
1512*bb4ee6a4SAndroid Build Coastguard Worker             length,
1513*bb4ee6a4SAndroid Build Coastguard Worker             mode,
1514*bb4ee6a4SAndroid Build Coastguard Worker             ..
1515*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1516*bb4ee6a4SAndroid Build Coastguard Worker 
1517*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.fallocate(
1518*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
1519*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1520*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
1521*bb4ee6a4SAndroid Build Coastguard Worker             mode,
1522*bb4ee6a4SAndroid Build Coastguard Worker             offset,
1523*bb4ee6a4SAndroid Build Coastguard Worker             length,
1524*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1525*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
1526*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1527*bb4ee6a4SAndroid Build Coastguard Worker         }
1528*bb4ee6a4SAndroid Build Coastguard Worker     }
1529*bb4ee6a4SAndroid Build Coastguard Worker 
lseek<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize>1530*bb4ee6a4SAndroid Build Coastguard Worker     fn lseek<R: Reader, W: Writer>(&self, in_header: InHeader, mut _r: R, w: W) -> Result<usize> {
1531*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = self.fs.lseek() {
1532*bb4ee6a4SAndroid Build Coastguard Worker             reply_error(e, in_header.unique, w)
1533*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1534*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
1535*bb4ee6a4SAndroid Build Coastguard Worker         }
1536*bb4ee6a4SAndroid Build Coastguard Worker     }
1537*bb4ee6a4SAndroid Build Coastguard Worker 
copy_file_range<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>1538*bb4ee6a4SAndroid Build Coastguard Worker     fn copy_file_range<R: Reader, W: Writer>(
1539*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1540*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1541*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1542*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1543*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1544*bb4ee6a4SAndroid Build Coastguard Worker         let CopyFileRangeIn {
1545*bb4ee6a4SAndroid Build Coastguard Worker             fh_src,
1546*bb4ee6a4SAndroid Build Coastguard Worker             off_src,
1547*bb4ee6a4SAndroid Build Coastguard Worker             nodeid_dst,
1548*bb4ee6a4SAndroid Build Coastguard Worker             fh_dst,
1549*bb4ee6a4SAndroid Build Coastguard Worker             off_dst,
1550*bb4ee6a4SAndroid Build Coastguard Worker             len,
1551*bb4ee6a4SAndroid Build Coastguard Worker             flags,
1552*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1553*bb4ee6a4SAndroid Build Coastguard Worker 
1554*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.copy_file_range(
1555*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
1556*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1557*bb4ee6a4SAndroid Build Coastguard Worker             fh_src.into(),
1558*bb4ee6a4SAndroid Build Coastguard Worker             off_src,
1559*bb4ee6a4SAndroid Build Coastguard Worker             nodeid_dst.into(),
1560*bb4ee6a4SAndroid Build Coastguard Worker             fh_dst.into(),
1561*bb4ee6a4SAndroid Build Coastguard Worker             off_dst,
1562*bb4ee6a4SAndroid Build Coastguard Worker             len,
1563*bb4ee6a4SAndroid Build Coastguard Worker             flags,
1564*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1565*bb4ee6a4SAndroid Build Coastguard Worker             Ok(count) => {
1566*bb4ee6a4SAndroid Build Coastguard Worker                 let out = WriteOut {
1567*bb4ee6a4SAndroid Build Coastguard Worker                     size: count as u32,
1568*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
1569*bb4ee6a4SAndroid Build Coastguard Worker                 };
1570*bb4ee6a4SAndroid Build Coastguard Worker 
1571*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(Some(out), None, in_header.unique, w)
1572*bb4ee6a4SAndroid Build Coastguard Worker             }
1573*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1574*bb4ee6a4SAndroid Build Coastguard Worker         }
1575*bb4ee6a4SAndroid Build Coastguard Worker     }
1576*bb4ee6a4SAndroid Build Coastguard Worker 
set_up_mapping<R, W, M>( &self, in_header: InHeader, mut r: R, w: W, mapper: M, ) -> Result<usize> where R: Reader, W: Writer, M: Mapper,1577*bb4ee6a4SAndroid Build Coastguard Worker     fn set_up_mapping<R, W, M>(
1578*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1579*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1580*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1581*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1582*bb4ee6a4SAndroid Build Coastguard Worker         mapper: M,
1583*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize>
1584*bb4ee6a4SAndroid Build Coastguard Worker     where
1585*bb4ee6a4SAndroid Build Coastguard Worker         R: Reader,
1586*bb4ee6a4SAndroid Build Coastguard Worker         W: Writer,
1587*bb4ee6a4SAndroid Build Coastguard Worker         M: Mapper,
1588*bb4ee6a4SAndroid Build Coastguard Worker     {
1589*bb4ee6a4SAndroid Build Coastguard Worker         let SetUpMappingIn {
1590*bb4ee6a4SAndroid Build Coastguard Worker             fh,
1591*bb4ee6a4SAndroid Build Coastguard Worker             foffset,
1592*bb4ee6a4SAndroid Build Coastguard Worker             len,
1593*bb4ee6a4SAndroid Build Coastguard Worker             flags,
1594*bb4ee6a4SAndroid Build Coastguard Worker             moffset,
1595*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1596*bb4ee6a4SAndroid Build Coastguard Worker         let flags = SetUpMappingFlags::from_bits_truncate(flags);
1597*bb4ee6a4SAndroid Build Coastguard Worker 
1598*bb4ee6a4SAndroid Build Coastguard Worker         let mut prot = 0;
1599*bb4ee6a4SAndroid Build Coastguard Worker         if flags.contains(SetUpMappingFlags::READ) {
1600*bb4ee6a4SAndroid Build Coastguard Worker             prot |= libc::PROT_READ as u32;
1601*bb4ee6a4SAndroid Build Coastguard Worker         }
1602*bb4ee6a4SAndroid Build Coastguard Worker         if flags.contains(SetUpMappingFlags::WRITE) {
1603*bb4ee6a4SAndroid Build Coastguard Worker             prot |= libc::PROT_WRITE as u32;
1604*bb4ee6a4SAndroid Build Coastguard Worker         }
1605*bb4ee6a4SAndroid Build Coastguard Worker 
1606*bb4ee6a4SAndroid Build Coastguard Worker         let size = if let Ok(s) = len.try_into() {
1607*bb4ee6a4SAndroid Build Coastguard Worker             s
1608*bb4ee6a4SAndroid Build Coastguard Worker         } else {
1609*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
1610*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::EOVERFLOW),
1611*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
1612*bb4ee6a4SAndroid Build Coastguard Worker                 w,
1613*bb4ee6a4SAndroid Build Coastguard Worker             );
1614*bb4ee6a4SAndroid Build Coastguard Worker         };
1615*bb4ee6a4SAndroid Build Coastguard Worker 
1616*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.set_up_mapping(
1617*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
1618*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1619*bb4ee6a4SAndroid Build Coastguard Worker             fh.into(),
1620*bb4ee6a4SAndroid Build Coastguard Worker             foffset,
1621*bb4ee6a4SAndroid Build Coastguard Worker             moffset,
1622*bb4ee6a4SAndroid Build Coastguard Worker             size,
1623*bb4ee6a4SAndroid Build Coastguard Worker             prot,
1624*bb4ee6a4SAndroid Build Coastguard Worker             mapper,
1625*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1626*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
1627*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
1628*bb4ee6a4SAndroid Build Coastguard Worker                 error!("set_up_mapping failed: {}", e);
1629*bb4ee6a4SAndroid Build Coastguard Worker                 reply_error(e, in_header.unique, w)
1630*bb4ee6a4SAndroid Build Coastguard Worker             }
1631*bb4ee6a4SAndroid Build Coastguard Worker         }
1632*bb4ee6a4SAndroid Build Coastguard Worker     }
1633*bb4ee6a4SAndroid Build Coastguard Worker 
remove_mapping<R, W, M>( &self, in_header: InHeader, mut r: R, w: W, mapper: M, ) -> Result<usize> where R: Reader, W: Writer, M: Mapper,1634*bb4ee6a4SAndroid Build Coastguard Worker     fn remove_mapping<R, W, M>(
1635*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1636*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1637*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1638*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1639*bb4ee6a4SAndroid Build Coastguard Worker         mapper: M,
1640*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize>
1641*bb4ee6a4SAndroid Build Coastguard Worker     where
1642*bb4ee6a4SAndroid Build Coastguard Worker         R: Reader,
1643*bb4ee6a4SAndroid Build Coastguard Worker         W: Writer,
1644*bb4ee6a4SAndroid Build Coastguard Worker         M: Mapper,
1645*bb4ee6a4SAndroid Build Coastguard Worker     {
1646*bb4ee6a4SAndroid Build Coastguard Worker         let RemoveMappingIn { count } = r.read_struct()?;
1647*bb4ee6a4SAndroid Build Coastguard Worker 
1648*bb4ee6a4SAndroid Build Coastguard Worker         // `FUSE_REMOVEMAPPING_MAX_ENTRY` is defined as
1649*bb4ee6a4SAndroid Build Coastguard Worker         // `PAGE_SIZE / sizeof(struct fuse_removemapping_one)` in /kernel/include/uapi/linux/fuse.h.
1650*bb4ee6a4SAndroid Build Coastguard Worker         let max_entry = pagesize() / std::mem::size_of::<RemoveMappingOne>();
1651*bb4ee6a4SAndroid Build Coastguard Worker 
1652*bb4ee6a4SAndroid Build Coastguard Worker         if max_entry < count as usize {
1653*bb4ee6a4SAndroid Build Coastguard Worker             return reply_error(
1654*bb4ee6a4SAndroid Build Coastguard Worker                 io::Error::from_raw_os_error(libc::EINVAL),
1655*bb4ee6a4SAndroid Build Coastguard Worker                 in_header.unique,
1656*bb4ee6a4SAndroid Build Coastguard Worker                 w,
1657*bb4ee6a4SAndroid Build Coastguard Worker             );
1658*bb4ee6a4SAndroid Build Coastguard Worker         }
1659*bb4ee6a4SAndroid Build Coastguard Worker 
1660*bb4ee6a4SAndroid Build Coastguard Worker         let mut msgs = Vec::with_capacity(count as usize);
1661*bb4ee6a4SAndroid Build Coastguard Worker         for _ in 0..(count as usize) {
1662*bb4ee6a4SAndroid Build Coastguard Worker             let msg: RemoveMappingOne = r.read_struct()?;
1663*bb4ee6a4SAndroid Build Coastguard Worker             msgs.push(msg);
1664*bb4ee6a4SAndroid Build Coastguard Worker         }
1665*bb4ee6a4SAndroid Build Coastguard Worker 
1666*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.remove_mapping(&msgs, mapper) {
1667*bb4ee6a4SAndroid Build Coastguard Worker             Ok(()) => reply_ok(None::<u8>, None, in_header.unique, w),
1668*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1669*bb4ee6a4SAndroid Build Coastguard Worker         }
1670*bb4ee6a4SAndroid Build Coastguard Worker     }
1671*bb4ee6a4SAndroid Build Coastguard Worker 
open_atomic<R: Reader, W: Writer>( &self, in_header: InHeader, mut r: R, w: W, ) -> Result<usize>1672*bb4ee6a4SAndroid Build Coastguard Worker     fn open_atomic<R: Reader, W: Writer>(
1673*bb4ee6a4SAndroid Build Coastguard Worker         &self,
1674*bb4ee6a4SAndroid Build Coastguard Worker         in_header: InHeader,
1675*bb4ee6a4SAndroid Build Coastguard Worker         mut r: R,
1676*bb4ee6a4SAndroid Build Coastguard Worker         w: W,
1677*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<usize> {
1678*bb4ee6a4SAndroid Build Coastguard Worker         let CreateIn {
1679*bb4ee6a4SAndroid Build Coastguard Worker             flags, mode, umask, ..
1680*bb4ee6a4SAndroid Build Coastguard Worker         } = r.read_struct()?;
1681*bb4ee6a4SAndroid Build Coastguard Worker 
1682*bb4ee6a4SAndroid Build Coastguard Worker         let buflen = (in_header.len as usize)
1683*bb4ee6a4SAndroid Build Coastguard Worker             .checked_sub(size_of::<InHeader>())
1684*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(|l| l.checked_sub(size_of::<CreateIn>()))
1685*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::InvalidHeaderLength)?;
1686*bb4ee6a4SAndroid Build Coastguard Worker 
1687*bb4ee6a4SAndroid Build Coastguard Worker         let mut buf = vec![0; buflen];
1688*bb4ee6a4SAndroid Build Coastguard Worker 
1689*bb4ee6a4SAndroid Build Coastguard Worker         r.read_exact(&mut buf).map_err(Error::DecodeMessage)?;
1690*bb4ee6a4SAndroid Build Coastguard Worker 
1691*bb4ee6a4SAndroid Build Coastguard Worker         let mut iter = buf.split_inclusive(|&c| c == b'\0');
1692*bb4ee6a4SAndroid Build Coastguard Worker         let name = iter
1693*bb4ee6a4SAndroid Build Coastguard Worker             .next()
1694*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or(Error::MissingParameter)
1695*bb4ee6a4SAndroid Build Coastguard Worker             .and_then(bytes_to_cstr)?;
1696*bb4ee6a4SAndroid Build Coastguard Worker 
1697*bb4ee6a4SAndroid Build Coastguard Worker         let split_pos = name.to_bytes_with_nul().len();
1698*bb4ee6a4SAndroid Build Coastguard Worker         let security_ctx = parse_selinux_xattr(&buf[split_pos..])?;
1699*bb4ee6a4SAndroid Build Coastguard Worker 
1700*bb4ee6a4SAndroid Build Coastguard Worker         match self.fs.atomic_open(
1701*bb4ee6a4SAndroid Build Coastguard Worker             Context::from(in_header),
1702*bb4ee6a4SAndroid Build Coastguard Worker             in_header.nodeid.into(),
1703*bb4ee6a4SAndroid Build Coastguard Worker             name,
1704*bb4ee6a4SAndroid Build Coastguard Worker             mode,
1705*bb4ee6a4SAndroid Build Coastguard Worker             flags,
1706*bb4ee6a4SAndroid Build Coastguard Worker             umask,
1707*bb4ee6a4SAndroid Build Coastguard Worker             security_ctx,
1708*bb4ee6a4SAndroid Build Coastguard Worker         ) {
1709*bb4ee6a4SAndroid Build Coastguard Worker             Ok((entry, handle, opts)) => {
1710*bb4ee6a4SAndroid Build Coastguard Worker                 let entry_out = EntryOut {
1711*bb4ee6a4SAndroid Build Coastguard Worker                     nodeid: entry.inode,
1712*bb4ee6a4SAndroid Build Coastguard Worker                     generation: entry.generation,
1713*bb4ee6a4SAndroid Build Coastguard Worker                     entry_valid: entry.entry_timeout.as_secs(),
1714*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid: entry.attr_timeout.as_secs(),
1715*bb4ee6a4SAndroid Build Coastguard Worker                     entry_valid_nsec: entry.entry_timeout.subsec_nanos(),
1716*bb4ee6a4SAndroid Build Coastguard Worker                     attr_valid_nsec: entry.attr_timeout.subsec_nanos(),
1717*bb4ee6a4SAndroid Build Coastguard Worker                     attr: entry.attr.into(),
1718*bb4ee6a4SAndroid Build Coastguard Worker                 };
1719*bb4ee6a4SAndroid Build Coastguard Worker                 let open_out = OpenOut {
1720*bb4ee6a4SAndroid Build Coastguard Worker                     fh: handle.map(Into::into).unwrap_or(0),
1721*bb4ee6a4SAndroid Build Coastguard Worker                     open_flags: opts.bits(),
1722*bb4ee6a4SAndroid Build Coastguard Worker                     ..Default::default()
1723*bb4ee6a4SAndroid Build Coastguard Worker                 };
1724*bb4ee6a4SAndroid Build Coastguard Worker 
1725*bb4ee6a4SAndroid Build Coastguard Worker                 // open_out passed the `data` argument, but the two out structs are independent
1726*bb4ee6a4SAndroid Build Coastguard Worker                 // This is a hack to return two out stucts in one fuse reply
1727*bb4ee6a4SAndroid Build Coastguard Worker                 reply_ok(
1728*bb4ee6a4SAndroid Build Coastguard Worker                     Some(entry_out),
1729*bb4ee6a4SAndroid Build Coastguard Worker                     Some(open_out.as_bytes()),
1730*bb4ee6a4SAndroid Build Coastguard Worker                     in_header.unique,
1731*bb4ee6a4SAndroid Build Coastguard Worker                     w,
1732*bb4ee6a4SAndroid Build Coastguard Worker                 )
1733*bb4ee6a4SAndroid Build Coastguard Worker             }
1734*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => reply_error(e, in_header.unique, w),
1735*bb4ee6a4SAndroid Build Coastguard Worker         }
1736*bb4ee6a4SAndroid Build Coastguard Worker     }
1737*bb4ee6a4SAndroid Build Coastguard Worker }
1738*bb4ee6a4SAndroid Build Coastguard Worker 
retry_ioctl<W: Writer>( unique: u64, input: Vec<IoctlIovec>, output: Vec<IoctlIovec>, mut w: W, ) -> Result<usize>1739*bb4ee6a4SAndroid Build Coastguard Worker fn retry_ioctl<W: Writer>(
1740*bb4ee6a4SAndroid Build Coastguard Worker     unique: u64,
1741*bb4ee6a4SAndroid Build Coastguard Worker     input: Vec<IoctlIovec>,
1742*bb4ee6a4SAndroid Build Coastguard Worker     output: Vec<IoctlIovec>,
1743*bb4ee6a4SAndroid Build Coastguard Worker     mut w: W,
1744*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<usize> {
1745*bb4ee6a4SAndroid Build Coastguard Worker     // We don't need to check for overflow here because if adding these 2 values caused an overflow
1746*bb4ee6a4SAndroid Build Coastguard Worker     // we would have run out of memory before reaching this point.
1747*bb4ee6a4SAndroid Build Coastguard Worker     if input.len() + output.len() > IOCTL_MAX_IOV {
1748*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::TooManyIovecs(
1749*bb4ee6a4SAndroid Build Coastguard Worker             input.len() + output.len(),
1750*bb4ee6a4SAndroid Build Coastguard Worker             IOCTL_MAX_IOV,
1751*bb4ee6a4SAndroid Build Coastguard Worker         ));
1752*bb4ee6a4SAndroid Build Coastguard Worker     }
1753*bb4ee6a4SAndroid Build Coastguard Worker 
1754*bb4ee6a4SAndroid Build Coastguard Worker     let len = size_of::<OutHeader>()
1755*bb4ee6a4SAndroid Build Coastguard Worker         + size_of::<IoctlOut>()
1756*bb4ee6a4SAndroid Build Coastguard Worker         + (input.len() * size_of::<IoctlIovec>())
1757*bb4ee6a4SAndroid Build Coastguard Worker         + (output.len() * size_of::<IoctlIovec>());
1758*bb4ee6a4SAndroid Build Coastguard Worker     let header = OutHeader {
1759*bb4ee6a4SAndroid Build Coastguard Worker         len: len as u32,
1760*bb4ee6a4SAndroid Build Coastguard Worker         error: 0,
1761*bb4ee6a4SAndroid Build Coastguard Worker         unique,
1762*bb4ee6a4SAndroid Build Coastguard Worker     };
1763*bb4ee6a4SAndroid Build Coastguard Worker     let out = IoctlOut {
1764*bb4ee6a4SAndroid Build Coastguard Worker         result: 0,
1765*bb4ee6a4SAndroid Build Coastguard Worker         flags: IoctlFlags::RETRY.bits(),
1766*bb4ee6a4SAndroid Build Coastguard Worker         in_iovs: input.len() as u32,
1767*bb4ee6a4SAndroid Build Coastguard Worker         out_iovs: output.len() as u32,
1768*bb4ee6a4SAndroid Build Coastguard Worker     };
1769*bb4ee6a4SAndroid Build Coastguard Worker 
1770*bb4ee6a4SAndroid Build Coastguard Worker     let mut total_bytes = size_of::<OutHeader>() + size_of::<IoctlOut>();
1771*bb4ee6a4SAndroid Build Coastguard Worker     w.write_all(header.as_bytes())
1772*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::EncodeMessage)?;
1773*bb4ee6a4SAndroid Build Coastguard Worker     w.write_all(out.as_bytes()).map_err(Error::EncodeMessage)?;
1774*bb4ee6a4SAndroid Build Coastguard Worker     for i in input.into_iter().chain(output.into_iter()) {
1775*bb4ee6a4SAndroid Build Coastguard Worker         total_bytes += i.as_bytes().len();
1776*bb4ee6a4SAndroid Build Coastguard Worker         w.write_all(i.as_bytes()).map_err(Error::EncodeMessage)?;
1777*bb4ee6a4SAndroid Build Coastguard Worker     }
1778*bb4ee6a4SAndroid Build Coastguard Worker 
1779*bb4ee6a4SAndroid Build Coastguard Worker     w.flush().map_err(Error::FlushMessage)?;
1780*bb4ee6a4SAndroid Build Coastguard Worker     debug_assert_eq!(len, total_bytes);
1781*bb4ee6a4SAndroid Build Coastguard Worker     Ok(len)
1782*bb4ee6a4SAndroid Build Coastguard Worker }
1783*bb4ee6a4SAndroid Build Coastguard Worker 
finish_ioctl<W: Writer>(unique: u64, res: io::Result<Vec<u8>>, w: W) -> Result<usize>1784*bb4ee6a4SAndroid Build Coastguard Worker fn finish_ioctl<W: Writer>(unique: u64, res: io::Result<Vec<u8>>, w: W) -> Result<usize> {
1785*bb4ee6a4SAndroid Build Coastguard Worker     let (out, data) = match res {
1786*bb4ee6a4SAndroid Build Coastguard Worker         Ok(data) => {
1787*bb4ee6a4SAndroid Build Coastguard Worker             let out = IoctlOut {
1788*bb4ee6a4SAndroid Build Coastguard Worker                 result: 0,
1789*bb4ee6a4SAndroid Build Coastguard Worker                 ..Default::default()
1790*bb4ee6a4SAndroid Build Coastguard Worker             };
1791*bb4ee6a4SAndroid Build Coastguard Worker             (out, Some(data))
1792*bb4ee6a4SAndroid Build Coastguard Worker         }
1793*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
1794*bb4ee6a4SAndroid Build Coastguard Worker             let out = IoctlOut {
1795*bb4ee6a4SAndroid Build Coastguard Worker                 result: -e.raw_os_error().unwrap_or(libc::EIO),
1796*bb4ee6a4SAndroid Build Coastguard Worker                 ..Default::default()
1797*bb4ee6a4SAndroid Build Coastguard Worker             };
1798*bb4ee6a4SAndroid Build Coastguard Worker             (out, None)
1799*bb4ee6a4SAndroid Build Coastguard Worker         }
1800*bb4ee6a4SAndroid Build Coastguard Worker     };
1801*bb4ee6a4SAndroid Build Coastguard Worker     reply_ok(Some(out), data.as_ref().map(|d| &d[..]), unique, w)
1802*bb4ee6a4SAndroid Build Coastguard Worker }
1803*bb4ee6a4SAndroid Build Coastguard Worker 
reply_readdir<W: Writer>(len: usize, unique: u64, mut w: W) -> Result<usize>1804*bb4ee6a4SAndroid Build Coastguard Worker fn reply_readdir<W: Writer>(len: usize, unique: u64, mut w: W) -> Result<usize> {
1805*bb4ee6a4SAndroid Build Coastguard Worker     let out = OutHeader {
1806*bb4ee6a4SAndroid Build Coastguard Worker         len: (size_of::<OutHeader>() + len) as u32,
1807*bb4ee6a4SAndroid Build Coastguard Worker         error: 0,
1808*bb4ee6a4SAndroid Build Coastguard Worker         unique,
1809*bb4ee6a4SAndroid Build Coastguard Worker     };
1810*bb4ee6a4SAndroid Build Coastguard Worker 
1811*bb4ee6a4SAndroid Build Coastguard Worker     w.write_all(out.as_bytes()).map_err(Error::EncodeMessage)?;
1812*bb4ee6a4SAndroid Build Coastguard Worker     w.flush().map_err(Error::FlushMessage)?;
1813*bb4ee6a4SAndroid Build Coastguard Worker     Ok(out.len as usize)
1814*bb4ee6a4SAndroid Build Coastguard Worker }
1815*bb4ee6a4SAndroid Build Coastguard Worker 
reply_ok<T: AsBytes, W: Writer>( out: Option<T>, data: Option<&[u8]>, unique: u64, mut w: W, ) -> Result<usize>1816*bb4ee6a4SAndroid Build Coastguard Worker fn reply_ok<T: AsBytes, W: Writer>(
1817*bb4ee6a4SAndroid Build Coastguard Worker     out: Option<T>,
1818*bb4ee6a4SAndroid Build Coastguard Worker     data: Option<&[u8]>,
1819*bb4ee6a4SAndroid Build Coastguard Worker     unique: u64,
1820*bb4ee6a4SAndroid Build Coastguard Worker     mut w: W,
1821*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<usize> {
1822*bb4ee6a4SAndroid Build Coastguard Worker     let mut len = size_of::<OutHeader>();
1823*bb4ee6a4SAndroid Build Coastguard Worker 
1824*bb4ee6a4SAndroid Build Coastguard Worker     if out.is_some() {
1825*bb4ee6a4SAndroid Build Coastguard Worker         len += size_of::<T>();
1826*bb4ee6a4SAndroid Build Coastguard Worker     }
1827*bb4ee6a4SAndroid Build Coastguard Worker 
1828*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(data) = data {
1829*bb4ee6a4SAndroid Build Coastguard Worker         len += data.len();
1830*bb4ee6a4SAndroid Build Coastguard Worker     }
1831*bb4ee6a4SAndroid Build Coastguard Worker 
1832*bb4ee6a4SAndroid Build Coastguard Worker     let header = OutHeader {
1833*bb4ee6a4SAndroid Build Coastguard Worker         len: len as u32,
1834*bb4ee6a4SAndroid Build Coastguard Worker         error: 0,
1835*bb4ee6a4SAndroid Build Coastguard Worker         unique,
1836*bb4ee6a4SAndroid Build Coastguard Worker     };
1837*bb4ee6a4SAndroid Build Coastguard Worker 
1838*bb4ee6a4SAndroid Build Coastguard Worker     let mut total_bytes = size_of::<OutHeader>();
1839*bb4ee6a4SAndroid Build Coastguard Worker     w.write_all(header.as_bytes())
1840*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::EncodeMessage)?;
1841*bb4ee6a4SAndroid Build Coastguard Worker 
1842*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(out) = out {
1843*bb4ee6a4SAndroid Build Coastguard Worker         total_bytes += out.as_bytes().len();
1844*bb4ee6a4SAndroid Build Coastguard Worker         w.write_all(out.as_bytes()).map_err(Error::EncodeMessage)?;
1845*bb4ee6a4SAndroid Build Coastguard Worker     }
1846*bb4ee6a4SAndroid Build Coastguard Worker 
1847*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(data) = data {
1848*bb4ee6a4SAndroid Build Coastguard Worker         total_bytes += data.len();
1849*bb4ee6a4SAndroid Build Coastguard Worker         w.write_all(data).map_err(Error::EncodeMessage)?;
1850*bb4ee6a4SAndroid Build Coastguard Worker     }
1851*bb4ee6a4SAndroid Build Coastguard Worker 
1852*bb4ee6a4SAndroid Build Coastguard Worker     w.flush().map_err(Error::FlushMessage)?;
1853*bb4ee6a4SAndroid Build Coastguard Worker     debug_assert_eq!(len, total_bytes);
1854*bb4ee6a4SAndroid Build Coastguard Worker     Ok(len)
1855*bb4ee6a4SAndroid Build Coastguard Worker }
1856*bb4ee6a4SAndroid Build Coastguard Worker 
reply_error<W: Writer>(e: io::Error, unique: u64, mut w: W) -> Result<usize>1857*bb4ee6a4SAndroid Build Coastguard Worker fn reply_error<W: Writer>(e: io::Error, unique: u64, mut w: W) -> Result<usize> {
1858*bb4ee6a4SAndroid Build Coastguard Worker     let header = OutHeader {
1859*bb4ee6a4SAndroid Build Coastguard Worker         len: size_of::<OutHeader>() as u32,
1860*bb4ee6a4SAndroid Build Coastguard Worker         error: -e.raw_os_error().unwrap_or(libc::EIO),
1861*bb4ee6a4SAndroid Build Coastguard Worker         unique,
1862*bb4ee6a4SAndroid Build Coastguard Worker     };
1863*bb4ee6a4SAndroid Build Coastguard Worker 
1864*bb4ee6a4SAndroid Build Coastguard Worker     w.write_all(header.as_bytes())
1865*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(Error::EncodeMessage)?;
1866*bb4ee6a4SAndroid Build Coastguard Worker     w.flush().map_err(Error::FlushMessage)?;
1867*bb4ee6a4SAndroid Build Coastguard Worker 
1868*bb4ee6a4SAndroid Build Coastguard Worker     Ok(header.len as usize)
1869*bb4ee6a4SAndroid Build Coastguard Worker }
1870*bb4ee6a4SAndroid Build Coastguard Worker 
bytes_to_cstr(buf: &[u8]) -> Result<&CStr>1871*bb4ee6a4SAndroid Build Coastguard Worker fn bytes_to_cstr(buf: &[u8]) -> Result<&CStr> {
1872*bb4ee6a4SAndroid Build Coastguard Worker     // Convert to a `CStr` first so that we can drop the '\0' byte at the end
1873*bb4ee6a4SAndroid Build Coastguard Worker     // and make sure there are no interior '\0' bytes.
1874*bb4ee6a4SAndroid Build Coastguard Worker     CStr::from_bytes_with_nul(buf).map_err(Error::InvalidCString)
1875*bb4ee6a4SAndroid Build Coastguard Worker }
1876*bb4ee6a4SAndroid Build Coastguard Worker 
add_dirent<W: Writer>( cursor: &mut W, max: usize, d: &DirEntry, entry: Option<Entry>, ) -> io::Result<usize>1877*bb4ee6a4SAndroid Build Coastguard Worker fn add_dirent<W: Writer>(
1878*bb4ee6a4SAndroid Build Coastguard Worker     cursor: &mut W,
1879*bb4ee6a4SAndroid Build Coastguard Worker     max: usize,
1880*bb4ee6a4SAndroid Build Coastguard Worker     d: &DirEntry,
1881*bb4ee6a4SAndroid Build Coastguard Worker     entry: Option<Entry>,
1882*bb4ee6a4SAndroid Build Coastguard Worker ) -> io::Result<usize> {
1883*bb4ee6a4SAndroid Build Coastguard Worker     // Strip the trailing '\0'.
1884*bb4ee6a4SAndroid Build Coastguard Worker     let name = d.name.to_bytes();
1885*bb4ee6a4SAndroid Build Coastguard Worker     if name.len() > u32::MAX as usize {
1886*bb4ee6a4SAndroid Build Coastguard Worker         return Err(io::Error::from_raw_os_error(libc::EOVERFLOW));
1887*bb4ee6a4SAndroid Build Coastguard Worker     }
1888*bb4ee6a4SAndroid Build Coastguard Worker 
1889*bb4ee6a4SAndroid Build Coastguard Worker     let dirent_len = size_of::<Dirent>()
1890*bb4ee6a4SAndroid Build Coastguard Worker         .checked_add(name.len())
1891*bb4ee6a4SAndroid Build Coastguard Worker         .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
1892*bb4ee6a4SAndroid Build Coastguard Worker 
1893*bb4ee6a4SAndroid Build Coastguard Worker     // Directory entries must be padded to 8-byte alignment.  If adding 7 causes
1894*bb4ee6a4SAndroid Build Coastguard Worker     // an overflow then this dirent cannot be properly padded.
1895*bb4ee6a4SAndroid Build Coastguard Worker     let padded_dirent_len = dirent_len
1896*bb4ee6a4SAndroid Build Coastguard Worker         .checked_add(7)
1897*bb4ee6a4SAndroid Build Coastguard Worker         .map(|l| l & !7)
1898*bb4ee6a4SAndroid Build Coastguard Worker         .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
1899*bb4ee6a4SAndroid Build Coastguard Worker 
1900*bb4ee6a4SAndroid Build Coastguard Worker     let total_len = if entry.is_some() {
1901*bb4ee6a4SAndroid Build Coastguard Worker         padded_dirent_len
1902*bb4ee6a4SAndroid Build Coastguard Worker             .checked_add(size_of::<EntryOut>())
1903*bb4ee6a4SAndroid Build Coastguard Worker             .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?
1904*bb4ee6a4SAndroid Build Coastguard Worker     } else {
1905*bb4ee6a4SAndroid Build Coastguard Worker         padded_dirent_len
1906*bb4ee6a4SAndroid Build Coastguard Worker     };
1907*bb4ee6a4SAndroid Build Coastguard Worker 
1908*bb4ee6a4SAndroid Build Coastguard Worker     if max < total_len {
1909*bb4ee6a4SAndroid Build Coastguard Worker         Ok(0)
1910*bb4ee6a4SAndroid Build Coastguard Worker     } else {
1911*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(entry) = entry {
1912*bb4ee6a4SAndroid Build Coastguard Worker             cursor.write_all(EntryOut::from(entry).as_bytes())?;
1913*bb4ee6a4SAndroid Build Coastguard Worker         }
1914*bb4ee6a4SAndroid Build Coastguard Worker 
1915*bb4ee6a4SAndroid Build Coastguard Worker         let dirent = Dirent {
1916*bb4ee6a4SAndroid Build Coastguard Worker             ino: d.ino,
1917*bb4ee6a4SAndroid Build Coastguard Worker             off: d.offset,
1918*bb4ee6a4SAndroid Build Coastguard Worker             namelen: name.len() as u32,
1919*bb4ee6a4SAndroid Build Coastguard Worker             type_: d.type_,
1920*bb4ee6a4SAndroid Build Coastguard Worker         };
1921*bb4ee6a4SAndroid Build Coastguard Worker 
1922*bb4ee6a4SAndroid Build Coastguard Worker         cursor.write_all(dirent.as_bytes())?;
1923*bb4ee6a4SAndroid Build Coastguard Worker         cursor.write_all(name)?;
1924*bb4ee6a4SAndroid Build Coastguard Worker 
1925*bb4ee6a4SAndroid Build Coastguard Worker         // We know that `dirent_len` <= `padded_dirent_len` due to the check above
1926*bb4ee6a4SAndroid Build Coastguard Worker         // so there's no need for checked arithmetic.
1927*bb4ee6a4SAndroid Build Coastguard Worker         let padding = padded_dirent_len - dirent_len;
1928*bb4ee6a4SAndroid Build Coastguard Worker         if padding > 0 {
1929*bb4ee6a4SAndroid Build Coastguard Worker             cursor.write_all(&DIRENT_PADDING[..padding])?;
1930*bb4ee6a4SAndroid Build Coastguard Worker         }
1931*bb4ee6a4SAndroid Build Coastguard Worker 
1932*bb4ee6a4SAndroid Build Coastguard Worker         Ok(total_len)
1933*bb4ee6a4SAndroid Build Coastguard Worker     }
1934*bb4ee6a4SAndroid Build Coastguard Worker }
1935*bb4ee6a4SAndroid Build Coastguard Worker 
1936*bb4ee6a4SAndroid Build Coastguard Worker /// Parses the value of the desired attribute from the FUSE request input and returns it as an
1937*bb4ee6a4SAndroid Build Coastguard Worker /// `Ok(CStr)`. Returns `Ok(None)` if `buf` is empty or appears to be a valid request extension that
1938*bb4ee6a4SAndroid Build Coastguard Worker /// does not contain any security context information.
1939*bb4ee6a4SAndroid Build Coastguard Worker ///
1940*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
1941*bb4ee6a4SAndroid Build Coastguard Worker ///
1942*bb4ee6a4SAndroid Build Coastguard Worker /// * `buf` - a byte array that contains the contents following any expected byte string parameters
1943*bb4ee6a4SAndroid Build Coastguard Worker ///   of the FUSE request from the server. It begins with a struct `SecctxHeader`, and then the
1944*bb4ee6a4SAndroid Build Coastguard Worker ///   subsequent entry is a struct `Secctx` followed by a nul-terminated string with the xattribute
1945*bb4ee6a4SAndroid Build Coastguard Worker ///   name and then another nul-terminated string with the value for that xattr.
1946*bb4ee6a4SAndroid Build Coastguard Worker ///
1947*bb4ee6a4SAndroid Build Coastguard Worker /// # Errors
1948*bb4ee6a4SAndroid Build Coastguard Worker ///
1949*bb4ee6a4SAndroid Build Coastguard Worker /// * `Error::InvalidHeaderLength` - indicates that there is an inconsistency between the size of
1950*bb4ee6a4SAndroid Build Coastguard Worker ///   the data read from `buf` and the stated `size` of the `SecctxHeader`, the respective `Secctx`
1951*bb4ee6a4SAndroid Build Coastguard Worker ///   struct, or `buf` itself.
1952*bb4ee6a4SAndroid Build Coastguard Worker /// * `Error::DecodeMessage` - indicates that the expected structs cannot be read from `buf`.
1953*bb4ee6a4SAndroid Build Coastguard Worker /// * `Error::MissingParameter` - indicates that either a security context `name` or `value` is
1954*bb4ee6a4SAndroid Build Coastguard Worker ///   missing from a security context entry.
parse_selinux_xattr(buf: &[u8]) -> Result<Option<&CStr>>1955*bb4ee6a4SAndroid Build Coastguard Worker fn parse_selinux_xattr(buf: &[u8]) -> Result<Option<&CStr>> {
1956*bb4ee6a4SAndroid Build Coastguard Worker     // Return early if request was not followed by context information
1957*bb4ee6a4SAndroid Build Coastguard Worker     if buf.is_empty() {
1958*bb4ee6a4SAndroid Build Coastguard Worker         return Ok(None);
1959*bb4ee6a4SAndroid Build Coastguard Worker     } else if buf.len() < size_of::<SecctxHeader>() {
1960*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::InvalidHeaderLength);
1961*bb4ee6a4SAndroid Build Coastguard Worker     }
1962*bb4ee6a4SAndroid Build Coastguard Worker 
1963*bb4ee6a4SAndroid Build Coastguard Worker     // Because the security context data block may have been preceded by variable-length strings,
1964*bb4ee6a4SAndroid Build Coastguard Worker     // `SecctxHeader` and the subsequent `Secctx` structs may not be correctly byte-aligned
1965*bb4ee6a4SAndroid Build Coastguard Worker     // within `buf`.
1966*bb4ee6a4SAndroid Build Coastguard Worker     let secctx_header = SecctxHeader::read_from_prefix(buf).ok_or(Error::DecodeMessage(
1967*bb4ee6a4SAndroid Build Coastguard Worker         io::Error::from_raw_os_error(libc::EINVAL),
1968*bb4ee6a4SAndroid Build Coastguard Worker     ))?;
1969*bb4ee6a4SAndroid Build Coastguard Worker 
1970*bb4ee6a4SAndroid Build Coastguard Worker     // FUSE 7.38 introduced a generic request extension with the same structure as  `SecctxHeader`.
1971*bb4ee6a4SAndroid Build Coastguard Worker     // A `nr_secctx` value above `MAX_NR_SECCTX` indicates that this data block does not contain
1972*bb4ee6a4SAndroid Build Coastguard Worker     // any security context information.
1973*bb4ee6a4SAndroid Build Coastguard Worker     if secctx_header.nr_secctx > MAX_NR_SECCTX {
1974*bb4ee6a4SAndroid Build Coastguard Worker         return Ok(None);
1975*bb4ee6a4SAndroid Build Coastguard Worker     }
1976*bb4ee6a4SAndroid Build Coastguard Worker 
1977*bb4ee6a4SAndroid Build Coastguard Worker     let mut cur_secctx_pos = size_of::<SecctxHeader>();
1978*bb4ee6a4SAndroid Build Coastguard Worker     for _ in 0..secctx_header.nr_secctx {
1979*bb4ee6a4SAndroid Build Coastguard Worker         // `SecctxHeader.size` denotes the total size for the `SecctxHeader`, each of the
1980*bb4ee6a4SAndroid Build Coastguard Worker         // `nr_secctx` `Secctx` structs along with the corresponding context name and value,
1981*bb4ee6a4SAndroid Build Coastguard Worker         // and any additional padding.
1982*bb4ee6a4SAndroid Build Coastguard Worker         if (cur_secctx_pos + size_of::<Secctx>()) > buf.len()
1983*bb4ee6a4SAndroid Build Coastguard Worker             || (cur_secctx_pos + size_of::<Secctx>()) > secctx_header.size as usize
1984*bb4ee6a4SAndroid Build Coastguard Worker         {
1985*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::InvalidHeaderLength);
1986*bb4ee6a4SAndroid Build Coastguard Worker         }
1987*bb4ee6a4SAndroid Build Coastguard Worker 
1988*bb4ee6a4SAndroid Build Coastguard Worker         let secctx =
1989*bb4ee6a4SAndroid Build Coastguard Worker             Secctx::read_from(&buf[cur_secctx_pos..(cur_secctx_pos + size_of::<Secctx>())]).ok_or(
1990*bb4ee6a4SAndroid Build Coastguard Worker                 Error::DecodeMessage(io::Error::from_raw_os_error(libc::EINVAL)),
1991*bb4ee6a4SAndroid Build Coastguard Worker             )?;
1992*bb4ee6a4SAndroid Build Coastguard Worker 
1993*bb4ee6a4SAndroid Build Coastguard Worker         cur_secctx_pos += size_of::<Secctx>();
1994*bb4ee6a4SAndroid Build Coastguard Worker 
1995*bb4ee6a4SAndroid Build Coastguard Worker         let secctx_data = &buf[cur_secctx_pos..]
1996*bb4ee6a4SAndroid Build Coastguard Worker             .split_inclusive(|&c| c == b'\0')
1997*bb4ee6a4SAndroid Build Coastguard Worker             .take(2)
1998*bb4ee6a4SAndroid Build Coastguard Worker             .map(bytes_to_cstr)
1999*bb4ee6a4SAndroid Build Coastguard Worker             .collect::<Result<Vec<&CStr>>>()?;
2000*bb4ee6a4SAndroid Build Coastguard Worker 
2001*bb4ee6a4SAndroid Build Coastguard Worker         if secctx_data.len() != 2 {
2002*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::MissingParameter);
2003*bb4ee6a4SAndroid Build Coastguard Worker         }
2004*bb4ee6a4SAndroid Build Coastguard Worker 
2005*bb4ee6a4SAndroid Build Coastguard Worker         let name = secctx_data[0];
2006*bb4ee6a4SAndroid Build Coastguard Worker         let value = secctx_data[1];
2007*bb4ee6a4SAndroid Build Coastguard Worker 
2008*bb4ee6a4SAndroid Build Coastguard Worker         cur_secctx_pos += name.to_bytes_with_nul().len() + value.to_bytes_with_nul().len();
2009*bb4ee6a4SAndroid Build Coastguard Worker         if cur_secctx_pos > secctx_header.size as usize {
2010*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::InvalidHeaderLength);
2011*bb4ee6a4SAndroid Build Coastguard Worker         }
2012*bb4ee6a4SAndroid Build Coastguard Worker 
2013*bb4ee6a4SAndroid Build Coastguard Worker         // `Secctx.size` contains the size of the security context value (not including the
2014*bb4ee6a4SAndroid Build Coastguard Worker         // corresponding context name).
2015*bb4ee6a4SAndroid Build Coastguard Worker         if value.to_bytes_with_nul().len() as u32 != secctx.size {
2016*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::InvalidHeaderLength);
2017*bb4ee6a4SAndroid Build Coastguard Worker         }
2018*bb4ee6a4SAndroid Build Coastguard Worker 
2019*bb4ee6a4SAndroid Build Coastguard Worker         if name.to_bytes_with_nul() == SELINUX_XATTR_CSTR {
2020*bb4ee6a4SAndroid Build Coastguard Worker             return Ok(Some(value));
2021*bb4ee6a4SAndroid Build Coastguard Worker         }
2022*bb4ee6a4SAndroid Build Coastguard Worker     }
2023*bb4ee6a4SAndroid Build Coastguard Worker 
2024*bb4ee6a4SAndroid Build Coastguard Worker     // `SecctxHeader.size` is always the total size of the security context data padded to an
2025*bb4ee6a4SAndroid Build Coastguard Worker     // 8-byte alignment. If adding 7 causes an overflow, then the `size` field of our header
2026*bb4ee6a4SAndroid Build Coastguard Worker     // is invalid, so we should return an error.
2027*bb4ee6a4SAndroid Build Coastguard Worker     let padded_secctx_size = cur_secctx_pos
2028*bb4ee6a4SAndroid Build Coastguard Worker         .checked_add(7)
2029*bb4ee6a4SAndroid Build Coastguard Worker         .map(|l| l & !7)
2030*bb4ee6a4SAndroid Build Coastguard Worker         .ok_or_else(|| Error::InvalidHeaderLength)?;
2031*bb4ee6a4SAndroid Build Coastguard Worker     if padded_secctx_size != secctx_header.size as usize {
2032*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::InvalidHeaderLength);
2033*bb4ee6a4SAndroid Build Coastguard Worker     }
2034*bb4ee6a4SAndroid Build Coastguard Worker 
2035*bb4ee6a4SAndroid Build Coastguard Worker     // None of the `nr_secctx` attributes we parsed had a `name` matching `SELINUX_XATTR_CSTR`.
2036*bb4ee6a4SAndroid Build Coastguard Worker     // Return `Ok(None)` to indicate that the security context data block was valid but there was no
2037*bb4ee6a4SAndroid Build Coastguard Worker     // specified selinux label attached to this request.
2038*bb4ee6a4SAndroid Build Coastguard Worker     Ok(None)
2039*bb4ee6a4SAndroid Build Coastguard Worker }
2040*bb4ee6a4SAndroid Build Coastguard Worker 
2041*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
2042*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
2043*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
2044*bb4ee6a4SAndroid Build Coastguard Worker 
create_secctx(ctxs: &[(&[u8], &[u8])], size_truncation: u32) -> Vec<u8>2045*bb4ee6a4SAndroid Build Coastguard Worker     fn create_secctx(ctxs: &[(&[u8], &[u8])], size_truncation: u32) -> Vec<u8> {
2046*bb4ee6a4SAndroid Build Coastguard Worker         let nr_secctx = ctxs.len();
2047*bb4ee6a4SAndroid Build Coastguard Worker         let total_size = (size_of::<SecctxHeader>() as u32
2048*bb4ee6a4SAndroid Build Coastguard Worker             + (size_of::<Secctx>() * nr_secctx) as u32
2049*bb4ee6a4SAndroid Build Coastguard Worker             + ctxs
2050*bb4ee6a4SAndroid Build Coastguard Worker                 .iter()
2051*bb4ee6a4SAndroid Build Coastguard Worker                 .fold(0, |s, &(n, v)| s + n.len() as u32 + v.len() as u32))
2052*bb4ee6a4SAndroid Build Coastguard Worker         .checked_add(7)
2053*bb4ee6a4SAndroid Build Coastguard Worker         .map(|l| l & !7)
2054*bb4ee6a4SAndroid Build Coastguard Worker         .expect("total_size padded to 8-byte boundary")
2055*bb4ee6a4SAndroid Build Coastguard Worker         .checked_sub(size_truncation)
2056*bb4ee6a4SAndroid Build Coastguard Worker         .expect("size truncated by bytes < total_size");
2057*bb4ee6a4SAndroid Build Coastguard Worker 
2058*bb4ee6a4SAndroid Build Coastguard Worker         let ctx_data: Vec<_> = ctxs
2059*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
2060*bb4ee6a4SAndroid Build Coastguard Worker             .map(|(n, v)| {
2061*bb4ee6a4SAndroid Build Coastguard Worker                 [
2062*bb4ee6a4SAndroid Build Coastguard Worker                     Secctx {
2063*bb4ee6a4SAndroid Build Coastguard Worker                         size: v.len() as u32,
2064*bb4ee6a4SAndroid Build Coastguard Worker                         padding: 0,
2065*bb4ee6a4SAndroid Build Coastguard Worker                     }
2066*bb4ee6a4SAndroid Build Coastguard Worker                     .as_bytes(),
2067*bb4ee6a4SAndroid Build Coastguard Worker                     n,
2068*bb4ee6a4SAndroid Build Coastguard Worker                     v,
2069*bb4ee6a4SAndroid Build Coastguard Worker                 ]
2070*bb4ee6a4SAndroid Build Coastguard Worker                 .concat()
2071*bb4ee6a4SAndroid Build Coastguard Worker             })
2072*bb4ee6a4SAndroid Build Coastguard Worker             .collect::<Vec<_>>()
2073*bb4ee6a4SAndroid Build Coastguard Worker             .concat();
2074*bb4ee6a4SAndroid Build Coastguard Worker 
2075*bb4ee6a4SAndroid Build Coastguard Worker         [
2076*bb4ee6a4SAndroid Build Coastguard Worker             SecctxHeader {
2077*bb4ee6a4SAndroid Build Coastguard Worker                 size: total_size,
2078*bb4ee6a4SAndroid Build Coastguard Worker                 nr_secctx: nr_secctx as u32,
2079*bb4ee6a4SAndroid Build Coastguard Worker             }
2080*bb4ee6a4SAndroid Build Coastguard Worker             .as_bytes(),
2081*bb4ee6a4SAndroid Build Coastguard Worker             ctx_data.as_slice(),
2082*bb4ee6a4SAndroid Build Coastguard Worker         ]
2083*bb4ee6a4SAndroid Build Coastguard Worker         .concat()
2084*bb4ee6a4SAndroid Build Coastguard Worker     }
2085*bb4ee6a4SAndroid Build Coastguard Worker 
2086*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_selinux_xattr_empty()2087*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_selinux_xattr_empty() {
2088*bb4ee6a4SAndroid Build Coastguard Worker         let v: Vec<u8> = vec![];
2089*bb4ee6a4SAndroid Build Coastguard Worker         let res = parse_selinux_xattr(&v);
2090*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(res.unwrap(), None);
2091*bb4ee6a4SAndroid Build Coastguard Worker     }
2092*bb4ee6a4SAndroid Build Coastguard Worker 
2093*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_selinux_xattr_basic()2094*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_selinux_xattr_basic() {
2095*bb4ee6a4SAndroid Build Coastguard Worker         let sec_value = CStr::from_bytes_with_nul(b"user_u:object_r:security_type:s0\0").unwrap();
2096*bb4ee6a4SAndroid Build Coastguard Worker         let v = create_secctx(&[(SELINUX_XATTR_CSTR, sec_value.to_bytes_with_nul())], 0);
2097*bb4ee6a4SAndroid Build Coastguard Worker 
2098*bb4ee6a4SAndroid Build Coastguard Worker         let res = parse_selinux_xattr(&v);
2099*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(res.unwrap(), Some(sec_value));
2100*bb4ee6a4SAndroid Build Coastguard Worker     }
2101*bb4ee6a4SAndroid Build Coastguard Worker 
2102*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_selinux_xattr_find_attr()2103*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_selinux_xattr_find_attr() {
2104*bb4ee6a4SAndroid Build Coastguard Worker         let foo_value: &CStr =
2105*bb4ee6a4SAndroid Build Coastguard Worker             CStr::from_bytes_with_nul(b"user_foo:object_foo:foo_type:s0\0").unwrap();
2106*bb4ee6a4SAndroid Build Coastguard Worker         let sec_value: &CStr =
2107*bb4ee6a4SAndroid Build Coastguard Worker             CStr::from_bytes_with_nul(b"user_u:object_r:security_type:s0\0").unwrap();
2108*bb4ee6a4SAndroid Build Coastguard Worker         let v = create_secctx(
2109*bb4ee6a4SAndroid Build Coastguard Worker             &[
2110*bb4ee6a4SAndroid Build Coastguard Worker                 (b"foo\0", foo_value.to_bytes_with_nul()),
2111*bb4ee6a4SAndroid Build Coastguard Worker                 (SELINUX_XATTR_CSTR, sec_value.to_bytes_with_nul()),
2112*bb4ee6a4SAndroid Build Coastguard Worker             ],
2113*bb4ee6a4SAndroid Build Coastguard Worker             0,
2114*bb4ee6a4SAndroid Build Coastguard Worker         );
2115*bb4ee6a4SAndroid Build Coastguard Worker 
2116*bb4ee6a4SAndroid Build Coastguard Worker         let res = parse_selinux_xattr(&v);
2117*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(res.unwrap(), Some(sec_value));
2118*bb4ee6a4SAndroid Build Coastguard Worker     }
2119*bb4ee6a4SAndroid Build Coastguard Worker 
2120*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_selinux_xattr_wrong_attr()2121*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_selinux_xattr_wrong_attr() {
2122*bb4ee6a4SAndroid Build Coastguard Worker         // Test with an xattr name that looks similar to security.selinux, but has extra
2123*bb4ee6a4SAndroid Build Coastguard Worker         // characters to ensure that `parse_selinux_xattr` will not return the associated
2124*bb4ee6a4SAndroid Build Coastguard Worker         // context value to the caller.
2125*bb4ee6a4SAndroid Build Coastguard Worker         let invalid_selinux_value: &CStr =
2126*bb4ee6a4SAndroid Build Coastguard Worker             CStr::from_bytes_with_nul(b"user_invalid:object_invalid:invalid_type:s0\0").unwrap();
2127*bb4ee6a4SAndroid Build Coastguard Worker         let v = create_secctx(
2128*bb4ee6a4SAndroid Build Coastguard Worker             &[(
2129*bb4ee6a4SAndroid Build Coastguard Worker                 b"invalid.security.selinux\0",
2130*bb4ee6a4SAndroid Build Coastguard Worker                 invalid_selinux_value.to_bytes_with_nul(),
2131*bb4ee6a4SAndroid Build Coastguard Worker             )],
2132*bb4ee6a4SAndroid Build Coastguard Worker             0,
2133*bb4ee6a4SAndroid Build Coastguard Worker         );
2134*bb4ee6a4SAndroid Build Coastguard Worker 
2135*bb4ee6a4SAndroid Build Coastguard Worker         let res = parse_selinux_xattr(&v);
2136*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(res.unwrap(), None);
2137*bb4ee6a4SAndroid Build Coastguard Worker     }
2138*bb4ee6a4SAndroid Build Coastguard Worker 
2139*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
parse_selinux_xattr_too_short()2140*bb4ee6a4SAndroid Build Coastguard Worker     fn parse_selinux_xattr_too_short() {
2141*bb4ee6a4SAndroid Build Coastguard Worker         // Test that parse_selinux_xattr will return an `Error::InvalidHeaderLength` when
2142*bb4ee6a4SAndroid Build Coastguard Worker         // the total size in the `SecctxHeader` does not encompass the entirety of the
2143*bb4ee6a4SAndroid Build Coastguard Worker         // associated data.
2144*bb4ee6a4SAndroid Build Coastguard Worker         let foo_value: &CStr =
2145*bb4ee6a4SAndroid Build Coastguard Worker             CStr::from_bytes_with_nul(b"user_foo:object_foo:foo_type:s0\0").unwrap();
2146*bb4ee6a4SAndroid Build Coastguard Worker         let sec_value: &CStr =
2147*bb4ee6a4SAndroid Build Coastguard Worker             CStr::from_bytes_with_nul(b"user_u:object_r:security_type:s0\0").unwrap();
2148*bb4ee6a4SAndroid Build Coastguard Worker         let v = create_secctx(
2149*bb4ee6a4SAndroid Build Coastguard Worker             &[
2150*bb4ee6a4SAndroid Build Coastguard Worker                 (b"foo\0", foo_value.to_bytes_with_nul()),
2151*bb4ee6a4SAndroid Build Coastguard Worker                 (SELINUX_XATTR_CSTR, sec_value.to_bytes_with_nul()),
2152*bb4ee6a4SAndroid Build Coastguard Worker             ],
2153*bb4ee6a4SAndroid Build Coastguard Worker             8,
2154*bb4ee6a4SAndroid Build Coastguard Worker         );
2155*bb4ee6a4SAndroid Build Coastguard Worker 
2156*bb4ee6a4SAndroid Build Coastguard Worker         let res = parse_selinux_xattr(&v);
2157*bb4ee6a4SAndroid Build Coastguard Worker         assert!(matches!(res, Err(Error::InvalidHeaderLength)));
2158*bb4ee6a4SAndroid Build Coastguard Worker     }
2159*bb4ee6a4SAndroid Build Coastguard Worker }
2160