1use std::io::{self, IoSlice, Read, Write};
7use std::mem::size_of;
8use std::sync::Arc;
9use std::time::Duration;
10use vm_memory::ByteValued;
11
12use super::{
13 MetricsHook, Server, ServerUtil, ServerVersion, SrvContext, ZcReader, ZcWriter,
14 BUFFER_HEADER_SIZE, DIRENT_PADDING, MAX_BUFFER_SIZE, MAX_REQ_PAGES, MIN_READ_BUFFER,
15};
16use crate::abi::fuse_abi::*;
17#[cfg(feature = "virtiofs")]
18use crate::abi::virtio_fs::{RemovemappingIn, RemovemappingOne, SetupmappingIn};
19use crate::api::filesystem::{
20 DirEntry, Entry, FileSystem, GetxattrReply, IoctlData, ListxattrReply,
21};
22#[cfg(feature = "fusedev")]
23use crate::transport::FuseDevWriter;
24use crate::transport::{pagesize, FsCacheReqHandler, Reader, Writer};
25use crate::{bytes_to_cstr, encode_io_error_kind, BitmapSlice, Error, Result};
26
27impl<F: FileSystem + Sync> Server<F> {
28 #[cfg(feature = "fusedev")]
29 pub fn notify_inval_entry<S: BitmapSlice>(
31 &self,
32 mut w: FuseDevWriter<'_, S>,
33 parent: u64,
34 name: &std::ffi::CStr,
35 ) -> Result<usize> {
36 let mut buffer_writer = w.split_at(0).map_err(Error::FailedToSplitWriter)?;
37 let mut entry = NotifyInvalEntryOut::default();
38 let mut header = OutHeader::default();
39 let name_with_null = name.to_bytes_with_nul();
40 header.unique = 0;
41 header.error = NotifyOpcode::InvalEntry as i32;
42 header.len = std::mem::size_of::<OutHeader>() as u32
43 + std::mem::size_of::<NotifyInvalEntryOut>() as u32
44 + name_with_null.len() as u32;
45 entry.namelen = (name_with_null.len() - 1) as u32;
47 entry.parent = parent;
48
49 buffer_writer
50 .write_obj(header)
51 .map_err(Error::FailedToWrite)?;
52 buffer_writer
53 .write_obj(entry)
54 .map_err(Error::FailedToWrite)?;
55 buffer_writer
56 .write(name_with_null)
57 .map_err(Error::FailedToWrite)?;
58 buffer_writer.commit(None).map_err(Error::InvalidMessage)
59 }
60 #[allow(unused_variables)]
66 pub fn handle_message<S: BitmapSlice>(
67 &self,
68 mut r: Reader<'_, S>,
69 w: Writer<'_, S>,
70 vu_req: Option<&mut dyn FsCacheReqHandler>,
71 hook: Option<&dyn MetricsHook>,
72 ) -> Result<usize> {
73 let in_header: InHeader = r.read_obj().map_err(Error::DecodeMessage)?;
74 let mut ctx = SrvContext::<F, S>::new(in_header, r, w);
75 self.fs
76 .id_remap(&mut ctx.context)
77 .map_err(|e| Error::FailedToRemapID((ctx.context.uid, ctx.context.gid)))?;
78 if ctx.in_header.len > (MAX_BUFFER_SIZE + BUFFER_HEADER_SIZE) {
79 if in_header.opcode == Opcode::Forget as u32
80 || in_header.opcode == Opcode::BatchForget as u32
81 {
82 return Err(Error::InvalidMessage(io::Error::from_raw_os_error(
84 libc::EOVERFLOW,
85 )));
86 }
87 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
88 }
89
90 trace!(
91 "fuse: new req {:?}: {:?}",
92 Opcode::from(in_header.opcode),
93 in_header
94 );
95
96 if let Some(h) = hook {
97 h.collect(&in_header);
98 }
99
100 let res = match in_header.opcode {
101 x if x == Opcode::Lookup as u32 => self.lookup(ctx),
102 x if x == Opcode::Forget as u32 => self.forget(ctx), x if x == Opcode::Getattr as u32 => self.getattr(ctx),
104 x if x == Opcode::Setattr as u32 => self.setattr(ctx),
105 x if x == Opcode::Readlink as u32 => self.readlink(ctx),
106 x if x == Opcode::Symlink as u32 => self.symlink(ctx),
107 x if x == Opcode::Mknod as u32 => self.mknod(ctx),
108 x if x == Opcode::Mkdir as u32 => self.mkdir(ctx),
109 x if x == Opcode::Unlink as u32 => self.unlink(ctx),
110 x if x == Opcode::Rmdir as u32 => self.rmdir(ctx),
111 x if x == Opcode::Rename as u32 => self.rename(ctx),
112 x if x == Opcode::Link as u32 => self.link(ctx),
113 x if x == Opcode::Open as u32 => self.open(ctx),
114 x if x == Opcode::Read as u32 => self.read(ctx),
115 x if x == Opcode::Write as u32 => self.write(ctx),
116 x if x == Opcode::Statfs as u32 => self.statfs(ctx),
117 x if x == Opcode::Release as u32 => self.release(ctx),
118 x if x == Opcode::Fsync as u32 => self.fsync(ctx),
119 x if x == Opcode::Setxattr as u32 => self.setxattr(ctx),
120 x if x == Opcode::Getxattr as u32 => self.getxattr(ctx),
121 x if x == Opcode::Listxattr as u32 => self.listxattr(ctx),
122 x if x == Opcode::Removexattr as u32 => self.removexattr(ctx),
123 x if x == Opcode::Flush as u32 => self.flush(ctx),
124 x if x == Opcode::Init as u32 => self.init(ctx),
125 x if x == Opcode::Opendir as u32 => self.opendir(ctx),
126 x if x == Opcode::Readdir as u32 => self.readdir(ctx),
127 x if x == Opcode::Releasedir as u32 => self.releasedir(ctx),
128 x if x == Opcode::Fsyncdir as u32 => self.fsyncdir(ctx),
129 x if x == Opcode::Getlk as u32 => self.getlk(ctx),
130 x if x == Opcode::Setlk as u32 => self.setlk(ctx),
131 x if x == Opcode::Setlkw as u32 => self.setlkw(ctx),
132 x if x == Opcode::Access as u32 => self.access(ctx),
133 x if x == Opcode::Create as u32 => self.create(ctx),
134 x if x == Opcode::Bmap as u32 => self.bmap(ctx),
135 x if x == Opcode::Ioctl as u32 => self.ioctl(ctx),
136 x if x == Opcode::Poll as u32 => self.poll(ctx),
137 x if x == Opcode::NotifyReply as u32 => self.notify_reply(ctx),
138 x if x == Opcode::BatchForget as u32 => self.batch_forget(ctx),
139 x if x == Opcode::Fallocate as u32 => self.fallocate(ctx),
140 #[cfg(target_os = "linux")]
141 x if x == Opcode::Readdirplus as u32 => self.readdirplus(ctx),
142 #[cfg(target_os = "linux")]
143 x if x == Opcode::Rename2 as u32 => self.rename2(ctx),
144 #[cfg(target_os = "linux")]
145 x if x == Opcode::Lseek as u32 => self.lseek(ctx),
146 #[cfg(feature = "virtiofs")]
147 x if x == Opcode::SetupMapping as u32 => self.setupmapping(ctx, vu_req),
148 #[cfg(feature = "virtiofs")]
149 x if x == Opcode::RemoveMapping as u32 => self.removemapping(ctx, vu_req),
150 x => match x {
152 x if x == Opcode::Interrupt as u32 => {
153 self.interrupt(ctx);
154 Ok(0)
155 }
156 x if x == Opcode::Destroy as u32 => {
157 self.destroy(ctx);
158 Ok(0)
159 }
160 _ => ctx.reply_error(io::Error::from_raw_os_error(libc::ENOSYS)),
161 },
162 };
163
164 if let Some(h) = hook {
168 h.release(None);
169 }
170
171 res
172 }
173
174 fn lookup<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
175 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
176 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
177 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
178 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
179 e
180 })?;
181
182 #[cfg(not(feature = "fuse-t"))]
183 let version = self.vers.load();
184 let result = self.fs.lookup(ctx.context(), ctx.nodeid(), name);
185
186 match result {
187 #[cfg(not(feature = "fuse-t"))]
189 Ok(entry)
190 if version.minor < KERNEL_MINOR_VERSION_LOOKUP_NEGATIVE_ENTRY_ZERO
191 && entry.inode == 0 =>
192 {
193 ctx.reply_error(io::Error::from_raw_os_error(libc::ENOENT))
194 }
195 #[cfg(feature = "fuse-t")]
196 Ok(entry) if entry.inode == 0 => {
197 ctx.reply_error(io::Error::from_raw_os_error(libc::ENOENT))
198 }
199 Ok(entry) => {
200 let out = EntryOut::from(entry);
201
202 ctx.reply_ok(Some(out), None)
203 }
204 Err(e) => ctx.reply_error(e),
205 }
206 }
207
208 pub(super) fn forget<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
209 let ForgetIn { nlookup } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
210
211 self.fs.forget(ctx.context(), ctx.nodeid(), nlookup);
212
213 Ok(0)
215 }
216
217 fn getattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
218 let GetattrIn { flags, fh, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
219 let handle = if (flags & GETATTR_FH) != 0 {
220 Some(fh.into())
221 } else {
222 None
223 };
224 let result = self.fs.getattr(ctx.context(), ctx.nodeid(), handle);
225
226 ctx.handle_attr_result(result)
227 }
228
229 fn setattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
230 let setattr_in: SetattrIn = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
231 let handle = if setattr_in.valid & FATTR_FH != 0 {
232 Some(setattr_in.fh.into())
233 } else {
234 None
235 };
236 let valid = SetattrValid::from_bits_truncate(setattr_in.valid);
237 let st: stat64 = setattr_in.into();
238 let result = self
239 .fs
240 .setattr(ctx.context(), ctx.nodeid(), st, handle, valid);
241
242 ctx.handle_attr_result(result)
243 }
244
245 pub(super) fn readlink<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
246 match self.fs.readlink(ctx.context(), ctx.nodeid()) {
247 Ok(linkname) => {
248 ctx.reply_ok(None::<u8>, Some(&linkname))
250 }
251 Err(e) => ctx.reply_error(e),
252 }
253 }
254
255 pub(super) fn symlink<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
256 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
257 let (name, linkname) = ServerUtil::extract_two_cstrs(&buf)?;
259
260 match self.fs.symlink(ctx.context(), linkname, ctx.nodeid(), name) {
261 Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
262 Err(e) => ctx.reply_error(e),
263 }
264 }
265
266 pub(super) fn mknod<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
267 let MknodIn {
268 mode, rdev, umask, ..
269 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
270 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<MknodIn>())?;
271 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
272 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
273 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
274 e
275 })?;
276
277 match self
278 .fs
279 .mknod(ctx.context(), ctx.nodeid(), name, mode, rdev, umask)
280 {
281 Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
282 Err(e) => ctx.reply_error(e),
283 }
284 }
285
286 pub(super) fn mkdir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
287 let MkdirIn { mode, umask } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
288 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<MkdirIn>())?;
289 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
290 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
291 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
292 e
293 })?;
294
295 match self
296 .fs
297 .mkdir(ctx.context(), ctx.nodeid(), name, mode, umask)
298 {
299 Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
300 Err(e) => ctx.reply_error(e),
301 }
302 }
303
304 pub(super) fn unlink<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
305 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
306 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
307 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
308 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
309 e
310 })?;
311
312 match self.fs.unlink(ctx.context(), ctx.nodeid(), name) {
313 Ok(()) => ctx.reply_ok(None::<u8>, None),
314 Err(e) => ctx.reply_error(e),
315 }
316 }
317
318 pub(super) fn rmdir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
319 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
320 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
321 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
322 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
323 e
324 })?;
325
326 match self.fs.rmdir(ctx.context(), ctx.nodeid(), name) {
327 Ok(()) => ctx.reply_ok(None::<u8>, None),
328 Err(e) => ctx.reply_error(e),
329 }
330 }
331
332 pub(super) fn do_rename<S: BitmapSlice>(
333 &self,
334 mut ctx: SrvContext<'_, F, S>,
335 msg_size: usize,
336 newdir: u64,
337 flags: u32,
338 ) -> Result<usize> {
339 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, msg_size)?;
340 let (oldname, newname) = ServerUtil::extract_two_cstrs(&buf)?;
341
342 match self.fs.rename(
343 ctx.context(),
344 ctx.nodeid(),
345 oldname,
346 newdir.into(),
347 newname,
348 flags,
349 ) {
350 Ok(()) => ctx.reply_ok(None::<u8>, None),
351 Err(e) => ctx.reply_error(e),
352 }
353 }
354
355 pub(super) fn rename<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
356 let RenameIn { newdir, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
357
358 self.do_rename(ctx, size_of::<RenameIn>(), newdir, 0)
359 }
360
361 #[cfg(target_os = "linux")]
362 pub(super) fn rename2<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
363 let Rename2In { newdir, flags, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
364
365 let flags =
366 flags & (libc::RENAME_EXCHANGE | libc::RENAME_NOREPLACE | libc::RENAME_WHITEOUT);
367
368 self.do_rename(ctx, size_of::<Rename2In>(), newdir, flags)
369 }
370
371 pub(super) fn link<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
372 let LinkIn { oldnodeid } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
373 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<LinkIn>())?;
374 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
375 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
376 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
377 e
378 })?;
379
380 match self
381 .fs
382 .link(ctx.context(), oldnodeid.into(), ctx.nodeid(), name)
383 {
384 Ok(entry) => ctx.reply_ok(Some(EntryOut::from(entry)), None),
385 Err(e) => ctx.reply_error(e),
386 }
387 }
388
389 fn open<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
390 let OpenIn { flags, fuse_flags } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
391
392 match self.fs.open(ctx.context(), ctx.nodeid(), flags, fuse_flags) {
393 Ok((handle, opts, passthrough)) => {
394 let out = OpenOut {
395 fh: handle.map(Into::into).unwrap_or(0),
396 open_flags: opts.bits(),
397 passthrough: passthrough.unwrap_or_default(),
398 };
399
400 ctx.reply_ok(Some(out), None)
401 }
402 Err(e) => ctx.reply_error(e),
403 }
404 }
405
406 fn read<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
407 let ReadIn {
408 fh,
409 offset,
410 size,
411 read_flags,
412 lock_owner,
413 flags,
414 ..
415 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
416
417 if size > MAX_BUFFER_SIZE {
418 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
419 }
420
421 let owner = if read_flags & READ_LOCKOWNER != 0 {
422 Some(lock_owner)
423 } else {
424 None
425 };
426
427 let w2 = match ctx.w.split_at(size_of::<OutHeader>()) {
429 Ok(v) => v,
430 Err(_e) => return Err(Error::InvalidHeaderLength),
431 };
432 let mut data_writer = ZcWriter(w2);
433
434 match self.fs.read(
435 ctx.context(),
436 ctx.nodeid(),
437 fh.into(),
438 &mut data_writer,
439 size,
440 offset,
441 owner,
442 flags,
443 ) {
444 Ok(count) => {
445 let out = OutHeader {
448 len: (size_of::<OutHeader>() + count) as u32,
449 error: 0,
450 unique: ctx.unique(),
451 };
452
453 ctx.w
454 .write_all(out.as_slice())
455 .map_err(Error::EncodeMessage)?;
456 ctx.w
457 .commit(Some(&data_writer.0))
458 .map_err(Error::EncodeMessage)?;
459 Ok(out.len as usize)
460 }
461 Err(e) => ctx.reply_error(e),
462 }
463 }
464
465 fn write<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
466 let WriteIn {
467 fh,
468 offset,
469 size,
470 fuse_flags,
471 lock_owner,
472 flags,
473 ..
474 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
475
476 if size > MAX_BUFFER_SIZE {
477 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
478 }
479
480 let owner = if fuse_flags & WRITE_LOCKOWNER != 0 {
481 Some(lock_owner)
482 } else {
483 None
484 };
485
486 let delayed_write = fuse_flags & WRITE_CACHE != 0;
487
488 let mut data_reader = ZcReader(ctx.take_reader());
489
490 match self.fs.write(
491 ctx.context(),
492 ctx.nodeid(),
493 fh.into(),
494 &mut data_reader,
495 size,
496 offset,
497 owner,
498 delayed_write,
499 flags,
500 fuse_flags,
501 ) {
502 Ok(count) => {
503 let out = WriteOut {
504 size: count as u32,
505 ..Default::default()
506 };
507
508 ctx.reply_ok(Some(out), None)
509 }
510 Err(e) => ctx.reply_error(e),
511 }
512 }
513
514 pub(super) fn statfs<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
515 match self.fs.statfs(ctx.context(), ctx.nodeid()) {
516 Ok(st) => ctx.reply_ok(Some(Kstatfs::from(st)), None),
517 Err(e) => ctx.reply_error(e),
518 }
519 }
520
521 pub(super) fn release<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
522 let ReleaseIn {
523 fh,
524 flags,
525 release_flags,
526 lock_owner,
527 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
528
529 let flush = release_flags & RELEASE_FLUSH != 0;
530 let flock_release = release_flags & RELEASE_FLOCK_UNLOCK != 0;
531 let lock_owner = if flush || flock_release {
532 Some(lock_owner)
533 } else {
534 None
535 };
536
537 match self.fs.release(
538 ctx.context(),
539 ctx.nodeid(),
540 flags,
541 fh.into(),
542 flush,
543 flock_release,
544 lock_owner,
545 ) {
546 Ok(()) => ctx.reply_ok(None::<u8>, None),
547 Err(e) => ctx.reply_error(e),
548 }
549 }
550
551 fn fsync<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
552 let FsyncIn {
553 fh, fsync_flags, ..
554 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
555 let datasync = fsync_flags & 0x1 != 0;
556
557 match self
558 .fs
559 .fsync(ctx.context(), ctx.nodeid(), datasync, fh.into())
560 {
561 Ok(()) => ctx.reply_ok(None::<u8>, None),
562 Err(e) => ctx.reply_error(e),
563 }
564 }
565
566 pub(super) fn setxattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
567 let SetxattrIn { size, flags } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
568 let buf =
569 ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<SetxattrIn>())?;
570
571 let split_pos = buf
573 .iter()
574 .position(|c| *c == b'\0')
575 .map(|p| p + 1)
576 .ok_or(Error::MissingParameter)?;
577 let (name, value) = buf.split_at(split_pos);
578
579 if size != value.len() as u32 {
580 return Err(Error::InvalidXattrSize((size, value.len())));
581 }
582 let name = bytes_to_cstr(name).map_err(|e| {
583 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
584 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
585 e
586 })?;
587
588 match self
589 .fs
590 .setxattr(ctx.context(), ctx.nodeid(), name, value, flags)
591 {
592 Ok(()) => ctx.reply_ok(None::<u8>, None),
593 Err(e) => ctx.reply_error(e),
594 }
595 }
596
597 pub(super) fn getxattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
598 let GetxattrIn { size, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
599 if size > MAX_BUFFER_SIZE {
600 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
601 }
602
603 let buf =
604 ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<GetxattrIn>())?;
605 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
606 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
607 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
608 e
609 })?;
610
611 match self.fs.getxattr(ctx.context(), ctx.nodeid(), name, size) {
612 Ok(GetxattrReply::Value(val)) => ctx.reply_ok(None::<u8>, Some(&val)),
613 Ok(GetxattrReply::Count(count)) => {
614 let out = GetxattrOut {
615 size: count,
616 ..Default::default()
617 };
618
619 ctx.reply_ok(Some(out), None)
620 }
621 Err(e) => ctx.reply_error(e),
622 }
623 }
624
625 pub(super) fn listxattr<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
626 let GetxattrIn { size, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
627
628 if size > MAX_BUFFER_SIZE {
629 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
630 }
631
632 match self.fs.listxattr(ctx.context(), ctx.nodeid(), size) {
633 Ok(ListxattrReply::Names(val)) => ctx.reply_ok(None::<u8>, Some(&val)),
634 Ok(ListxattrReply::Count(count)) => {
635 let out = GetxattrOut {
636 size: count,
637 ..Default::default()
638 };
639
640 ctx.reply_ok(Some(out), None)
641 }
642 Err(e) => ctx.reply_error(e),
643 }
644 }
645
646 pub(super) fn removexattr<S: BitmapSlice>(
647 &self,
648 mut ctx: SrvContext<'_, F, S>,
649 ) -> Result<usize> {
650 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, 0)?;
651 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
652 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
653 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
654 e
655 })?;
656
657 match self.fs.removexattr(ctx.context(), ctx.nodeid(), name) {
658 Ok(()) => ctx.reply_ok(None::<u8>, None),
659 Err(e) => ctx.reply_error(e),
660 }
661 }
662
663 pub(super) fn flush<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
664 let FlushIn { fh, lock_owner, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
665
666 match self
667 .fs
668 .flush(ctx.context(), ctx.nodeid(), fh.into(), lock_owner)
669 {
670 Ok(()) => ctx.reply_ok(None::<u8>, None),
671 Err(e) => ctx.reply_error(e),
672 }
673 }
674
675 pub(super) fn init<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
676 let InitIn {
677 major,
678 minor,
679 max_readahead,
680 flags,
681 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
682
683 if major < KERNEL_VERSION {
684 error!("Unsupported fuse protocol version: {}.{}", major, minor);
685 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EPROTO));
686 }
687
688 if major > KERNEL_VERSION {
689 let out = InitOut {
691 major: KERNEL_VERSION,
692 minor: KERNEL_MINOR_VERSION,
693 ..Default::default()
694 };
695
696 return ctx.reply_ok(Some(out), None);
697 }
698
699 #[cfg(target_os = "macos")]
700 let flags_u64 = flags as u64;
701 #[cfg(target_os = "linux")]
702 let mut flags_u64 = flags as u64;
703 #[cfg(target_os = "linux")]
704 if flags_u64 & FsOptions::INIT_EXT.bits() != 0 {
705 let InitIn2 { flags2, unused: _ } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
706 flags_u64 |= (flags2 as u64) << 32;
707 }
708 let capable = FsOptions::from_bits_truncate(flags_u64);
709
710 match self.fs.init(capable) {
711 Ok(want) => {
712 let enabled = capable & want;
713 info!(
714 "FUSE INIT major {} minor {}\n in_opts: {:?}\nout_opts: {:?}",
715 major, minor, capable, enabled
716 );
717
718 let readahead = if cfg!(target_os = "macos") {
719 0
720 } else {
721 max_readahead
722 };
723
724 let enabled_flags = enabled.bits();
725 let mut out = InitOut {
726 major: KERNEL_VERSION,
727 minor: KERNEL_MINOR_VERSION,
728 max_readahead: readahead,
729 flags: enabled_flags as u32,
730 max_background: ::std::u16::MAX,
731 congestion_threshold: (::std::u16::MAX / 4) * 3,
732 max_write: MIN_READ_BUFFER - BUFFER_HEADER_SIZE,
733 time_gran: 1, flags2: (enabled_flags >> 32) as u32,
735 ..Default::default()
736 };
737 if enabled.contains(FsOptions::BIG_WRITES) {
738 out.max_write = MAX_REQ_PAGES as u32 * pagesize() as u32;
739 }
740 #[cfg(target_os = "linux")]
741 if enabled.contains(FsOptions::MAX_PAGES) {
742 out.max_pages = MAX_REQ_PAGES;
743 out.max_write = MAX_REQ_PAGES as u32 * pagesize() as u32; }
745 let vers = ServerVersion { major, minor };
746 self.vers.store(Arc::new(vers));
747 if minor < KERNEL_MINOR_VERSION_INIT_OUT_SIZE {
748 ctx.reply_ok(
749 Some(
750 *<[u8; FUSE_COMPAT_INIT_OUT_SIZE]>::from_slice(
751 out.as_slice().split_at(FUSE_COMPAT_INIT_OUT_SIZE).0,
752 )
753 .unwrap(),
754 ),
755 None,
756 )
757 } else if minor < KERNEL_MINOR_VERSION_INIT_22_OUT_SIZE {
758 ctx.reply_ok(
759 Some(
760 *<[u8; FUSE_COMPAT_22_INIT_OUT_SIZE]>::from_slice(
761 out.as_slice().split_at(FUSE_COMPAT_22_INIT_OUT_SIZE).0,
762 )
763 .unwrap(),
764 ),
765 None,
766 )
767 } else {
768 ctx.reply_ok(Some(out), None)
769 }
770 }
771 Err(e) => ctx.reply_error(e),
772 }
773 }
774
775 pub(super) fn opendir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
776 let OpenIn { flags, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
777
778 match self.fs.opendir(ctx.context(), ctx.nodeid(), flags) {
779 Ok((handle, opts)) => {
780 let out = OpenOut {
781 fh: handle.map(Into::into).unwrap_or(0),
782 open_flags: opts.bits(),
783 ..Default::default()
784 };
785
786 ctx.reply_ok(Some(out), None)
787 }
788 Err(e) => ctx.reply_error(e),
789 }
790 }
791
792 fn do_readdir<S: BitmapSlice>(
793 &self,
794 mut ctx: SrvContext<'_, F, S>,
795 plus: bool,
796 ) -> Result<usize> {
797 let ReadIn {
798 fh, offset, size, ..
799 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
800
801 if size > MAX_BUFFER_SIZE {
802 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
803 }
804
805 let available_bytes = ctx.w.available_bytes();
806 if available_bytes < size as usize {
807 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
808 }
809
810 let mut cursor = match ctx.w.split_at(size_of::<OutHeader>()) {
812 Ok(v) => v,
813 Err(_e) => return Err(Error::InvalidHeaderLength),
814 };
815
816 let res = if plus {
817 self.fs.readdirplus(
818 ctx.context(),
819 ctx.nodeid(),
820 fh.into(),
821 size,
822 offset,
823 &mut |d, e| add_dirent(&mut cursor, size, d, Some(e)),
824 )
825 } else {
826 self.fs.readdir(
827 ctx.context(),
828 ctx.nodeid(),
829 fh.into(),
830 size,
831 offset,
832 &mut |d| add_dirent(&mut cursor, size, d, None),
833 )
834 };
835
836 if let Err(e) = res {
837 ctx.reply_error_explicit(e)
838 } else {
839 let out = OutHeader {
842 len: (size_of::<OutHeader>() + cursor.bytes_written()) as u32,
843 error: 0,
844 unique: ctx.unique(),
845 };
846
847 ctx.w
848 .write_all(out.as_slice())
849 .map_err(Error::EncodeMessage)?;
850 ctx.w.commit(Some(&cursor)).map_err(Error::EncodeMessage)?;
851 Ok(out.len as usize)
852 }
853 }
854
855 pub(super) fn readdir<S: BitmapSlice>(&self, ctx: SrvContext<'_, F, S>) -> Result<usize> {
856 self.do_readdir(ctx, false)
857 }
858
859 #[cfg(target_os = "linux")]
860 pub(super) fn readdirplus<S: BitmapSlice>(&self, ctx: SrvContext<'_, F, S>) -> Result<usize> {
861 self.do_readdir(ctx, true)
862 }
863
864 pub(super) fn releasedir<S: BitmapSlice>(
865 &self,
866 mut ctx: SrvContext<'_, F, S>,
867 ) -> Result<usize> {
868 let ReleaseIn { fh, flags, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
869
870 match self
871 .fs
872 .releasedir(ctx.context(), ctx.nodeid(), flags, fh.into())
873 {
874 Ok(()) => ctx.reply_ok(None::<u8>, None),
875 Err(e) => ctx.reply_error(e),
876 }
877 }
878
879 fn fsyncdir<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
880 let FsyncIn {
881 fh, fsync_flags, ..
882 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
883 let datasync = fsync_flags & 0x1 != 0;
884
885 match self
886 .fs
887 .fsyncdir(ctx.context(), ctx.nodeid(), datasync, fh.into())
888 {
889 Ok(()) => ctx.reply_ok(None::<u8>, None),
890 Err(e) => ctx.reply_error(e),
891 }
892 }
893
894 pub(super) fn getlk<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
895 let LkIn {
896 fh,
897 owner,
898 lk,
899 lk_flags,
900 ..
901 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
902 match self.fs.getlk(
903 ctx.context(),
904 ctx.nodeid(),
905 fh.into(),
906 owner,
907 lk.into(),
908 lk_flags,
909 ) {
910 Ok(l) => ctx.reply_ok(Some(LkOut { lk: l.into() }), None),
911 Err(e) => ctx.reply_error(e),
912 }
913 }
914
915 pub(super) fn setlk<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
916 let LkIn {
917 fh,
918 owner,
919 lk,
920 lk_flags,
921 ..
922 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
923 match self.fs.setlk(
924 ctx.context(),
925 ctx.nodeid(),
926 fh.into(),
927 owner,
928 lk.into(),
929 lk_flags,
930 ) {
931 Ok(()) => ctx.reply_ok(None::<u8>, None),
932 Err(e) => ctx.reply_error(e),
933 }
934 }
935
936 pub(super) fn setlkw<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
937 let LkIn {
938 fh,
939 owner,
940 lk,
941 lk_flags,
942 ..
943 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
944 match self.fs.setlk(
945 ctx.context(),
946 ctx.nodeid(),
947 fh.into(),
948 owner,
949 lk.into(),
950 lk_flags,
951 ) {
952 Ok(()) => ctx.reply_ok(None::<u8>, None),
953 Err(e) => ctx.reply_error(e),
954 }
955 }
956
957 pub(super) fn access<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
958 let AccessIn { mask, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
959
960 match self.fs.access(ctx.context(), ctx.nodeid(), mask) {
961 Ok(()) => ctx.reply_ok(None::<u8>, None),
962 Err(e) => ctx.reply_error(e),
963 }
964 }
965
966 fn create<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
967 let args: CreateIn = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
968 let buf = ServerUtil::get_message_body(&mut ctx.r, &ctx.in_header, size_of::<CreateIn>())?;
969 let name = bytes_to_cstr(buf.as_ref()).map_err(|e| {
970 let _ = ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL));
971 error!("fuse: bytes to cstr error: {:?}, {:?}", buf, e);
972 e
973 })?;
974
975 match self.fs.create(ctx.context(), ctx.nodeid(), name, args) {
976 Ok((entry, handle, opts, passthrough)) => {
977 let entry_out = EntryOut {
978 nodeid: entry.inode,
979 generation: entry.generation,
980 entry_valid: entry.entry_timeout.as_secs(),
981 attr_valid: entry.attr_timeout.as_secs(),
982 entry_valid_nsec: entry.entry_timeout.subsec_nanos(),
983 attr_valid_nsec: entry.attr_timeout.subsec_nanos(),
984 attr: entry.attr.into(),
985 };
986
987 let open_out = OpenOut {
988 fh: handle.map(Into::into).unwrap_or(0),
989 open_flags: opts.bits(),
990 passthrough: passthrough.unwrap_or_default(),
991 };
992
993 ctx.reply_ok(Some(entry_out), Some(open_out.as_slice()))
995 }
996 Err(e) => ctx.reply_error(e),
997 }
998 }
999
1000 pub(super) fn interrupt<S: BitmapSlice>(&self, _ctx: SrvContext<'_, F, S>) {}
1001
1002 pub(super) fn bmap<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1003 let BmapIn {
1004 block, blocksize, ..
1005 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1006
1007 match self.fs.bmap(ctx.context(), ctx.nodeid(), block, blocksize) {
1008 Ok(block) => ctx.reply_ok(Some(BmapOut { block }), None),
1009 Err(e) => ctx.reply_error(e),
1010 }
1011 }
1012
1013 pub(super) fn destroy<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) {
1014 self.fs.destroy();
1015 if let Err(e) = ctx.reply_ok(None::<u8>, None) {
1016 warn!("fuse channel reply destroy failed {:?}", e);
1017 }
1018 }
1019
1020 pub(super) fn ioctl<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1021 let IoctlIn {
1022 fh,
1023 flags,
1024 cmd,
1025 arg: _,
1026 in_size,
1027 out_size,
1028 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1029 let mut buf = IoctlData {
1031 ..Default::default()
1032 };
1033 let in_size = in_size as usize;
1034 if in_size > ctx.r.available_bytes() {
1036 return ctx.reply_error(io::Error::from_raw_os_error(libc::ENOTTY));
1037 }
1038 let mut data = vec![0u8; in_size];
1039 if in_size > 0 {
1040 let size = ctx.r.read(&mut data).map_err(Error::DecodeMessage)?;
1041 if size > 0 {
1042 buf.data = Some(&data[..size]);
1043 }
1044 }
1045 match self.fs.ioctl(
1046 ctx.context(),
1047 ctx.nodeid(),
1048 fh.into(),
1049 flags,
1050 cmd,
1051 buf,
1052 out_size,
1053 ) {
1054 Ok(res) => ctx.reply_ok(
1055 Some(IoctlOut {
1056 result: res.result,
1057 ..Default::default()
1058 }),
1059 res.data,
1060 ),
1061 Err(e) => ctx.reply_error(e),
1062 }
1063 }
1064
1065 pub(super) fn poll<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1066 let PollIn {
1067 fh,
1068 kh,
1069 flags,
1070 events,
1071 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1072
1073 match self.fs.poll(
1074 ctx.context(),
1075 ctx.nodeid(),
1076 fh.into(),
1077 kh.into(),
1078 flags,
1079 events,
1080 ) {
1081 Ok(revents) => ctx.reply_ok(
1082 Some(PollOut {
1083 revents,
1084 padding: 0,
1085 }),
1086 None,
1087 ),
1088 Err(e) => ctx.reply_error(e),
1089 }
1090 }
1091
1092 pub(super) fn notify_reply<S: BitmapSlice>(
1093 &self,
1094 mut ctx: SrvContext<'_, F, S>,
1095 ) -> Result<usize> {
1096 if let Err(e) = self.fs.notify_reply() {
1097 ctx.reply_error(e)
1098 } else {
1099 Ok(0)
1100 }
1101 }
1102
1103 pub(super) fn batch_forget<S: BitmapSlice>(
1104 &self,
1105 mut ctx: SrvContext<'_, F, S>,
1106 ) -> Result<usize> {
1107 let BatchForgetIn { count, .. } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1108
1109 if let Some(size) = (count as usize).checked_mul(size_of::<ForgetOne>()) {
1110 if size
1111 > (MAX_BUFFER_SIZE + BUFFER_HEADER_SIZE
1112 - size_of::<BatchForgetIn>() as u32
1113 - size_of::<InHeader>() as u32) as usize
1114 {
1115 return Err(Error::InvalidMessage(io::Error::from_raw_os_error(
1116 libc::EOVERFLOW,
1117 )));
1118 }
1119 } else {
1120 return Err(Error::InvalidMessage(io::Error::from_raw_os_error(
1121 libc::EOVERFLOW,
1122 )));
1123 }
1124
1125 let mut requests = Vec::with_capacity(count as usize);
1126 for _ in 0..count {
1127 requests.push(
1128 ctx.r
1129 .read_obj::<ForgetOne>()
1130 .map(|f| (f.nodeid.into(), f.nlookup))
1131 .map_err(Error::DecodeMessage)?,
1132 );
1133 }
1134
1135 self.fs.batch_forget(ctx.context(), requests);
1136
1137 Ok(0)
1139 }
1140
1141 fn fallocate<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1142 let FallocateIn {
1143 fh,
1144 offset,
1145 length,
1146 mode,
1147 ..
1148 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1149
1150 match self
1151 .fs
1152 .fallocate(ctx.context(), ctx.nodeid(), fh.into(), mode, offset, length)
1153 {
1154 Ok(()) => ctx.reply_ok(None::<u8>, None),
1155 Err(e) => ctx.reply_error(e),
1156 }
1157 }
1158
1159 #[cfg(target_os = "linux")]
1160 pub(super) fn lseek<S: BitmapSlice>(&self, mut ctx: SrvContext<'_, F, S>) -> Result<usize> {
1161 let LseekIn {
1162 fh, offset, whence, ..
1163 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1164
1165 match self
1166 .fs
1167 .lseek(ctx.context(), ctx.nodeid(), fh.into(), offset, whence)
1168 {
1169 Ok(offset) => {
1170 let out = LseekOut { offset };
1171
1172 ctx.reply_ok(Some(out), None)
1173 }
1174 Err(e) => ctx.reply_error(e),
1175 }
1176 }
1177}
1178
1179#[cfg(feature = "virtiofs")]
1180impl<F: FileSystem + Sync> Server<F> {
1181 pub(super) fn setupmapping<S: BitmapSlice>(
1182 &self,
1183 mut ctx: SrvContext<'_, F, S>,
1184 vu_req: Option<&mut dyn FsCacheReqHandler>,
1185 ) -> Result<usize> {
1186 if let Some(req) = vu_req {
1187 let SetupmappingIn {
1188 fh,
1189 foffset,
1190 len,
1191 flags,
1192 moffset,
1193 } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1194
1195 match self.fs.setupmapping(
1196 ctx.context(),
1197 ctx.nodeid(),
1198 fh.into(),
1199 foffset,
1200 len,
1201 flags,
1202 moffset,
1203 req,
1204 ) {
1205 Ok(()) => ctx.reply_ok(None::<u8>, None),
1206 Err(e) => ctx.reply_error(e),
1207 }
1208 } else {
1209 ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL))
1210 }
1211 }
1212
1213 pub(super) fn removemapping<S: BitmapSlice>(
1214 &self,
1215 mut ctx: SrvContext<'_, F, S>,
1216 vu_req: Option<&mut dyn FsCacheReqHandler>,
1217 ) -> Result<usize> {
1218 if let Some(req) = vu_req {
1219 let RemovemappingIn { count } = ctx.r.read_obj().map_err(Error::DecodeMessage)?;
1220
1221 if let Some(size) = (count as usize).checked_mul(size_of::<RemovemappingOne>()) {
1222 if size > MAX_BUFFER_SIZE as usize {
1223 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::ENOMEM));
1224 }
1225 } else {
1226 return ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EOVERFLOW));
1227 }
1228
1229 let mut requests = Vec::with_capacity(count as usize);
1230 for _ in 0..count {
1231 requests.push(
1232 ctx.r
1233 .read_obj::<RemovemappingOne>()
1234 .map_err(Error::DecodeMessage)?,
1235 );
1236 }
1237
1238 match self
1239 .fs
1240 .removemapping(ctx.context(), ctx.nodeid(), requests, req)
1241 {
1242 Ok(()) => ctx.reply_ok(None::<u8>, None),
1243 Err(e) => ctx.reply_error(e),
1244 }
1245 } else {
1246 ctx.reply_error_explicit(io::Error::from_raw_os_error(libc::EINVAL))
1247 }
1248 }
1249}
1250
1251impl<'a, F: FileSystem, S: BitmapSlice> SrvContext<'a, F, S> {
1252 fn reply_ok<T: ByteValued>(&mut self, out: Option<T>, data: Option<&[u8]>) -> Result<usize> {
1253 let data2 = out.as_ref().map(|v| v.as_slice()).unwrap_or(&[]);
1254 let data3 = data.unwrap_or(&[]);
1255 let len = size_of::<OutHeader>() + data2.len() + data3.len();
1256 let header = OutHeader {
1257 len: len as u32,
1258 error: 0,
1259 unique: self.unique(),
1260 };
1261 trace!("fuse: new reply {:?}", header);
1262
1263 match (data2.len(), data3.len()) {
1264 (0, 0) => self
1265 .w
1266 .write(header.as_slice())
1267 .map_err(Error::EncodeMessage)?,
1268 (0, _) => self
1269 .w
1270 .write_vectored(&[IoSlice::new(header.as_slice()), IoSlice::new(data3)])
1271 .map_err(Error::EncodeMessage)?,
1272 (_, 0) => self
1273 .w
1274 .write_vectored(&[IoSlice::new(header.as_slice()), IoSlice::new(data2)])
1275 .map_err(Error::EncodeMessage)?,
1276 (_, _) => self
1277 .w
1278 .write_vectored(&[
1279 IoSlice::new(header.as_slice()),
1280 IoSlice::new(data2),
1281 IoSlice::new(data3),
1282 ])
1283 .map_err(Error::EncodeMessage)?,
1284 };
1285
1286 debug_assert_eq!(len, self.w.bytes_written());
1287 Ok(self.w.bytes_written())
1288 }
1289
1290 fn do_reply_error(&mut self, err: io::Error, explicit: bool) -> Result<usize> {
1291 let header = OutHeader {
1292 len: size_of::<OutHeader>() as u32,
1293 error: -err
1294 .raw_os_error()
1295 .unwrap_or_else(|| encode_io_error_kind(err.kind())),
1296 unique: self.unique(),
1297 };
1298
1299 if explicit || err.raw_os_error().is_none() {
1300 error!("fuse: reply error header {:?}, error {:?}", header, err);
1301 } else {
1302 trace!("fuse: reply error header {:?}, error {:?}", header, err);
1303 }
1304 self.w
1305 .write_all(header.as_slice())
1306 .map_err(Error::EncodeMessage)?;
1307
1308 self.w
1310 .commit(None)
1311 .map(|_| {
1312 debug_assert_eq!(header.len as usize, self.w.bytes_written());
1313 self.w.bytes_written()
1314 })
1315 .map_err(Error::EncodeMessage)
1316 }
1317
1318 fn reply_error(&mut self, err: io::Error) -> Result<usize> {
1321 self.do_reply_error(err, false)
1322 }
1323
1324 fn reply_error_explicit(&mut self, err: io::Error) -> Result<usize> {
1325 self.do_reply_error(err, true)
1326 }
1327
1328 fn handle_attr_result(&mut self, result: io::Result<(stat64, Duration)>) -> Result<usize> {
1329 match result {
1330 Ok((st, timeout)) => {
1331 let out = AttrOut {
1332 attr_valid: timeout.as_secs(),
1333 attr_valid_nsec: timeout.subsec_nanos(),
1334 dummy: 0,
1335 attr: st.into(),
1336 };
1337 self.reply_ok(Some(out), None)
1338 }
1339 Err(e) => self.reply_error(e),
1340 }
1341 }
1342}
1343
1344fn add_dirent<S: BitmapSlice>(
1345 cursor: &mut Writer<'_, S>,
1346 max: u32,
1347 d: DirEntry,
1348 entry: Option<Entry>,
1349) -> io::Result<usize> {
1350 if d.name.len() > ::std::u32::MAX as usize {
1351 return Err(io::Error::from_raw_os_error(libc::EOVERFLOW));
1352 }
1353
1354 let dirent_len = size_of::<Dirent>()
1355 .checked_add(d.name.len())
1356 .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
1357
1358 let padded_dirent_len = dirent_len
1361 .checked_add(7)
1362 .map(|l| l & !7)
1363 .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?;
1364
1365 let total_len = if entry.is_some() {
1366 padded_dirent_len
1367 .checked_add(size_of::<EntryOut>())
1368 .ok_or_else(|| io::Error::from_raw_os_error(libc::EOVERFLOW))?
1369 } else {
1370 padded_dirent_len
1371 };
1372
1373 if (max as usize).saturating_sub(cursor.bytes_written()) < total_len {
1375 Ok(0)
1376 } else {
1377 if let Some(entry) = entry {
1378 cursor.write_all(EntryOut::from(entry).as_slice())?;
1379 }
1380
1381 let dirent = Dirent {
1382 ino: d.ino,
1383 off: d.offset,
1384 namelen: d.name.len() as u32,
1385 type_: d.type_,
1386 };
1387
1388 cursor.write_all(dirent.as_slice())?;
1389 cursor.write_all(d.name)?;
1390
1391 let padding = padded_dirent_len - dirent_len;
1394 if padding > 0 {
1395 cursor.write_all(&DIRENT_PADDING[..padding])?;
1396 }
1397
1398 Ok(total_len)
1399 }
1400}