Statistics
| Branch: | Tag: | Revision:

root / pithos / lib / fuse.py @ 6749c3bd

History | View | Annotate | Download (22.3 kB)

1 49350be7 Giorgos Verigakis
# Copyright (c) 2008 Giorgos Verigakis <verigak@gmail.com>
2 49350be7 Giorgos Verigakis
# 
3 49350be7 Giorgos Verigakis
# Permission to use, copy, modify, and distribute this software for any
4 49350be7 Giorgos Verigakis
# purpose with or without fee is hereby granted, provided that the above
5 49350be7 Giorgos Verigakis
# copyright notice and this permission notice appear in all copies.
6 49350be7 Giorgos Verigakis
# 
7 49350be7 Giorgos Verigakis
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 49350be7 Giorgos Verigakis
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 49350be7 Giorgos Verigakis
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 49350be7 Giorgos Verigakis
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 49350be7 Giorgos Verigakis
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 49350be7 Giorgos Verigakis
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 49350be7 Giorgos Verigakis
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 49350be7 Giorgos Verigakis
15 49350be7 Giorgos Verigakis
from __future__ import division
16 49350be7 Giorgos Verigakis
17 49350be7 Giorgos Verigakis
from ctypes import *
18 49350be7 Giorgos Verigakis
from ctypes.util import find_library
19 49350be7 Giorgos Verigakis
from errno import *
20 49350be7 Giorgos Verigakis
from functools import partial
21 49350be7 Giorgos Verigakis
from os import strerror
22 49350be7 Giorgos Verigakis
from platform import machine, system
23 49350be7 Giorgos Verigakis
from stat import S_IFDIR
24 49350be7 Giorgos Verigakis
from traceback import print_exc
25 49350be7 Giorgos Verigakis
26 49350be7 Giorgos Verigakis
27 49350be7 Giorgos Verigakis
class c_timespec(Structure):
28 49350be7 Giorgos Verigakis
    _fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)]
29 49350be7 Giorgos Verigakis
30 49350be7 Giorgos Verigakis
class c_utimbuf(Structure):
31 49350be7 Giorgos Verigakis
    _fields_ = [('actime', c_timespec), ('modtime', c_timespec)]
32 49350be7 Giorgos Verigakis
33 49350be7 Giorgos Verigakis
class c_stat(Structure):
34 49350be7 Giorgos Verigakis
    pass    # Platform dependent
35 49350be7 Giorgos Verigakis
36 49350be7 Giorgos Verigakis
_system = system()
37 49350be7 Giorgos Verigakis
if _system in ('Darwin', 'FreeBSD'):
38 49350be7 Giorgos Verigakis
    _libiconv = CDLL(find_library("iconv"), RTLD_GLOBAL)     # libfuse dependency
39 49350be7 Giorgos Verigakis
    ENOTSUP = 45
40 49350be7 Giorgos Verigakis
    c_dev_t = c_int32
41 49350be7 Giorgos Verigakis
    c_fsblkcnt_t = c_ulong
42 49350be7 Giorgos Verigakis
    c_fsfilcnt_t = c_ulong
43 49350be7 Giorgos Verigakis
    c_gid_t = c_uint32
44 49350be7 Giorgos Verigakis
    c_mode_t = c_uint16
45 49350be7 Giorgos Verigakis
    c_off_t = c_int64
46 49350be7 Giorgos Verigakis
    c_pid_t = c_int32
47 49350be7 Giorgos Verigakis
    c_uid_t = c_uint32
48 49350be7 Giorgos Verigakis
    setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
49 49350be7 Giorgos Verigakis
        c_size_t, c_int, c_uint32)
50 49350be7 Giorgos Verigakis
    getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
51 49350be7 Giorgos Verigakis
        c_size_t, c_uint32)
52 49350be7 Giorgos Verigakis
    c_stat._fields_ = [
53 49350be7 Giorgos Verigakis
        ('st_dev', c_dev_t),
54 49350be7 Giorgos Verigakis
        ('st_ino', c_uint32),
55 49350be7 Giorgos Verigakis
        ('st_mode', c_mode_t),
56 49350be7 Giorgos Verigakis
        ('st_nlink', c_uint16),
57 49350be7 Giorgos Verigakis
        ('st_uid', c_uid_t),
58 49350be7 Giorgos Verigakis
        ('st_gid', c_gid_t),
59 49350be7 Giorgos Verigakis
        ('st_rdev', c_dev_t),
60 49350be7 Giorgos Verigakis
        ('st_atimespec', c_timespec),
61 49350be7 Giorgos Verigakis
        ('st_mtimespec', c_timespec),
62 49350be7 Giorgos Verigakis
        ('st_ctimespec', c_timespec),
63 49350be7 Giorgos Verigakis
        ('st_size', c_off_t),
64 49350be7 Giorgos Verigakis
        ('st_blocks', c_int64),
65 49350be7 Giorgos Verigakis
        ('st_blksize', c_int32)]
66 49350be7 Giorgos Verigakis
elif _system == 'Linux':
67 49350be7 Giorgos Verigakis
    ENOTSUP = 95
68 49350be7 Giorgos Verigakis
    c_dev_t = c_ulonglong
69 49350be7 Giorgos Verigakis
    c_fsblkcnt_t = c_ulonglong
70 49350be7 Giorgos Verigakis
    c_fsfilcnt_t = c_ulonglong
71 49350be7 Giorgos Verigakis
    c_gid_t = c_uint
72 49350be7 Giorgos Verigakis
    c_mode_t = c_uint
73 49350be7 Giorgos Verigakis
    c_off_t = c_longlong
74 49350be7 Giorgos Verigakis
    c_pid_t = c_int
75 49350be7 Giorgos Verigakis
    c_uid_t = c_uint
76 49350be7 Giorgos Verigakis
    setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t, c_int)
77 49350be7 Giorgos Verigakis
    getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t)
78 49350be7 Giorgos Verigakis
    
79 49350be7 Giorgos Verigakis
    _machine = machine()
80 49350be7 Giorgos Verigakis
    if _machine == 'x86_64':
