Skip to content

Commit d36a421

Browse files
author
dzsekijo
committed
added support for utimens and bmap methods
1 parent c5bd818 commit d36a421

4 files changed

Lines changed: 88 additions & 18 deletions

File tree

README.new_fusepy_api

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,8 @@ Complete support for hi-lib
287287

288288
The Python bindings support all highlevel (pathname based) methods of
289289
the Fuse library as of API revision 26, including `create`, `access`,
290-
`flush` and *extended attributes*.
290+
`flush`, extended attributes, advisory file locking, nanosec precise
291+
setting of acces/modify times, and `bmap`.
291292

292293

293294
Reflection

example/xmp.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ def mkdir(self, path, mode):
114114
def utime(self, path, times):
115115
os.utime("." + path, times)
116116

117+
# The following utimens method would do the same as the above utime method.
118+
# We can't make it better though as the Python stdlib doesn't know of
119+
# subsecond preciseness in acces/modify times.
120+
#
121+
# def utimens(self, path, ts_acc, ts_mod):
122+
# os.utime("." + path, (ts_acc.tv_sec, ts_mod.tv_sec))
123+
117124
def access(self, path, mode):
118125
if not os.access("." + path, mode):
119126
return -EACCES

fuse.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,15 @@ class Flock(FuseStruct):
450450
pass
451451

452452

453+
class Timespec(FuseStruct):
454+
"""
455+
Cf. struct timespec in time.h:
456+
http://www.opengroup.org/onlinepubs/009695399/basedefs/time.h.html
457+
"""
458+
459+
pass
460+
461+
453462
class FuseFileInfo(FuseStruct):
454463

455464
def __init__(self, **kw):
@@ -514,6 +523,8 @@ def feature_needs(*feas):
514523
'has_fsinit': ('has_init'),
515524
'has_fsdestroy': ('has_destroy'),
516525
'has_lock': 26,
526+
'has_utimens': 26,
527+
'has_bmap': 26,
517528
'has_init': 23,
518529
'has_destroy': 23,
519530
'*': '!re:^\*$'}
@@ -606,8 +617,8 @@ class Fuse(object):
606617
'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release',
607618
'statfs', 'fsync', 'create', 'opendir', 'releasedir', 'fsyncdir',
608619
'flush', 'fgetattr', 'ftruncate', 'getxattr', 'listxattr',
609-
'setxattr', 'removexattr', 'access', 'lock', 'fsinit',
610-
'fsdestroy']
620+
'setxattr', 'removexattr', 'access', 'lock', 'utimens', 'bmap',
621+
'fsinit', 'fsdestroy']
611622

612623
fusage = "%prog [mountpoint] [options]"
613624

