@@ -148,7 +148,7 @@ func (f *fuseImpl) SetAddress(addr netip.AddrPort) error {
148
148
// The third argument, the mode bits, are currently ignored
149
149
func (f * fuseImpl ) Create (path string , flags int , _ uint32 ) (int , uint64 ) {
150
150
log .Debugf ("Create(%s, %#x)" , path , flags )
151
- fe , _ , errCode := f .openHandle (path , true , flags & os . O_APPEND == os . O_APPEND )
151
+ fe , _ , errCode := f .openHandle (path , flags | fuse . O_CREAT )
152
152
if errCode < 0 {
153
153
return errCode , 0
154
154
}
@@ -229,14 +229,20 @@ func (f *fuseImpl) Mkdir(path string, mode uint32) int {
229
229
err := f .withConn (func (conn * ftp.ServerConn ) error {
230
230
return conn .MakeDir (relpath (path ))
231
231
})
232
+ var tpe * textproto.Error
233
+ if errors .As (err , & tpe ) && tpe .Code == ftp .StatusFileUnavailable {
234
+ if _ , ec := f .getEntry (path ); ec == 0 {
235
+ return - fuse .EEXIST
236
+ }
237
+ }
232
238
return f .errToFuseErr (err )
233
239
}
234
240
235
241
// Open ensures checks if the file exists, and if it doesn't, ensure that
236
242
// a file of size zero can be created in the server.
237
243
func (f * fuseImpl ) Open (path string , flags int ) (int , uint64 ) {
238
244
log .Debugf ("Open(%s, %#x)" , path , flags )
239
- fe , _ , errCode := f .openHandle (path , flags & os . O_CREATE == os . O_CREATE , flags & os . O_APPEND == os . O_APPEND )
245
+ fe , _ , errCode := f .openHandle (path , flags )
240
246
if errCode < 0 {
241
247
return errCode , 0
242
248
}
@@ -247,7 +253,7 @@ func (f *fuseImpl) Open(path string, flags int) (int, uint64) {
247
253
// Opendir is like Open but will fail unless the path represents a directory
248
254
func (f * fuseImpl ) Opendir (path string ) (int , uint64 ) {
249
255
log .Debugf ("Opendir(%s)" , path )
250
- fe , e , errCode := f .openHandle (path , false , false )
256
+ fe , e , errCode := f .openHandle (path , fuse . O_RDONLY )
251
257
if errCode < 0 {
252
258
return errCode , 0
253
259
}
@@ -322,7 +328,7 @@ func (f *fuseImpl) Readdir(path string, fill func(name string, stat *fuse.Stat_t
322
328
var fe * info
323
329
var errCode int
324
330
if fh == math .MaxUint64 {
325
- fe , _ , errCode = f .openHandle (path , false , false )
331
+ fe , _ , errCode = f .openHandle (path , fuse . O_RDONLY )
326
332
defer f .delete (fe .fh )
327
333
} else {
328
334
fe , errCode = f .loadHandle (fh )
@@ -374,13 +380,35 @@ func (f *fuseImpl) Rename(oldpath string, newpath string) int {
374
380
// Rmdir removes the directory at path. The directory must be empty
375
381
func (f * fuseImpl ) Rmdir (path string ) int {
376
382
log .Debugf ("Rmdir(%s)" , path )
377
- return f .errToFuseErr (f .withConn (func (conn * ftp.ServerConn ) error {
383
+ err := f .withConn (func (conn * ftp.ServerConn ) error {
384
+ e , err := conn .GetEntry (relpath (path ))
385
+ if err != nil {
386
+ return err
387
+ }
388
+ if e .Type != ftp .EntryTypeFolder {
389
+ return & fs.PathError {
390
+ Op : "rmdir" ,
391
+ Path : path ,
392
+ Err : & textproto.Error {
393
+ Code : ftp .StatusFile ,
394
+ Msg : "not a directory" ,
395
+ },
396
+ }
397
+ }
378
398
if err := conn .RemoveDir (relpath (path )); err != nil {
379
399
return err
380
400
}
381
401
f .clearPath (path )
382
402
return nil
383
- }))
403
+ })
404
+ var tpe * textproto.Error
405
+ if errors .As (err , & tpe ) && tpe .Code == ftp .StatusFileUnavailable {
406
+ log .Debugf ("%s is unavailable" , path )
407
+ if _ , ec := f .getEntry (path ); ec == 0 {
408
+ return - fuse .ENOTEMPTY
409
+ }
410
+ }
411
+ return f .errToFuseErr (err )
384
412
}
385
413
386
414
// Truncate will truncate the given file to a certain size using a STOR command
@@ -390,7 +418,7 @@ func (f *fuseImpl) Truncate(path string, size int64, fh uint64) int {
390
418
var fe * info
391
419
var errCode int
392
420
if fh == math .MaxUint64 {
393
- fe , _ , errCode = f .openHandle (path , false , false )
421
+ fe , _ , errCode = f .openHandle (path , fuse . O_WRONLY )
394
422
defer f .delete (fe .fh )
395
423
} else {
396
424
fe , errCode = f .loadHandle (fh )
@@ -543,6 +571,8 @@ func (f *fuseImpl) errToFuseErr(err error) int {
543
571
return - fuse .EHOSTUNREACH
544
572
case ftp .StatusBadFileName :
545
573
return - fuse .EINVAL
574
+ case ftp .StatusFileUnavailable :
575
+ return - fuse .ENOENT
546
576
}
547
577
}
548
578
em := err .Error ()
@@ -611,7 +641,7 @@ func (f *fuseImpl) loadHandle(fh uint64) (*info, int) {
611
641
return fe , 0
612
642
}
613
643
614
- func (f * fuseImpl ) openHandle (path string , create , append bool ) (nfe * info , e * ftp.Entry , errCode int ) {
644
+ func (f * fuseImpl ) openHandle (path string , flags int ) (nfe * info , e * ftp.Entry , errCode int ) {
615
645
f .RLock ()
616
646
shuttingDown := f .shuttingDown
617
647
f .RUnlock ()
@@ -632,7 +662,7 @@ func (f *fuseImpl) openHandle(path string, create, append bool) (nfe *info, e *f
632
662
633
663
if e , err = conn .GetEntry (relpath (path )); err != nil {
634
664
errCode = f .errToFuseErr (err )
635
- if ! (create && errCode == - fuse .ENOENT ) {
665
+ if ! (flags & fuse . O_CREAT == fuse . O_CREAT && errCode == - fuse .ENOENT ) {
636
666
return nil , nil , errCode
637
667
}
638
668
@@ -645,6 +675,10 @@ func (f *fuseImpl) openHandle(path string, create, append bool) (nfe *info, e *f
645
675
Type : ftp .EntryTypeFile ,
646
676
Time : time .Now (),
647
677
}
678
+ } else {
679
+ if flags & (fuse .O_RDWR | fuse .O_WRONLY ) != 0 && e .Type == ftp .EntryTypeFolder {
680
+ return nil , nil , - fuse .EISDIR
681
+ }
648
682
}
649
683
650
684
f .Lock ()
@@ -657,7 +691,7 @@ func (f *fuseImpl) openHandle(path string, create, append bool) (nfe *info, e *f
657
691
conn : conn ,
658
692
entry : * e ,
659
693
}
660
- if append {
694
+ if flags & fuse . O_APPEND == fuse . O_APPEND {
661
695
nfe .wof = e .Size
662
696
}
663
697
f .current [fh ] = nfe
0 commit comments