81 49350be7 Giorgos Verigakis
        c_stat._fields_ = [
82 49350be7 Giorgos Verigakis
            ('st_dev', c_dev_t),
83 49350be7 Giorgos Verigakis
            ('st_ino', c_ulong),
84 49350be7 Giorgos Verigakis
            ('st_nlink', c_ulong),
85 49350be7 Giorgos Verigakis
            ('st_mode', c_mode_t),
86 49350be7 Giorgos Verigakis
            ('st_uid', c_uid_t),
87 49350be7 Giorgos Verigakis
            ('st_gid', c_gid_t),
88 49350be7 Giorgos Verigakis
            ('__pad0', c_int),
89 49350be7 Giorgos Verigakis
            ('st_rdev', c_dev_t),
90 49350be7 Giorgos Verigakis
            ('st_size', c_off_t),
91 49350be7 Giorgos Verigakis
            ('st_blksize', c_long),
92 49350be7 Giorgos Verigakis
            ('st_blocks', c_long),
93 49350be7 Giorgos Verigakis
            ('st_atimespec', c_timespec),
94 49350be7 Giorgos Verigakis
            ('st_mtimespec', c_timespec),
95 49350be7 Giorgos Verigakis
            ('st_ctimespec', c_timespec)]
96 49350be7 Giorgos Verigakis
    elif _machine == 'ppc':
97 49350be7 Giorgos Verigakis
        c_stat._fields_ = [
98 49350be7 Giorgos Verigakis
            ('st_dev', c_dev_t),
99 49350be7 Giorgos Verigakis
            ('st_ino', c_ulonglong),
100 49350be7 Giorgos Verigakis
            ('st_mode', c_mode_t),
101 49350be7 Giorgos Verigakis
            ('st_nlink', c_uint),
102 49350be7 Giorgos Verigakis
            ('st_uid', c_uid_t),
103 49350be7 Giorgos Verigakis
            ('st_gid', c_gid_t),
104 49350be7 Giorgos Verigakis
            ('st_rdev', c_dev_t),
105 49350be7 Giorgos Verigakis
            ('__pad2', c_ushort),
106 49350be7 Giorgos Verigakis
            ('st_size', c_off_t),
107 49350be7 Giorgos Verigakis
            ('st_blksize', c_long),
108 49350be7 Giorgos Verigakis
            ('st_blocks', c_longlong),
109 49350be7 Giorgos Verigakis
            ('st_atimespec', c_timespec),
110 49350be7 Giorgos Verigakis
            ('st_mtimespec', c_timespec),
111 49350be7 Giorgos Verigakis
            ('st_ctimespec', c_timespec)]
112 49350be7 Giorgos Verigakis
    else:
113 49350be7 Giorgos Verigakis
        # i686, use as fallback for everything else
114 49350be7 Giorgos Verigakis
        c_stat._fields_ = [
115 49350be7 Giorgos Verigakis
            ('st_dev', c_dev_t),
116 49350be7 Giorgos Verigakis
            ('__pad1', c_ushort),
117 49350be7 Giorgos Verigakis
            ('__st_ino', c_ulong),
118 49350be7 Giorgos Verigakis
            ('st_mode', c_mode_t),
119 49350be7 Giorgos Verigakis
            ('st_nlink', c_uint),
120 49350be7 Giorgos Verigakis
            ('st_uid', c_uid_t),
121 49350be7 Giorgos Verigakis
            ('st_gid', c_gid_t),
122 49350be7 Giorgos Verigakis
            ('st_rdev', c_dev_t),
123 49350be7 Giorgos Verigakis
            ('__pad2', c_ushort),
124 49350be7 Giorgos Verigakis
            ('st_size', c_off_t),
125 49350be7 Giorgos Verigakis
            ('st_blksize', c_long),
126 49350be7 Giorgos Verigakis
            ('st_blocks', c_longlong),
127 49350be7 Giorgos Verigakis
            ('st_atimespec', c_timespec),
128 49350be7 Giorgos Verigakis
            ('st_mtimespec', c_timespec),
129 49350be7 Giorgos Verigakis
            ('st_ctimespec', c_timespec),
130 49350be7 Giorgos Verigakis
            ('st_ino', c_ulonglong)]
131 49350be7 Giorgos Verigakis
else:
132 49350be7 Giorgos Verigakis
    raise NotImplementedError('%s is not supported.' % _system)
133 49350be7 Giorgos Verigakis
134 49350be7 Giorgos Verigakis
135 49350be7 Giorgos Verigakis
class c_statvfs(Structure):
136 49350be7 Giorgos Verigakis
    _fields_ = [
137 49350be7 Giorgos Verigakis
        ('f_bsize', c_ulong),
138 49350be7 Giorgos Verigakis
        ('f_frsize', c_ulong),
139 49350be7 Giorgos Verigakis
        ('f_blocks', c_fsblkcnt_t),
140 49350be7 Giorgos Verigakis
        ('f_bfree', c_fsblkcnt_t),
141 49350be7 Giorgos Verigakis
        ('f_bavail', c_fsblkcnt_t),
142 49350be7 Giorgos Verigakis
        ('f_files', c_fsfilcnt_t),
143 49350be7 Giorgos Verigakis
        ('f_ffree', c_fsfilcnt_t),
144 49350be7 Giorgos Verigakis
        ('f_favail', c_fsfilcnt_t)]
145 49350be7 Giorgos Verigakis
146 49350be7 Giorgos Verigakis
if _system == 'FreeBSD':
147 49350be7 Giorgos Verigakis
    c_fsblkcnt_t = c_uint64
148 49350be7 Giorgos Verigakis
    c_fsfilcnt_t = c_uint64
149 49350be7 Giorgos Verigakis
    setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t, c_int)
150 49350be7 Giorgos Verigakis
    getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte), c_size_t)
151 49350be7 Giorgos Verigakis
    class c_statvfs(Structure):
152 49350be7 Giorgos Verigakis
        _fields_ = [
153 49350be7 Giorgos Verigakis
            ('f_bavail', c_fsblkcnt_t),
154 49350be7 Giorgos Verigakis
            ('f_bfree', c_fsblkcnt_t),
155 49350be7 Giorgos Verigakis
            ('f_blocks', c_fsblkcnt_t),
156 49350be7 Giorgos Verigakis
            ('f_favail', c_fsfilcnt_t),
157 49350be7 Giorgos Verigakis
            ('f_ffree', c_fsfilcnt_t),
158 49350be7 Giorgos Verigakis
            ('f_files', c_fsfilcnt_t),
159 49350be7 Giorgos Verigakis
            ('f_bsize', c_ulong),
160 49350be7 Giorgos Verigakis
            ('f_flag', c_ulong),
161 49350be7 Giorgos Verigakis
            ('f_frsize', c_ulong)]