@@ -700,15 +711,20 @@ def lowwrap(self, fname):
700711
"""
701712
fun = getattr(self, fname)
702713

703-
if not fname in ('open', 'create'):
704-
return fun
705-
706-
def wrap(*a, **kw):
707-
res = fun(*a, **kw)
708-
if not res or type(res) == type(0):
709-
return res
710-
else:
711-
return (res, type(res) != FuseFileInfo)
714+
if fname in ('open', 'create'):
715+
def wrap(*a, **kw):
716+
res = fun(*a, **kw)
717+
if not res or type(res) == type(0):
718+
return res
719+
else:
720+
return (res, type(res) != FuseFileInfo)
721+
elif fname == 'utimens':
722+
def wrap(path, acc_sec, acc_nsec, mod_sec, mod_nsec):
723+
ts_acc = Timespec(tv_sec = acc_sec, tv_nsec = acc_nsec)
724+
ts_mod = Timespec(tv_sec = mod_sec, tv_nsec = mod_nsec)
725+
return fun(path, ts_acc, ts_mod)
726+
else:
727+
wrap = fun
712728

713729
return wrap
714730

fuseparts/_fusemodule.c

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ static PyObject *getattr_cb=NULL, *readlink_cb=NULL, *readdir_cb=NULL,
4343
*statfs_cb=NULL, *fsync_cb=NULL, *create_cb=NULL, *opendir_cb=NULL,
4444
*releasedir_cb=NULL, *fsyncdir_cb=NULL, *flush_cb=NULL, *ftruncate_cb=NULL,
4545
*fgetattr_cb=NULL, *getxattr_cb=NULL, *listxattr_cb=NULL, *setxattr_cb=NULL,
46-
*removexattr_cb=NULL, *access_cb=NULL, *lock_cb = NULL, *fsinit_cb=NULL,
47-
*fsdestroy_cb = NULL;
46+
*removexattr_cb=NULL, *access_cb=NULL, *lock_cb = NULL, *utimens_cb = NULL,
47+
*bmap_cb = NULL, *fsinit_cb=NULL, *fsdestroy_cb = NULL;
4848

4949
static PyObject *Py_FuseError;
5050
static PyInterpreterState *interp;
@@ -792,6 +792,7 @@ fsdestroy_func(void *param)
792792
}
793793
#endif
794794

795+
#if FUSE_VERSION >= 26
795796
static inline PyObject *
796797
lock_func_i(const char *path, struct fuse_file_info *fi, int cmd,
797798
struct flock *lock)
@@ -841,6 +842,48 @@ lock_func(const char *path, struct fuse_file_info *fi, int cmd,
841842
EPILOGUE
842843
}
843844

845+
static int
846+
utimens_func(const char *path, const struct timespec ts[2])
847+
{
848+
PROLOGUE(
849+
PyObject_CallFunction(utimens_cb, "siiii", path,
850+
ts[0].tv_sec, ts[0].tv_nsec,
851+
ts[1].tv_sec, ts[1].tv_nsec)
852+
)
853+
854+
EPILOGUE
855+
}
856+
857+
static int
858+
bmap_func(const char *path, size_t blocksize, uint64_t *idx)
859+
{
860+
PyObject *pytmp;
861+
unsigned long long ctmp;
862+
struct { uint64_t idx; } idxwrapper;
863+
864+
PROLOGUE(
865+
#if PY_VERSION_HEX < 0x02050000
866+
PyObject_CallFunction(bmap_cb, "siK", path, blocksize, *idx)
867+
#else
868+
PyObject_CallFunction(bmap_cb, "snK", path, blocksize, *idx)
869+
#endif
870+
)
871+
872+
/*
873+
* We can make use of our py -> C numeric conversion macro with some
874+
* customization of the parameters...
875+
*/
876+
pytmp = v;
877+
Py_INCREF(pytmp);
878+
py2attr(&idxwrapper, idx);
879+
880+
*idx = idxwrapper.idx;
881+
ret = 0;
882+
883+
EPILOGUE
884+
}
885+
#endif
886+
844887
static int
845888
pyfuse_loop_mt(struct fuse *f)
846889
{
@@ -882,14 +925,14 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
882925
"open", "read", "write", "release", "statfs", "fsync",
883926
"create", "opendir", "releasedir", "fsyncdir", "flush",
884927
"ftruncate", "fgetattr", "getxattr", "listxattr", "setxattr",
885-
"removexattr", "access", "lock", "fsinit", "fsdestroy",
886-
"fuse_args", "multithreaded", NULL
928+
"removexattr", "access", "lock", "utimens", "bmap",
929+
"fsinit", "fsdestroy", "fuse_args", "multithreaded", NULL
887930
};
888931

889932
memset(&op, 0, sizeof(op));
890933

891934
if (!PyArg_ParseTupleAndKeywords(args, kw,
892-
"|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOi",
935+
"|OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOi",
893936
kwlist, &getattr_cb, &readlink_cb,
894937
&readdir_cb, &mknod_cb, &mkdir_cb,
895938
&unlink_cb, &rmdir_cb, &symlink_cb,
@@ -902,7 +945,8 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
902945
&flush_cb, &ftruncate_cb,
903946
&fgetattr_cb, &getxattr_cb,
904947
&listxattr_cb, &setxattr_cb,
905-
&removexattr_cb, &access_cb, &lock_cb,
948+
&removexattr_cb, &access_cb,
949+
&lock_cb, &utimens_cb, &bmap_cb,
906950
&fsinit_cb, &fsdestroy_cb,
907951
&fargseq, &multithreaded))
908952
return NULL;
@@ -957,6 +1001,8 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
9571001
#endif
9581002
#if FUSE_VERSION >= 26
9591003
DO_ONE_ATTR(lock);
1004+
DO_ONE_ATTR(utimens);
1005+
DO_ONE_ATTR(bmap);
9601006
#endif
9611007
#if FUSE_VERSION >= 23
9621008
DO_ONE_ATTR_AS(init, fsinit);

0 commit comments

Comments
 (0)