package fs import ( "io" "os" "syscall" "github.com/barakmich/kubelwagen" "github.com/hanwen/go-fuse/fuse" ) func (fs *LocalFs) handleFile(r *kubelwagen.Request) *kubelwagen.Response { switch r.Method { case kubelwagen.MethodOpen: return fs.open(r) case kubelwagen.MethodCreate: return fs.create(r) case kubelwagen.MethodFileRead: return fs.fileread(r) case kubelwagen.MethodFileWrite: return fs.filewrite(r) case kubelwagen.MethodFileRelease: return fs.filerelease(r) case kubelwagen.MethodFileFlock: return fs.fileflock(r) case kubelwagen.MethodFileGetAttr: return fs.filegetattr(r) case kubelwagen.MethodFileFsync: return fs.filefsync(r) case kubelwagen.MethodFileTruncate: return fs.filetruncate(r) case kubelwagen.MethodFileChown: return fs.filechown(r) case kubelwagen.MethodFileChmod: return fs.filechmod(r) case kubelwagen.MethodFileAllocate: return fs.fileallocate(r) default: return &kubelwagen.Response{ ID: r.ID, Code: fuse.ENOSYS, } } } func (fs *LocalFs) open(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() fh := fs.nextfile fs.nextfile++ f, err := os.OpenFile(fs.getPath(r), int(r.Flags), 0) if err != nil { return kubelwagen.ErrorResp(r, err) } fs.openfiles[fh] = f return &kubelwagen.Response{ ID: r.ID, Code: fuse.OK, FileHandle: fh, } } func (fs *LocalFs) create(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() fh := fs.nextfile fs.nextfile++ f, err := os.OpenFile(fs.getPath(r), int(r.Flags)|os.O_CREATE, os.FileMode(r.Mode)) if err != nil { return kubelwagen.ErrorResp(r, err) } fs.openfiles[fh] = f return &kubelwagen.Response{ ID: r.ID, Code: fuse.OK, FileHandle: fh, } } func (fs *LocalFs) fileflock(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } code := fuse.ToStatus(syscall.Flock(int(f.Fd()), int(r.Flags))) return &kubelwagen.Response{ ID: r.ID, Code: code, FileHandle: r.FileHandle, } } func (fs *LocalFs) filegetattr(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } var at *fuse.Attr fi, err := f.Stat() code := fuse.ToStatus(err) if err == nil { at = fuse.ToAttr(fi) } return &kubelwagen.Response{ ID: r.ID, Code: code, FileHandle: r.FileHandle, Stat: at, } } func (fs *LocalFs) filefsync(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } code := fuse.ToStatus(f.Sync()) return &kubelwagen.Response{ ID: r.ID, Code: code, FileHandle: r.FileHandle, } } func (fs *LocalFs) filetruncate(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } code := fuse.ToStatus(syscall.Ftruncate(int(f.Fd()), int64(r.Size))) return &kubelwagen.Response{ ID: r.ID, Code: code, FileHandle: r.FileHandle, } } func (fs *LocalFs) filechown(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } code := fuse.ToStatus(f.Chown(int(r.UID), int(r.GID))) return &kubelwagen.Response{ ID: r.ID, Code: code, FileHandle: r.FileHandle, } } func (fs *LocalFs) filechmod(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } code := fuse.ToStatus(f.Chmod(os.FileMode(r.Mode))) return &kubelwagen.Response{ ID: r.ID, Code: code, FileHandle: r.FileHandle, } } //TODO(barakmich): Linux only; support OS X func (fs *LocalFs) fileallocate(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } code := fuse.ToStatus(syscall.Fallocate(int(f.Fd()), r.Mode, r.Offset, int64(r.Size))) return &kubelwagen.Response{ ID: r.ID, Code: code, FileHandle: r.FileHandle, } } func (fs *LocalFs) fileread(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } buf := make([]byte, r.Size) n, err := f.ReadAt(buf, r.Offset) if err != nil && err != io.EOF { return kubelwagen.ErrorResp(r, err) } buf = buf[:n] return &kubelwagen.Response{ ID: r.ID, Code: fuse.OK, FileHandle: r.FileHandle, Data: buf, } } func (fs *LocalFs) filewrite(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } n, err := f.WriteAt(r.Data, r.Offset) return &kubelwagen.Response{ ID: r.ID, Code: fuse.ToStatus(err), FileHandle: r.FileHandle, WriteSize: n, } } func (fs *LocalFs) filerelease(r *kubelwagen.Request) *kubelwagen.Response { fs.Lock() defer fs.Unlock() f, ok := fs.openfiles[r.FileHandle] if !ok { return kubelwagen.ErrorResp(r, os.ErrClosed) } err := f.Close() delete(fs.openfiles, r.FileHandle) return &kubelwagen.Response{ ID: r.ID, Code: fuse.ToStatus(err), FileHandle: r.FileHandle, } }