162 49350be7 Giorgos Verigakis
163 49350be7 Giorgos Verigakis
class fuse_file_info(Structure):
164 49350be7 Giorgos Verigakis
    _fields_ = [
165 49350be7 Giorgos Verigakis
        ('flags', c_int),
166 49350be7 Giorgos Verigakis
        ('fh_old', c_ulong),
167 49350be7 Giorgos Verigakis
        ('writepage', c_int),
168 49350be7 Giorgos Verigakis
        ('direct_io', c_uint, 1),
169 49350be7 Giorgos Verigakis
        ('keep_cache', c_uint, 1),
170 49350be7 Giorgos Verigakis
        ('flush', c_uint, 1),
171 49350be7 Giorgos Verigakis
        ('padding', c_uint, 29),
172 49350be7 Giorgos Verigakis
        ('fh', c_uint64),
173 49350be7 Giorgos Verigakis
        ('lock_owner', c_uint64)]
174 49350be7 Giorgos Verigakis
175 49350be7 Giorgos Verigakis
class fuse_context(Structure):
176 49350be7 Giorgos Verigakis
    _fields_ = [
177 49350be7 Giorgos Verigakis
        ('fuse', c_voidp),
178 49350be7 Giorgos Verigakis
        ('uid', c_uid_t),
179 49350be7 Giorgos Verigakis
        ('gid', c_gid_t),
180 49350be7 Giorgos Verigakis
        ('pid', c_pid_t),
181 49350be7 Giorgos Verigakis
        ('private_data', c_voidp)]
182 49350be7 Giorgos Verigakis
183 49350be7 Giorgos Verigakis
class fuse_operations(Structure):
184 49350be7 Giorgos Verigakis
    _fields_ = [
185 49350be7 Giorgos Verigakis
        ('getattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_stat))),
186 49350be7 Giorgos Verigakis
        ('readlink', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t)),
187 49350be7 Giorgos Verigakis
        ('getdir', c_voidp),    # Deprecated, use readdir
188 49350be7 Giorgos Verigakis
        ('mknod', CFUNCTYPE(c_int, c_char_p, c_mode_t, c_dev_t)),
189 49350be7 Giorgos Verigakis
        ('mkdir', CFUNCTYPE(c_int, c_char_p, c_mode_t)),
190 49350be7 Giorgos Verigakis
        ('unlink', CFUNCTYPE(c_int, c_char_p)),
191 49350be7 Giorgos Verigakis
        ('rmdir', CFUNCTYPE(c_int, c_char_p)),
192 49350be7 Giorgos Verigakis
        ('symlink', CFUNCTYPE(c_int, c_char_p, c_char_p)),
193 49350be7 Giorgos Verigakis
        ('rename', CFUNCTYPE(c_int, c_char_p, c_char_p)),
194 49350be7 Giorgos Verigakis
        ('link', CFUNCTYPE(c_int, c_char_p, c_char_p)),
195 49350be7 Giorgos Verigakis
        ('chmod', CFUNCTYPE(c_int, c_char_p, c_mode_t)),
196 49350be7 Giorgos Verigakis
        ('chown', CFUNCTYPE(c_int, c_char_p, c_uid_t, c_gid_t)),
197 49350be7 Giorgos Verigakis
        ('truncate', CFUNCTYPE(c_int, c_char_p, c_off_t)),
198 49350be7 Giorgos Verigakis
        ('utime', c_voidp),     # Deprecated, use utimens
199 49350be7 Giorgos Verigakis
        ('open', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
200 49350be7 Giorgos Verigakis
        ('read', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t, c_off_t,
201 49350be7 Giorgos Verigakis
            POINTER(fuse_file_info))),
202 49350be7 Giorgos Verigakis
        ('write', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t, c_off_t,
203 49350be7 Giorgos Verigakis
            POINTER(fuse_file_info))),
204 49350be7 Giorgos Verigakis
        ('statfs', CFUNCTYPE(c_int, c_char_p, POINTER(c_statvfs))),
205 49350be7 Giorgos Verigakis
        ('flush', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
206 49350be7 Giorgos Verigakis
        ('release', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
207 49350be7 Giorgos Verigakis
        ('fsync', CFUNCTYPE(c_int, c_char_p, c_int, POINTER(fuse_file_info))),
208 49350be7 Giorgos Verigakis
        ('setxattr', setxattr_t),
209 49350be7 Giorgos Verigakis
        ('getxattr', getxattr_t),
210 49350be7 Giorgos Verigakis
        ('listxattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t)),
211 49350be7 Giorgos Verigakis
        ('removexattr', CFUNCTYPE(c_int, c_char_p, c_char_p)),
212 49350be7 Giorgos Verigakis
        ('opendir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
213 49350be7 Giorgos Verigakis
        ('readdir', CFUNCTYPE(c_int, c_char_p, c_voidp, CFUNCTYPE(c_int, c_voidp,
214 49350be7 Giorgos Verigakis
            c_char_p, POINTER(c_stat), c_off_t), c_off_t, POINTER(fuse_file_info))),
215 49350be7 Giorgos Verigakis
        ('releasedir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
216 49350be7 Giorgos Verigakis
        ('fsyncdir', CFUNCTYPE(c_int, c_char_p, c_int, POINTER(fuse_file_info))),
217 49350be7 Giorgos Verigakis
        ('init', CFUNCTYPE(c_voidp, c_voidp)),
218 49350be7 Giorgos Verigakis
        ('destroy', CFUNCTYPE(c_voidp, c_voidp)),
219 49350be7 Giorgos Verigakis
        ('access', CFUNCTYPE(c_int, c_char_p, c_int)),
220 49350be7 Giorgos Verigakis
        ('create', CFUNCTYPE(c_int, c_char_p, c_mode_t, POINTER(fuse_file_info))),
221 49350be7 Giorgos Verigakis
        ('ftruncate', CFUNCTYPE(c_int, c_char_p, c_off_t, POINTER(fuse_file_info))),
222 49350be7 Giorgos Verigakis
        ('fgetattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_stat),
223 49350be7 Giorgos Verigakis
            POINTER(fuse_file_info))),
224 49350be7 Giorgos Verigakis
        ('lock', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info), c_int, c_voidp)),
225 49350be7 Giorgos Verigakis
        ('utimens', CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf))),
