244 lines
5.6 KiB
Go
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,
|
|
}
|
|
}
|