kubelwagen/fs/localfile.go
2018-03-31 16:58:46 -07:00

244 lines
5.6 KiB
Go

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,
}
}