@@ -487,6 +487,13 @@ FS.staticInit();
487487 stream . stream_ops ?. dup ?. ( stream ) ;
488488 return stream ;
489489 } ,
490+ doSetAttr( stream , node, attr ) {
491+ var setattr = stream ?. stream_ops . setattr ;
492+ var arg = setattr ? stream : node ;
493+ setattr ??= node . node_ops . setattr ;
494+ FS . checkOpExists ( setattr , { { { cDefs. EPERM } } } )
495+ setattr ( arg, attr) ;
496+ } ,
490497
491498 //
492499 // devices
@@ -966,11 +973,24 @@ FS.staticInit();
966973 return getattr ( node ) ;
967974 } ,
968975 fstat ( fd ) {
969- return FS . stat ( FS . getStreamChecked ( fd ) . path ) ;
976+ var stream = FS . getStreamChecked ( fd ) ;
977+ var node = stream . node ;
978+ var getattr = stream . stream_ops . getattr ;
979+ var arg = getattr ? stream : node ;
980+ getattr ??= node . node_ops . getattr ;
981+ FS . checkOpExists ( getattr , { { { cDefs. EPERM } } } )
982+ return getattr ( arg ) ;
970983 } ,
971984 lstat ( path ) {
972985 return FS . stat ( path , true ) ;
973986 } ,
987+ doChmod ( stream , node , mode , dontFollow ) {
988+ FS . doSetAttr ( stream , node , {
989+ mode : ( mode & { { { cDefs . S_IALLUGO } } } ) | ( node . mode & ~ { { { cDefs . S_IALLUGO } } } ) ,
990+ ctime : Date . now ( ) ,
991+ dontFollow
992+ } ) ;
993+ } ,
974994 chmod ( path , mode , dontFollow ) {
975995 var node ;
976996 if ( typeof path == 'string' ) {
@@ -979,19 +999,21 @@ FS.staticInit();
979999 } else {
9801000 node = path ;
9811001 }
982- var setattr = FS . checkOpExists ( node . node_ops . setattr , { { { cDefs. EPERM } } } ) ;
983- setattr ( node , {
984- mode : ( mode & { { { cDefs . S_IALLUGO } } } ) | ( node . mode & ~ { { { cDefs . S_IALLUGO } } } ) ,
985- ctime : Date . now ( ) ,
986- dontFollow
987- } ) ;
1002+ FS . doChmod ( null , node, mode, dontFollow) ;
9881003 } ,
9891004 lchmod ( path , mode ) {
9901005 FS . chmod ( path , mode , true ) ;
9911006 } ,
9921007 fchmod ( fd , mode ) {
9931008 var stream = FS . getStreamChecked ( fd ) ;
994- FS . chmod ( stream . node , mode ) ;
1009+ FS . doChmod ( stream , stream . node , mode , false ) ;
1010+ } ,
1011+ doChown ( stream , node , dontFollow ) {
1012+ FS . doSetAttr ( stream , node , {
1013+ timestamp : Date . now ( ) ,
1014+ dontFollow
1015+ // we ignore the uid / gid for now
1016+ } ) ;
9951017 } ,
9961018 chown ( path , uid , gid , dontFollow ) {
9971019 var node ;
@@ -1001,31 +1023,16 @@ FS.staticInit();
10011023 } else {
10021024 node = path ;
10031025 }
1004- var setattr = FS . checkOpExists ( node . node_ops . setattr , { { { cDefs. EPERM } } } ) ;
1005- setattr ( node , {
1006- timestamp : Date . now ( ) ,
1007- dontFollow
1008- // we ignore the uid / gid for now
1009- } ) ;
1026+ FS . doChown ( null , node , dontFollow ) ;
10101027 } ,
10111028 lchown ( path , uid , gid ) {
10121029 FS . chown ( path , uid , gid , true ) ;
10131030 } ,
10141031 fchown ( fd , uid , gid ) {
10151032 var stream = FS . getStreamChecked ( fd ) ;
1016- FS . chown ( stream . node , uid , gid ) ;
1033+ FS . doChown ( stream , stream . node , false ) ;
10171034 } ,
1018- truncate( path , len ) {
1019- if ( len < 0 ) {
1020- throw new FS . ErrnoError ( { { { cDefs . EINVAL } } } ) ;
1021- }
1022- var node ;
1023- if ( typeof path = = 'string' ) {
1024- var lookup = FS . lookupPath ( path , { follow : true } ) ;
1025- node = lookup . node ;
1026- } else {
1027- node = path ;
1028- }
1035+ doTruncate ( stream , node , len ) {
10291036 if ( FS . isDir ( node . mode ) ) {
10301037 throw new FS . ErrnoError ( { { { cDefs . EISDIR } } } ) ;
10311038 }
@@ -1036,18 +1043,30 @@ FS.staticInit();
10361043 if ( errCode ) {
10371044 throw new FS . ErrnoError ( errCode ) ;
10381045 }
1039- var setattr = FS . checkOpExists ( node . node_ops . setattr , { { { cDefs. EPERM } } } ) ;
1040- setattr ( node , {
1046+ FS . doSetAttr ( stream , node , {
10411047 size : len ,
10421048 timestamp : Date . now ( )
10431049 } ) ;
10441050 } ,
1051+ truncate ( path , len ) {
1052+ if ( len < 0 ) {
1053+ throw new FS . ErrnoError ( { { { cDefs . EINVAL } } } ) ;
1054+ }
1055+ var node ;
1056+ if ( typeof path == 'string' ) {
1057+ var lookup = FS . lookupPath ( path , { follow : true } ) ;
1058+ node = lookup . node ;
1059+ } else {
1060+ node = path ;
1061+ }
1062+ FS . doTruncate ( null , node , len ) ;
1063+ } ,
10451064 ftruncate ( fd , len ) {
10461065 var stream = FS . getStreamChecked ( fd ) ;
1047- if ( ( stream . flags & { { { cDefs . O_ACCMODE } } } ) === { { { cDefs . O_RDONLY } } } ) {
1066+ if ( len < 0 || ( stream . flags & { { { cDefs . O_ACCMODE } } } ) === { { { cDefs . O_RDONLY } } } ) {
10481067 throw new FS . ErrnoError ( { { { cDefs . EINVAL } } } ) ;
10491068 }
1050- FS . truncate ( stream . node, len) ;
1069+ FS . doTruncate ( stream , stream. node , len) ;
10511070 } ,
10521071 utime( path , atime, mtime ) {
10531072 var lookup = FS . lookupPath ( path , { follow : true } ) ;
0 commit comments