@@ -24,6 +24,7 @@ use crate::drivers::virtio::virtqueue::error::VirtqError;
2424use crate :: errno:: Errno ;
2525use crate :: executor:: block_on;
2626use crate :: fd:: PollEvent ;
27+ use crate :: fs:: fuse:: ops:: SetAttrValidFields ;
2728use crate :: fs:: {
2829 self , AccessPermission , DirectoryEntry , FileAttr , NodeKind , ObjectInterface , OpenOption ,
2930 SeekWhence , VfsNode ,
@@ -63,11 +64,12 @@ pub(crate) mod ops {
6364 use alloc:: boxed:: Box ;
6465 use alloc:: ffi:: CString ;
6566
67+ use fuse_abi:: linux;
6668 use fuse_abi:: linux:: * ;
6769
6870 use super :: Cmd ;
6971 use crate :: fd:: PollEvent ;
70- use crate :: fs:: SeekWhence ;
72+ use crate :: fs:: { FileAttr , SeekWhence } ;
7173
7274 #[ repr( C ) ]
7375 #[ derive( Debug , Default , Copy , Clone , Hash , PartialEq , Eq ) ]
@@ -270,6 +272,76 @@ pub(crate) mod ops {
270272 }
271273 }
272274
275+ #[ derive( Debug ) ]
276+ pub ( crate ) struct Setattr ;
277+
278+ impl Op for Setattr {
279+ const OP_CODE : fuse_opcode = fuse_opcode:: FUSE_SETATTR ;
280+ type InStruct = fuse_setattr_in ;
281+ type InPayload = ( ) ;
282+ type OutStruct = fuse_attr_out ;
283+ type OutPayload = ( ) ;
284+ }
285+
286+ bitflags ! {
287+ #[ derive( Debug , Copy , Clone , Default ) ]
288+ pub struct SetAttrValidFields : u32 {
289+ const FATTR_MODE = linux:: FATTR_MODE ;
290+ const FATTR_UID = linux:: FATTR_UID ;
291+ const FATTR_GID = linux:: FATTR_GID ;
292+ const FATTR_SIZE = linux:: FATTR_SIZE ;
293+ const FATTR_ATIME = linux:: FATTR_ATIME ;
294+ const FATTR_MTIME = linux:: FATTR_MTIME ;
295+ const FATTR_FH = linux:: FATTR_FH ;
296+ const FATTR_ATIME_NOW = linux:: FATTR_ATIME_NOW ;
297+ const FATTR_MTIME_NOW = linux:: FATTR_MTIME_NOW ;
298+ const FATTR_LOCKOWNER = linux:: FATTR_LOCKOWNER ;
299+ const FATTR_CTIME = linux:: FATTR_CTIME ;
300+ const FATTR_KILL_SUIDGID = linux:: FATTR_KILL_SUIDGID ;
301+ }
302+ }
303+
304+ impl Setattr {
305+ pub ( crate ) fn create (
306+ nid : u64 ,
307+ fh : u64 ,
308+ attr : FileAttr ,
309+ valid_attr : SetAttrValidFields ,
310+ ) -> ( Cmd < Self > , u32 ) {
311+ let cmd = Cmd :: new (
312+ nid,
313+ fuse_setattr_in {
314+ valid : valid_attr
315+ . difference (
316+ // Remove unsupported attributes
317+ SetAttrValidFields :: FATTR_LOCKOWNER ,
318+ )
319+ . bits ( ) ,
320+ padding : 0 ,
321+ fh,
322+
323+ // Fuse attributes mapping: https://github.com/libfuse/libfuse/blob/fc1c8da0cf8a18d222cb1feed0057ba44ea4d18f/lib/fuse_lowlevel.c#L105
324+ size : attr. st_size as u64 ,
325+ atime : attr. st_atim . tv_sec as u64 ,
326+ atimensec : attr. st_atim . tv_nsec as u32 ,
327+ mtime : attr. st_ctim . tv_sec as u64 ,
328+ mtimensec : attr. st_ctim . tv_nsec as u32 ,
329+ ctime : attr. st_ctim . tv_sec as u64 ,
330+ ctimensec : attr. st_ctim . tv_nsec as u32 ,
331+ mode : attr. st_mode . bits ( ) ,
332+ unused4 : 0 ,
333+ uid : attr. st_uid ,
334+ gid : attr. st_gid ,
335+ unused5 : 0 ,
336+
337+ lock_owner : 0 , // unsupported
338+ } ,
339+ ) ;
340+
341+ ( cmd, 0 )
342+ }
343+ }
344+
273345 #[ derive( Debug ) ]
274346 pub ( crate ) struct Readlink ;
275347
@@ -758,6 +830,23 @@ impl FuseFileHandleInner {
758830 Err ( Errno :: Io )
759831 }
760832 }
833+
834+ fn set_attr ( & mut self , attr : FileAttr , valid : SetAttrValidFields ) -> io:: Result < FileAttr > {
835+ debug ! ( "FUSE setattr" ) ;
836+ if let ( Some ( nid) , Some ( fh) ) = ( self . fuse_nid , self . fuse_fh ) {
837+ let ( cmd, rsp_payload_len) = ops:: Setattr :: create ( nid, fh, attr, valid) ;
838+ let rsp = get_filesystem_driver ( )
839+ . ok_or ( Errno :: Nosys ) ?
840+ . lock ( )
841+ . send_command ( cmd, rsp_payload_len) ?;
842+ if rsp. headers . out_header . error < 0 {
843+ return Err ( Errno :: Io ) ;
844+ }
845+ Ok ( rsp. headers . op_header . attr . into ( ) )
846+ } else {
847+ Err ( Errno :: Io )
848+ }
849+ }
761850}
762851
763852impl Drop for FuseFileHandleInner {
@@ -804,6 +893,32 @@ impl ObjectInterface for FuseFileHandle {
804893 async fn fstat ( & self ) -> io:: Result < FileAttr > {
805894 self . 0 . lock ( ) . await . fstat ( )
806895 }
896+
897+ async fn truncate ( & self , size : usize ) -> io:: Result < ( ) > {
898+ let attr = FileAttr {
899+ st_size : size. try_into ( ) . unwrap ( ) ,
900+ ..FileAttr :: default ( )
901+ } ;
902+
903+ self . 0
904+ . lock ( )
905+ . await
906+ . set_attr ( attr, SetAttrValidFields :: FATTR_SIZE )
907+ . map ( |_| ( ) )
908+ }
909+
910+ async fn chmod ( & self , access_permission : AccessPermission ) -> io:: Result < ( ) > {
911+ let attr = FileAttr {
912+ st_mode : access_permission,
913+ ..FileAttr :: default ( )
914+ } ;
915+
916+ self . 0
917+ . lock ( )
918+ . await
919+ . set_attr ( attr, SetAttrValidFields :: FATTR_MODE )
920+ . map ( |_| ( ) )
921+ }
807922}
808923
809924impl Clone for FuseFileHandle {
0 commit comments