226 49350be7 Giorgos Verigakis
        ('bmap', CFUNCTYPE(c_int, c_char_p, c_size_t, POINTER(c_ulonglong)))]
227 49350be7 Giorgos Verigakis
228 49350be7 Giorgos Verigakis
229 49350be7 Giorgos Verigakis
def time_of_timespec(ts):
230 49350be7 Giorgos Verigakis
    return ts.tv_sec + ts.tv_nsec / 10 ** 9
231 49350be7 Giorgos Verigakis
232 49350be7 Giorgos Verigakis
def set_st_attrs(st, attrs):
233 49350be7 Giorgos Verigakis
    for key, val in attrs.items():
234 49350be7 Giorgos Verigakis
        if key in ('st_atime', 'st_mtime', 'st_ctime'):
235 49350be7 Giorgos Verigakis
            timespec = getattr(st, key + 'spec')
236 49350be7 Giorgos Verigakis
            timespec.tv_sec = int(val)
237 49350be7 Giorgos Verigakis
            timespec.tv_nsec = int((val - timespec.tv_sec) * 10 ** 9)
238 49350be7 Giorgos Verigakis
        elif hasattr(st, key):
239 49350be7 Giorgos Verigakis
            setattr(st, key, val)
240 49350be7 Giorgos Verigakis
241 49350be7 Giorgos Verigakis
242 49350be7 Giorgos Verigakis
_libfuse_path = find_library('fuse')
243 49350be7 Giorgos Verigakis
if not _libfuse_path:
244 49350be7 Giorgos Verigakis
    raise EnvironmentError('Unable to find libfuse')
245 49350be7 Giorgos Verigakis
_libfuse = CDLL(_libfuse_path)
246 49350be7 Giorgos Verigakis
_libfuse.fuse_get_context.restype = POINTER(fuse_context)
247 49350be7 Giorgos Verigakis
248 49350be7 Giorgos Verigakis
249 49350be7 Giorgos Verigakis
def fuse_get_context():
250 49350be7 Giorgos Verigakis
    """Returns a (uid, gid, pid) tuple"""
251 49350be7 Giorgos Verigakis
    ctxp = _libfuse.fuse_get_context()
252 49350be7 Giorgos Verigakis
    ctx = ctxp.contents
253 49350be7 Giorgos Verigakis
    return ctx.uid, ctx.gid, ctx.pid
254 49350be7 Giorgos Verigakis
255 49350be7 Giorgos Verigakis
256 49350be7 Giorgos Verigakis
class FuseOSError(OSError):
257 49350be7 Giorgos Verigakis
    def __init__(self, errno):
258 49350be7 Giorgos Verigakis
        super(FuseOSError, self).__init__(errno, strerror(errno))
259 49350be7 Giorgos Verigakis
260 49350be7 Giorgos Verigakis
261 49350be7 Giorgos Verigakis
class FUSE(object):
262 49350be7 Giorgos Verigakis
    """This class is the lower level interface and should not be subclassed
263 49350be7 Giorgos Verigakis
       under normal use. Its methods are called by fuse.
264 49350be7 Giorgos Verigakis
       Assumes API version 2.6 or later."""
265 49350be7 Giorgos Verigakis
    
266 49350be7 Giorgos Verigakis
    def __init__(self, operations, mountpoint, raw_fi=False, **kwargs):
267 49350be7 Giorgos Verigakis
        """Setting raw_fi to True will cause FUSE to pass the fuse_file_info
268 49350be7 Giorgos Verigakis
           class as is to Operations, instead of just the fh field.
269 49350be7 Giorgos Verigakis
           This gives you access to direct_io, keep_cache, etc."""
270 49350be7 Giorgos Verigakis
        
271 49350be7 Giorgos Verigakis
        self.operations = operations
272 49350be7 Giorgos Verigakis
        self.raw_fi = raw_fi
273 49350be7 Giorgos Verigakis
        args = ['fuse']
274 49350be7 Giorgos Verigakis
        if kwargs.pop('foreground', False):
275 49350be7 Giorgos Verigakis
            args.append('-f')
276 49350be7 Giorgos Verigakis
        if kwargs.pop('debug', False):
277 49350be7 Giorgos Verigakis
            args.append('-d')
278 49350be7 Giorgos Verigakis
        if kwargs.pop('nothreads', False):
279 49350be7 Giorgos Verigakis
            args.append('-s')
280 49350be7 Giorgos Verigakis
        kwargs.setdefault('fsname', operations.__class__.__name__)
281 49350be7 Giorgos Verigakis
        args.append('-o')
282 49350be7 Giorgos Verigakis
        args.append(','.join(key if val == True else '%s=%s' % (key, val)
283 49350be7 Giorgos Verigakis
            for key, val in kwargs.items()))
284 49350be7 Giorgos Verigakis
        args.append(mountpoint)
285 49350be7 Giorgos Verigakis
        argv = (c_char_p * len(args))(*args)
286 49350be7 Giorgos Verigakis
        
287 49350be7 Giorgos Verigakis
        fuse_ops = fuse_operations()
288 49350be7 Giorgos Verigakis
        for name, prototype in fuse_operations._fields_:
289 49350be7 Giorgos Verigakis
            if prototype != c_voidp and getattr(operations, name, None):
290 49350be7 Giorgos Verigakis
                op = partial(self._wrapper_, getattr(self, name))
291 49350be7 Giorgos Verigakis
                setattr(fuse_ops, name, prototype(op))
292 49350be7 Giorgos Verigakis
        err = _libfuse.fuse_main_real(len(args), argv, pointer(fuse_ops),
293 49350be7 Giorgos Verigakis
            sizeof(fuse_ops), None)            
294 49350be7 Giorgos Verigakis
        del self.operations     # Invoke the destructor
295 49350be7 Giorgos Verigakis
        if err:
296 49350be7 Giorgos Verigakis
            raise RuntimeError(err)
297 49350be7 Giorgos Verigakis
    
298 49350be7 Giorgos Verigakis
    def _wrapper_(self, func, *args, **kwargs):
299 49350be7 Giorgos Verigakis
        """Decorator for the methods that follow"""
300 49350be7 Giorgos Verigakis
        try:
