Switch getattr / statfs to an object oriented interface.
This commit is contained in:
parent
4158d7b0f7
commit
0a3be77f65
5 changed files with 154 additions and 112 deletions
14
ChangeLog
14
ChangeLog
|
|
@ -1,3 +1,9 @@
|
||||||
|
2006-05-28 Csaba Henk <csaba.henk@creo.hu>
|
||||||
|
* Switch getattr / statfs to an object oriented interface:
|
||||||
|
- Revert the addition of the statvfs method.
|
||||||
|
- Implement compat conversion for old getattr / statfs
|
||||||
|
results.
|
||||||
|
|
||||||
2006-05-27 Csaba Henk <csaba.henk@creo.hu>
|
2006-05-27 Csaba Henk <csaba.henk@creo.hu>
|
||||||
* setup.py related fixes:
|
* setup.py related fixes:
|
||||||
- fix missing installation of fuse.py
|
- fix missing installation of fuse.py
|
||||||
|
|
@ -19,7 +25,7 @@
|
||||||
deprecated, keep statfs useable via statfs -> statvfs conversion
|
deprecated, keep statfs useable via statfs -> statvfs conversion
|
||||||
|
|
||||||
2006-05-24 Csaba Henk <csaba.henk@creo.hu>
|
2006-05-24 Csaba Henk <csaba.henk@creo.hu>
|
||||||
* Revamp fs initialization code.
|
* Revamp fs initialization code:
|
||||||
- Get rid of both of the kopts/lopts and the fuse_opt stuff,
|
- Get rid of both of the kopts/lopts and the fuse_opt stuff,
|
||||||
just keep opts in a dict and assemble a simple argc/argv pair
|
just keep opts in a dict and assemble a simple argc/argv pair
|
||||||
from that. This means that for all supported API versions we can
|
from that. This means that for all supported API versions we can
|
||||||
|
|
@ -36,12 +42,12 @@
|
||||||
- Fix indetation, uniformize look.
|
- Fix indetation, uniformize look.
|
||||||
|
|
||||||
2006-05-23 Csaba Henk <csaba.henk@creo.hu>
|
2006-05-23 Csaba Henk <csaba.henk@creo.hu>
|
||||||
* Fix statfs index mismatch in xmp.py.
|
* Fix statfs index mismatch in xmp.py:
|
||||||
* Rebase build system on pkg-config.
|
* Rebase build system on pkg-config:
|
||||||
- Credits: setup.py based on that of shout-python (python bindings to
|
- Credits: setup.py based on that of shout-python (python bindings to
|
||||||
libshout, part of the icecast project)
|
libshout, part of the icecast project)
|
||||||
* Update code so that it can be compiled against FUSE libs with API from
|
* Update code so that it can be compiled against FUSE libs with API from
|
||||||
21 to 26
|
21 to 26:
|
||||||
- Credits: aggregated from contributions, code snippets and ideas of
|
- Credits: aggregated from contributions, code snippets and ideas of
|
||||||
Simon Barner, Csaba Henk, Roman Shterenzon and Miklos Szeredi
|
Simon Barner, Csaba Henk, Roman Shterenzon and Miklos Szeredi
|
||||||
* Result of argument type check was ignored in FuseInvalidate(), fix
|
* Result of argument type check was ignored in FuseInvalidate(), fix
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,34 @@ routine (that's a short piece of code). However, you are encouraged to
|
||||||
switch to the new parsing interface, which serves you with easy but
|
switch to the new parsing interface, which serves you with easy but
|
||||||
powerful commandline parsing.
|
powerful commandline parsing.
|
||||||
|
|
||||||
|
We also changed the ``getattr`` and ``statfs`` fs methods.
|
||||||
|
We switched to an object oriented interface. Instead of returning a
|
||||||
|
sequence, you have to return an object with appropriate attributes
|
||||||
|
(if any of them is lacking, the fs user will get an ``EINVAL``).
|
||||||
|
For ``getattr``, the attributes are just like those of the return
|
||||||
|
value of ``os.stat()``: ``st_mode``, ``st_ino``, ... For ``statfs``,
|
||||||
|
the attributes are just like those of the return value of ``os.statvfs()``:
|
||||||
|
``f_bsize``, ``f_frsize``, ... [#]_
|
||||||
|
|
||||||
|
If you start from scratch (ie., you are not passing on an ``os.stat()`` or
|
||||||
|
``os.statvfs()`` result), you can use the auxiliary classes ``fuse.Stat`` and
|
||||||
|
``fuse.StatVFS`` for instantiating appropriate objects. For ``fuse.Stat``, you
|
||||||
|
have to define each of these attributes, for ``fuse.StatVfs`` they are initated
|
||||||
|
with a 0 default value [#]_.
|
||||||
|
|
||||||
|
.. _statvfs: http://docs.python.org/lib/module-statvfs.html
|
||||||
|
|
||||||
.. [#] We follow the convention that we refer to instance attributes like
|
.. [#] We follow the convention that we refer to instance attributes like
|
||||||
``Klass#attr``. If it's a method, we'll use ``Klass#meth()``.
|
``Klass#attr``. If it's a method, we'll use ``Klass#meth()``.
|
||||||
|
|
||||||
|
.. [#] Traditionally, ``os.stat()`` and ``os.statvfs()`` returned tuples.
|
||||||
|
Since Python 2.2, they return dedicated object which both implement the
|
||||||
|
sequence protocol and have the aforementioned attributes (when you print
|
||||||
|
them, they look like a tuple).
|
||||||
|
|
||||||
|
.. [#] We might go stricter and leave some of the ``statfs`` attributes
|
||||||
|
undef'd.
|
||||||
|
|
||||||
What's on the gain side?
|
What's on the gain side?
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
|
@ -104,11 +129,3 @@ This is what's addressed by the new API.
|
||||||
partially parsed pieces of the FUSE command line to the C code, which
|
partially parsed pieces of the FUSE command line to the C code, which
|
||||||
used these directly in low level functions of the library, getting behind
|
used these directly in low level functions of the library, getting behind
|
||||||
the main commandline parsing routine of the FUSE lib with no real reason.
|
the main commandline parsing routine of the FUSE lib with no real reason.
|
||||||
|
|
||||||
Anything else?
|
|
||||||
--------------
|
|
||||||
|
|
||||||
We deprecated the ``statfs()`` method (which was to return a tuple containing
|
|
||||||
some fs characteristics, in a somewhat ad hoc order). Instead of that, you are
|
|
||||||
suggested to implement ``statvfs()`` which is to return a tuple of the same
|
|
||||||
layout as of ``os.statvfs()`` return values.
|
|
||||||
|
|
|
||||||
|
|
@ -72,34 +72,31 @@ OUT: \
|
||||||
static int
|
static int
|
||||||
getattr_func(const char *path, struct stat *st)
|
getattr_func(const char *path, struct stat *st)
|
||||||
{
|
{
|
||||||
int i;
|
PyObject *tmp;
|
||||||
PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
|
PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
|
||||||
|
|
||||||
PROLOGUE
|
PROLOGUE
|
||||||
|
|
||||||
if (!PySequence_Check(v))
|
#define fetchattr(st, attr) \
|
||||||
goto OUT_DECREF;
|
if (!(tmp = PyObject_GetAttrString(v, #attr))) \
|
||||||
|
goto OUT_DECREF; \
|
||||||
|
if (!(PyInt_Check(tmp) || PyLong_Check(tmp))) \
|
||||||
|
goto OUT_DECREF; \
|
||||||
|
st->attr = PyInt_AsLong(tmp);
|
||||||
|
|
||||||
if(PySequence_Size(v) < 10)
|
fetchattr(st, st_mode);
|
||||||
goto OUT_DECREF;
|
fetchattr(st, st_ino);
|
||||||
|
fetchattr(st, st_dev);
|
||||||
for(i=0; i<10; i++) {
|
fetchattr(st, st_nlink);
|
||||||
PyObject *tmp = PySequence_GetItem(v, i);
|
fetchattr(st, st_uid);
|
||||||
if (!(PyInt_Check(tmp) || PyLong_Check(tmp)))
|
fetchattr(st, st_gid);
|
||||||
goto OUT_DECREF;
|
fetchattr(st, st_size);
|
||||||
}
|
fetchattr(st, st_atime);
|
||||||
|
fetchattr(st, st_mtime);
|
||||||
st->st_mode = PyInt_AsLong(PySequence_GetItem(v, 0));
|
fetchattr(st, st_ctime);
|
||||||
st->st_ino = PyInt_AsLong(PySequence_GetItem(v, 1));
|
|
||||||
st->st_dev = PyInt_AsLong(PySequence_GetItem(v, 2));
|
|
||||||
st->st_nlink = PyInt_AsLong(PySequence_GetItem(v, 3));
|
|
||||||
st->st_uid = PyInt_AsLong(PySequence_GetItem(v, 4));
|
|
||||||
st->st_gid = PyInt_AsLong(PySequence_GetItem(v, 5));
|
|
||||||
st->st_size = PyInt_AsLong(PySequence_GetItem(v, 6));
|
|
||||||
st->st_atime = PyInt_AsLong(PySequence_GetItem(v, 7));
|
|
||||||
st->st_mtime = PyInt_AsLong(PySequence_GetItem(v, 8));
|
|
||||||
st->st_ctime = PyInt_AsLong(PySequence_GetItem(v, 9));
|
|
||||||
|
|
||||||
|
#undef fetchattr
|
||||||
|
|
||||||
/* Fill in fields not provided by Python lstat() */
|
/* Fill in fields not provided by Python lstat() */
|
||||||
st->st_blksize= 4096;
|
st->st_blksize= 4096;
|
||||||
st->st_blocks= (st->st_size + 511)/512;
|
st->st_blocks= (st->st_size + 511)/512;
|
||||||
|
|
@ -118,7 +115,7 @@ readlink_func(const char *path, char *link, size_t size)
|
||||||
PROLOGUE
|
PROLOGUE
|
||||||
|
|
||||||
if(!PyString_Check(v)) {
|
if(!PyString_Check(v)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto OUT_DECREF;
|
goto OUT_DECREF;
|
||||||
}
|
}
|
||||||
s = PyString_AsString(v);
|
s = PyString_AsString(v);
|
||||||
|
|
@ -374,45 +371,38 @@ static int
|
||||||
statfs_func(const char *dummy, struct statfs *fst)
|
statfs_func(const char *dummy, struct statfs *fst)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int i;
|
PyObject *tmp;
|
||||||
long retvalues[10];
|
|
||||||
PyObject *v = PyObject_CallFunction(statfs_cb, "");
|
PyObject *v = PyObject_CallFunction(statfs_cb, "");
|
||||||
|
|
||||||
PROLOGUE
|
PROLOGUE
|
||||||
|
|
||||||
if (!PySequence_Check(v))
|
#define fetchattr(st, attr) \
|
||||||
goto OUT_DECREF;
|
if (!(tmp = PyObject_GetAttrString(v, #attr))) \
|
||||||
if (PySequence_Size(v) < 10)
|
goto OUT_DECREF; \
|
||||||
goto OUT_DECREF;
|
if (!(PyInt_Check(tmp) || PyLong_Check(tmp))) \
|
||||||
|
goto OUT_DECREF; \
|
||||||
|
st->attr = PyInt_Check(tmp) ? PyInt_AsLong(tmp) : \
|
||||||
|
(PyLong_Check(tmp) ? PyLong_AsLong(tmp) : 0);
|
||||||
|
|
||||||
for(i = 0; i < 10; i++) {
|
|
||||||
PyObject *tmp = PySequence_GetItem(v, i);
|
|
||||||
retvalues[i] = PyInt_Check(tmp) ? PyInt_AsLong(tmp) :
|
|
||||||
(PyLong_Check(tmp) ? PyLong_AsLong(tmp) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
fetchattr(fst, f_bsize);
|
||||||
* To be completely theoretically correct, we should identify
|
|
||||||
* the indices via Python's statvfs module, but these indices
|
|
||||||
* are unlikely to change, so we just use direct idexing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fst->f_bsize = retvalues[0];
|
|
||||||
#if FUSE_VERSION >= 25
|
#if FUSE_VERSION >= 25
|
||||||
fst->f_frsize = retvalues[1];
|
fetchattr(fst, f_frsize);
|
||||||
#endif
|
#endif
|
||||||
fst->f_blocks = retvalues[2];
|
fetchattr(fst, f_blocks);
|
||||||
fst->f_bfree = retvalues[3];
|
fetchattr(fst, f_bfree);
|
||||||
fst->f_bavail = retvalues[4];
|
fetchattr(fst, f_bavail);
|
||||||
fst->f_files = retvalues[5];
|
fetchattr(fst, f_files);
|
||||||
fst->f_ffree = retvalues[6];
|
fetchattr(fst, f_ffree);
|
||||||
#if FUSE_VERSION >= 25
|
#if FUSE_VERSION >= 25
|
||||||
fst->f_favail = retvalues[7];
|
fetchattr(fst, f_favail);
|
||||||
fst->f_flag = retvalues[8];
|
fetchattr(fst, f_flag);
|
||||||
fst->f_namemax = retvalues[9];
|
fetchattr(fst, f_namemax);
|
||||||
#else
|
#else
|
||||||
fst->f_namelen = retvalues[9];
|
fetchattr(fst, f_namelen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#undef fetchattr
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
|
@ -496,7 +486,7 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
|
||||||
"getattr", "readlink", "getdir", "mknod",
|
"getattr", "readlink", "getdir", "mknod",
|
||||||
"mkdir", "unlink", "rmdir", "symlink", "rename",
|
"mkdir", "unlink", "rmdir", "symlink", "rename",
|
||||||
"link", "chmod", "chown", "truncate", "utime",
|
"link", "chmod", "chown", "truncate", "utime",
|
||||||
"open", "read", "write", "release", "statvfs", "fsync",
|
"open", "read", "write", "release", "statfs", "fsync",
|
||||||
"fuse_args", "multithreaded", NULL};
|
"fuse_args", "multithreaded", NULL};
|
||||||
|
|
||||||
memset(&op, 0, sizeof(op));
|
memset(&op, 0, sizeof(op));
|
||||||
|
|
|
||||||
98
fuse.py
98
fuse.py
|
|
@ -405,7 +405,7 @@ class FuseOptParse(OptionParser):
|
||||||
##########
|
##########
|
||||||
|
|
||||||
|
|
||||||
class ErrnoWrapper:
|
class ErrnoWrapper(object):
|
||||||
|
|
||||||
def __init__(self, func):
|
def __init__(self, func):
|
||||||
self.func = func
|
self.func = func
|
||||||
|
|
@ -419,6 +419,35 @@ class ErrnoWrapper:
|
||||||
return -detail
|
return -detail
|
||||||
|
|
||||||
|
|
||||||
|
class Stat(object):
|
||||||
|
"""
|
||||||
|
Auxiliary class which can be filled up stat attributes.
|
||||||
|
The attributes are undefined by default.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class StatVfs(object):
|
||||||
|
"""
|
||||||
|
Auxiliary class which can be filled up statvfs attributes.
|
||||||
|
The attributes are 0 by default.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.f_bsize = 0
|
||||||
|
self.f_frsize = 0
|
||||||
|
self.f_blocks = 0
|
||||||
|
self.f_bfree = 0
|
||||||
|
self.f_bavail = 0
|
||||||
|
self.f_files = 0
|
||||||
|
self.f_ffree = 0
|
||||||
|
self.f_favail = 0
|
||||||
|
self.f_flag = 0
|
||||||
|
self.f_namemax = 0
|
||||||
|
|
||||||
|
|
||||||
class Fuse(object):
|
class Fuse(object):
|
||||||
"""
|
"""
|
||||||
Python interface to FUSE.
|
Python interface to FUSE.
|
||||||
|
|
@ -427,7 +456,7 @@ class Fuse(object):
|
||||||
_attrs = ['getattr', 'readlink', 'getdir', 'mknod', 'mkdir',
|
_attrs = ['getattr', 'readlink', 'getdir', 'mknod', 'mkdir',
|
||||||
'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
|
'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
|
||||||
'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release',
|
'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release',
|
||||||
'statvfs', 'fsync']
|
'statfs', 'fsync']
|
||||||
|
|
||||||
fusage = "%prog [mountpoint] [options]"
|
fusage = "%prog [mountpoint] [options]"
|
||||||
|
|
||||||
|
|
@ -436,35 +465,6 @@ class Fuse(object):
|
||||||
self.fuse_args = \
|
self.fuse_args = \
|
||||||
kw.has_key('fuse_args') and kw.pop('fuse_args') or FuseArgs()
|
kw.has_key('fuse_args') and kw.pop('fuse_args') or FuseArgs()
|
||||||
|
|
||||||
# Convert statfs to the new, Python statvfs compatible statvfs method
|
|
||||||
if not hasattr(self, 'statvfs') and hasattr(self, 'statfs'):
|
|
||||||
def statvfs(self):
|
|
||||||
import statvfs
|
|
||||||
|
|
||||||
if not compat_0_1:
|
|
||||||
from warnings import warn
|
|
||||||
warn("`statfs' fs method is deprecated, use `statvfs' instead",
|
|
||||||
DeprecationWarning, stacklevel=1)
|
|
||||||
|
|
||||||
oout = self.statfs()
|
|
||||||
lo = len(oout)
|
|
||||||
|
|
||||||
nout = [0] * 10
|
|
||||||
nout[statvfs.F_BSIZE] = oout[0] # 0
|
|
||||||
nout[statvfs.F_FRSIZE] = oout[lo >= 8 and 7 or 0] # 1
|
|
||||||
nout[statvfs.F_BLOCKS] = oout[1] # 2
|
|
||||||
nout[statvfs.F_BFREE] = oout[2] # 3
|
|
||||||
nout[statvfs.F_BAVAIL] = oout[3] # 4
|
|
||||||
nout[statvfs.F_FILES] = oout[4] # 5
|
|
||||||
nout[statvfs.F_FFREE] = oout[5] # 6
|
|
||||||
nout[statvfs.F_FAVAIL] = lo >= 9 and oout[8] or 0 # 7
|
|
||||||
nout[statvfs.F_FLAG] = lo >= 10 and oout[9] or 0 # 8
|
|
||||||
nout[statvfs.F_NAMEMAX] = oout[6] # 9
|
|
||||||
|
|
||||||
return nout
|
|
||||||
|
|
||||||
self.__class__.statvfs = statvfs
|
|
||||||
|
|
||||||
if compat_0_1:
|
if compat_0_1:
|
||||||
return self.__init_0_1__(*args, **kw)
|
return self.__init_0_1__(*args, **kw)
|
||||||
|
|
||||||
|
|
@ -506,7 +506,11 @@ class Fuse(object):
|
||||||
|
|
||||||
for a in self._attrs:
|
for a in self._attrs:
|
||||||
if hasattr(self,a):
|
if hasattr(self,a):
|
||||||
d[a] = ErrnoWrapper(getattr(self, a))
|
b = a
|
||||||
|
if compat_0_1:
|
||||||
|
if self.compatmap.has_key(a):
|
||||||
|
b = self.compatmap[a]
|
||||||
|
d[a] = ErrnoWrapper(getattr(self, b))
|
||||||
|
|
||||||
domount = True
|
domount = True
|
||||||
if not args:
|
if not args:
|
||||||
|
|
@ -614,8 +618,34 @@ class Fuse(object):
|
||||||
if hasattr(self, 'debug'):
|
if hasattr(self, 'debug'):
|
||||||
self.fuse_args.add('debug')
|
self.fuse_args.add('debug')
|
||||||
|
|
||||||
if hasattr(self,'allow_other'):
|
if hasattr(self, 'allow_other'):
|
||||||
self.fuse_args.add('allow_other')
|
self.fuse_args.add('allow_other')
|
||||||
|
|
||||||
if hasattr(self,'kernel_cache'):
|
if hasattr(self, 'kernel_cache'):
|
||||||
self.fuse_args.add('kernel_cache')
|
self.fuse_args.add('kernel_cache')
|
||||||
|
|
||||||
|
def tuple2stat(self, *a):
|
||||||
|
from os import stat_result
|
||||||
|
|
||||||
|
return stat_result(self.getattr(*a))
|
||||||
|
|
||||||
|
def statfs2statvfs(self, *a):
|
||||||
|
|
||||||
|
oout = self.statfs(*a)
|
||||||
|
lo = len(oout)
|
||||||
|
|
||||||
|
svf = StatVfs()
|
||||||
|
svf.f_bsize = oout[0] # 0
|
||||||
|
svf.f_frsize = oout[lo >= 8 and 7 or 0] # 1
|
||||||
|
svf.f_blocks = oout[1] # 2
|
||||||
|
svf.f_bfree = oout[2] # 3
|
||||||
|
svf.f_bavail = oout[3] # 4
|
||||||
|
svf.f_files = oout[4] # 5
|
||||||
|
svf.f_ffree = oout[5] # 6
|
||||||
|
svf.f_favail = lo >= 9 and oout[8] or 0 # 7
|
||||||
|
svf.f_flag = lo >= 10 and oout[9] or 0 # 8
|
||||||
|
svf.f_namemax = oout[6] # 9
|
||||||
|
|
||||||
|
return svf
|
||||||
|
|
||||||
|
compatmap = { 'getattr' : 'tuple2stat', 'statfs' : 'statfs2statvfs' }
|
||||||
|
|
|
||||||
27
xmp.py
27
xmp.py
|
|
@ -123,24 +123,23 @@ class Xmp(Fuse):
|
||||||
print "xmp.py:Xmp:release: %s %s" % (path, flags)
|
print "xmp.py:Xmp:release: %s %s" % (path, flags)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def statvfs(self):
|
def statfs(self):
|
||||||
"""
|
"""
|
||||||
Should return a tuple like those returned by os.statvfs().
|
Should return an object with statvfs attributes (f_bsize, f_frsize...).
|
||||||
|
Eg., the return value of os.statvfs() is such a thing (since py 2.2).
|
||||||
|
If you are not reusing an existing statvfs object, start with
|
||||||
|
fuse.StatVFS(), and define the attributes.
|
||||||
|
|
||||||
Feel free to set any of the above values to 0, which tells
|
To provide usable information (ie., you want sensible df(1)
|
||||||
the kernel that the info is not available.
|
output, you are suggested to specify the following attributes:
|
||||||
|
|
||||||
However, to provide usable information (ie., you want sensible df(1)
|
- f_bsize - preferred size of file blocks, in bytes
|
||||||
output, you are suggested to specify at least the following 7 values
|
- f_frsize - fundamental size of file blcoks, in bytes
|
||||||
(in that order):
|
|
||||||
|
|
||||||
- blocksize - preferred size of file blocks, in bytes
|
|
||||||
- frsize - fundamental size of file blcoks, in bytes
|
|
||||||
[if you have no idea, use the same as blocksize]
|
[if you have no idea, use the same as blocksize]
|
||||||
- totalblocks - total number of blocks in the filesystem
|
- f_blocks - total number of blocks in the filesystem
|
||||||
- freeblocks - number of free blocks
|
- f_bfree - number of free blocks
|
||||||
- totalfiles - total number of file inodes
|
- f_files - total number of file inodes
|
||||||
- freefiles - nunber of free file inodes
|
- f_ffree - nunber of free file inodes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return os.statvfs(self.root)
|
return os.statvfs(self.root)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue