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