mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-23 20:24:17 +08:00
fix
This commit is contained in:
parent
406bf11df0
commit
874d95da5b
27
ChangeLog
27
ChangeLog
@ -1,3 +1,30 @@
|
||||
2003-12-11 Miklos Szeredi <mszeredi@inf.bme.hu>
|
||||
|
||||
* Add file locking for mount/unmount (based on patch by Valient
|
||||
Gough)
|
||||
|
||||
2003-12-11 David McNab <david@rebirthing.co.nz>
|
||||
|
||||
* Python filesystem - was broken with python2.3, now fixed:
|
||||
- changed PyTuple_* calls to PySequence_*, because os.lstat
|
||||
is no longer returning a pure tuple
|
||||
- changed PyInt_Check() calls to also call PyLong_Check,
|
||||
to cover for cases (eg os.lstat) where longs are returned
|
||||
- Added support for file 'release' handling, which IMO is
|
||||
essential since this signals to a FS that writes to a file
|
||||
are complete (and therefore the file can now be disposed of
|
||||
meaningfully at the python filesystem's discretion)
|
||||
- Added '__init__' handler to base Fuse class, which allows
|
||||
your Python class to know the mountpoint and mount args,
|
||||
as attributes myfs.mountpoint, myfs.optlist, myfs.optdict
|
||||
|
||||
* General:
|
||||
- added 'mount.fuse' script (in util/ dir), which is meant to be
|
||||
symlinked from /sbin, and which allows FUSE filesystems to
|
||||
be mounted with the 'mount' command, and listed in fstab;
|
||||
also, mount arguments get passed to your filesystem
|
||||
|
||||
|
||||
2003-11-04 Miklos Szeredi <mszeredi@inf.bme.hu>
|
||||
|
||||
* Fix kernel version detection (again). Bugreport by Peter Levart
|
||||
|
@ -1,3 +1,8 @@
|
||||
#@+leo-ver=4
|
||||
#@+node:@file README
|
||||
#@@comment
|
||||
|
||||
|
||||
General Information
|
||||
===================
|
||||
|
||||
@ -22,6 +27,20 @@ for some reason,
|
||||
fusermount <mount point> python <script name>
|
||||
does not seem to work. (why?)
|
||||
|
||||
Update
|
||||
======
|
||||
|
||||
Updated Dec 2003 by David McNab <david@rebirthing.co.nz>:
|
||||
|
||||
- added support for 'release' events (ie when file gets closed)
|
||||
- added __init__ to base class, which picks off parameters and
|
||||
stores them as instance attributes:
|
||||
- self.mountpoint - the mountpoint as given in the mount command
|
||||
- self.optlist - unnamed options (eg 'rw', 'exec' etc)
|
||||
- self.optdict - named options (eg, '-o arg1=val1,arg2=val2...' from mount cmd)
|
||||
- fixed incompatibility issues with recent pythons (original was broken
|
||||
under python2.3)
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
@ -58,3 +77,5 @@ License, Version 2. Future versions, if any, will be available at [3].
|
||||
[1] http://www.python.org
|
||||
[2] http://sourceforge.net/projects/avf/
|
||||
[3] http://unpythonic.dhs.org/~jepler/fuse/
|
||||
#@-node:@file README
|
||||
#@-leo
|
||||
|
@ -1,3 +1,6 @@
|
||||
//@+leo-ver=4
|
||||
//@+node:@file _fusemodule.c
|
||||
//@@language c
|
||||
/*
|
||||
Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
|
||||
|
||||
@ -5,59 +8,84 @@
|
||||
See the file COPYING.
|
||||
*/
|
||||
|
||||
//@+others
|
||||
//@+node:includes
|
||||
#include <Python.h>
|
||||
#include <fuse.h>
|
||||
#include <time.h>
|
||||
//@-node:includes
|
||||
//@+node:globals
|
||||
|
||||
static PyObject *getattr_cb=NULL, *readlink_cb=NULL, *getdir_cb=NULL,
|
||||
*mknod_cb=NULL, *mkdir_cb=NULL, *unlink_cb=NULL, *rmdir_cb=NULL,
|
||||
*symlink_cb=NULL, *rename_cb=NULL, *link_cb=NULL, *chmod_cb=NULL,
|
||||
*chown_cb=NULL, *truncate_cb=NULL, *utime_cb=NULL,
|
||||
*open_cb=NULL, *read_cb=NULL, *write_cb=NULL;
|
||||
|
||||
*open_cb=NULL, *read_cb=NULL, *write_cb=NULL, *release_cb=NULL;
|
||||
//@-node:globals
|
||||
//@+node:PROLOGUE
|
||||
#define PROLOGUE \
|
||||
int ret = -EINVAL; \
|
||||
if (!v) { PyErr_Print(); goto OUT; } \
|
||||
if(v == Py_None) { ret = 0; goto OUT_DECREF; } \
|
||||
if(PyInt_Check(v)) { ret = PyInt_AsLong(v); goto OUT_DECREF; }
|
||||
int ret = -EINVAL; \
|
||||
if (!v) { PyErr_Print(); goto OUT; } \
|
||||
if(v == Py_None) { ret = 0; goto OUT_DECREF; } \
|
||||
if(PyInt_Check(v)) { ret = PyInt_AsLong(v); goto OUT_DECREF; }
|
||||
|
||||
//@-node:PROLOGUE
|
||||
//@+node:EPILOGUE
|
||||
#define EPILOGUE \
|
||||
OUT_DECREF: \
|
||||
Py_DECREF(v); \
|
||||
OUT: \
|
||||
return ret;
|
||||
OUT_DECREF: \
|
||||
Py_DECREF(v); \
|
||||
OUT: \
|
||||
return ret;
|
||||
//@-node:EPILOGUE
|
||||
//@+node:getattr_func
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
* Changed by David McNab (david@rebirthing.co.nz) to work with recent pythons.
|
||||
* Namely, replacing PyTuple_* with PySequence_*, and checking numerical values
|
||||
* with both PyInt_Check and PyLong_Check.
|
||||
*/
|
||||
|
||||
static int getattr_func(const char *path, struct stat *st)
|
||||
{
|
||||
int i;
|
||||
PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
|
||||
PROLOGUE
|
||||
int i;
|
||||
PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
|
||||
PROLOGUE
|
||||
|
||||
if(!PyTuple_Check(v)) { goto OUT_DECREF; }
|
||||
if(PyTuple_Size(v) < 10) { goto OUT_DECREF; }
|
||||
for(i=0; i<10; i++) {
|
||||
if (!PyInt_Check(PyTuple_GetItem(v, 0))) goto OUT_DECREF;
|
||||
}
|
||||
|
||||
st->st_mode = PyInt_AsLong(PyTuple_GetItem(v, 0));
|
||||
st->st_ino = PyInt_AsLong(PyTuple_GetItem(v, 1));
|
||||
st->st_dev = PyInt_AsLong(PyTuple_GetItem(v, 2));
|
||||
st->st_nlink= PyInt_AsLong(PyTuple_GetItem(v, 3));
|
||||
st->st_uid = PyInt_AsLong(PyTuple_GetItem(v, 4));
|
||||
st->st_gid = PyInt_AsLong(PyTuple_GetItem(v, 5));
|
||||
st->st_size = PyInt_AsLong(PyTuple_GetItem(v, 6));
|
||||
st->st_atime= PyInt_AsLong(PyTuple_GetItem(v, 7));
|
||||
st->st_mtime= PyInt_AsLong(PyTuple_GetItem(v, 8));
|
||||
st->st_ctime= PyInt_AsLong(PyTuple_GetItem(v, 9));
|
||||
|
||||
/* Fill in fields not provided by Python lstat() */
|
||||
st->st_blksize= 4096;
|
||||
st->st_blocks= (st->st_size + 511)/512;
|
||||
st->st_ino = 0;
|
||||
|
||||
ret = 0;
|
||||
EPILOGUE
|
||||
if(!PySequence_Check(v)) { goto OUT_DECREF; }
|
||||
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));
|
||||
|
||||
/* Fill in fields not provided by Python lstat() */
|
||||
st->st_blksize= 4096;
|
||||
st->st_blocks= (st->st_size + 511)/512;
|
||||
st->st_ino = 0;
|
||||
|
||||
ret = 0;
|
||||
EPILOGUE
|
||||
}
|
||||
|
||||
//@-node:getattr_func
|
||||
//@+node:readlink_func
|
||||
|
||||
static int readlink_func(const char *path, char *link, size_t size)
|
||||
{
|
||||
PyObject *v = PyObject_CallFunction(readlink_cb, "s", path);
|
||||
@ -72,6 +100,8 @@ static int readlink_func(const char *path, char *link, size_t size)
|
||||
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:readlink_func
|
||||
//@+node:getdir_add_entry
|
||||
|
||||
static int getdir_add_entry(PyObject *w, fuse_dirh_t dh, fuse_dirfil_t df)
|
||||
{
|
||||
@ -108,6 +138,8 @@ out_decref:
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
//@-node:getdir_add_entry
|
||||
//@+node:getdir_func
|
||||
|
||||
static int getdir_func(const char *path, fuse_dirh_t dh, fuse_dirfil_t df)
|
||||
{
|
||||
@ -130,6 +162,8 @@ static int getdir_func(const char *path, fuse_dirh_t dh, fuse_dirfil_t df)
|
||||
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:getdir_func
|
||||
//@+node:mknod_func
|
||||
|
||||
static int mknod_func(const char *path, mode_t m, dev_t d)
|
||||
{
|
||||
@ -137,6 +171,8 @@ static int mknod_func(const char *path, mode_t m, dev_t d)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:mknod_func
|
||||
//@+node:mkdir_func
|
||||
|
||||
static int mkdir_func(const char *path, mode_t m)
|
||||
{
|
||||
@ -144,6 +180,8 @@ static int mkdir_func(const char *path, mode_t m)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:mkdir_func
|
||||
//@+node:unlink_func
|
||||
|
||||
static int unlink_func(const char *path)
|
||||
{
|
||||
@ -151,6 +189,8 @@ static int unlink_func(const char *path)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:unlink_func
|
||||
//@+node:rmdir_func
|
||||
|
||||
static int rmdir_func(const char *path)
|
||||
{
|
||||
@ -158,6 +198,8 @@ static int rmdir_func(const char *path)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:rmdir_func
|
||||
//@+node:symlink_func
|
||||
|
||||
static int symlink_func(const char *path, const char *path1)
|
||||
{
|
||||
@ -165,6 +207,8 @@ static int symlink_func(const char *path, const char *path1)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:symlink_func
|
||||
//@+node:rename_func
|
||||
|
||||
static int rename_func(const char *path, const char *path1)
|
||||
{
|
||||
@ -172,6 +216,8 @@ static int rename_func(const char *path, const char *path1)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:rename_func
|
||||
//@+node:link_func
|
||||
|
||||
static int link_func(const char *path, const char *path1)
|
||||
{
|
||||
@ -179,6 +225,8 @@ static int link_func(const char *path, const char *path1)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:link_func
|
||||
//@+node:chmod_func
|
||||
|
||||
static int chmod_func(const char *path, mode_t m)
|
||||
{
|
||||
@ -186,6 +234,8 @@ static int chmod_func(const char *path, mode_t m)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:chmod_func
|
||||
//@+node:chown_func
|
||||
|
||||
static int chown_func(const char *path, uid_t u, gid_t g)
|
||||
{
|
||||
@ -193,6 +243,8 @@ static int chown_func(const char *path, uid_t u, gid_t g)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:chown_func
|
||||
//@+node:truncate_func
|
||||
|
||||
static int truncate_func(const char *path, off_t o)
|
||||
{
|
||||
@ -200,6 +252,8 @@ static int truncate_func(const char *path, off_t o)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:truncate_func
|
||||
//@+node:utime_func
|
||||
|
||||
static int utime_func(const char *path, struct utimbuf *u) {
|
||||
int actime = u ? u->actime : time(NULL);
|
||||
@ -209,6 +263,8 @@ static int utime_func(const char *path, struct utimbuf *u) {
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:utime_func
|
||||
//@+node:read_func
|
||||
|
||||
static int read_func(const char *path, char *buf, size_t s, off_t off)
|
||||
{
|
||||
@ -221,6 +277,8 @@ static int read_func(const char *path, char *buf, size_t s, off_t off)
|
||||
}
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:read_func
|
||||
//@+node:write_func
|
||||
|
||||
static int write_func(const char *path, const char *buf, size_t t, off_t off)
|
||||
{
|
||||
@ -228,13 +286,28 @@ static int write_func(const char *path, const char *buf, size_t t, off_t off)
|
||||
PROLOGUE
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:write_func
|
||||
//@+node:open_func
|
||||
|
||||
static int open_func(const char *path, int mode)
|
||||
{
|
||||
PyObject *v = PyObject_CallFunction(open_cb, "si", path, mode);
|
||||
PROLOGUE
|
||||
printf("open_func: path=%s\n", path);
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:open_func
|
||||
//@+node:release_func
|
||||
|
||||
static int release_func(const char *path)
|
||||
{
|
||||
PyObject *v = PyObject_CallFunction(release_cb, "s", path);
|
||||
PROLOGUE
|
||||
printf("release_func: path=%s\n", path);
|
||||
EPILOGUE
|
||||
}
|
||||
//@-node:release_func
|
||||
//@+node:process_cmd
|
||||
|
||||
static void process_cmd(struct fuse *f, struct fuse_cmd *cmd, void *data)
|
||||
{
|
||||
@ -250,6 +323,8 @@ static void process_cmd(struct fuse *f, struct fuse_cmd *cmd, void *data)
|
||||
PyThreadState_Delete(state);
|
||||
PyEval_ReleaseLock();
|
||||
}
|
||||
//@-node:process_cmd
|
||||
//@+node:pyfuse_loop_mt
|
||||
|
||||
static void pyfuse_loop_mt(struct fuse *f)
|
||||
{
|
||||
@ -263,6 +338,8 @@ static void pyfuse_loop_mt(struct fuse *f)
|
||||
/* Not yet reached: */
|
||||
PyEval_RestoreThread(save);
|
||||
}
|
||||
//@-node:pyfuse_loop_mt
|
||||
//@+node:Fuse_main
|
||||
|
||||
|
||||
static PyObject *
|
||||
@ -278,15 +355,15 @@ 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", "flags", "multithreaded", NULL};
|
||||
"open", "read", "write", "release", "flags", "multithreaded", NULL};
|
||||
|
||||
memset(&op, 0, sizeof(op));
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOOOOOOOOOOOOii",
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOOOOOOOOOOOOOii",
|
||||
kwlist, &getattr_cb, &readlink_cb, &getdir_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, &flags, &multithreaded))
|
||||
&open_cb, &read_cb, &write_cb, &release_cb, &flags, &multithreaded))
|
||||
return NULL;
|
||||
|
||||
#define DO_ONE_ATTR(name) if(name ## _cb) { Py_INCREF(name ## _cb); op.name = name ## _func; } else { op.name = NULL; }
|
||||
@ -308,6 +385,7 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
|
||||
DO_ONE_ATTR(open);
|
||||
DO_ONE_ATTR(read);
|
||||
DO_ONE_ATTR(write);
|
||||
DO_ONE_ATTR(release);
|
||||
|
||||
fuse = fuse_new(0, flags, &op);
|
||||
if(multithreaded)
|
||||
@ -315,11 +393,18 @@ Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
|
||||
else
|
||||
fuse_loop(fuse);
|
||||
|
||||
//printf("Fuse_main: called\n");
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
/* List of functions defined in the module */
|
||||
//@-node:Fuse_main
|
||||
//@+node:DL_EXPORT
|
||||
//@+at
|
||||
//@nonl
|
||||
// List of functions defined in the module
|
||||
//@-at
|
||||
//@@c
|
||||
|
||||
static PyMethodDef Fuse_methods[] = {
|
||||
{"main", (PyCFunction)Fuse_main, METH_VARARGS|METH_KEYWORDS},
|
||||
@ -344,11 +429,8 @@ init_fuse(void)
|
||||
PyDict_SetItemString(d, "error", ErrorObject);
|
||||
PyDict_SetItemString(d, "DEBUG", PyInt_FromLong(FUSE_DEBUG));
|
||||
}
|
||||
//@-node:DL_EXPORT
|
||||
//@-others
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
||||
//@-node:@file _fusemodule.c
|
||||
//@-leo
|
||||
|
110
python/fuse.py
110
python/fuse.py
@ -1,3 +1,5 @@
|
||||
#@+leo-ver=4
|
||||
#@+node:@file fuse.py
|
||||
#
|
||||
# Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
|
||||
#
|
||||
@ -5,34 +7,92 @@
|
||||
# See the file COPYING.
|
||||
#
|
||||
|
||||
|
||||
#@@language python
|
||||
#@+others
|
||||
#@+node:imports
|
||||
# suppress version mismatch warnings
|
||||
try:
|
||||
import warnings
|
||||
warnings.filterwarnings('ignore',
|
||||
'Python C API version mismatch',
|
||||
RuntimeWarning,
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
from _fuse import main, DEBUG
|
||||
import os
|
||||
import os, sys
|
||||
from errno import *
|
||||
|
||||
#@-node:imports
|
||||
#@+node:class ErrnoWrapper
|
||||
class ErrnoWrapper:
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
try:
|
||||
return apply(self.func, args, kw)
|
||||
except (IOError, OSError), detail:
|
||||
# Sometimes this is an int, sometimes an instance...
|
||||
if hasattr(detail, "errno"): detail = detail.errno
|
||||
return -detail
|
||||
|
||||
#@ @+others
|
||||
#@+node:__init__
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
#@-node:__init__
|
||||
#@+node:__call__
|
||||
def __call__(self, *args, **kw):
|
||||
try:
|
||||
return apply(self.func, args, kw)
|
||||
except (IOError, OSError), detail:
|
||||
# Sometimes this is an int, sometimes an instance...
|
||||
if hasattr(detail, "errno"): detail = detail.errno
|
||||
return -detail
|
||||
#@-node:__call__
|
||||
#@-others
|
||||
#@-node:class ErrnoWrapper
|
||||
#@+node:class Fuse
|
||||
class Fuse:
|
||||
_attrs = ['getattr', 'readlink', 'getdir', 'mknod', 'mkdir',
|
||||
'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
|
||||
'chown', 'truncate', 'utime', 'open', 'read', 'write']
|
||||
|
||||
flags = 0
|
||||
multithreaded = 0
|
||||
def main(self):
|
||||
d = {'flags': self.flags}
|
||||
d['multithreaded'] = self.multithreaded
|
||||
for a in self._attrs:
|
||||
if hasattr(self,a):
|
||||
d[a] = ErrnoWrapper(getattr(self, a))
|
||||
apply(main, (), d)
|
||||
|
||||
#@ @+others
|
||||
#@+node:attribs
|
||||
_attrs = ['getattr', 'readlink', 'getdir', 'mknod', 'mkdir',
|
||||
'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
|
||||
'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release']
|
||||
|
||||
flags = 0
|
||||
multithreaded = 0
|
||||
|
||||
#@-node:attribs
|
||||
#@+node:__init__
|
||||
def __init__(self, *args, **kw):
|
||||
|
||||
# default attributes
|
||||
self.optlist = []
|
||||
self.optdict = {}
|
||||
self.mountpoint = None
|
||||
|
||||
# grab arguments, if any
|
||||
argv = sys.argv
|
||||
argc = len(argv)
|
||||
if argc > 1:
|
||||
# we've been given the mountpoint
|
||||
self.mountpoint = argv[1]
|
||||
if argc > 2:
|
||||
# we've received mount args
|
||||
optstr = argv[2]
|
||||
opts = optstr.split(",")
|
||||
for o in opts:
|
||||
try:
|
||||
k, v = o.split("=", 1)
|
||||
self.optdict[k] = v
|
||||
except:
|
||||
self.optlist.append(o)
|
||||
#@-node:__init__
|
||||
#@+node:main
|
||||
def main(self):
|
||||
d = {'flags': self.flags}
|
||||
d['multithreaded'] = self.multithreaded
|
||||
for a in self._attrs:
|
||||
if hasattr(self,a):
|
||||
d[a] = ErrnoWrapper(getattr(self, a))
|
||||
apply(main, (), d)
|
||||
#@-node:main
|
||||
#@-others
|
||||
#@-node:class Fuse
|
||||
#@-others
|
||||
#@-node:@file fuse.py
|
||||
#@-leo
|
||||
|
202
python/xmp.py
202
python/xmp.py
@ -1,4 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#@+leo-ver=4
|
||||
#@+node:@file xmp.py
|
||||
#@@first #!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
|
||||
#
|
||||
@ -6,78 +9,153 @@
|
||||
# See the file COPYING.
|
||||
#
|
||||
|
||||
#@+others
|
||||
#@+node:imports
|
||||
|
||||
from fuse import Fuse
|
||||
import os
|
||||
from errno import *
|
||||
from stat import *
|
||||
|
||||
import thread
|
||||
#@-node:imports
|
||||
#@+node:class Xmp
|
||||
class Xmp(Fuse):
|
||||
flags = 1
|
||||
|
||||
def getattr(self, path):
|
||||
return os.lstat(path)
|
||||
|
||||
def readlink(self, path):
|
||||
return os.readlink(path)
|
||||
|
||||
def getdir(self, path):
|
||||
return map(lambda x: (x,0), os.listdir(path))
|
||||
|
||||
def unlink(self, path):
|
||||
return os.unlink(path)
|
||||
|
||||
def rmdir(self, path):
|
||||
return os.rmdir(path)
|
||||
|
||||
def symlink(self, path, path1):
|
||||
return os.symlink(path, path1)
|
||||
|
||||
def rename(self, path, path1):
|
||||
return os.rename(path, path1)
|
||||
|
||||
def link(self, path, path1):
|
||||
return os.link(path, path1)
|
||||
|
||||
def chmod(self, path, mode):
|
||||
return os.chmod(path, mode)
|
||||
|
||||
def chown(self, path, user, group):
|
||||
return os.chown(path, user, group)
|
||||
|
||||
def truncate(self, path, size):
|
||||
f = open(path, "w+")
|
||||
return f.truncate(size)
|
||||
|
||||
def mknod(self, path, mode, dev):
|
||||
""" Python has no os.mknod, so we can only do some things """
|
||||
if S_ISREG(mode):
|
||||
open(path, "w")
|
||||
else:
|
||||
return -EINVAL
|
||||
|
||||
def mkdir(self, path, mode):
|
||||
return os.mkdir(path, mode)
|
||||
|
||||
def utime(self, path, times):
|
||||
return os.utime(path, times)
|
||||
|
||||
def open(self, path, flags):
|
||||
os.close(os.open(path, flags))
|
||||
return 0
|
||||
|
||||
def read(self, path, len, offset):
|
||||
f = open(path, "r")
|
||||
f.seek(offset)
|
||||
return f.read(len)
|
||||
|
||||
def write(self, path, buf, off):
|
||||
f = open(path, "r+")
|
||||
f.seek(off)
|
||||
f.write(buf)
|
||||
return len(buf)
|
||||
#@ @+others
|
||||
#@+node:__init__
|
||||
def __init__(self, *args, **kw):
|
||||
|
||||
Fuse.__init__(self, *args, **kw)
|
||||
|
||||
if 1:
|
||||
print "mountpoint: %s" % repr(self.mountpoint)
|
||||
print "unnamed mount options: %s" % self.optlist
|
||||
print "named mount options: %s" % self.optdict
|
||||
|
||||
# do stuff to set up your filesystem here, if you want
|
||||
#thread.start_new_thread(self.mythread, ())
|
||||
pass
|
||||
#@-node:__init__
|
||||
#@+node:mythread
|
||||
def mythread(self):
|
||||
|
||||
"""
|
||||
The beauty of the FUSE python implementation is that with the python interp
|
||||
running in foreground, you can have threads
|
||||
"""
|
||||
print "mythread: started"
|
||||
#while 1:
|
||||
# time.sleep(120)
|
||||
# print "mythread: ticking"
|
||||
|
||||
#@-node:mythread
|
||||
#@+node:attribs
|
||||
flags = 1
|
||||
|
||||
#@-node:attribs
|
||||
#@+node:getattr
|
||||
def getattr(self, path):
|
||||
return os.lstat(path)
|
||||
#@-node:getattr
|
||||
#@+node:readlink
|
||||
def readlink(self, path):
|
||||
return os.readlink(path)
|
||||
#@-node:readlink
|
||||
#@+node:getdir
|
||||
def getdir(self, path):
|
||||
return map(lambda x: (x,0), os.listdir(path))
|
||||
#@-node:getdir
|
||||
#@+node:unlink
|
||||
def unlink(self, path):
|
||||
return os.unlink(path)
|
||||
#@-node:unlink
|
||||
#@+node:rmdir
|
||||
def rmdir(self, path):
|
||||
return os.rmdir(path)
|
||||
#@-node:rmdir
|
||||
#@+node:symlink
|
||||
def symlink(self, path, path1):
|
||||
return os.symlink(path, path1)
|
||||
#@-node:symlink
|
||||
#@+node:rename
|
||||
def rename(self, path, path1):
|
||||
return os.rename(path, path1)
|
||||
#@-node:rename
|
||||
#@+node:link
|
||||
def link(self, path, path1):
|
||||
return os.link(path, path1)
|
||||
#@-node:link
|
||||
#@+node:chmod
|
||||
def chmod(self, path, mode):
|
||||
return os.chmod(path, mode)
|
||||
#@-node:chmod
|
||||
#@+node:chown
|
||||
def chown(self, path, user, group):
|
||||
return os.chown(path, user, group)
|
||||
#@-node:chown
|
||||
#@+node:truncate
|
||||
def truncate(self, path, size):
|
||||
f = open(path, "w+")
|
||||
return f.truncate(size)
|
||||
#@-node:truncate
|
||||
#@+node:mknod
|
||||
def mknod(self, path, mode, dev):
|
||||
""" Python has no os.mknod, so we can only do some things """
|
||||
if S_ISREG(mode):
|
||||
open(path, "w")
|
||||
else:
|
||||
return -EINVAL
|
||||
#@-node:mknod
|
||||
#@+node:mkdir
|
||||
def mkdir(self, path, mode):
|
||||
return os.mkdir(path, mode)
|
||||
#@-node:mkdir
|
||||
#@+node:utime
|
||||
def utime(self, path, times):
|
||||
return os.utime(path, times)
|
||||
#@-node:utime
|
||||
#@+node:open
|
||||
def open(self, path, flags):
|
||||
#print "open: %s" % path
|
||||
os.close(os.open(path, flags))
|
||||
return 0
|
||||
|
||||
#@-node:open
|
||||
#@+node:read
|
||||
def read(self, path, len, offset):
|
||||
#print "read: %s" % path
|
||||
f = open(path, "r")
|
||||
f.seek(offset)
|
||||
return f.read(len)
|
||||
|
||||
#@-node:read
|
||||
#@+node:write
|
||||
def write(self, path, buf, off):
|
||||
#print "write: %s" % path
|
||||
f = open(path, "r+")
|
||||
f.seek(off)
|
||||
f.write(buf)
|
||||
return len(buf)
|
||||
|
||||
#@-node:write
|
||||
#@+node:release
|
||||
def release(self, path):
|
||||
#print "release: %s" % path
|
||||
return 0
|
||||
|
||||
#@-node:release
|
||||
#@-others
|
||||
#@-node:class Xmp
|
||||
#@+node:mainline
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
server = Xmp()
|
||||
server.flags = 0
|
||||
server.multithreaded = 1;
|
||||
server.main()
|
||||
#@-node:mainline
|
||||
#@-others
|
||||
#@-node:@file xmp.py
|
||||
#@-leo
|
||||
|
@ -59,6 +59,33 @@ static const char *get_user_name()
|
||||
}
|
||||
}
|
||||
|
||||
/* use a lock file so that multiple fusermount processes don't try and
|
||||
modify the mtab file at once! */
|
||||
static int lock_mtab()
|
||||
{
|
||||
const char *mtab_lock = _PATH_MOUNTED ".fuselock";
|
||||
int mtablock;
|
||||
int res;
|
||||
|
||||
mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
|
||||
if(mtablock >= 0) {
|
||||
res = lockf(mtablock, F_LOCK, 0);
|
||||
if(res < 0)
|
||||
perror("error getting lock: %s");
|
||||
} else
|
||||
fprintf(stderr, "unable to open fuse lock file, continuing anyway\n");
|
||||
|
||||
return mtablock;
|
||||
}
|
||||
|
||||
static void unlock_mtab(int mtablock)
|
||||
{
|
||||
if(mtablock >= 0) {
|
||||
lockf(mtablock, F_ULOCK, 0);
|
||||
close(mtablock);
|
||||
}
|
||||
}
|
||||
|
||||
static int add_mount(const char *dev, const char *mnt, const char *type)
|
||||
{
|
||||
int res;
|
||||
@ -343,6 +370,7 @@ static int mount_fuse(const char *mnt, int flags)
|
||||
const char *dev = FUSE_DEV;
|
||||
const char *type = "fuse";
|
||||
struct stat stbuf;
|
||||
int mtablock;
|
||||
|
||||
res = check_perm(mnt, &stbuf);
|
||||
if(res == -1)
|
||||
@ -371,8 +399,10 @@ static int mount_fuse(const char *mnt, int flags)
|
||||
res = do_mount(dev, mnt, type, stbuf.st_mode & S_IFMT, fd, flags);
|
||||
if(res == -1)
|
||||
return -1;
|
||||
|
||||
|
||||
mtablock = lock_mtab();
|
||||
res = add_mount(dev, mnt, type);
|
||||
unlock_mtab(mtablock);
|
||||
if(res == -1) {
|
||||
umount(mnt);
|
||||
return -1;
|
||||
@ -530,7 +560,9 @@ int main(int argc, char *argv[])
|
||||
restore_privs();
|
||||
|
||||
if(unmount) {
|
||||
int mtablock = lock_mtab();
|
||||
res = remove_mount(mnt);
|
||||
unlock_mtab(mtablock);
|
||||
if(res == -1)
|
||||
exit(1);
|
||||
|
||||
|
85
util/mount.fuse
Normal file
85
util/mount.fuse
Normal file
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
#@+leo-ver=4
|
||||
#@+node:@file mount.fuse
|
||||
#@@first #!/usr/bin/env python
|
||||
|
||||
"""
|
||||
This utility allows FUSE filesystems to be mounted with the regular *nix
|
||||
'mount' command, or even be listed in /etc/fstab
|
||||
|
||||
To enable this, you need to:
|
||||
1. set execute-permission on this script
|
||||
2. symlink this script into /sbin/mount.fuse
|
||||
|
||||
Usage:
|
||||
|
||||
You can use this in 3 ways:
|
||||
1. mount -t fuse /path/to/script/or/program /path/of/mount/point [options]
|
||||
2. mount -t fuse none /path/of/mount/point -o fs=/path/to/script/or/prog[,opt=val...]
|
||||
3. in /etc/fstab, add:
|
||||
/path/to/script/or/prog /path/of/mount/point fuse noauto[,...]
|
||||
"""
|
||||
|
||||
import sys, os, time
|
||||
|
||||
progname = sys.argv[0]
|
||||
|
||||
def usage(ret):
|
||||
print "Usage: %s /path/to/fuse/fs /path/of/mountpoint [-o options]" % progname
|
||||
print "or: %s none /path/of/mountpoint [-o fs=/path/to/fuse/fs[,...]]" % progname
|
||||
sys.exit(ret)
|
||||
|
||||
def main():
|
||||
|
||||
# initial sanity check
|
||||
argc = len(sys.argv)
|
||||
if argc < 3 or sys.argv[3] != "-o":
|
||||
usage(1)
|
||||
|
||||
dev = sys.argv[1]
|
||||
mountpoint = sys.argv[2]
|
||||
|
||||
# grab options, if any
|
||||
optdict = {}
|
||||
optlist = []
|
||||
if argc > 4:
|
||||
odata = sys.argv[4]
|
||||
opts = odata.split(",")
|
||||
#print opts
|
||||
for o in opts:
|
||||
try:
|
||||
k, v = o.split("=", 1)
|
||||
optdict[k] = v
|
||||
except:
|
||||
optlist.append(o)
|
||||
else:
|
||||
odata = ""
|
||||
|
||||
#print sys.argv
|
||||
if dev == 'none':
|
||||
if not optdict.has_key("fs"):
|
||||
print "%s: Must specify python file with 'fs' option\n" % progname
|
||||
usage(1)
|
||||
pyfile = optdict['fs']
|
||||
else:
|
||||
pyfile = dev
|
||||
|
||||
if not os.path.isfile(pyfile):
|
||||
print "%s: file %s doesn't exist, or is not a file" % (progname, pyfile)
|
||||
sys.exit(1)
|
||||
pypath = os.path.abspath(pyfile)
|
||||
|
||||
#print optdict, optlist
|
||||
|
||||
# all seems ok - run our fuse fs as a child
|
||||
if os.fork() == 0:
|
||||
os.system("fusermount -c -x %s %s %s %s" % (mountpoint, pypath, mountpoint, odata))
|
||||
else:
|
||||
#print "parent exiting..."
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
#@-node:@file mount.fuse
|
||||
#@-leo
|
Loading…
Reference in New Issue
Block a user