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>
|
||||
* setup.py related fixes:
|
||||
- fix missing installation of fuse.py
|
||||
|
|
@ -19,7 +25,7 @@
|
|||
deprecated, keep statfs useable via statfs -> statvfs conversion
|
||||
|
||||
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,
|
||||
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
|
||||
|
|
@ -36,12 +42,12 @@
|
|||
- Fix indetation, uniformize look.
|
||||
|
||||
2006-05-23 Csaba Henk <csaba.henk@creo.hu>
|
||||
* Fix statfs index mismatch in xmp.py.
|
||||
* Rebase build system on pkg-config.
|
||||
* Fix statfs index mismatch in xmp.py:
|
||||
* Rebase build system on pkg-config:
|
||||
- Credits: setup.py based on that of shout-python (python bindings to
|
||||
libshout, part of the icecast project)
|
||||
* 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
|
||||
Simon Barner, Csaba Henk, Roman Shterenzon and Miklos Szeredi
|
||||
* 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
|
||||
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
|
||||
``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?
|
||||
------------------------
|
||||
|
||||
|
|
@ -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
|
||||
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.
|
||||
|
||||
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
|
||||
getattr_func(const char *path, struct stat *st)
|
||||
{
|
||||
int i;
|
||||
PyObject *tmp;
|
||||
PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
|
||||
|
||||
PROLOGUE
|
||||
|
||||
if (!PySequence_Check(v))
|
||||
goto OUT_DECREF;
|
||||
#define fetchattr(st, attr) \
|
||||
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)
|
||||
goto OUT_DECREF;
|
||||
|
||||
for(i=0; i<10; i++) {
|
||||
PyObject *tmp = PySequence_GetItem(v, i);
|
||||
if (!(PyInt_Check(tmp) || PyLong_Check(tmp)))
|
||||
goto OUT_DECREF;
|
||||
}
|
||||
|
||||
st->st_mode = PyInt_AsLong(PySequence_GetItem(v, 0));
|
||||
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));
|
||||
fetchattr(st, st_mode);
|
||||
fetchattr(st, st_ino);
|
||||
fetchattr(st, st_dev);
|
||||
fetchattr(st, st_nlink);
|
||||
fetchattr(st, st_uid);
|
||||
fetchattr(st, st_gid);
|
||||
fetchattr(st, st_size);
|
||||
fetchattr(st, st_atime);
|
||||
fetchattr(st, st_mtime);
|
||||
fetchattr(st, st_ctime);
|
||||
|
||||
#undef fetchattr
|
||||
|
||||
/* Fill in fields not provided by Python lstat() */
|
||||
st->st_blksize= 4096;
|
||||
st->st_blocks= (st->st_size + 511)/512;
|
||||
|
|
@ -118,7 +115,7 @@ readlink_func(const char *path, char *link, size_t size)
|
|||
PROLOGUE
|
||||
|
||||
if(!PyString_Check(v)) {
|
||||
ret = -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto OUT_DECREF;
|
||||
}
|
||||
s = PyString_AsString(v);
|
||||
|
|
@ -374,45 +371,38 @@ static int
|
|||
statfs_func(const char *dummy, struct statfs *fst)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
long retvalues[10];
|
||||
PyObject *tmp;
|
||||
PyObject *v = PyObject_CallFunction(statfs_cb, "");
|
||||
|
||||
PROLOGUE
|
||||
|
||||
if (!PySequence_Check(v))
|
||||
goto OUT_DECREF;
|
||||
if (PySequence_Size(v) < 10)
|
||||
goto OUT_DECREF;
|
||||
#define fetchattr(st, attr) \
|
||||
if (!(tmp = PyObject_GetAttrString(v, #attr))) \
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
fetchattr(fst, f_bsize);
|
||||
#if FUSE_VERSION >= 25
|
||||
fst->f_frsize = retvalues[1];
|
||||
fetchattr(fst, f_frsize);
|
||||
#endif
|
||||
fst->f_blocks = retvalues[2];
|
||||
fst->f_bfree = retvalues[3];
|
||||
fst->f_bavail = retvalues[4];
|
||||
fst->f_files = retvalues[5];
|
||||
fst->f_ffree = retvalues[6];
|
||||
fetchattr(fst, f_blocks);
|
||||
fetchattr(fst, f_bfree);
|
||||
fetchattr(fst, f_bavail);
|
||||
fetchattr(fst, f_files);
|
||||
fetchattr(fst, f_ffree);
|
||||
#if FUSE_VERSION >= 25
|
||||
fst->f_favail = retvalues[7];
|
||||
fst->f_flag = retvalues[8];
|
||||
fst->f_namemax = retvalues[9];
|
||||
fetchattr(fst, f_favail);
|
||||
fetchattr(fst, f_flag);
|
||||
fetchattr(fst, f_namemax);
|
||||
#else
|
||||
fst->f_namelen = retvalues[9];
|
||||
fetchattr(fst, f_namelen);
|
||||
#endif
|
||||
|
||||
#undef fetchattr
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
|
@ -496,7 +486,7 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
|
|||
"getattr", "readlink", "getdir", "mknod",
|
||||
"mkdir", "unlink", "rmdir", "symlink", "rename",
|
||||
"link", "chmod", "chown", "truncate", "utime",
|
||||
"open", "read", "write", "release", "statvfs", "fsync",
|
||||
"open", "read", "write", "release", "statfs", "fsync",
|
||||
"fuse_args", "multithreaded", NULL};
|
||||
|
||||
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):
|
||||
self.func = func
|
||||
|
|
@ -419,6 +419,35 @@ class ErrnoWrapper:
|
|||
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):
|
||||
"""
|
||||
Python interface to FUSE.
|
||||
|
|
@ -427,7 +456,7 @@ class Fuse(object):
|
|||
_attrs = ['getattr', 'readlink', 'getdir', 'mknod', 'mkdir',
|
||||
'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
|
||||
'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release',
|
||||
'statvfs', 'fsync']
|
||||
'statfs', 'fsync']
|
||||
|
||||
fusage = "%prog [mountpoint] [options]"
|
||||
|
||||
|
|
@ -436,35 +465,6 @@ class Fuse(object):
|
|||
self.fuse_args = \
|
||||
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:
|
||||
return self.__init_0_1__(*args, **kw)
|
||||
|
||||
|
|
@ -506,7 +506,11 @@ class Fuse(object):
|
|||
|
||||
for a in self._attrs:
|
||||
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
|
||||
if not args:
|
||||
|
|
@ -614,8 +618,34 @@ class Fuse(object):
|
|||
if hasattr(self, 'debug'):
|
||||
self.fuse_args.add('debug')
|
||||
|
||||
if hasattr(self,'allow_other'):
|
||||
if hasattr(self, 'allow_other'):
|
||||
self.fuse_args.add('allow_other')
|
||||
|
||||
if hasattr(self,'kernel_cache'):
|
||||
if hasattr(self, '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)
|
||||
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
|
||||
the kernel that the info is not available.
|
||||
To provide usable information (ie., you want sensible df(1)
|
||||
output, you are suggested to specify the following attributes:
|
||||
|
||||
However, to provide usable information (ie., you want sensible df(1)
|
||||
output, you are suggested to specify at least the following 7 values
|
||||
(in that order):
|
||||
|
||||
- blocksize - preferred size of file blocks, in bytes
|
||||
- frsize - fundamental size of file blcoks, in bytes
|
||||
- f_bsize - preferred size of file blocks, in bytes
|
||||
- f_frsize - fundamental size of file blcoks, in bytes
|
||||
[if you have no idea, use the same as blocksize]
|
||||
- totalblocks - total number of blocks in the filesystem
|
||||
- freeblocks - number of free blocks
|
||||
- totalfiles - total number of file inodes
|
||||
- freefiles - nunber of free file inodes
|
||||
- f_blocks - total number of blocks in the filesystem
|
||||
- f_bfree - number of free blocks
|
||||
- f_files - total number of file inodes
|
||||
- f_ffree - nunber of free file inodes
|
||||
"""
|
||||
|
||||
return os.statvfs(self.root)
|
||||
|
|
|
|||
Loading…
Reference in a new issue