301 49350be7 Giorgos Verigakis
            return func(*args, **kwargs) or 0
302 49350be7 Giorgos Verigakis
        except OSError, e:
303 49350be7 Giorgos Verigakis
            return -(e.errno or EFAULT)
304 49350be7 Giorgos Verigakis
        except:
305 49350be7 Giorgos Verigakis
            print_exc()
306 49350be7 Giorgos Verigakis
            return -EFAULT
307 49350be7 Giorgos Verigakis
    
308 49350be7 Giorgos Verigakis
    def getattr(self, path, buf):
309 49350be7 Giorgos Verigakis
        return self.fgetattr(path, buf, None)
310 49350be7 Giorgos Verigakis
    
311 49350be7 Giorgos Verigakis
    def readlink(self, path, buf, bufsize):
312 49350be7 Giorgos Verigakis
        ret = self.operations('readlink', path)
313 49350be7 Giorgos Verigakis
        data = create_string_buffer(ret[:bufsize - 1])
314 49350be7 Giorgos Verigakis
        memmove(buf, data, len(data))
315 49350be7 Giorgos Verigakis
        return 0
316 49350be7 Giorgos Verigakis
    
317 49350be7 Giorgos Verigakis
    def mknod(self, path, mode, dev):
318 49350be7 Giorgos Verigakis
        return self.operations('mknod', path, mode, dev)
319 49350be7 Giorgos Verigakis
    
320 49350be7 Giorgos Verigakis
    def mkdir(self, path, mode):
321 49350be7 Giorgos Verigakis
        return self.operations('mkdir', path, mode)
322 49350be7 Giorgos Verigakis
    
323 49350be7 Giorgos Verigakis
    def unlink(self, path):
324 49350be7 Giorgos Verigakis
        return self.operations('unlink', path)
325 49350be7 Giorgos Verigakis
    
326 49350be7 Giorgos Verigakis
    def rmdir(self, path):
327 49350be7 Giorgos Verigakis
        return self.operations('rmdir', path)
328 49350be7 Giorgos Verigakis
    
329 49350be7 Giorgos Verigakis
    def symlink(self, source, target):
330 49350be7 Giorgos Verigakis
        return self.operations('symlink', target, source)
331 49350be7 Giorgos Verigakis
    
332 49350be7 Giorgos Verigakis
    def rename(self, old, new):
333 49350be7 Giorgos Verigakis
        return self.operations('rename', old, new)
334 49350be7 Giorgos Verigakis
    
335 49350be7 Giorgos Verigakis
    def link(self, source, target):
336 49350be7 Giorgos Verigakis
        return self.operations('link', target, source)
337 49350be7 Giorgos Verigakis
    
338 49350be7 Giorgos Verigakis
    def chmod(self, path, mode):
339 49350be7 Giorgos Verigakis
        return self.operations('chmod', path, mode)
340 49350be7 Giorgos Verigakis
    
341 49350be7 Giorgos Verigakis
    def chown(self, path, uid, gid):
342 49350be7 Giorgos Verigakis
        # Check if any of the arguments is a -1 that has overflowed
343 49350be7 Giorgos Verigakis
        if c_uid_t(uid + 1).value == 0:
344 49350be7 Giorgos Verigakis
            uid = -1
345 49350be7 Giorgos Verigakis
        if c_gid_t(gid + 1).value == 0:
346 49350be7 Giorgos Verigakis
            gid = -1
347 49350be7 Giorgos Verigakis
        return self.operations('chown', path, uid, gid)
348 49350be7 Giorgos Verigakis
    
349 49350be7 Giorgos Verigakis
    def truncate(self, path, length):
350 49350be7 Giorgos Verigakis
        return self.operations('truncate', path, length)
351 49350be7 Giorgos Verigakis
    
352 49350be7 Giorgos Verigakis
    def open(self, path, fip):
353 49350be7 Giorgos Verigakis
        fi = fip.contents
354 49350be7 Giorgos Verigakis
        if self.raw_fi:
355 49350be7 Giorgos Verigakis
            return self.operations('open', path, fi)
356 49350be7 Giorgos Verigakis
        else:
357 49350be7 Giorgos Verigakis
            fi.fh = self.operations('open', path, fi.flags)
358 49350be7 Giorgos Verigakis
            return 0
359 49350be7 Giorgos Verigakis
    
360 49350be7 Giorgos Verigakis
    def read(self, path, buf, size, offset, fip):
361 49350be7 Giorgos Verigakis
        fh = fip.contents if self.raw_fi else fip.contents.fh
362 49350be7 Giorgos Verigakis
        ret = self.operations('read', path, size, offset, fh)
363 49350be7 Giorgos Verigakis
        if not ret:
364 49350be7 Giorgos Verigakis
            return 0
365 49350be7 Giorgos Verigakis
        data = create_string_buffer(ret[:size], size)
366 49350be7 Giorgos Verigakis
        memmove(buf, data, size)
367 49350be7 Giorgos Verigakis
        return size
368 49350be7 Giorgos Verigakis
    
369 49350be7 Giorgos Verigakis
    def write(self, path, buf, size, offset, fip):
370 49350be7 Giorgos Verigakis
        data = string_at(buf, size)
371 49350be7 Giorgos Verigakis
        fh = fip.contents if self.raw_fi else fip.contents.fh
372 49350be7 Giorgos Verigakis
        return self.operations('write', path, data, offset, fh)
373 49350be7 Giorgos Verigakis
    
374 49350be7 Giorgos Verigakis
    def statfs(self, path, buf):
375 49350be7 Giorgos Verigakis
        stv = buf.contents
376 49350be7 Giorgos Verigakis
        attrs = self.operations('statfs', path)
377 49350be7 Giorgos Verigakis
        for key, val in attrs.items():
378 49350be7 Giorgos Verigakis
            if hasattr(stv, key):
379 49350be7 Giorgos Verigakis
                setattr(stv, key, val)
380 49350be7 Giorgos Verigakis
        return 0
381 49350be7 Giorgos Verigakis
    
382 49350be7 Giorgos Verigakis
    def flush(self, path, fip):
383 49350be7 Giorgos Verigakis
        fh = fip.contents if self.raw_fi else fip.contents.fh
384 49350be7 Giorgos Verigakis
        return self.operations('flush', path, fh)
385 49350be7 Giorgos Verigakis
    
