Added support for the rest of FUSE methods.

(flush, fgetattr, ftruncate, access, getxattr, listxattr, setxattr,
removexattr)
This commit is contained in:
dzsekijo 2006-06-04 14:35:45 +00:00
parent 54d8d40891
commit 3c340d7470
4 changed files with 225 additions and 23 deletions

View file

@ -1,3 +1,8 @@
2006-06-04 Csaba Henk <csaba.henk@creo.hu>
* Added support for the rest of FUSE methods:
flush, fgetattr, ftruncate, access, getxattr, listxattr, setxattr,
removexattr.
2006-06-01 Csaba Henk <csaba.henk@creo.hu>
* Distillate Fuse instance -> <file> method proxying code into a
dedicated class.

View file

@ -34,8 +34,9 @@ static PyObject *getattr_cb=NULL, *readlink_cb=NULL, *readdir_cb=NULL,
*chown_cb=NULL, *truncate_cb=NULL, *utime_cb=NULL,
*open_cb=NULL, *read_cb=NULL, *write_cb=NULL, *release_cb=NULL,
*statfs_cb=NULL, *fsync_cb=NULL, *create_cb=NULL, *opendir_cb=NULL,
*releasedir_cb=NULL, *fsyncdir_cb=NULL
;
*releasedir_cb=NULL, *fsyncdir_cb=NULL, *flush_cb=NULL, *ftruncate_cb=NULL,
*fgetattr_cb=NULL, *getxattr_cb=NULL, *listxattr_cb=NULL, *setxattr_cb=NULL,
*removexattr_cb=NULL, *access_cb=NULL;
static PyObject *Py_FuseError;
@ -103,10 +104,9 @@ fi_to_py(struct fuse_file_info *fi)
*/
static int
getattr_func(const char *path, struct stat *st)
getattr_backend(struct stat *st, PyObject *v)
{
PyObject *tmp;
PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
PROLOGUE
@ -159,6 +159,24 @@ getattr_func(const char *path, struct stat *st)
EPILOGUE
}
static int
getattr_func(const char *path, struct stat *st)
{
PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
return getattr_backend(st, v);
}
#if FUSE_VERSION >= 25
static int
fgetattr_func(const char *path, struct stat *st, struct fuse_file_info *fi)
{
PyObject *v = PYO_CALLWITHFI(fi, fgetattr_cb, s, path);
return getattr_backend(st, v);
}
#endif
static int
readlink_func(const char *path, char *link, size_t size)
{
@ -374,14 +392,25 @@ chown_func(const char *path, uid_t u, gid_t g)
}
static int
truncate_func(const char *path, off_t o)
truncate_func(const char *path, off_t length)
{
PyObject *v = PyObject_CallFunction(truncate_cb, "sK", path, o);
PyObject *v = PyObject_CallFunction(truncate_cb, "sK", path, length);
PROLOGUE
EPILOGUE
}
#if FUSE_VERSION >= 25
static int
ftruncate_func(const char *path, off_t length, struct fuse_file_info *fi)
{
PyObject *v = PYO_CALLWITHFI(fi, ftruncate_cb, sK, path, length);
PROLOGUE
EPILOGUE
}
#endif
static int
utime_func(const char *path, struct utimbuf *u)
{
@ -540,6 +569,119 @@ fsync_func(const char *path, int datasync)
EPILOGUE
}
#if FUSE_VERSION >= 22
static int
flush_func(const char *path, struct fuse_file_info *fi)
#else
static int
flush_func(const char *path)
#endif
{
PyObject *v = PYO_CALLWITHFI(fi, flush_cb, s, path);
PROLOGUE
EPILOGUE
}
static int
getxattr_func(const char *path, const char *name, char *value, size_t size)
{
PyObject *v = PyObject_CallFunction(getxattr_cb, "ssi", path, name,
size);
PROLOGUE
if(PyString_Check(v)) {
if(PyString_Size(v) > size)
goto OUT_DECREF;
memcpy(value, PyString_AsString(v), PyString_Size(v));
ret = PyString_Size(v);
}
EPILOGUE
}
static int
listxattr_func(const char *path, char *list, size_t size)
{
PyObject *v = PyObject_CallFunction(listxattr_cb, "si", path, size);
PyObject *iter, *w;
char *lx = list;
PROLOGUE
iter = PyObject_GetIter(v);
if(!iter) {
PyErr_Print();
goto OUT_DECREF;
}
for (;;) {
int ilen;
w = PyIter_Next(iter);
if (!w) {
ret = lx - list;
break;
}
if (!PyString_Check(w)) {
Py_DECREF(w);
break;
}
ilen = PyString_Size(w);
if (lx - list + ilen >= size) {
Py_DECREF(w);
break;
}
strncpy(lx, PyString_AsString(w), ilen + 1);
lx += ilen + 1;
Py_DECREF(w);
}
Py_DECREF(iter);
if (PyErr_Occurred()) {
PyErr_Print();
ret = -EINVAL;
}
EPILOGUE
}
static int
setxattr_func(const char *path, const char *name, const char *value,
size_t size, int flags)
{
PyObject *v = PyObject_CallFunction(setxattr_cb, "sss#i", path, name,
value, size, flags);
PROLOGUE
EPILOGUE
}
static int
removexattr_func(const char *path, const char *name)
{
PyObject *v = PyObject_CallFunction(removexattr_cb, "ss", path, name);
PROLOGUE
EPILOGUE
}
#if FUSE_VERSION >= 25
static int
access_func(const char *path, int mask)
{
PyObject *v = PyObject_CallFunction(access_cb, "si", path, mask);
PROLOGUE
EPILOGUE
}
#endif
static void
process_cmd(struct fuse *f, struct fuse_cmd *cmd, void *data)
{
@ -603,18 +745,29 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
"mkdir", "unlink", "rmdir", "symlink", "rename",
"link", "chmod", "chown", "truncate", "utime",
"open", "read", "write", "release", "statfs", "fsync",
"create", "opendir", "releasedir", "fsyncdir",
"fuse_args", "multithreaded", NULL};
"create", "opendir", "releasedir", "fsyncdir", "flush",
"ftruncate", "fgetattr", "getxattr", "listxattr", "setxattr",
"removexattr", "access", "fuse_args", "multithreaded", NULL
};
memset(&op, 0, sizeof(op));
if (!PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOOOOOOOOOOOOOOOOOOOOi",
kwlist, &getattr_cb, &readlink_cb, &readdir_cb, &mknod_cb,
&mkdir_cb, &unlink_cb, &rmdir_cb, &symlink_cb, &rename_cb,
&link_cb, &chmod_cb, &chown_cb, &truncate_cb, &utime_cb,
&open_cb, &read_cb, &write_cb, &release_cb, &statfs_cb, &fsync_cb,
&create_cb, &opendir_cb, &releasedir_cb, &fsyncdir_cb,
&fargseq, &multithreaded))
if (!PyArg_ParseTupleAndKeywords(args, kw,
"|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOi",
kwlist, &getattr_cb, &readlink_cb,
&readdir_cb, &mknod_cb, &mkdir_cb,
&unlink_cb, &rmdir_cb, &symlink_cb,
&rename_cb, &link_cb, &chmod_cb,
&chown_cb, &truncate_cb, &utime_cb,
&open_cb, &read_cb, &write_cb,
&release_cb, &statfs_cb, &fsync_cb,
&create_cb, &opendir_cb,
&releasedir_cb, &fsyncdir_cb,
&flush_cb, &ftruncate_cb,
&fgetattr_cb, &getxattr_cb,
&listxattr_cb, &setxattr_cb,
&removexattr_cb, &access_cb,
&fargseq, &multithreaded))
return NULL;
#define DO_ONE_ATTR_AS(fname, pyname) \
@ -654,7 +807,15 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
DO_ONE_ATTR(release);
DO_ONE_ATTR(statfs);
DO_ONE_ATTR(fsync);
DO_ONE_ATTR(flush);
DO_ONE_ATTR(getxattr);
DO_ONE_ATTR(listxattr);
DO_ONE_ATTR(setxattr);
DO_ONE_ATTR(removexattr);
#if FUSE_VERSION >= 25
DO_ONE_ATTR(ftruncate);
DO_ONE_ATTR(fgetattr);
DO_ONE_ATTR(access);
DO_ONE_ATTR(create);
#endif

