/[fuse_dbi]/fuse/trunk/python/code.leo
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /fuse/trunk/python/code.leo

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (hide annotations)
Wed Aug 4 11:40:49 2004 UTC (19 years, 8 months ago) by dpavlin
File size: 35101 byte(s)
copy CVS to trunk

1 dpavlin 4 <?xml version="1.0" encoding="UTF-8"?>
2     <leo_file>
3     <leo_header file_format="2" tnodes="0" max_tnode_index="69" clone_windows="0"/>
4     <globals body_outline_ratio="0.2448559670781893">
5     <global_window_position top="129" left="90" height="631" width="1124"/>
6     <global_log_window_position top="0" left="0" height="0" width="0"/>
7     </globals>
8     <preferences>
9     </preferences>
10     <find_panel_settings>
11     <find_string></find_string>
12     <change_string></change_string>
13     </find_panel_settings>
14     <vnodes>
15     <v t="davidmcnab.121303142957" a="E"><vh>fuse python bindings</vh>
16     <v t="davidmcnab.121303142957.1" a="E" tnodeList="davidmcnab.121303142957.1,davidmcnab.121303142957.2,davidmcnab.121303142957.3,davidmcnab.121303142957.4,davidmcnab.121303142957.5,davidmcnab.121303142957.6,davidmcnab.121303142957.7,davidmcnab.121303142957.8,davidmcnab.121303142957.9,davidmcnab.121303142957.10,davidmcnab.121303142957.11,davidmcnab.121303142957.12,davidmcnab.121303142957.13,davidmcnab.121303142957.14,davidmcnab.121303142957.15,davidmcnab.121303142957.16,davidmcnab.121303142957.17,davidmcnab.121303142957.18,davidmcnab.121303142957.19,davidmcnab.121303142957.20,davidmcnab.121303142957.21,davidmcnab.121303142957.22,davidmcnab.121303142957.23,davidmcnab.121303142957.24,davidmcnab.121303144441,davidmcnab.121303144441.1,davidmcnab.121303142957.25,davidmcnab.121303142957.26,davidmcnab.121303142957.27,davidmcnab.121303142957.28"><vh>@file _fusemodule.c</vh>
17     <v t="davidmcnab.121303142957.2"><vh>includes</vh></v>
18     <v t="davidmcnab.121303142957.3" a="M"><vh>globals</vh></v>
19     <v t="davidmcnab.121303142957.4"><vh>PROLOGUE</vh></v>
20     <v t="davidmcnab.121303142957.5"><vh>EPILOGUE</vh></v>
21     <v t="davidmcnab.121303142957.6"><vh>getattr_func</vh></v>
22     <v t="davidmcnab.121303142957.7"><vh>readlink_func</vh></v>
23     <v t="davidmcnab.121303142957.8"><vh>getdir_add_entry</vh></v>
24     <v t="davidmcnab.121303142957.9"><vh>getdir_func</vh></v>
25     <v t="davidmcnab.121303142957.10"><vh>mknod_func</vh></v>
26     <v t="davidmcnab.121303142957.11"><vh>mkdir_func</vh></v>
27     <v t="davidmcnab.121303142957.12"><vh>unlink_func</vh></v>
28     <v t="davidmcnab.121303142957.13"><vh>rmdir_func</vh></v>
29     <v t="davidmcnab.121303142957.14"><vh>symlink_func</vh></v>
30     <v t="davidmcnab.121303142957.15"><vh>rename_func</vh></v>
31     <v t="davidmcnab.121303142957.16"><vh>link_func</vh></v>
32     <v t="davidmcnab.121303142957.17"><vh>chmod_func</vh></v>
33     <v t="davidmcnab.121303142957.18"><vh>chown_func</vh></v>
34     <v t="davidmcnab.121303142957.19"><vh>truncate_func</vh></v>
35     <v t="davidmcnab.121303142957.20"><vh>utime_func</vh></v>
36     <v t="davidmcnab.121303142957.21"><vh>read_func</vh></v>
37     <v t="davidmcnab.121303142957.22"><vh>write_func</vh></v>
38     <v t="davidmcnab.121303142957.23"><vh>open_func</vh></v>
39     <v t="davidmcnab.121303142957.24" a="M"><vh>release_func</vh></v>
40     <v t="davidmcnab.121303144441"><vh>statfs_func</vh></v>
41     <v t="davidmcnab.121303144441.1"><vh>fsync_func</vh></v>
42     <v t="davidmcnab.121303142957.25" a="M"><vh>process_cmd</vh></v>
43     <v t="davidmcnab.121303142957.26"><vh>pyfuse_loop_mt</vh></v>
44     <v t="davidmcnab.121303142957.27" a="M"><vh>Fuse_main</vh></v>
45     <v t="davidmcnab.121303142957.28"><vh>DL_EXPORT</vh></v>
46     </v>
47     <v t="davidmcnab.121303142957.29" tnodeList="davidmcnab.121303142957.29,davidmcnab.121303142957.30,davidmcnab.121303142957.31,davidmcnab.121303142957.32,davidmcnab.121303142957.33,davidmcnab.121303142957.34,davidmcnab.121303142957.35,davidmcnab.121303142957.36,davidmcnab.121303142957.37"><vh>@file fuse.py</vh>
48     <v t="davidmcnab.121303142957.30"><vh>imports</vh></v>
49     <v t="davidmcnab.121303142957.31" a="E"><vh>class ErrnoWrapper</vh>
50     <v t="davidmcnab.121303142957.32"><vh>__init__</vh></v>
51     <v t="davidmcnab.121303142957.33"><vh>__call__</vh></v>
52     </v>
53     <v t="davidmcnab.121303142957.34" a="E"><vh>class Fuse</vh>
54     <v t="davidmcnab.121303142957.35" a="M"><vh>attribs</vh></v>
55     <v t="davidmcnab.121303142957.36"><vh>__init__</vh></v>
56     <v t="davidmcnab.121303142957.37"><vh>main</vh></v>
57     </v>
58     </v>
59     <v t="davidmcnab.121303142957.38" tnodeList="davidmcnab.121303142957.38"><vh>@file Makefile</vh></v>
60     <v t="davidmcnab.121303142957.39" a="E" tnodeList="davidmcnab.121303142957.39,davidmcnab.121303142957.40,davidmcnab.121303142957.41,davidmcnab.121303142957.42,davidmcnab.121303142957.43,davidmcnab.121303142957.44,davidmcnab.121303142957.45,davidmcnab.121303142957.46,davidmcnab.121303142957.47,davidmcnab.121303142957.48,davidmcnab.121303142957.49,davidmcnab.121303142957.50,davidmcnab.121303142957.51,davidmcnab.121303142957.52,davidmcnab.121303142957.53,davidmcnab.121303142957.54,davidmcnab.121303142957.55,davidmcnab.121303142957.56,davidmcnab.121303142957.57,davidmcnab.121303142957.58,davidmcnab.121303142957.59,davidmcnab.121303142957.60,davidmcnab.121303142957.61,davidmcnab.121303142957.62,davidmcnab.121303144134,davidmcnab.121303144134.1,davidmcnab.121303142957.63"><vh>@file xmp.py</vh>
61     <v t="davidmcnab.121303142957.40"><vh>imports</vh></v>
62     <v t="davidmcnab.121303142957.41" a="E"><vh>class Xmp</vh>
63     <v t="davidmcnab.121303142957.42"><vh>__init__</vh></v>
64     <v t="davidmcnab.121303142957.43"><vh>mythread</vh></v>
65     <v t="davidmcnab.121303142957.44"><vh>attribs</vh></v>
66     <v t="davidmcnab.121303142957.45"><vh>getattr</vh></v>
67     <v t="davidmcnab.121303142957.46"><vh>readlink</vh></v>
68     <v t="davidmcnab.121303142957.47"><vh>getdir</vh></v>
69     <v t="davidmcnab.121303142957.48"><vh>unlink</vh></v>
70     <v t="davidmcnab.121303142957.49"><vh>rmdir</vh></v>
71     <v t="davidmcnab.121303142957.50"><vh>symlink</vh></v>
72     <v t="davidmcnab.121303142957.51"><vh>rename</vh></v>
73     <v t="davidmcnab.121303142957.52"><vh>link</vh></v>
74     <v t="davidmcnab.121303142957.53"><vh>chmod</vh></v>
75     <v t="davidmcnab.121303142957.54"><vh>chown</vh></v>
76     <v t="davidmcnab.121303142957.55"><vh>truncate</vh></v>
77     <v t="davidmcnab.121303142957.56"><vh>mknod</vh></v>
78     <v t="davidmcnab.121303142957.57"><vh>mkdir</vh></v>
79     <v t="davidmcnab.121303142957.58"><vh>utime</vh></v>
80     <v t="davidmcnab.121303142957.59"><vh>open</vh></v>
81     <v t="davidmcnab.121303142957.60"><vh>read</vh></v>
82     <v t="davidmcnab.121303142957.61"><vh>write</vh></v>
83     <v t="davidmcnab.121303142957.62" a="M"><vh>release</vh></v>
84     <v t="davidmcnab.121303144134"><vh>statfs</vh></v>
85     <v t="davidmcnab.121303144134.1"><vh>fsync</vh></v>
86     </v>
87     <v t="davidmcnab.121303142957.63"><vh>mainline</vh></v>
88     </v>
89     <v t="davidmcnab.121303142957.64" tnodeList="davidmcnab.121303142957.64"><vh>@file setup.py</vh></v>
90     <v t="davidmcnab.121303142957.65" tnodeList="davidmcnab.121303142957.65"><vh>@file README</vh></v>
91     <v t="davidmcnab.121303142957.67" a="E" tnodeList="davidmcnab.121303142957.67"><vh>@file mount.fuse</vh></v>
92     <v t="davidmcnab.121403050157" a="E"><vh>@file fuse.py</vh>
93     <v t="davidmcnab.121403050157.1"><vh>&lt;&lt; fuse declarations &gt;&gt;</vh></v>
94     <v t="davidmcnab.121403050157.2" a="E"><vh>class ErrnoWrapper</vh>
95     <v t="davidmcnab.121403050157.3"><vh>&lt;&lt; class ErrnoWrapper declarations &gt;&gt;</vh></v>
96     <v t="davidmcnab.121403050157.4"><vh>__init__</vh></v>
97     <v t="davidmcnab.121403050157.5" a="V"><vh>__call__</vh></v>
98     </v>
99     <v t="davidmcnab.121403050157.6" a="E"><vh>class Fuse</vh>
100     <v t="davidmcnab.121403050157.7"><vh>&lt;&lt; class Fuse declarations &gt;&gt;</vh></v>
101     <v t="davidmcnab.121403050157.8"><vh>__init__</vh></v>
102     <v t="davidmcnab.121403050157.9"><vh>main</vh></v>
103     </v>
104     </v>
105     </v>
106     </vnodes>
107     <tnodes>
108     <t tx="davidmcnab.121303142957"></t>
109     <t tx="davidmcnab.121303142957.1">@language c
110     /*
111     Copyright (C) 2001 Jeff Epler &lt;jepler@unpythonic.dhs.org&gt;
112    
113     This program can be distributed under the terms of the GNU GPL.
114     See the file COPYING.
115     */
116    
117     @others
118    
119     </t>
120     <t tx="davidmcnab.121303142957.2">#include &lt;Python.h&gt;
121     #include &lt;fuse.h&gt;
122     #include &lt;time.h&gt;
123     </t>
124     <t tx="davidmcnab.121303142957.3">
125     static PyObject *getattr_cb=NULL, *readlink_cb=NULL, *getdir_cb=NULL,
126     *mknod_cb=NULL, *mkdir_cb=NULL, *unlink_cb=NULL, *rmdir_cb=NULL,
127     *symlink_cb=NULL, *rename_cb=NULL, *link_cb=NULL, *chmod_cb=NULL,
128     *chown_cb=NULL, *truncate_cb=NULL, *utime_cb=NULL,
129     *open_cb=NULL, *read_cb=NULL, *write_cb=NULL, *release_cb=NULL,
130     *statfs_cb=NULL, *fsync_cb=NULL
131     ;
132     </t>
133     <t tx="davidmcnab.121303142957.4">#define PROLOGUE \
134     int ret = -EINVAL; \
135     if (!v) { PyErr_Print(); goto OUT; } \
136     if(v == Py_None) { ret = 0; goto OUT_DECREF; } \
137     if(PyInt_Check(v)) { ret = PyInt_AsLong(v); goto OUT_DECREF; }
138    
139     </t>
140     <t tx="davidmcnab.121303142957.5">#define EPILOGUE \
141     OUT_DECREF: \
142     Py_DECREF(v); \
143     OUT: \
144     return ret;
145     </t>
146     <t tx="davidmcnab.121303142957.6">
147     /*
148     * Local Variables:
149     * indent-tabs-mode: t
150     * c-basic-offset: 8
151     * End:
152     * Changed by David McNab (david@rebirthing.co.nz) to work with recent pythons.
153     * Namely, replacing PyTuple_* with PySequence_*, and checking numerical values
154     * with both PyInt_Check and PyLong_Check.
155     */
156    
157     static int getattr_func(const char *path, struct stat *st)
158     {
159     int i;
160     PyObject *v = PyObject_CallFunction(getattr_cb, "s", path);
161     PROLOGUE
162    
163     if(!PySequence_Check(v)) { goto OUT_DECREF; }
164     if(PySequence_Size(v) &lt; 10) { goto OUT_DECREF; }
165     for(i=0; i&lt;10; i++)
166     {
167     PyObject *tmp = PySequence_GetItem(v, i);
168     if (!(PyInt_Check(tmp) || PyLong_Check(tmp))) goto OUT_DECREF;
169     }
170    
171     st-&gt;st_mode = PyInt_AsLong(PySequence_GetItem(v, 0));
172     st-&gt;st_ino = PyInt_AsLong(PySequence_GetItem(v, 1));
173     st-&gt;st_dev = PyInt_AsLong(PySequence_GetItem(v, 2));
174     st-&gt;st_nlink= PyInt_AsLong(PySequence_GetItem(v, 3));
175     st-&gt;st_uid = PyInt_AsLong(PySequence_GetItem(v, 4));
176     st-&gt;st_gid = PyInt_AsLong(PySequence_GetItem(v, 5));
177     st-&gt;st_size = PyInt_AsLong(PySequence_GetItem(v, 6));
178     st-&gt;st_atime= PyInt_AsLong(PySequence_GetItem(v, 7));
179     st-&gt;st_mtime= PyInt_AsLong(PySequence_GetItem(v, 8));
180     st-&gt;st_ctime= PyInt_AsLong(PySequence_GetItem(v, 9));
181    
182     /* Fill in fields not provided by Python lstat() */
183     st-&gt;st_blksize= 4096;
184     st-&gt;st_blocks= (st-&gt;st_size + 511)/512;
185     st-&gt;st_ino = 0;
186    
187     ret = 0;
188     EPILOGUE
189     }
190    
191     </t>
192     <t tx="davidmcnab.121303142957.7">
193     static int readlink_func(const char *path, char *link, size_t size)
194     {
195     PyObject *v = PyObject_CallFunction(readlink_cb, "s", path);
196     char *s;
197     PROLOGUE
198    
199     if(!PyString_Check(v)) { ret = -EINVAL; goto OUT_DECREF; }
200     s = PyString_AsString(v);
201     strncpy(link, s, size);
202     link[size-1] = '\0';
203     ret = 0;
204    
205     EPILOGUE
206     }
207     </t>
208     <t tx="davidmcnab.121303142957.8">
209     static int getdir_add_entry(PyObject *w, fuse_dirh_t dh, fuse_dirfil_t df)
210     {
211     PyObject *o0;
212     PyObject *o1;
213     int ret = -EINVAL;
214    
215     if(!PySequence_Check(w)) {
216     printf("getdir item not sequence\n");
217     goto out;
218     }
219     if(PySequence_Length(w) != 2) {
220     printf("getdir item not len 2\n");
221     goto out;
222     }
223     o0 = PySequence_GetItem(w, 0);
224     o1 = PySequence_GetItem(w, 1);
225    
226     if(!PyString_Check(o0)) {
227     printf("getdir item[0] not string\n");
228     goto out_decref;
229     }
230     if(!PyInt_Check(o1)) {
231     printf("getdir item[1] not int\n");
232     goto out_decref;
233     }
234    
235     ret = df(dh, PyString_AsString(o0), PyInt_AsLong(o1));
236    
237     out_decref:
238     Py_DECREF(o0);
239     Py_DECREF(o1);
240    
241     out:
242     return ret;
243     }
244     </t>
245     <t tx="davidmcnab.121303142957.9">
246     static int getdir_func(const char *path, fuse_dirh_t dh, fuse_dirfil_t df)
247     {
248     PyObject *v = PyObject_CallFunction(getdir_cb, "s", path);
249     int i;
250     PROLOGUE
251    
252     if(!PySequence_Check(v)) {
253     printf("getdir_func not sequence\n");
254     goto OUT_DECREF;
255     }
256     for(i=0; i &lt; PySequence_Length(v); i++) {
257     PyObject *w = PySequence_GetItem(v, i);
258     ret = getdir_add_entry(w, dh, df);
259     Py_DECREF(w);
260     if(ret != 0)
261     goto OUT_DECREF;
262     }
263     ret = 0;
264    
265     EPILOGUE
266     }
267     </t>
268     <t tx="davidmcnab.121303142957.10">
269     static int mknod_func(const char *path, mode_t m, dev_t d)
270     {
271     PyObject *v = PyObject_CallFunction(mknod_cb, "sii", path, m, d);
272     PROLOGUE
273     EPILOGUE
274     }
275     </t>
276     <t tx="davidmcnab.121303142957.11">
277     static int mkdir_func(const char *path, mode_t m)
278     {
279     PyObject *v = PyObject_CallFunction(mkdir_cb, "si", path, m);
280     PROLOGUE
281     EPILOGUE
282     }
283     </t>
284     <t tx="davidmcnab.121303142957.12">
285     static int unlink_func(const char *path)
286     {
287     PyObject *v = PyObject_CallFunction(unlink_cb, "s", path);
288     PROLOGUE
289     EPILOGUE
290     }
291     </t>
292     <t tx="davidmcnab.121303142957.13">
293     static int rmdir_func(const char *path)
294     {
295     PyObject *v = PyObject_CallFunction(rmdir_cb, "s", path);
296     PROLOGUE
297     EPILOGUE
298     }
299     </t>
300     <t tx="davidmcnab.121303142957.14">
301     static int symlink_func(const char *path, const char *path1)
302     {
303     PyObject *v = PyObject_CallFunction(symlink_cb, "ss", path, path1);
304     PROLOGUE
305     EPILOGUE
306     }
307     </t>
308     <t tx="davidmcnab.121303142957.15">
309     static int rename_func(const char *path, const char *path1)
310     {
311     PyObject *v = PyObject_CallFunction(rename_cb, "ss", path, path1);
312     PROLOGUE
313     EPILOGUE
314     }
315     </t>
316     <t tx="davidmcnab.121303142957.16">
317     static int link_func(const char *path, const char *path1)
318     {
319     PyObject *v = PyObject_CallFunction(link_cb, "ss", path, path1);
320     PROLOGUE
321     EPILOGUE
322     }
323     </t>
324     <t tx="davidmcnab.121303142957.17">
325     static int chmod_func(const char *path, mode_t m)
326     {
327     PyObject *v = PyObject_CallFunction(chmod_cb, "si", path, m);
328     PROLOGUE
329     EPILOGUE
330     }
331     </t>
332     <t tx="davidmcnab.121303142957.18">
333     static int chown_func(const char *path, uid_t u, gid_t g)
334     {
335     PyObject *v = PyObject_CallFunction(chown_cb, "sii", path, u, g);
336     PROLOGUE
337     EPILOGUE
338     }
339     </t>
340     <t tx="davidmcnab.121303142957.19">
341     static int truncate_func(const char *path, off_t o)
342     {
343     PyObject *v = PyObject_CallFunction(truncate_cb, "si", path, o);
344     PROLOGUE
345     EPILOGUE
346     }
347     </t>
348     <t tx="davidmcnab.121303142957.20">
349     static int utime_func(const char *path, struct utimbuf *u) {
350     int actime = u ? u-&gt;actime : time(NULL);
351     int modtime = u ? u-&gt;modtime : actime;
352     PyObject *v = PyObject_CallFunction(utime_cb, "s(ii)",
353     path, actime, modtime);
354     PROLOGUE
355     EPILOGUE
356     }
357     </t>
358     <t tx="davidmcnab.121303142957.21">
359     static int read_func(const char *path, char *buf, size_t s, off_t off)
360     {
361     PyObject *v = PyObject_CallFunction(read_cb, "sii", path, s, off);
362     PROLOGUE
363     if(PyString_Check(v)) {
364     if(PyString_Size(v) &gt; s) goto OUT_DECREF;
365     memcpy(buf, PyString_AsString(v), PyString_Size(v));
366     ret = PyString_Size(v);
367     }
368     EPILOGUE
369     }
370     </t>
371     <t tx="davidmcnab.121303142957.22">
372     static int write_func(const char *path, const char *buf, size_t t, off_t off)
373     {
374     PyObject *v = PyObject_CallFunction(write_cb,"ss#i", path, buf, t, off);
375     PROLOGUE
376     EPILOGUE
377     }
378     </t>
379     <t tx="davidmcnab.121303142957.23">
380     static int open_func(const char *path, int mode)
381     {
382     PyObject *v = PyObject_CallFunction(open_cb, "si", path, mode);
383     PROLOGUE
384     printf("open_func: path=%s\n", path);
385     EPILOGUE
386     }
387     </t>
388     <t tx="davidmcnab.121303142957.24">static int release_func(const char *path, int flags)
389     {
390     PyObject *v = PyObject_CallFunction(release_cb, "si", path, flags);
391     PROLOGUE
392     //printf("release_func: path=%s flags=%d\n", path, flags);
393     EPILOGUE
394     }
395     </t>
396     <t tx="davidmcnab.121303142957.25">
397     static void process_cmd(struct fuse *f, struct fuse_cmd *cmd, void *data)
398     {
399     PyInterpreterState *interp = (PyInterpreterState *) data;
400     PyThreadState *state;
401    
402     PyEval_AcquireLock();
403     state = PyThreadState_New(interp);
404     PyThreadState_Swap(state);
405     __fuse_process_cmd(f, cmd);
406     PyThreadState_Clear(state);
407     PyThreadState_Swap(NULL);
408     PyThreadState_Delete(state);
409     PyEval_ReleaseLock();
410     }
411     </t>
412     <t tx="davidmcnab.121303142957.26">
413     static void pyfuse_loop_mt(struct fuse *f)
414     {
415     PyInterpreterState *interp;
416     PyThreadState *save;
417    
418     PyEval_InitThreads();
419     interp = PyThreadState_Get()-&gt;interp;
420     save = PyEval_SaveThread();
421     __fuse_loop_mt(f, process_cmd, interp);
422     /* Not yet reached: */
423     PyEval_RestoreThread(save);
424     }
425     </t>
426     <t tx="davidmcnab.121303142957.27">
427    
428     static PyObject *
429     Fuse_main(PyObject *self, PyObject *args, PyObject *kw)
430     {
431     int flags=0;
432     int multithreaded=0;
433     static struct fuse *fuse=NULL;
434    
435     struct fuse_operations op;
436    
437     static char *kwlist[] = {
438     "getattr", "readlink", "getdir", "mknod",
439     "mkdir", "unlink", "rmdir", "symlink", "rename",
440     "link", "chmod", "chown", "truncate", "utime",
441     "open", "read", "write", "release", "statfs", "fsync",
442     "flags", "multithreaded", NULL};
443    
444     memset(&amp;op, 0, sizeof(op));
445    
446     if (!PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOOOOOOOOOOOOOOOii",
447     kwlist, &amp;getattr_cb, &amp;readlink_cb, &amp;getdir_cb, &amp;mknod_cb,
448     &amp;mkdir_cb, &amp;unlink_cb, &amp;rmdir_cb, &amp;symlink_cb, &amp;rename_cb,
449     &amp;link_cb, &amp;chmod_cb, &amp;chown_cb, &amp;truncate_cb, &amp;utime_cb,
450     &amp;open_cb, &amp;read_cb, &amp;write_cb, &amp;release_cb, &amp;statfs_cb, &amp;fsync_cb,
451     &amp;flags, &amp;multithreaded))
452     return NULL;
453    
454     #define DO_ONE_ATTR(name) if(name ## _cb) { Py_INCREF(name ## _cb); op.name = name ## _func; } else { op.name = NULL; }
455    
456     DO_ONE_ATTR(getattr);
457     DO_ONE_ATTR(readlink);
458     DO_ONE_ATTR(getdir);
459     DO_ONE_ATTR(mknod);
460     DO_ONE_ATTR(mkdir);
461     DO_ONE_ATTR(unlink);
462     DO_ONE_ATTR(rmdir);
463     DO_ONE_ATTR(symlink);
464     DO_ONE_ATTR(rename);
465     DO_ONE_ATTR(link);
466     DO_ONE_ATTR(chmod);
467     DO_ONE_ATTR(chown);
468     DO_ONE_ATTR(truncate);
469     DO_ONE_ATTR(utime);
470     DO_ONE_ATTR(open);
471     DO_ONE_ATTR(read);
472     DO_ONE_ATTR(write);
473     DO_ONE_ATTR(release);
474     DO_ONE_ATTR(statfs);
475     DO_ONE_ATTR(fsync);
476    
477     fuse = fuse_new(0, flags, &amp;op);
478     if(multithreaded)
479     pyfuse_loop_mt(fuse);
480     else
481     fuse_loop(fuse);
482    
483     //printf("Fuse_main: called\n");
484    
485     Py_INCREF(Py_None);
486     return Py_None;
487     }
488     </t>
489     <t tx="davidmcnab.121303142957.28">@ List of functions defined in the module
490     @c
491    
492     static PyMethodDef Fuse_methods[] = {
493     {"main", (PyCFunction)Fuse_main, METH_VARARGS|METH_KEYWORDS},
494     {NULL, NULL} /* sentinel */
495     };
496    
497    
498     /* Initialization function for the module (*must* be called init_fuse) */
499    
500     DL_EXPORT(void)
501     init_fuse(void)
502     {
503     PyObject *m, *d;
504     static PyObject *ErrorObject;
505    
506     /* Create the module and add the functions */
507     m = Py_InitModule("_fuse", Fuse_methods);
508    
509     /* Add some symbolic constants to the module */
510     d = PyModule_GetDict(m);
511     ErrorObject = PyErr_NewException("fuse.error", NULL, NULL);
512     PyDict_SetItemString(d, "error", ErrorObject);
513     PyDict_SetItemString(d, "DEBUG", PyInt_FromLong(FUSE_DEBUG));
514     }
515     </t>
516     <t tx="davidmcnab.121303142957.29">#
517     # Copyright (C) 2001 Jeff Epler &lt;jepler@unpythonic.dhs.org&gt;
518     #
519     # This program can be distributed under the terms of the GNU GPL.
520     # See the file COPYING.
521     #
522    
523    
524     @language python
525     @others
526     </t>
527     <t tx="davidmcnab.121303142957.30"># suppress version mismatch warnings
528     try:
529     import warnings
530     warnings.filterwarnings('ignore',
531     'Python C API version mismatch',
532     RuntimeWarning,
533     )
534     except:
535     pass
536    
537     from _fuse import main, DEBUG
538     import os, sys
539     from errno import *
540    
541     </t>
542     <t tx="davidmcnab.121303142957.31">class ErrnoWrapper:
543     @others
544     </t>
545     <t tx="davidmcnab.121303142957.32">def __init__(self, func):
546     self.func = func
547     </t>
548     <t tx="davidmcnab.121303142957.33">def __call__(self, *args, **kw):
549     try:
550     return apply(self.func, args, kw)
551     except (IOError, OSError), detail:
552     # Sometimes this is an int, sometimes an instance...
553     if hasattr(detail, "errno"): detail = detail.errno
554     return -detail
555     </t>
556     <t tx="davidmcnab.121303142957.34">class Fuse:
557    
558     @others
559     </t>
560     <t tx="davidmcnab.121303142957.35">_attrs = ['getattr', 'readlink', 'getdir', 'mknod', 'mkdir',
561     'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
562     'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release',
563     'statfs', 'fsync']
564    
565     flags = 0
566     multithreaded = 0
567    
568     </t>
569     <t tx="davidmcnab.121303142957.36">def __init__(self, *args, **kw):
570    
571     # default attributes
572     self.optlist = []
573     self.optdict = {}
574     self.mountpoint = None
575    
576     # grab arguments, if any
577     argv = sys.argv
578     argc = len(argv)
579     if argc &gt; 1:
580     # we've been given the mountpoint
581     self.mountpoint = argv[1]
582     if argc &gt; 2:
583     # we've received mount args
584     optstr = argv[2]
585     opts = optstr.split(",")
586     for o in opts:
587     try:
588     k, v = o.split("=", 1)
589     self.optdict[k] = v
590     except:
591     self.optlist.append(o)
592     </t>
593     <t tx="davidmcnab.121303142957.37">def main(self):
594     d = {'flags': self.flags}
595     d['multithreaded'] = self.multithreaded
596     for a in self._attrs:
597     if hasattr(self,a):
598     d[a] = ErrnoWrapper(getattr(self, a))
599     apply(main, (), d)
600     </t>
601     <t tx="davidmcnab.121303142957.38"># Makefile now uses distutils
602    
603     _fusemodule.so: _fusemodule.c
604     #gcc -g3 -I/usr/include/python2.1 _fusemodule.c -Wl,-shared -o _fusemodule.so -Wimplicit -lfuse &amp;&amp; python -c 'import _fuse'
605     python setup.py build_ext --inplace
606    
607     install: _fusemodule.so
608     python setup.py install
609    
610     clean:
611     rm -rf _fusemodule.so *.pyc *.pyo *~ build
612     </t>
613     <t tx="davidmcnab.121303142957.39">@first #!/usr/bin/env python
614     #
615     # Copyright (C) 2001 Jeff Epler &lt;jepler@unpythonic.dhs.org&gt;
616     #
617     # This program can be distributed under the terms of the GNU GPL.
618     # See the file COPYING.
619     #
620    
621     @others
622     </t>
623     <t tx="davidmcnab.121303142957.40">
624     from fuse import Fuse
625     import os
626     from errno import *
627     from stat import *
628    
629     import thread
630     </t>
631     <t tx="davidmcnab.121303142957.41">class Xmp(Fuse):
632    
633     @others
634     </t>
635     <t tx="davidmcnab.121303142957.42">def __init__(self, *args, **kw):
636    
637     Fuse.__init__(self, *args, **kw)
638    
639     if 0:
640     print "xmp.py:Xmp:mountpoint: %s" % repr(self.mountpoint)
641     print "xmp.py:Xmp:unnamed mount options: %s" % self.optlist
642     print "xmp.py:Xmp:named mount options: %s" % self.optdict
643    
644     # do stuff to set up your filesystem here, if you want
645     #thread.start_new_thread(self.mythread, ())
646     pass
647     </t>
648     <t tx="davidmcnab.121303142957.43">def mythread(self):
649    
650     """
651     The beauty of the FUSE python implementation is that with the python interp
652     running in foreground, you can have threads
653     """
654     print "mythread: started"
655     #while 1:
656     # time.sleep(120)
657     # print "mythread: ticking"
658    
659     </t>
660     <t tx="davidmcnab.121303142957.44">flags = 1
661    
662     </t>
663     <t tx="davidmcnab.121303142957.45">def getattr(self, path):
664     return os.lstat(path)
665     </t>
666     <t tx="davidmcnab.121303142957.46">def readlink(self, path):
667     return os.readlink(path)
668     </t>
669     <t tx="davidmcnab.121303142957.47">def getdir(self, path):
670     return map(lambda x: (x,0), os.listdir(path))
671     </t>
672     <t tx="davidmcnab.121303142957.48">def unlink(self, path):
673     return os.unlink(path)
674     </t>
675     <t tx="davidmcnab.121303142957.49">def rmdir(self, path):
676     return os.rmdir(path)
677     </t>
678     <t tx="davidmcnab.121303142957.50">def symlink(self, path, path1):
679     return os.symlink(path, path1)
680     </t>
681     <t tx="davidmcnab.121303142957.51">def rename(self, path, path1):
682     return os.rename(path, path1)
683     </t>
684     <t tx="davidmcnab.121303142957.52">def link(self, path, path1):
685     return os.link(path, path1)
686     </t>
687     <t tx="davidmcnab.121303142957.53">def chmod(self, path, mode):
688     return os.chmod(path, mode)
689     </t>
690     <t tx="davidmcnab.121303142957.54">def chown(self, path, user, group):
691     return os.chown(path, user, group)
692     </t>
693     <t tx="davidmcnab.121303142957.55">def truncate(self, path, size):
694     f = open(path, "w+")
695     return f.truncate(size)
696     </t>
697     <t tx="davidmcnab.121303142957.56">def mknod(self, path, mode, dev):
698     """ Python has no os.mknod, so we can only do some things """
699     if S_ISREG(mode):
700     open(path, "w")
701     else:
702     return -EINVAL
703     </t>
704     <t tx="davidmcnab.121303142957.57">def mkdir(self, path, mode):
705     return os.mkdir(path, mode)
706     </t>
707     <t tx="davidmcnab.121303142957.58">def utime(self, path, times):
708     return os.utime(path, times)
709     </t>
710     <t tx="davidmcnab.121303142957.59">def open(self, path, flags):
711     #print "xmp.py:Xmp:open: %s" % path
712     os.close(os.open(path, flags))
713     return 0
714    
715     </t>
716     <t tx="davidmcnab.121303142957.60">def read(self, path, len, offset):
717     #print "xmp.py:Xmp:read: %s" % path
718     f = open(path, "r")
719     f.seek(offset)
720     return f.read(len)
721    
722     </t>
723     <t tx="davidmcnab.121303142957.61">def write(self, path, buf, off):
724     #print "xmp.py:Xmp:write: %s" % path
725     f = open(path, "r+")
726     f.seek(off)
727     f.write(buf)
728     return len(buf)
729    
730     </t>
731     <t tx="davidmcnab.121303142957.62">def release(self, path, flags):
732     print "xmp.py:Xmp:release: %s %s" % (path, flags)
733     return 0
734     </t>
735     <t tx="davidmcnab.121303142957.63">
736     if __name__ == '__main__':
737    
738     server = Xmp()
739     server.flags = 0
740     server.multithreaded = 1;
741     server.main()
742     </t>
743     <t tx="davidmcnab.121303142957.64">"""
744     distutils script for FUSE python module
745     """
746    
747     from distutils.core import setup, Extension
748    
749     setup(name="fuse",
750     version="0.1",
751     ext_modules=[Extension("_fusemodule", ["_fusemodule.c"],
752     library_dirs=["../lib",],
753     libraries=["fuse",],
754     ),
755     ],
756     py_modules=["fuse"],
757     )
758    
759     </t>
760     <t tx="davidmcnab.121303142957.65">@language
761    
762     Refer to the INSTALL file for build/install instructions
763    
764     General Information
765     ===================
766    
767     This is a Python[1] interface to FUSE[2].
768    
769     FUSE (Filesystem in USErspace) is a simple interface for userspace
770     programs to export a virtual filesystem to the linux kernel. FUSE
771     also aims to provide a secure method for non privileged users to
772     create and mount their own filesystem implementations.
773    
774     When run from the commandline, "fuse.py" simply reexports the root
775     filesystem within the mount point as example/fusexmp does in the main
776     FUSE distribution. It also offers a class, fuse.Fuse, which can be
777     subclassed to create a filesystem. fuse.Xmp is the example filesystem
778     implementation.
779    
780     In your subclass of fuse, add attributes with the expected names
781     ("getattr", "readlink", etc) and call signatures (refer to fuse.Xmp)
782     then call main(). Make it runnable as a #! script, and mount with
783     fusermount &lt;mount point&gt; &lt;script name&gt;
784     for some reason,
785     fusermount &lt;mount point&gt; python &lt;script name&gt;
786     does not seem to work. (why?)
787    
788     Update
789     ======
790    
791     Updated 13-Dec-2003 by David McNab &lt;david@rebirthing.co.nz&gt;
792    
793     - changed Makefile to use Pyton distutils
794     - added setup.py for distutils
795    
796     - added 'code.leo' file for convenience of those who use the Leo
797     code editor (leo.sf.net)
798    
799     - added support for 'statfs' and 'fsync' methods (refer xmp.py)
800    
801     Updated Dec 2003 by David McNab &lt;david@rebirthing.co.nz&gt;:
802    
803     - added support for 'release' events (ie when file gets closed)
804     - added __init__ to base class, which picks off parameters and
805     stores them as instance attributes:
806     - self.mountpoint - the mountpoint as given in the mount command
807     - self.optlist - unnamed options (eg 'rw', 'exec' etc)
808     - self.optdict - named options (eg, '-o arg1=val1,arg2=val2...' from mount cmd)
809     - fixed incompatibility issues with recent pythons (original was broken
810     under python2.3)
811    
812     Limitations
813     ===========
814    
815     This is minimally tested, though I think I have exercised each function.
816     There's no documentation, docstrings, or tests.
817    
818     Python's lstat() does not return some fields which must be filled in
819     (st_blksize, st_blocks, st_ino), and _fusemodule assumes that the return
820     value from the lstat() method is identical to Python's lstat(). This
821     limitation should be lifted, and some standard order chosen for these
822     three values. For now, though, default values are chosen and du returns a
823     number similar to the "real" one.
824    
825     The Python Global Interpreter Lock is not handled, so using
826     fuse.MULTITHREAD will not work. Modifying the PROLOGUE and EPILOGUE
827     functions may take care of this. For now, just run without
828     fuse.MULTITHREAD in flags.
829    
830     Author
831     ======
832    
833     I'm Jeff Epler &lt;jepler@unpythonic.dhs.org&gt;. I've been dabbling in
834     Python for nearly 7 years now, and interested (despite the lack of a
835     real practical use) in userspace filesystems ever since I couldn't get
836     userfs to compile way back in '93 or so. FUSE is cool, but i'm still
837     not sure what it's good for in practical terms.
838    
839     I don't know how high a level of interest I'll maintain in this project,
840     so if you want to do something with it feel free to do so. Like FUSE,
841     this software is distributed under the terms of the GNU General Public
842     License, Version 2. Future versions, if any, will be available at [3].
843    
844    
845     [1] http://www.python.org
846     [2] http://sourceforge.net/projects/avf/
847     [3] http://unpythonic.dhs.org/~jepler/fuse/
848     </t>
849     <t tx="davidmcnab.121303142957.67">@first #!/usr/bin/env python
850    
851     """
852     This utility allows FUSE filesystems to be mounted with the regular *nix
853     'mount' command, or even be listed in /etc/fstab
854    
855     To enable this, you need to:
856     1. set execute-permission on this script
857     2. symlink this script into /sbin/mount.fuse
858    
859     Usage:
860    
861     You can use this in 3 ways:
862     1. mount -t fuse /path/to/script/or/program /path/of/mount/point [options]
863     2. mount -t fuse none /path/of/mount/point -o fs=/path/to/script/or/prog[,opt=val...]
864     3. in /etc/fstab, add:
865     /path/to/script/or/prog /path/of/mount/point fuse noauto[,...]
866     """
867    
868     import sys, os, time
869    
870     progname = sys.argv[0]
871    
872     def usage(ret):
873     print "Usage: %s /path/to/fuse/fs /path/of/mountpoint [-o options]" % progname
874     print "or: %s none /path/of/mountpoint [-o fs=/path/to/fuse/fs[,...]]" % progname
875     sys.exit(ret)
876    
877     def main():
878    
879     # initial sanity check
880     argc = len(sys.argv)
881     if argc &lt; 3 or sys.argv[3] != "-o":
882     usage(1)
883    
884     dev = sys.argv[1]
885     mountpoint = sys.argv[2]
886    
887     # grab options, if any
888     optdict = {}
889     optlist = []
890     if argc &gt; 4:
891     odata = sys.argv[4]
892     opts = odata.split(",")
893     #print opts
894     for o in opts:
895     try:
896     k, v = o.split("=", 1)
897     optdict[k] = v
898     except:
899     optlist.append(o)
900     else:
901     odata = ""
902    
903     #print sys.argv
904     if dev == 'none':
905     if not optdict.has_key("fs"):
906     print "%s: Must specify python file with 'fs' option\n" % progname
907     usage(1)
908     pyfile = optdict['fs']
909     else:
910     pyfile = dev
911    
912     if not os.path.isfile(pyfile):
913     print "%s: file %s doesn't exist, or is not a file" % (progname, pyfile)
914     sys.exit(1)
915     pypath = os.path.abspath(pyfile)
916    
917     #print optdict, optlist
918    
919     # all seems ok - run our fuse fs as a child
920     if os.fork() == 0:
921     os.system("fusermount -c -x %s %s %s %s" % (mountpoint, pypath, mountpoint, odata))
922     else:
923     #print "parent exiting..."
924     pass
925    
926     if __name__ == '__main__':
927     main()
928    
929     </t>
930     <t tx="davidmcnab.121303144134">def statfs(self):
931     """
932     Should return a tuple with the following 6 elements:
933     - blocksize - size of file blocks, in bytes
934     - totalblocks - total number of blocks in the filesystem
935     - freeblocks - number of free blocks
936     - totalfiles - total number of file inodes
937     - freefiles - nunber of free file inodes
938    
939     Feel free to set any of the above values to 0, which tells
940     the kernel that the info is not available.
941     """
942     print "xmp.py:Xmp:statfs: returning fictitious values"
943     blocks_size = 1024
944     blocks = 100000
945     blocks_free = 25000
946     files = 100000
947     files_free = 60000
948     namelen = 80
949     return (blocks_size, blocks, blocks_free, files, files_free, namelen)
950     </t>
951     <t tx="davidmcnab.121303144134.1">def fsync(self, path, isfsyncfile):
952     print "xmp.py:Xmp:fsync: path=%s, isfsyncfile=%s" % (path, isfsyncfile)
953     return 0
954    
955     </t>
956     <t tx="davidmcnab.121303144441">static int statfs_func(struct fuse_statfs *fst)
957     {
958     int i;
959     long retvalues[6];
960     PyObject *v = PyObject_CallFunction(statfs_cb, "");
961     PROLOGUE
962    
963     if (!PySequence_Check(v))
964     { goto OUT_DECREF; }
965     if (PySequence_Size(v) &lt; 6)
966     { goto OUT_DECREF; }
967     for(i=0; i&lt;6; i++)
968     {
969     PyObject *tmp = PySequence_GetItem(v, i);
970     retvalues[i] = PyInt_Check(tmp)
971     ? PyInt_AsLong(tmp)
972     : (PyLong_Check(tmp)
973     ? PyLong_AsLong(tmp)
974     : 0);
975     }
976    
977     fst-&gt;block_size = retvalues[0];
978     fst-&gt;blocks = retvalues[1];
979     fst-&gt;blocks_free = retvalues[2];
980     fst-&gt;files = retvalues[3];
981     fst-&gt;files_free = retvalues[4];
982     fst-&gt;namelen = retvalues[5];
983     ret = 0;
984    
985     #ifdef IGNORE_THIS
986     printf("block_size=%ld, blocks=%ld, blocks_free=%ld, files=%ld, files_free=%ld, namelen=%ld\n",
987     retvalues[0], retvalues[1], retvalues[2], retvalues[3], retvalues[4], retvalues[5]);
988     #endif
989    
990     EPILOGUE
991    
992     }
993    
994     </t>
995     <t tx="davidmcnab.121303144441.1">static int fsync_func(const char *path, int isfsyncfile)
996     {
997     PyObject *v = PyObject_CallFunction(fsync_cb, "si", path, isfsyncfile);
998     PROLOGUE
999     EPILOGUE
1000     }
1001    
1002     </t>
1003     <t tx="davidmcnab.121403050157">@ignore
1004     @language python
1005     &lt;&lt; fuse declarations &gt;&gt;
1006     @others
1007     #@-node:main
1008     #@-others
1009     #@-node:class Fuse
1010     #@-others
1011     #@-node:@file fuse.py
1012     #@-leo
1013     </t>
1014     <t tx="davidmcnab.121403050157.1">#@+leo-ver=4
1015     #@+node:@file fuse.py
1016     #
1017     # Copyright (C) 2001 Jeff Epler &lt;jepler@unpythonic.dhs.org&gt;
1018     #
1019     # This program can be distributed under the terms of the GNU GPL.
1020     # See the file COPYING.
1021     #
1022    
1023    
1024     #@@language python
1025     #@+others
1026     #@+node:imports
1027     # suppress version mismatch warnings
1028     try:
1029     import warnings
1030     warnings.filterwarnings('ignore',
1031     'Python C API version mismatch',
1032     RuntimeWarning,
1033     )
1034     except:
1035     pass
1036    
1037     from _fuse import main, DEBUG
1038     import os, sys
1039     from errno import *
1040    
1041     #@-node:imports
1042     #@+node:class ErrnoWrapper
1043     </t>
1044     <t tx="davidmcnab.121403050157.2">class ErrnoWrapper:
1045     &lt;&lt; class ErrnoWrapper declarations &gt;&gt;
1046     @others
1047     </t>
1048     <t tx="davidmcnab.121403050157.3"> #@ @+others
1049     #@+node:__init__
1050     </t>
1051     <t tx="davidmcnab.121403050157.4">def __init__(self, func):
1052     self.func = func
1053     </t>
1054     <t tx="davidmcnab.121403050157.5">#@-node:__init__
1055     #@+node:__call__
1056     def __call__(self, *args, **kw):
1057     try:
1058     return apply(self.func, args, kw)
1059     except (IOError, OSError), detail:
1060     # Sometimes this is an int, sometimes an instance...
1061     if hasattr(detail, "errno"): detail = detail.errno
1062     return -detail
1063     </t>
1064     <t tx="davidmcnab.121403050157.6"> #@-node:__call__
1065     #@-others
1066     #@-node:class ErrnoWrapper
1067     #@+node:class Fuse
1068     class Fuse:
1069     &lt;&lt; class Fuse declarations &gt;&gt;
1070     @others
1071     </t>
1072     <t tx="davidmcnab.121403050157.7">#@ @+others
1073     #@+node:attribs
1074     _attrs = ['getattr', 'readlink', 'getdir', 'mknod', 'mkdir',
1075     'unlink', 'rmdir', 'symlink', 'rename', 'link', 'chmod',
1076     'chown', 'truncate', 'utime', 'open', 'read', 'write', 'release',
1077     'statfs', 'fsync']
1078    
1079     flags = 0
1080     multithreaded = 0
1081    
1082     #@-node:attribs
1083     #@+node:__init__
1084     </t>
1085     <t tx="davidmcnab.121403050157.8">def __init__(self, *args, **kw):
1086    
1087     # default attributes
1088     self.optlist = []
1089     self.optdict = {}
1090     self.mountpoint = None
1091    
1092     # grab arguments, if any
1093     argv = sys.argv
1094     argc = len(argv)
1095     if argc &gt; 1:
1096     # we've been given the mountpoint
1097     self.mountpoint = argv[1]
1098     if argc &gt; 2:
1099     # we've received mount args
1100     optstr = argv[2]
1101     opts = optstr.split(",")
1102     for o in opts:
1103     try:
1104     k, v = o.split("=", 1)
1105     self.optdict[k] = v
1106     except:
1107     self.optlist.append(o)
1108     </t>
1109     <t tx="davidmcnab.121403050157.9">#@-node:__init__
1110     #@+node:main
1111     def main(self):
1112     d = {'flags': self.flags}
1113     d['multithreaded'] = self.multithreaded
1114     for a in self._attrs:
1115     if hasattr(self,a):
1116     d[a] = ErrnoWrapper(getattr(self, a))
1117     apply(main, (), d)
1118     </t>
1119     </tnodes>
1120     </leo_file>

  ViewVC Help
Powered by ViewVC 1.1.26