386 49350be7 Giorgos Verigakis
    def release(self, path, fip):
387 49350be7 Giorgos Verigakis
        fh = fip.contents if self.raw_fi else fip.contents.fh
388 49350be7 Giorgos Verigakis
        return self.operations('release', path, fh)
389 49350be7 Giorgos Verigakis
    
390 49350be7 Giorgos Verigakis
    def fsync(self, path, datasync, fip):
391 49350be7 Giorgos Verigakis
        fh = fip.contents if self.raw_fi else fip.contents.fh
392 49350be7 Giorgos Verigakis
        return self.operations('fsync', path, datasync, fh)
393 49350be7 Giorgos Verigakis
    
394 49350be7 Giorgos Verigakis
    def setxattr(self, path, name, value, size, options, *args):
395 49350be7 Giorgos Verigakis
        data = string_at(value, size)
396 49350be7 Giorgos Verigakis
        return self.operations('setxattr', path, name, data, options, *args)
397 49350be7 Giorgos Verigakis
    
398 49350be7 Giorgos Verigakis
    def getxattr(self, path, name, value, size, *args):
399 49350be7 Giorgos Verigakis
        ret = self.operations('getxattr', path, name, *args)
400 49350be7 Giorgos Verigakis
        retsize = len(ret)
401 49350be7 Giorgos Verigakis
        buf = create_string_buffer(ret, retsize)    # Does not add trailing 0
402 49350be7 Giorgos Verigakis
        if bool(value):
403 49350be7 Giorgos Verigakis
            if retsize > size:
404 49350be7 Giorgos Verigakis
                return -ERANGE
405 49350be7 Giorgos Verigakis
            memmove(value, buf, retsize)
406 49350be7 Giorgos Verigakis
        return retsize
407 49350be7 Giorgos Verigakis
    
408 49350be7 Giorgos Verigakis
    def listxattr(self, path, namebuf, size):
409 49350be7 Giorgos Verigakis
        ret = self.operations('listxattr', path)
410 49350be7 Giorgos Verigakis
        buf = create_string_buffer('\x00'.join(ret)) if ret else ''
411 49350be7 Giorgos Verigakis
        bufsize = len(buf)
412 49350be7 Giorgos Verigakis
        if bool(namebuf):
413 49350be7 Giorgos Verigakis
            if bufsize > size:
414 49350be7 Giorgos Verigakis
                return -ERANGE
415 49350be7 Giorgos Verigakis
            memmove(namebuf, buf, bufsize)
416 49350be7 Giorgos Verigakis
        return bufsize
417 49350be7 Giorgos Verigakis
    
418 49350be7 Giorgos Verigakis
    def removexattr(self, path, name):
419 49350be7 Giorgos Verigakis
        return self.operations('removexattr', path, name)
420 49350be7 Giorgos Verigakis
    
421 49350be7 Giorgos Verigakis
    def opendir(self, path, fip):
422 49350be7 Giorgos Verigakis
        # Ignore raw_fi
423 49350be7 Giorgos Verigakis
        fip.contents.fh = self.operations('opendir', path)
424 49350be7 Giorgos Verigakis
        return 0
425 49350be7 Giorgos Verigakis
    
426 49350be7 Giorgos Verigakis
    def readdir(self, path, buf, filler, offset, fip):
427 49350be7 Giorgos Verigakis
        # Ignore raw_fi
428 49350be7 Giorgos Verigakis
        for item in self.operations('readdir', path, fip.contents.fh):
429 49350be7 Giorgos Verigakis
            if isinstance(item, (str, unicode)):
430 49350be7 Giorgos Verigakis
                name, st, offset = item, None, 0
431 49350be7 Giorgos Verigakis
            else:
432 49350be7 Giorgos Verigakis
                name, attrs, offset = item
433 49350be7 Giorgos Verigakis
                if attrs:
434 49350be7 Giorgos Verigakis
                    st = c_stat()
435 49350be7 Giorgos Verigakis
                    set_st_attrs(st, attrs)
436 49350be7 Giorgos Verigakis
                else:
437 49350be7 Giorgos Verigakis
                    st = None
438 49350be7 Giorgos Verigakis
            if filler(buf, name, st, offset) != 0:
439 49350be7 Giorgos Verigakis
                break
440 49350be7 Giorgos Verigakis
        return 0
441 49350be7 Giorgos Verigakis
    
442 49350be7 Giorgos Verigakis
    def releasedir(self, path, fip):
443 49350be7 Giorgos Verigakis
        # Ignore raw_fi
444 49350be7 Giorgos Verigakis
        return self.operations('releasedir', path, fip.contents.fh)
445 49350be7 Giorgos Verigakis
    
446 49350be7 Giorgos Verigakis
    def fsyncdir(self, path, datasync, fip):
447 49350be7 Giorgos Verigakis
        # Ignore raw_fi
448 49350be7 Giorgos Verigakis
        return self.operations('fsyncdir', path, datasync, fip.contents.fh)
449 49350be7 Giorgos Verigakis
    
450 49350be7 Giorgos Verigakis
    def init(self, conn):
451 49350be7 Giorgos Verigakis
        return self.operations('init', '/')
452 49350be7 Giorgos Verigakis
    
453 49350be7 Giorgos Verigakis
    def destroy(self, private_data):
454 49350be7 Giorgos Verigakis
        return self.operations('destroy', '/')
455 49350be7 Giorgos Verigakis
    
456 49350be7 Giorgos Verigakis
    def access(self, path, amode):
457 49350be7 Giorgos Verigakis
        return self.operations('access', path, amode)
458 49350be7 Giorgos Verigakis
    
459 49350be7 Giorgos Verigakis
    def create(self, path, mode, fip):
460 49350be7 Giorgos Verigakis
        fi = fip.contents
461 49350be7 Giorgos Verigakis
        if self.raw_fi:
462 49350be7 Giorgos Verigakis
            return self.operations('create', path, mode, fi)
463 49350be7 Giorgos Verigakis
        else:
464 49350be7 Giorgos Verigakis
            fi.fh = self.operations('create', path, mode)
465 49350be7 Giorgos Verigakis
            return 0
466 49350be7 Giorgos Verigakis
    
467 49350be7 Giorgos Verigakis
    def ftruncate(self, path, length, fip):