View file

@ -488,7 +488,9 @@ class Fuse(object):
_attrs = ['getattr', 'readlink', 'readdir', 'mknod', 'mkdir',
'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release',
'statfs', 'fsync', 'create', 'opendir', 'releasedir', 'fsyncdir']
'statfs', 'fsync', 'create', 'opendir', 'releasedir', 'fsyncdir',
'flush', 'fgetattr', 'ftruncate', 'getxattr', 'listxattr',
'setxattr', 'removexattr', 'access']
fusage = "%prog [mountpoint] [options]"
@ -637,7 +639,8 @@ class Fuse(object):
_add_class_type = classmethod(_add_class_type)
Methproxy._add_class_type('file', ('open', 'create'),
('read', 'write', 'fsync', 'release'))
('read', 'write', 'fsync', 'release', 'flush',
'fgetattr', 'ftruncate'))
Methproxy._add_class_type('dir', ('opendir',),
[ m + 'dir' for m in 'read', 'fsync', 'release'])

45
xmp.py
View file

@ -102,6 +102,29 @@ class Xmp(Fuse):
def utime(self, path, times):
return os.utime(self.root + path, times)
def access(self, path, mode):
if not os.access(self.root + path, mode):
import errno
return -errno.EACCES
# This is how we could add a stub extended attribute interface...
#
# def getxattr(self, path, name, size):
# val = name.swapcase() + '@' + path
# if size == 0:
# # We are asked for size of the value.
# return len(val)
# return val
#
# def listxattr(self, path, size):
# # We use the "user" namespace to please XFS utils
# aa = ["user." + a for a in ("foo", "bar")]
# if size == 0:
# # We are asked for size of the attr list, ie. joint size of attrs
# # plus null separators.
# return len("".join(aa)) + len(aa)
# return aa
def statfs(self):
"""
Should return an object with statvfs attributes (f_bsize, f_frsize...).
@ -131,28 +154,38 @@ class Xmp(Fuse):
server = self
class XmpFile:
def __init__(self, path, flags, *mode):
self.file = os.fdopen(os.open(server.root + path, flags, *mode),
flag2mode(flags))
self.fd = self.file.fileno()
def read(self, length, offset):
self.file.seek(offset)
return self.file.read(length)
def write(self, buf, offset):
self.file.seek(offset)
self.file.write(buf)
return len(buf)
def release(self, flags):
self.file.close()
def fsync(self, isfsyncfile):
if isfsyncfile and hasattr(os, 'fdatasync'):
os.fdatasync(self.file.fileno())
os.fdatasync(self.fd)
else:
os.fsync(self.file.fileno())
os.fsync(self.fd)
def flush(self):
os.close(os.dup(self.fd))
def fgetattr(self):
return os.fstat(self.fd)
def ftruncate(self, len):
os.ftruncate(self.fd, len)
self.file_class = XmpFile