/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 <?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