468 49350be7 Giorgos Verigakis
        fh = fip.contents if self.raw_fi else fip.contents.fh
469 49350be7 Giorgos Verigakis
        return self.operations('truncate', path, length, fh)
470 49350be7 Giorgos Verigakis
    
471 49350be7 Giorgos Verigakis
    def fgetattr(self, path, buf, fip):
472 49350be7 Giorgos Verigakis
        memset(buf, 0, sizeof(c_stat))
473 49350be7 Giorgos Verigakis
        st = buf.contents
474 49350be7 Giorgos Verigakis
        fh = fip and (fip.contents if self.raw_fi else fip.contents.fh)
475 49350be7 Giorgos Verigakis
        attrs = self.operations('getattr', path, fh)
476 49350be7 Giorgos Verigakis
        set_st_attrs(st, attrs)
477 49350be7 Giorgos Verigakis
        return 0
478 49350be7 Giorgos Verigakis
    
479 49350be7 Giorgos Verigakis
    def lock(self, path, fip, cmd, lock):
480 49350be7 Giorgos Verigakis
        fh = fip.contents if self.raw_fi else fip.contents.fh
481 49350be7 Giorgos Verigakis
        return self.operations('lock', path, fh, cmd, lock)
482 49350be7 Giorgos Verigakis
    
483 49350be7 Giorgos Verigakis
    def utimens(self, path, buf):
484 49350be7 Giorgos Verigakis
        if buf:
485 49350be7 Giorgos Verigakis
            atime = time_of_timespec(buf.contents.actime)
486 49350be7 Giorgos Verigakis
            mtime = time_of_timespec(buf.contents.modtime)
487 49350be7 Giorgos Verigakis
            times = (atime, mtime)
488 49350be7 Giorgos Verigakis
        else:
489 49350be7 Giorgos Verigakis
            times = None
490 49350be7 Giorgos Verigakis
        return self.operations('utimens', path, times)
491 49350be7 Giorgos Verigakis
    
492 49350be7 Giorgos Verigakis
    def bmap(self, path, blocksize, idx):
493 49350be7 Giorgos Verigakis
        return self.operations('bmap', path, blocksize, idx)
494 49350be7 Giorgos Verigakis
495 49350be7 Giorgos Verigakis
496 49350be7 Giorgos Verigakis
class Operations(object):
497 49350be7 Giorgos Verigakis
    """This class should be subclassed and passed as an argument to FUSE on
498 49350be7 Giorgos Verigakis
       initialization. All operations should raise a FuseOSError exception
499 49350be7 Giorgos Verigakis
       on error.
500 49350be7 Giorgos Verigakis
       
501 49350be7 Giorgos Verigakis
       When in doubt of what an operation should do, check the FUSE header
502 49350be7 Giorgos Verigakis
       file or the corresponding system call man page."""
503 49350be7 Giorgos Verigakis
    
504 49350be7 Giorgos Verigakis
    def __call__(self, op, *args):
505 49350be7 Giorgos Verigakis
        if not hasattr(self, op):
506 49350be7 Giorgos Verigakis
            raise FuseOSError(EFAULT)
507 49350be7 Giorgos Verigakis
        return getattr(self, op)(*args)
508 49350be7 Giorgos Verigakis
        
509 49350be7 Giorgos Verigakis
    def access(self, path, amode):
510 49350be7 Giorgos Verigakis
        return 0
511 49350be7 Giorgos Verigakis
    
512 49350be7 Giorgos Verigakis
    bmap = None
513 49350be7 Giorgos Verigakis
    
514 49350be7 Giorgos Verigakis
    def chmod(self, path, mode):
515 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
516 49350be7 Giorgos Verigakis
    
517 49350be7 Giorgos Verigakis
    def chown(self, path, uid, gid):
518 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
519 49350be7 Giorgos Verigakis
    
520 49350be7 Giorgos Verigakis
    def create(self, path, mode, fi=None):
521 49350be7 Giorgos Verigakis
        """When raw_fi is False (default case), fi is None and create should
522 49350be7 Giorgos Verigakis
           return a numerical file handle.
523 49350be7 Giorgos Verigakis
           When raw_fi is True the file handle should be set directly by create
524 49350be7 Giorgos Verigakis
           and return 0."""
525 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
526 49350be7 Giorgos Verigakis
    
527 49350be7 Giorgos Verigakis
    def destroy(self, path):
528 49350be7 Giorgos Verigakis
        """Called on filesystem destruction. Path is always /"""
529 49350be7 Giorgos Verigakis
        pass
530 49350be7 Giorgos Verigakis
    
531 49350be7 Giorgos Verigakis
    def flush(self, path, fh):
532 49350be7 Giorgos Verigakis
        return 0
533 49350be7 Giorgos Verigakis
    
534 49350be7 Giorgos Verigakis
    def fsync(self, path, datasync, fh):
535 49350be7 Giorgos Verigakis
        return 0
536 49350be7 Giorgos Verigakis
    
537 49350be7 Giorgos Verigakis
    def fsyncdir(self, path, datasync, fh):
538 49350be7 Giorgos Verigakis
        return 0
539 49350be7 Giorgos Verigakis
    
540 49350be7 Giorgos Verigakis
    def getattr(self, path, fh=None):
541 49350be7 Giorgos Verigakis
        """Returns a dictionary with keys identical to the stat C structure
542 49350be7 Giorgos Verigakis
           of stat(2).
543 49350be7 Giorgos Verigakis
           st_atime, st_mtime and st_ctime should be floats.
544 49350be7 Giorgos Verigakis
           NOTE: There is an incombatibility between Linux and Mac OS X concerning
545 49350be7 Giorgos Verigakis
           st_nlink of directories. Mac OS X counts all files inside the directory,
546 49350be7 Giorgos Verigakis
           while Linux counts only the subdirectories."""
547 49350be7 Giorgos Verigakis
        
548 49350be7 Giorgos Verigakis
        if path != '/':
549 49350be7 Giorgos Verigakis
            raise FuseOSError(ENOENT)
550 49350be7 Giorgos Verigakis
        return dict(st_mode=(S_IFDIR | 0755), st_nlink=2)
551 49350be7 Giorgos Verigakis
    
552 49350be7 Giorgos Verigakis
    def getxattr(self, path, name, position=0):
553 49350be7 Giorgos Verigakis
        raise FuseOSError(ENOTSUP)
