Skip to content

Commit 3d4f686

Browse files
authored
Merge pull request #7 from datawire/thallgren/open-handle
Fix issue with file and directory when opening handle
2 parents b1b6741 + 67edb91 commit 3d4f686

File tree

1 file changed

+44
-10
lines changed

1 file changed

+44
-10
lines changed

pkg/fs/ftp.go

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func (f *fuseImpl) SetAddress(addr netip.AddrPort) error {
148148
// The third argument, the mode bits, are currently ignored
149149
func (f *fuseImpl) Create(path string, flags int, _ uint32) (int, uint64) {
150150
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)
152152
if errCode < 0 {
153153
return errCode, 0
154154
}
@@ -229,14 +229,20 @@ func (f *fuseImpl) Mkdir(path string, mode uint32) int {
229229
err := f.withConn(func(conn *ftp.ServerConn) error {
230230
return conn.MakeDir(relpath(path))
231231
})
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+
}
232238
return f.errToFuseErr(err)
233239
}
234240

235241
// Open ensures checks if the file exists, and if it doesn't, ensure that
236242
// a file of size zero can be created in the server.
237243
func (f *fuseImpl) Open(path string, flags int) (int, uint64) {
238244
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)
240246
if errCode < 0 {
241247
return errCode, 0
242248
}
@@ -247,7 +253,7 @@ func (f *fuseImpl) Open(path string, flags int) (int, uint64) {
247253
// Opendir is like Open but will fail unless the path represents a directory
248254
func (f *fuseImpl) Opendir(path string) (int, uint64) {
249255
log.Debugf("Opendir(%s)", path)
250-
fe, e, errCode := f.openHandle(path, false, false)
256+
fe, e, errCode := f.openHandle(path, fuse.O_RDONLY)
251257
if errCode < 0 {
252258
return errCode, 0
253259
}
@@ -322,7 +328,7 @@ func (f *fuseImpl) Readdir(path string, fill func(name string, stat *fuse.Stat_t
322328
var fe *info
323329
var errCode int
324330
if fh == math.MaxUint64 {
325-
fe, _, errCode = f.openHandle(path, false, false)
331+
fe, _, errCode = f.openHandle(path, fuse.O_RDONLY)
326332
defer f.delete(fe.fh)
327333
} else {
328334
fe, errCode = f.loadHandle(fh)
@@ -374,13 +380,35 @@ func (f *fuseImpl) Rename(oldpath string, newpath string) int {
374380
// Rmdir removes the directory at path. The directory must be empty
375381
func (f *fuseImpl) Rmdir(path string) int {
376382
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+
}
378398
if err := conn.RemoveDir(relpath(path)); err != nil {
379399
return err
380400
}
381401
f.clearPath(path)
382402
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)
384412
}
385413

386414
// 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 {
390418
var fe *info
391419
var errCode int
392420
if fh == math.MaxUint64 {
393-
fe, _, errCode = f.openHandle(path, false, false)
421+
fe, _, errCode = f.openHandle(path, fuse.O_WRONLY)
394422
defer f.delete(fe.fh)
395423
} else {
396424
fe, errCode = f.loadHandle(fh)
@@ -543,6 +571,8 @@ func (f *fuseImpl) errToFuseErr(err error) int {
543571
return -fuse.EHOSTUNREACH
544572
case ftp.StatusBadFileName:
545573
return -fuse.EINVAL
574+
case ftp.StatusFileUnavailable:
575+
return -fuse.ENOENT
546576
}
547577
}
548578
em := err.Error()
@@ -611,7 +641,7 @@ func (f *fuseImpl) loadHandle(fh uint64) (*info, int) {
611641
return fe, 0
612642
}
613643

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) {
615645
f.RLock()
616646
shuttingDown := f.shuttingDown
617647
f.RUnlock()
@@ -632,7 +662,7 @@ func (f *fuseImpl) openHandle(path string, create, append bool) (nfe *info, e *f
632662

633663
if e, err = conn.GetEntry(relpath(path)); err != nil {
634664
errCode = f.errToFuseErr(err)
635-
if !(create && errCode == -fuse.ENOENT) {
665+
if !(flags&fuse.O_CREAT == fuse.O_CREAT && errCode == -fuse.ENOENT) {
636666
return nil, nil, errCode
637667
}
638668

@@ -645,6 +675,10 @@ func (f *fuseImpl) openHandle(path string, create, append bool) (nfe *info, e *f
645675
Type: ftp.EntryTypeFile,
646676
Time: time.Now(),
647677
}
678+
} else {
679+
if flags&(fuse.O_RDWR|fuse.O_WRONLY) != 0 && e.Type == ftp.EntryTypeFolder {
680+
return nil, nil, -fuse.EISDIR
681+
}
648682
}
649683

650684
f.Lock()
@@ -657,7 +691,7 @@ func (f *fuseImpl) openHandle(path string, create, append bool) (nfe *info, e *f
657691
conn: conn,
658692
entry: *e,
659693
}
660-
if append {
694+
if flags&fuse.O_APPEND == fuse.O_APPEND {
661695
nfe.wof = e.Size
662696
}
663697
f.current[fh] = nfe

0 commit comments

Comments
 (0)