554 49350be7 Giorgos Verigakis
    
555 49350be7 Giorgos Verigakis
    def init(self, path):
556 49350be7 Giorgos Verigakis
        """Called on filesystem initialization. Path is always /
557 49350be7 Giorgos Verigakis
           Use it instead of __init__ if you start threads on initialization."""
558 49350be7 Giorgos Verigakis
        pass
559 49350be7 Giorgos Verigakis
    
560 49350be7 Giorgos Verigakis
    def link(self, target, source):
561 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
562 49350be7 Giorgos Verigakis
    
563 49350be7 Giorgos Verigakis
    def listxattr(self, path):
564 49350be7 Giorgos Verigakis
        return []
565 49350be7 Giorgos Verigakis
        
566 49350be7 Giorgos Verigakis
    lock = None
567 49350be7 Giorgos Verigakis
    
568 49350be7 Giorgos Verigakis
    def mkdir(self, path, mode):
569 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
570 49350be7 Giorgos Verigakis
    
571 49350be7 Giorgos Verigakis
    def mknod(self, path, mode, dev):
572 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
573 49350be7 Giorgos Verigakis
    
574 49350be7 Giorgos Verigakis
    def open(self, path, flags):
575 49350be7 Giorgos Verigakis
        """When raw_fi is False (default case), open should return a numerical
576 49350be7 Giorgos Verigakis
           file handle.
577 49350be7 Giorgos Verigakis
           When raw_fi is True the signature of open becomes:
578 49350be7 Giorgos Verigakis
               open(self, path, fi)
579 49350be7 Giorgos Verigakis
           and the file handle should be set directly."""
580 49350be7 Giorgos Verigakis
        return 0
581 49350be7 Giorgos Verigakis
    
582 49350be7 Giorgos Verigakis
    def opendir(self, path):
583 49350be7 Giorgos Verigakis
        """Returns a numerical file handle."""
584 49350be7 Giorgos Verigakis
        return 0
585 49350be7 Giorgos Verigakis
    
586 49350be7 Giorgos Verigakis
    def read(self, path, size, offset, fh):
587 49350be7 Giorgos Verigakis
        """Returns a string containing the data requested."""
588 49350be7 Giorgos Verigakis
        raise FuseOSError(EIO)
589 49350be7 Giorgos Verigakis
    
590 49350be7 Giorgos Verigakis
    def readdir(self, path, fh):
591 49350be7 Giorgos Verigakis
        """Can return either a list of names, or a list of (name, attrs, offset)
592 49350be7 Giorgos Verigakis
           tuples. attrs is a dict as in getattr."""
593 49350be7 Giorgos Verigakis
        return ['.', '..']
594 49350be7 Giorgos Verigakis
    
595 49350be7 Giorgos Verigakis
    def readlink(self, path):
596 49350be7 Giorgos Verigakis
        raise FuseOSError(ENOENT)
597 49350be7 Giorgos Verigakis
    
598 49350be7 Giorgos Verigakis
    def release(self, path, fh):
599 49350be7 Giorgos Verigakis
        return 0
600 49350be7 Giorgos Verigakis
    
601 49350be7 Giorgos Verigakis
    def releasedir(self, path, fh):
602 49350be7 Giorgos Verigakis
        return 0
603 49350be7 Giorgos Verigakis
    
604 49350be7 Giorgos Verigakis
    def removexattr(self, path, name):
605 49350be7 Giorgos Verigakis
        raise FuseOSError(ENOTSUP)
606 49350be7 Giorgos Verigakis
    
607 49350be7 Giorgos Verigakis
    def rename(self, old, new):
608 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
609 49350be7 Giorgos Verigakis
    
610 49350be7 Giorgos Verigakis
    def rmdir(self, path):
611 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
612 49350be7 Giorgos Verigakis
    
613 49350be7 Giorgos Verigakis
    def setxattr(self, path, name, value, options, position=0):
614 49350be7 Giorgos Verigakis
        raise FuseOSError(ENOTSUP)
615 49350be7 Giorgos Verigakis
    
616 49350be7 Giorgos Verigakis
    def statfs(self, path):
617 49350be7 Giorgos Verigakis
        """Returns a dictionary with keys identical to the statvfs C structure
618 49350be7 Giorgos Verigakis
           of statvfs(3).
619 49350be7 Giorgos Verigakis
           On Mac OS X f_bsize and f_frsize must be a power of 2 (minimum 512)."""
620 49350be7 Giorgos Verigakis
        return {}
621 49350be7 Giorgos Verigakis
    
622 49350be7 Giorgos Verigakis
    def symlink(self, target, source):
623 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
624 49350be7 Giorgos Verigakis
    
625 49350be7 Giorgos Verigakis
    def truncate(self, path, length, fh=None):
626 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
627 49350be7 Giorgos Verigakis
    
628 49350be7 Giorgos Verigakis
    def unlink(self, path):
629 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
630 49350be7 Giorgos Verigakis
    
631 49350be7 Giorgos Verigakis
    def utimens(self, path, times=None):
632 49350be7 Giorgos Verigakis
        """Times is a (atime, mtime) tuple. If None use current time."""
633 49350be7 Giorgos Verigakis
        return 0
634 49350be7 Giorgos Verigakis
    
635 49350be7 Giorgos Verigakis
    def write(self, path, data, offset, fh):
636 49350be7 Giorgos Verigakis
        raise FuseOSError(EROFS)
637 49350be7 Giorgos Verigakis
638 49350be7 Giorgos Verigakis
639 49350be7 Giorgos Verigakis
class LoggingMixIn:
640 49350be7 Giorgos Verigakis
    def __call__(self, op, path, *args):
641 49350be7 Giorgos Verigakis
        print '->', op, path, repr(args)
642 49350be7 Giorgos Verigakis
        ret = '[Unhandled Exception]'
643 49350be7 Giorgos Verigakis
        try:
644 49350be7 Giorgos Verigakis
            ret = getattr(self, op)(path, *args)
645 49350be7 Giorgos Verigakis
            return ret
646 49350be7 Giorgos Verigakis
        except OSError, e:
647 49350be7 Giorgos Verigakis
            ret = str(e)
648 49350be7 Giorgos Verigakis
            raise
649 49350be7 Giorgos Verigakis
        finally:
650 49350be7 Giorgos Verigakis
            print '<-', op, repr(ret)