Codebase list python-fusepy / upstream/3.0.1
New upstream version 3.0.1 Sascha Steinbiss 5 years ago
8 changed file(s) with 657 addition(s) and 305 deletion(s). Raw diff Collapse all Expand all
0 Metadata-Version: 1.1
0 Metadata-Version: 1.2
11 Name: fusepy
2 Version: 2.0.4
2 Version: 3.0.1
33 Summary: Simple ctypes bindings for FUSE
4 Home-page: http://github.com/terencehonles/fusepy
5 Author: Terence Honles
6 Author-email: terence@honles.com
4 Home-page: http://github.com/fusepy/fusepy
5 Author: Giorgos Verigakis
6 Author-email: verigak@gmail.com
7 Maintainer: Terence Honles
8 Maintainer-email: terence@honles.com
79 License: ISC
810 Description: fusepy
911 ======
12
13 **NOTE**: *This project has moved to be under a GitHub organization and can
14 be found at https://github.com/fusepy/fusepy. The project has new
15 maintainers and will be looking to incorporate pull requests in a more
16 timely manner. If you would like to help maintain this package please open
17 a pull request and demonstrate willingness to help (we will leave
18 maintainer criteria up to the current maintainers).*
1019
1120 ``fusepy`` is a Python module that provides a simple interface to FUSE_ and
1221 MacFUSE_. It's just one file and is implemented using ctypes.
4049 .. _`Google Code`: http://code.google.com/p/fusepy/
4150
4251 .. _officially hosted on GitHub: source_
43 .. _download: https://github.com/terencehonles/fusepy/zipball/master
44 .. _source: http://github.com/terencehonles/fusepy
52 .. _download: https://github.com/fusepy/fusepy/zipball/master
53 .. _source: http://github.com/fusepy/fusepy
4554
4655 .. examples
47 .. _memory: http://github.com/terencehonles/fusepy/blob/master/examples/memory.py
48 .. _loopback: http://github.com/terencehonles/fusepy/blob/master/examples/loopback.py
49 .. _context: http://github.com/terencehonles/fusepy/blob/master/examples/context.py
50 .. _sftp: http://github.com/terencehonles/fusepy/blob/master/examples/sftp.py
56 .. _memory: http://github.com/fusepy/fusepy/blob/master/examples/memory.py
57 .. _loopback: http://github.com/fusepy/fusepy/blob/master/examples/loopback.py
58 .. _context: http://github.com/fusepy/fusepy/blob/master/examples/context.py
59 .. _sftp: http://github.com/fusepy/fusepy/blob/master/examples/sftp.py
5160
5261 Platform: UNKNOWN
5362 Classifier: Intended Audience :: Developers
+0
-1
README less more
0 README.rst
0 fusepy
1 ======
2
3 **NOTE**: *This project has moved to be under a GitHub organization and can
4 be found at https://github.com/fusepy/fusepy. The project has new
5 maintainers and will be looking to incorporate pull requests in a more
6 timely manner. If you would like to help maintain this package please open
7 a pull request and demonstrate willingness to help (we will leave
8 maintainer criteria up to the current maintainers).*
9
10 ``fusepy`` is a Python module that provides a simple interface to FUSE_ and
11 MacFUSE_. It's just one file and is implemented using ctypes.
12
13 The original version of ``fusepy`` was hosted on `Google Code`_, but is now
14 `officially hosted on GitHub`_.
15
16 ``fusepy`` is written in 2x syntax, but trying to pay attention to bytes and
17 other changes 3x would care about.
18
19 examples
20 --------
21 See some examples of how you can use fusepy:
22
23 :memory_: A simple memory filesystem
24 :loopback_: A loopback filesystem
25 :context_: Sample usage of fuse_get_context()
26 :sftp_: A simple SFTP filesystem (requires paramiko)
27
28 To get started download_ fusepy or just browse the source_.
29
30 fusepy requires FUSE 2.6 (or later) and runs on:
31
32 - Linux (i386, x86_64, PPC, arm64, MIPS)
33 - Mac OS X (Intel, PowerPC)
34 - FreeBSD (i386, amd64)
35
36
37 .. _FUSE: http://fuse.sourceforge.net/
38 .. _MacFUSE: http://code.google.com/p/macfuse/
39 .. _`Google Code`: http://code.google.com/p/fusepy/
40
41 .. _officially hosted on GitHub: source_
42 .. _download: https://github.com/fusepy/fusepy/zipball/master
43 .. _source: http://github.com/fusepy/fusepy
44
45 .. examples
46 .. _memory: http://github.com/fusepy/fusepy/blob/master/examples/memory.py
47 .. _loopback: http://github.com/fusepy/fusepy/blob/master/examples/loopback.py
48 .. _context: http://github.com/fusepy/fusepy/blob/master/examples/context.py
49 .. _sftp: http://github.com/fusepy/fusepy/blob/master/examples/sftp.py
00 fusepy
11 ======
2
3 **NOTE**: *This project has moved to be under a GitHub organization and can
4 be found at https://github.com/fusepy/fusepy. The project has new
5 maintainers and will be looking to incorporate pull requests in a more
6 timely manner. If you would like to help maintain this package please open
7 a pull request and demonstrate willingness to help (we will leave
8 maintainer criteria up to the current maintainers).*
29
310 ``fusepy`` is a Python module that provides a simple interface to FUSE_ and
411 MacFUSE_. It's just one file and is implemented using ctypes.
3239 .. _`Google Code`: http://code.google.com/p/fusepy/
3340
3441 .. _officially hosted on GitHub: source_
35 .. _download: https://github.com/terencehonles/fusepy/zipball/master
36 .. _source: http://github.com/terencehonles/fusepy
42 .. _download: https://github.com/fusepy/fusepy/zipball/master
43 .. _source: http://github.com/fusepy/fusepy
3744
3845 .. examples
39 .. _memory: http://github.com/terencehonles/fusepy/blob/master/examples/memory.py
40 .. _loopback: http://github.com/terencehonles/fusepy/blob/master/examples/loopback.py
41 .. _context: http://github.com/terencehonles/fusepy/blob/master/examples/context.py
42 .. _sftp: http://github.com/terencehonles/fusepy/blob/master/examples/sftp.py
46 .. _memory: http://github.com/fusepy/fusepy/blob/master/examples/memory.py
47 .. _loopback: http://github.com/fusepy/fusepy/blob/master/examples/loopback.py
48 .. _context: http://github.com/fusepy/fusepy/blob/master/examples/context.py
49 .. _sftp: http://github.com/fusepy/fusepy/blob/master/examples/sftp.py
+552
-273
fuse.py less more
1414
1515 from __future__ import print_function, absolute_import, division
1616
17 from ctypes import *
17 import ctypes
18 import errno
19 import logging
20 import os
21 import warnings
22
1823 from ctypes.util import find_library
19 from errno import *
20 from os import strerror
2124 from platform import machine, system
2225 from signal import signal, SIGINT, SIG_DFL
2326 from stat import S_IFDIR
2427 from traceback import print_exc
2528
26 import logging
2729
2830 try:
2931 from functools import partial
4547 except NameError:
4648 basestring = str
4749
48 class c_timespec(Structure):
49 _fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)]
50
51 class c_utimbuf(Structure):
52 _fields_ = [('actime', c_timespec), ('modtime', c_timespec)]
53
54 class c_stat(Structure):
55 pass # Platform dependent
56
50 log = logging.getLogger("fuse")
5751 _system = system()
5852 _machine = machine()
5953
60 if _system == 'Darwin':
61 _libiconv = CDLL(find_library('iconv'), RTLD_GLOBAL) # libfuse dependency
62 _libfuse_path = (find_library('fuse4x') or find_library('osxfuse') or
63 find_library('fuse'))
54 if _system == 'Windows':
55 # NOTE:
56 #
57 # sizeof(long)==4 on Windows 32-bit and 64-bit
58 # sizeof(long)==4 on Cygwin 32-bit and ==8 on Cygwin 64-bit
59 #
60 # We have to fix up c_long and c_ulong so that it matches the
61 # Cygwin (and UNIX) sizes when run on Windows.
62 import sys
63 if sys.maxsize > 0xffffffff:
64 c_win_long = ctypes.c_int64
65 c_win_ulong = ctypes.c_uint64
66 else:
67 c_win_long = ctypes.c_int32
68 c_win_ulong = ctypes.c_uint32
69
70 if _system == 'Windows' or _system.startswith('CYGWIN'):
71 class c_timespec(ctypes.Structure):
72 _fields_ = [('tv_sec', c_win_long), ('tv_nsec', c_win_long)]
6473 else:
65 _libfuse_path = find_library('fuse')
74 class c_timespec(ctypes.Structure):
75 _fields_ = [('tv_sec', ctypes.c_long), ('tv_nsec', ctypes.c_long)]
76
77 class c_utimbuf(ctypes.Structure):
78 _fields_ = [('actime', c_timespec), ('modtime', c_timespec)]
79
80 class c_stat(ctypes.Structure):
81 pass # Platform dependent
82
83 _libfuse_path = os.environ.get('FUSE_LIBRARY_PATH')
84 if not _libfuse_path:
85 if _system == 'Darwin':
86 # libfuse dependency
87 _libiconv = ctypes.CDLL(find_library('iconv'), ctypes.RTLD_GLOBAL)
88
89 _libfuse_path = (find_library('fuse4x') or find_library('osxfuse') or
90 find_library('fuse'))
91 elif _system == 'Windows':
92 try:
93 import _winreg as reg
94 except ImportError:
95 import winreg as reg
96 def Reg32GetValue(rootkey, keyname, valname):
97 key, val = None, None
98 try:
99 key = reg.OpenKey(rootkey, keyname, 0, reg.KEY_READ | reg.KEY_WOW64_32KEY)
100 val = str(reg.QueryValueEx(key, valname)[0])
101 except WindowsError:
102 pass
103 finally:
104 if key is not None:
105 reg.CloseKey(key)
106 return val
107 _libfuse_path = Reg32GetValue(reg.HKEY_LOCAL_MACHINE, r"SOFTWARE\WinFsp", r"InstallDir")
108 if _libfuse_path:
109 _libfuse_path += r"bin\winfsp-%s.dll" % ("x64" if sys.maxsize > 0xffffffff else "x86")
110 else:
111 _libfuse_path = find_library('fuse')
66112
67113 if not _libfuse_path:
68114 raise EnvironmentError('Unable to find libfuse')
69115 else:
70 _libfuse = CDLL(_libfuse_path)
116 _libfuse = ctypes.CDLL(_libfuse_path)
71117
72118 if _system == 'Darwin' and hasattr(_libfuse, 'macfuse_version'):
73119 _system = 'Darwin-MacFuse'
75121
76122 if _system in ('Darwin', 'Darwin-MacFuse', 'FreeBSD'):
77123 ENOTSUP = 45
78 c_dev_t = c_int32
79 c_fsblkcnt_t = c_ulong
80 c_fsfilcnt_t = c_ulong
81 c_gid_t = c_uint32
82 c_mode_t = c_uint16
83 c_off_t = c_int64
84 c_pid_t = c_int32
85 c_uid_t = c_uint32
86 setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
87 c_size_t, c_int, c_uint32)
88 getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
89 c_size_t, c_uint32)
124
125 c_dev_t = ctypes.c_int32
126 c_fsblkcnt_t = ctypes.c_ulong
127 c_fsfilcnt_t = ctypes.c_ulong
128 c_gid_t = ctypes.c_uint32
129 c_mode_t = ctypes.c_uint16
130 c_off_t = ctypes.c_int64
131 c_pid_t = ctypes.c_int32
132 c_uid_t = ctypes.c_uint32
133 setxattr_t = ctypes.CFUNCTYPE(
134 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
135 ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int,
136 ctypes.c_uint32)
137 getxattr_t = ctypes.CFUNCTYPE(
138 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
139 ctypes.POINTER(ctypes.c_byte),
140 ctypes.c_size_t, ctypes.c_uint32)
90141 if _system == 'Darwin':
91142 c_stat._fields_ = [
92143 ('st_dev', c_dev_t),
93144 ('st_mode', c_mode_t),
94 ('st_nlink', c_uint16),
95 ('st_ino', c_uint64),
145 ('st_nlink', ctypes.c_uint16),
146 ('st_ino', ctypes.c_uint64),
96147 ('st_uid', c_uid_t),
97148 ('st_gid', c_gid_t),
98149 ('st_rdev', c_dev_t),
101152 ('st_ctimespec', c_timespec),
102153 ('st_birthtimespec', c_timespec),
103154 ('st_size', c_off_t),
104 ('st_blocks', c_int64),
105 ('st_blksize', c_int32),
106 ('st_flags', c_int32),
107 ('st_gen', c_int32),
108 ('st_lspare', c_int32),
109 ('st_qspare', c_int64)]
155 ('st_blocks', ctypes.c_int64),
156 ('st_blksize', ctypes.c_int32),
157 ('st_flags', ctypes.c_int32),
158 ('st_gen', ctypes.c_int32),
159 ('st_lspare', ctypes.c_int32),
160 ('st_qspare', ctypes.c_int64)]
110161 else:
111162 c_stat._fields_ = [
112163 ('st_dev', c_dev_t),
113 ('st_ino', c_uint32),
164 ('st_ino', ctypes.c_uint32),
114165 ('st_mode', c_mode_t),
115 ('st_nlink', c_uint16),
166 ('st_nlink', ctypes.c_uint16),
116167 ('st_uid', c_uid_t),
117168 ('st_gid', c_gid_t),
118169 ('st_rdev', c_dev_t),
120171 ('st_mtimespec', c_timespec),
121172 ('st_ctimespec', c_timespec),
122173 ('st_size', c_off_t),
123 ('st_blocks', c_int64),
124 ('st_blksize', c_int32)]
174 ('st_blocks', ctypes.c_int64),
175 ('st_blksize', ctypes.c_int32)]
125176 elif _system == 'Linux':
126177 ENOTSUP = 95
127 c_dev_t = c_ulonglong
128 c_fsblkcnt_t = c_ulonglong
129 c_fsfilcnt_t = c_ulonglong
130 c_gid_t = c_uint
131 c_mode_t = c_uint
132 c_off_t = c_longlong
133 c_pid_t = c_int
134 c_uid_t = c_uint
135 setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
136 c_size_t, c_int)
137
138 getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
139 c_size_t)
178
179 c_dev_t = ctypes.c_ulonglong
180 c_fsblkcnt_t = ctypes.c_ulonglong
181 c_fsfilcnt_t = ctypes.c_ulonglong
182 c_gid_t = ctypes.c_uint
183 c_mode_t = ctypes.c_uint
184 c_off_t = ctypes.c_longlong
185 c_pid_t = ctypes.c_int
186 c_uid_t = ctypes.c_uint
187 setxattr_t = ctypes.CFUNCTYPE(
188 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
189 ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int)
190
191 getxattr_t = ctypes.CFUNCTYPE(
192 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
193 ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t)
140194
141195 if _machine == 'x86_64':
142196 c_stat._fields_ = [
143197 ('st_dev', c_dev_t),
144 ('st_ino', c_ulong),
145 ('st_nlink', c_ulong),
198 ('st_ino', ctypes.c_ulong),
199 ('st_nlink', ctypes.c_ulong),
146200 ('st_mode', c_mode_t),
147201 ('st_uid', c_uid_t),
148202 ('st_gid', c_gid_t),
149 ('__pad0', c_int),
203 ('__pad0', ctypes.c_int),
150204 ('st_rdev', c_dev_t),
151205 ('st_size', c_off_t),
152 ('st_blksize', c_long),
153 ('st_blocks', c_long),
206 ('st_blksize', ctypes.c_long),
207 ('st_blocks', ctypes.c_long),
154208 ('st_atimespec', c_timespec),
155209 ('st_mtimespec', c_timespec),
156210 ('st_ctimespec', c_timespec)]
157211 elif _machine == 'mips':
158212 c_stat._fields_ = [
159213 ('st_dev', c_dev_t),
160 ('__pad1_1', c_ulong),
161 ('__pad1_2', c_ulong),
162 ('__pad1_3', c_ulong),
163 ('st_ino', c_ulong),
214 ('__pad1_1', ctypes.c_ulong),
215 ('__pad1_2', ctypes.c_ulong),
216 ('__pad1_3', ctypes.c_ulong),
217 ('st_ino', ctypes.c_ulong),
164218 ('st_mode', c_mode_t),
165 ('st_nlink', c_ulong),
219 ('st_nlink', ctypes.c_ulong),
166220 ('st_uid', c_uid_t),
167221 ('st_gid', c_gid_t),
168222 ('st_rdev', c_dev_t),
169 ('__pad2_1', c_ulong),
170 ('__pad2_2', c_ulong),
223 ('__pad2_1', ctypes.c_ulong),
224 ('__pad2_2', ctypes.c_ulong),
171225 ('st_size', c_off_t),
172 ('__pad3', c_ulong),
226 ('__pad3', ctypes.c_ulong),
173227 ('st_atimespec', c_timespec),
174 ('__pad4', c_ulong),
228 ('__pad4', ctypes.c_ulong),
175229 ('st_mtimespec', c_timespec),
176 ('__pad5', c_ulong),
230 ('__pad5', ctypes.c_ulong),
177231 ('st_ctimespec', c_timespec),
178 ('__pad6', c_ulong),
179 ('st_blksize', c_long),
180 ('st_blocks', c_long),
181 ('__pad7_1', c_ulong),
182 ('__pad7_2', c_ulong),
183 ('__pad7_3', c_ulong),
184 ('__pad7_4', c_ulong),
185 ('__pad7_5', c_ulong),
186 ('__pad7_6', c_ulong),
187 ('__pad7_7', c_ulong),
188 ('__pad7_8', c_ulong),
189 ('__pad7_9', c_ulong),
190 ('__pad7_10', c_ulong),
191 ('__pad7_11', c_ulong),
192 ('__pad7_12', c_ulong),
193 ('__pad7_13', c_ulong),
194 ('__pad7_14', c_ulong)]
232 ('__pad6', ctypes.c_ulong),
233 ('st_blksize', ctypes.c_long),
234 ('st_blocks', ctypes.c_long),
235 ('__pad7_1', ctypes.c_ulong),
236 ('__pad7_2', ctypes.c_ulong),
237 ('__pad7_3', ctypes.c_ulong),
238 ('__pad7_4', ctypes.c_ulong),
239 ('__pad7_5', ctypes.c_ulong),
240 ('__pad7_6', ctypes.c_ulong),
241 ('__pad7_7', ctypes.c_ulong),
242 ('__pad7_8', ctypes.c_ulong),
243 ('__pad7_9', ctypes.c_ulong),
244 ('__pad7_10', ctypes.c_ulong),
245 ('__pad7_11', ctypes.c_ulong),
246 ('__pad7_12', ctypes.c_ulong),
247 ('__pad7_13', ctypes.c_ulong),
248 ('__pad7_14', ctypes.c_ulong)]
195249 elif _machine == 'ppc':
196250 c_stat._fields_ = [
197251 ('st_dev', c_dev_t),
198 ('st_ino', c_ulonglong),
252 ('st_ino', ctypes.c_ulonglong),
199253 ('st_mode', c_mode_t),
200 ('st_nlink', c_uint),
254 ('st_nlink', ctypes.c_uint),
201255 ('st_uid', c_uid_t),
202256 ('st_gid', c_gid_t),
203257 ('st_rdev', c_dev_t),
204 ('__pad2', c_ushort),
258 ('__pad2', ctypes.c_ushort),
205259 ('st_size', c_off_t),
206 ('st_blksize', c_long),
207 ('st_blocks', c_longlong),
260 ('st_blksize', ctypes.c_long),
261 ('st_blocks', ctypes.c_longlong),
262 ('st_atimespec', c_timespec),
263 ('st_mtimespec', c_timespec),
264 ('st_ctimespec', c_timespec)]
265 elif _machine == 'ppc64' or _machine == 'ppc64le':
266 c_stat._fields_ = [
267 ('st_dev', c_dev_t),
268 ('st_ino', ctypes.c_ulong),
269 ('st_nlink', ctypes.c_ulong),
270 ('st_mode', c_mode_t),
271 ('st_uid', c_uid_t),
272 ('st_gid', c_gid_t),
273 ('__pad', ctypes.c_uint),
274 ('st_rdev', c_dev_t),
275 ('st_size', c_off_t),
276 ('st_blksize', ctypes.c_long),
277 ('st_blocks', ctypes.c_long),
208278 ('st_atimespec', c_timespec),
209279 ('st_mtimespec', c_timespec),
210280 ('st_ctimespec', c_timespec)]
211281 elif _machine == 'aarch64':
212282 c_stat._fields_ = [
213283 ('st_dev', c_dev_t),
214 ('st_ino', c_ulong),
284 ('st_ino', ctypes.c_ulong),
215285 ('st_mode', c_mode_t),
216 ('st_nlink', c_uint),
286 ('st_nlink', ctypes.c_uint),
217287 ('st_uid', c_uid_t),
218288 ('st_gid', c_gid_t),
219289 ('st_rdev', c_dev_t),
220 ('__pad1', c_ulong),
290 ('__pad1', ctypes.c_ulong),
221291 ('st_size', c_off_t),
222 ('st_blksize', c_int),
223 ('__pad2', c_int),
224 ('st_blocks', c_long),
292 ('st_blksize', ctypes.c_int),
293 ('__pad2', ctypes.c_int),
294 ('st_blocks', ctypes.c_long),
225295 ('st_atimespec', c_timespec),
226296 ('st_mtimespec', c_timespec),
227297 ('st_ctimespec', c_timespec)]
229299 # i686, use as fallback for everything else
230300 c_stat._fields_ = [
231301 ('st_dev', c_dev_t),
232 ('__pad1', c_ushort),
233 ('__st_ino', c_ulong),
302 ('__pad1', ctypes.c_ushort),
303 ('__st_ino', ctypes.c_ulong),
234304 ('st_mode', c_mode_t),
235 ('st_nlink', c_uint),
305 ('st_nlink', ctypes.c_uint),
236306 ('st_uid', c_uid_t),
237307 ('st_gid', c_gid_t),
238308 ('st_rdev', c_dev_t),
239 ('__pad2', c_ushort),
309 ('__pad2', ctypes.c_ushort),
240310 ('st_size', c_off_t),
241 ('st_blksize', c_long),
242 ('st_blocks', c_longlong),
311 ('st_blksize', ctypes.c_long),
312 ('st_blocks', ctypes.c_longlong),
243313 ('st_atimespec', c_timespec),
244314 ('st_mtimespec', c_timespec),
245315 ('st_ctimespec', c_timespec),
246 ('st_ino', c_ulonglong)]
316 ('st_ino', ctypes.c_ulonglong)]
317 elif _system == 'Windows' or _system.startswith('CYGWIN'):
318 ENOTSUP = 129 if _system == 'Windows' else 134
319 c_dev_t = ctypes.c_uint
320 c_fsblkcnt_t = c_win_ulong
321 c_fsfilcnt_t = c_win_ulong
322 c_gid_t = ctypes.c_uint
323 c_mode_t = ctypes.c_uint
324 c_off_t = ctypes.c_longlong
325 c_pid_t = ctypes.c_int
326 c_uid_t = ctypes.c_uint
327 setxattr_t = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
328 ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int)
329 getxattr_t = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
330 ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t)
331 c_stat._fields_ = [
332 ('st_dev', c_dev_t),
333 ('st_ino', ctypes.c_ulonglong),
334 ('st_mode', c_mode_t),
335 ('st_nlink', ctypes.c_ushort),
336 ('st_uid', c_uid_t),
337 ('st_gid', c_gid_t),
338 ('st_rdev', c_dev_t),
339 ('st_size', c_off_t),
340 ('st_atimespec', c_timespec),
341 ('st_mtimespec', c_timespec),
342 ('st_ctimespec', c_timespec),
343 ('st_blksize', ctypes.c_int),
344 ('st_blocks', ctypes.c_longlong),
345 ('st_birthtimespec', c_timespec)]
247346 else:
248347 raise NotImplementedError('%s is not supported.' % _system)
249348
250349
251 class c_statvfs(Structure):
252 _fields_ = [
253 ('f_bsize', c_ulong),
254 ('f_frsize', c_ulong),
255 ('f_blocks', c_fsblkcnt_t),
256 ('f_bfree', c_fsblkcnt_t),
257 ('f_bavail', c_fsblkcnt_t),
258 ('f_files', c_fsfilcnt_t),
259 ('f_ffree', c_fsfilcnt_t),
260 ('f_favail', c_fsfilcnt_t),
261 ('f_fsid', c_ulong),
262 #('unused', c_int),
263 ('f_flag', c_ulong),
264 ('f_namemax', c_ulong)]
265
266350 if _system == 'FreeBSD':
267 c_fsblkcnt_t = c_uint64
268 c_fsfilcnt_t = c_uint64
269 setxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
270 c_size_t, c_int)
271
272 getxattr_t = CFUNCTYPE(c_int, c_char_p, c_char_p, POINTER(c_byte),
273 c_size_t)
274
275 class c_statvfs(Structure):
351 c_fsblkcnt_t = ctypes.c_uint64
352 c_fsfilcnt_t = ctypes.c_uint64
353 setxattr_t = ctypes.CFUNCTYPE(
354 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
355 ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t, ctypes.c_int)
356
357 getxattr_t = ctypes.CFUNCTYPE(
358 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p,
359 ctypes.POINTER(ctypes.c_byte), ctypes.c_size_t)
360
361 class c_statvfs(ctypes.Structure):
276362 _fields_ = [
277363 ('f_bavail', c_fsblkcnt_t),
278364 ('f_bfree', c_fsblkcnt_t),
280366 ('f_favail', c_fsfilcnt_t),
281367 ('f_ffree', c_fsfilcnt_t),
282368 ('f_files', c_fsfilcnt_t),
283 ('f_bsize', c_ulong),
284 ('f_flag', c_ulong),
285 ('f_frsize', c_ulong)]
286
287 class fuse_file_info(Structure):
369 ('f_bsize', ctypes.c_ulong),
370 ('f_flag', ctypes.c_ulong),
371 ('f_frsize', ctypes.c_ulong)]
372 elif _system == 'Windows' or _system.startswith('CYGWIN'):
373 class c_statvfs(ctypes.Structure):
374 _fields_ = [
375 ('f_bsize', c_win_ulong),
376 ('f_frsize', c_win_ulong),
377 ('f_blocks', c_fsblkcnt_t),
378 ('f_bfree', c_fsblkcnt_t),
379 ('f_bavail', c_fsblkcnt_t),
380 ('f_files', c_fsfilcnt_t),
381 ('f_ffree', c_fsfilcnt_t),
382 ('f_favail', c_fsfilcnt_t),
383 ('f_fsid', c_win_ulong),
384 ('f_flag', c_win_ulong),
385 ('f_namemax', c_win_ulong)]
386 else:
387 class c_statvfs(ctypes.Structure):
388 _fields_ = [
389 ('f_bsize', ctypes.c_ulong),
390 ('f_frsize', ctypes.c_ulong),
391 ('f_blocks', c_fsblkcnt_t),
392 ('f_bfree', c_fsblkcnt_t),
393 ('f_bavail', c_fsblkcnt_t),
394 ('f_files', c_fsfilcnt_t),
395 ('f_ffree', c_fsfilcnt_t),
396 ('f_favail', c_fsfilcnt_t),
397 ('f_fsid', ctypes.c_ulong),
398 # ('unused', ctypes.c_int),
399 ('f_flag', ctypes.c_ulong),
400 ('f_namemax', ctypes.c_ulong)]
401
402 if _system == 'Windows' or _system.startswith('CYGWIN'):
403 class fuse_file_info(ctypes.Structure):
404 _fields_ = [
405 ('flags', ctypes.c_int),
406 ('fh_old', ctypes.c_int),
407 ('writepage', ctypes.c_int),
408 ('direct_io', ctypes.c_uint, 1),
409 ('keep_cache', ctypes.c_uint, 1),
410 ('flush', ctypes.c_uint, 1),
411 ('padding', ctypes.c_uint, 29),
412 ('fh', ctypes.c_uint64),
413 ('lock_owner', ctypes.c_uint64)]
414 else:
415 class fuse_file_info(ctypes.Structure):
416 _fields_ = [
417 ('flags', ctypes.c_int),
418 ('fh_old', ctypes.c_ulong),
419 ('writepage', ctypes.c_int),
420 ('direct_io', ctypes.c_uint, 1),
421 ('keep_cache', ctypes.c_uint, 1),
422 ('flush', ctypes.c_uint, 1),
423 ('nonseekable', ctypes.c_uint, 1),
424 ('flock_release', ctypes.c_uint, 1),
425 ('padding', ctypes.c_uint, 27),
426 ('fh', ctypes.c_uint64),
427 ('lock_owner', ctypes.c_uint64)]
428
429 class fuse_context(ctypes.Structure):
288430 _fields_ = [
289 ('flags', c_int),
290 ('fh_old', c_ulong),
291 ('writepage', c_int),
292 ('direct_io', c_uint, 1),
293 ('keep_cache', c_uint, 1),
294 ('flush', c_uint, 1),
295 ('padding', c_uint, 29),
296 ('fh', c_uint64),
297 ('lock_owner', c_uint64)]
298
299 class fuse_context(Structure):
300 _fields_ = [
301 ('fuse', c_voidp),
431 ('fuse', ctypes.c_voidp),
302432 ('uid', c_uid_t),
303433 ('gid', c_gid_t),
304434 ('pid', c_pid_t),
305 ('private_data', c_voidp)]
306
307 _libfuse.fuse_get_context.restype = POINTER(fuse_context)
308
309
310 class fuse_operations(Structure):
435 ('private_data', ctypes.c_voidp)]
436
437 _libfuse.fuse_get_context.restype = ctypes.POINTER(fuse_context)
438
439
440 class fuse_operations(ctypes.Structure):
311441 _fields_ = [
312 ('getattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_stat))),
313 ('readlink', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t)),
314 ('getdir', c_voidp), # Deprecated, use readdir
315 ('mknod', CFUNCTYPE(c_int, c_char_p, c_mode_t, c_dev_t)),
316 ('mkdir', CFUNCTYPE(c_int, c_char_p, c_mode_t)),
317 ('unlink', CFUNCTYPE(c_int, c_char_p)),
318 ('rmdir', CFUNCTYPE(c_int, c_char_p)),
319 ('symlink', CFUNCTYPE(c_int, c_char_p, c_char_p)),
320 ('rename', CFUNCTYPE(c_int, c_char_p, c_char_p)),
321 ('link', CFUNCTYPE(c_int, c_char_p, c_char_p)),
322 ('chmod', CFUNCTYPE(c_int, c_char_p, c_mode_t)),
323 ('chown', CFUNCTYPE(c_int, c_char_p, c_uid_t, c_gid_t)),
324 ('truncate', CFUNCTYPE(c_int, c_char_p, c_off_t)),
325 ('utime', c_voidp), # Deprecated, use utimens
326 ('open', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
327
328 ('read', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t,
329 c_off_t, POINTER(fuse_file_info))),
330
331 ('write', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t,
332 c_off_t, POINTER(fuse_file_info))),
333
334 ('statfs', CFUNCTYPE(c_int, c_char_p, POINTER(c_statvfs))),
335 ('flush', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
336 ('release', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
337 ('fsync', CFUNCTYPE(c_int, c_char_p, c_int, POINTER(fuse_file_info))),
442 ('getattr', ctypes.CFUNCTYPE(
443 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(c_stat))),
444
445 ('readlink', ctypes.CFUNCTYPE(
446 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(ctypes.c_byte),
447 ctypes.c_size_t)),
448
449 ('getdir', ctypes.c_voidp), # Deprecated, use readdir
450
451 ('mknod', ctypes.CFUNCTYPE(
452 ctypes.c_int, ctypes.c_char_p, c_mode_t, c_dev_t)),
453
454 ('mkdir', ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, c_mode_t)),
455 ('unlink', ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p)),
456 ('rmdir', ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p)),
457
458 ('symlink', ctypes.CFUNCTYPE(
459 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p)),
460
461 ('rename', ctypes.CFUNCTYPE(
462 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p)),
463
464 ('link', ctypes.CFUNCTYPE(
465 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p)),
466
467 ('chmod', ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, c_mode_t)),
468
469 ('chown', ctypes.CFUNCTYPE(
470 ctypes.c_int, ctypes.c_char_p, c_uid_t, c_gid_t)),
471
472 ('truncate', ctypes.CFUNCTYPE(
473 ctypes.c_int, ctypes.c_char_p, c_off_t)),
474
475 ('utime', ctypes.c_voidp), # Deprecated, use utimens
476 ('open', ctypes.CFUNCTYPE(
477 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(fuse_file_info))),
478
479 ('read', ctypes.CFUNCTYPE(
480 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(ctypes.c_byte),
481 ctypes.c_size_t, c_off_t, ctypes.POINTER(fuse_file_info))),
482
483 ('write', ctypes.CFUNCTYPE(
484 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(ctypes.c_byte),
485 ctypes.c_size_t, c_off_t, ctypes.POINTER(fuse_file_info))),
486
487 ('statfs', ctypes.CFUNCTYPE(
488 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(c_statvfs))),
489
490 ('flush', ctypes.CFUNCTYPE(
491 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(fuse_file_info))),
492
493 ('release', ctypes.CFUNCTYPE(
494 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(fuse_file_info))),
495
496 ('fsync', ctypes.CFUNCTYPE(
497 ctypes.c_int, ctypes.c_char_p, ctypes.c_int,
498 ctypes.POINTER(fuse_file_info))),
499
338500 ('setxattr', setxattr_t),
339501 ('getxattr', getxattr_t),
340 ('listxattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_byte), c_size_t)),
341 ('removexattr', CFUNCTYPE(c_int, c_char_p, c_char_p)),
342 ('opendir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
343
344 ('readdir', CFUNCTYPE(c_int, c_char_p, c_voidp,
345 CFUNCTYPE(c_int, c_voidp, c_char_p,
346 POINTER(c_stat), c_off_t),
347 c_off_t, POINTER(fuse_file_info))),
348
349 ('releasedir', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info))),
350
351 ('fsyncdir', CFUNCTYPE(c_int, c_char_p, c_int,
352 POINTER(fuse_file_info))),
353
354 ('init', CFUNCTYPE(c_voidp, c_voidp)),
355 ('destroy', CFUNCTYPE(c_voidp, c_voidp)),
356 ('access', CFUNCTYPE(c_int, c_char_p, c_int)),
357
358 ('create', CFUNCTYPE(c_int, c_char_p, c_mode_t,
359 POINTER(fuse_file_info))),
360
361 ('ftruncate', CFUNCTYPE(c_int, c_char_p, c_off_t,
362 POINTER(fuse_file_info))),
363
364 ('fgetattr', CFUNCTYPE(c_int, c_char_p, POINTER(c_stat),
365 POINTER(fuse_file_info))),
366
367 ('lock', CFUNCTYPE(c_int, c_char_p, POINTER(fuse_file_info),
368 c_int, c_voidp)),
369
370 ('utimens', CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf))),
371 ('bmap', CFUNCTYPE(c_int, c_char_p, c_size_t, POINTER(c_ulonglong))),
372 ('flag_nullpath_ok', c_uint, 1),
373 ('flag_nopath', c_uint, 1),
374 ('flag_utime_omit_ok', c_uint, 1),
375 ('flag_reserved', c_uint, 29),
502
503 ('listxattr', ctypes.CFUNCTYPE(
504 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(ctypes.c_byte),
505 ctypes.c_size_t)),
506
507 ('removexattr', ctypes.CFUNCTYPE(
508 ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p)),
509
510 ('opendir', ctypes.CFUNCTYPE(
511 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(fuse_file_info))),
512
513 ('readdir', ctypes.CFUNCTYPE(
514 ctypes.c_int,
515 ctypes.c_char_p,
516 ctypes.c_voidp,
517 ctypes.CFUNCTYPE(
518 ctypes.c_int, ctypes.c_voidp, ctypes.c_char_p,
519 ctypes.POINTER(c_stat), c_off_t),
520 c_off_t,
521 ctypes.POINTER(fuse_file_info))),
522
523 ('releasedir', ctypes.CFUNCTYPE(
524 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(fuse_file_info))),
525
526 ('fsyncdir', ctypes.CFUNCTYPE(
527 ctypes.c_int, ctypes.c_char_p, ctypes.c_int,
528 ctypes.POINTER(fuse_file_info))),
529
530 ('init', ctypes.CFUNCTYPE(ctypes.c_voidp, ctypes.c_voidp)),
531 ('destroy', ctypes.CFUNCTYPE(ctypes.c_voidp, ctypes.c_voidp)),
532
533 ('access', ctypes.CFUNCTYPE(
534 ctypes.c_int, ctypes.c_char_p, ctypes.c_int)),
535
536 ('create', ctypes.CFUNCTYPE(
537 ctypes.c_int, ctypes.c_char_p, c_mode_t,
538 ctypes.POINTER(fuse_file_info))),
539
540 ('ftruncate', ctypes.CFUNCTYPE(
541 ctypes.c_int, ctypes.c_char_p, c_off_t,
542 ctypes.POINTER(fuse_file_info))),
543
544 ('fgetattr', ctypes.CFUNCTYPE(
545 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(c_stat),
546 ctypes.POINTER(fuse_file_info))),
547
548 ('lock', ctypes.CFUNCTYPE(
549 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(fuse_file_info),
550 ctypes.c_int, ctypes.c_voidp)),
551
552 ('utimens', ctypes.CFUNCTYPE(
553 ctypes.c_int, ctypes.c_char_p, ctypes.POINTER(c_utimbuf))),
554
555 ('bmap', ctypes.CFUNCTYPE(
556 ctypes.c_int, ctypes.c_char_p, ctypes.c_size_t,
557 ctypes.POINTER(ctypes.c_ulonglong))),
558
559 ('flag_nullpath_ok', ctypes.c_uint, 1),
560 ('flag_nopath', ctypes.c_uint, 1),
561 ('flag_utime_omit_ok', ctypes.c_uint, 1),
562 ('flag_reserved', ctypes.c_uint, 29),
563
564 ('ioctl', ctypes.CFUNCTYPE(
565 ctypes.c_int, ctypes.c_char_p, ctypes.c_uint, ctypes.c_void_p,
566 ctypes.POINTER(fuse_file_info), ctypes.c_uint, ctypes.c_void_p)),
376567 ]
377568
378569
379 def time_of_timespec(ts):
380 return ts.tv_sec + ts.tv_nsec / 10 ** 9
381
382 def set_st_attrs(st, attrs):
570 def time_of_timespec(ts, use_ns=False):
571 if use_ns:
572 return ts.tv_sec * 10 ** 9 + ts.tv_nsec
573 else:
574 return ts.tv_sec + ts.tv_nsec / 1E9
575
576 def set_st_attrs(st, attrs, use_ns=False):
383577 for key, val in attrs.items():
384578 if key in ('st_atime', 'st_mtime', 'st_ctime', 'st_birthtime'):
385579 timespec = getattr(st, key + 'spec', None)
386580 if timespec is None:
387581 continue
388 timespec.tv_sec = int(val)
389 timespec.tv_nsec = int((val - timespec.tv_sec) * 10 ** 9)
582
583 if use_ns:
584 timespec.tv_sec, timespec.tv_nsec = divmod(int(val), 10 ** 9)
585 else:
586 timespec.tv_sec = int(val)
587 timespec.tv_nsec = int((val - timespec.tv_sec) * 1E9)
390588 elif hasattr(st, key):
391589 setattr(st, key, val)
392590
399597 return ctx.uid, ctx.gid, ctx.pid
400598
401599
600 def fuse_exit():
601 '''
602 This will shutdown the FUSE mount and cause the call to FUSE(...) to
603 return, similar to sending SIGINT to the process.
604
605 Flags the native FUSE session as terminated and will cause any running FUSE
606 event loops to exit on the next opportunity. (see fuse.c::fuse_exit)
607 '''
608 fuse_ptr = ctypes.c_void_p(_libfuse.fuse_get_context().contents.fuse)
609 _libfuse.fuse_exit(fuse_ptr)
610
611
402612 class FuseOSError(OSError):
403613 def __init__(self, errno):
404 super(FuseOSError, self).__init__(errno, strerror(errno))
614 super(FuseOSError, self).__init__(errno, os.strerror(errno))
405615
406616
407617 class FUSE(object):
431641 self.operations = operations
432642 self.raw_fi = raw_fi
433643 self.encoding = encoding
644 self.__critical_exception = None
645
646 self.use_ns = getattr(operations, 'use_ns', False)
647 if not self.use_ns:
648 warnings.warn(
649 'Time as floating point seconds for utimens is deprecated!\n'
650 'To enable time as nanoseconds set the property "use_ns" to '
651 'True in your operations class or set your fusepy '
652 'requirements to <4.',
653 DeprecationWarning)
434654
435655 args = ['fuse']
436656
443663 args.append(mountpoint)
444664
445665 args = [arg.encode(encoding) for arg in args]
446 argv = (c_char_p * len(args))(*args)
666 argv = (ctypes.c_char_p * len(args))(*args)
447667
448668 fuse_ops = fuse_operations()
449669 for ent in fuse_operations._fields_:
450670 name, prototype = ent[:2]
451671
452 val = getattr(operations, name, None)
672 check_name = name
673
674 # ftruncate()/fgetattr() are implemented in terms of their
675 # non-f-prefixed versions in the operations object
676 if check_name in ["ftruncate", "fgetattr"]:
677 check_name = check_name[1:]
678
679 val = getattr(operations, check_name, None)
453680 if val is None:
454681 continue
455682
466693 except ValueError:
467694 old_handler = SIG_DFL
468695
469 err = _libfuse.fuse_main_real(len(args), argv, pointer(fuse_ops),
470 sizeof(fuse_ops), None)
696 err = _libfuse.fuse_main_real(
697 len(args), argv, ctypes.pointer(fuse_ops),
698 ctypes.sizeof(fuse_ops),
699 None)
471700
472701 try:
473702 signal(SIGINT, old_handler)
475704 pass
476705
477706 del self.operations # Invoke the destructor
707 if self.__critical_exception:
708 raise self.__critical_exception
478709 if err:
479710 raise RuntimeError(err)
480711
482713 def _normalize_fuse_options(**kargs):
483714 for key, value in kargs.items():
484715 if isinstance(value, bool):
485 if value is True: yield key
716 if value is True:
717 yield key
486718 else:
487719 yield '%s=%s' % (key, value)
488720
491723 'Decorator for the methods that follow'
492724
493725 try:
494 return func(*args, **kwargs) or 0
495 except OSError as e:
496 return -(e.errno or EFAULT)
497 except:
498 print_exc()
499 return -EFAULT
726 if func.__name__ == "init":
727 # init may not fail, as its return code is just stored as
728 # private_data field of struct fuse_context
729 return func(*args, **kwargs) or 0
730
731 else:
732 try:
733 return func(*args, **kwargs) or 0
734
735 except OSError as e:
736 if e.errno > 0:
737 log.debug(
738 "FUSE operation %s raised a %s, returning errno %s.",
739 func.__name__, type(e), e.errno, exc_info=True)
740 return -e.errno
741 else:
742 log.error(
743 "FUSE operation %s raised an OSError with negative "
744 "errno %s, returning errno.EINVAL.",
745 func.__name__, e.errno, exc_info=True)
746 return -errno.EINVAL
747
748 except Exception:
749 log.error("Uncaught exception from FUSE operation %s, "
750 "returning errno.EINVAL.",
751 func.__name__, exc_info=True)
752 return -errno.EINVAL
753
754 except BaseException as e:
755 self.__critical_exception = e
756 log.critical(
757 "Uncaught critical exception from FUSE operation %s, aborting.",
758 func.__name__, exc_info=True)
759 # the raised exception (even SystemExit) will be caught by FUSE
760 # potentially causing SIGSEGV, so tell system to stop/interrupt FUSE
761 fuse_exit()
762 return -errno.EFAULT
500763
501764 def _decode_optional_path(self, path):
502765 # NB: this method is intended for fuse operations that
515778
516779 # copies a string into the given buffer
517780 # (null terminated and truncated if necessary)
518 data = create_string_buffer(ret[:bufsize - 1])
519 memmove(buf, data, len(data))
781 data = ctypes.create_string_buffer(ret[:bufsize - 1])
782 ctypes.memmove(buf, data, len(data))
520783 return 0
521784
522785 def mknod(self, path, mode, dev):
581844 ret = self.operations('read', self._decode_optional_path(path), size,
582845 offset, fh)
583846
584 if not ret: return 0
847 if not ret:
848 return 0
585849
586850 retsize = len(ret)
587851 assert retsize <= size, \
588852 'actual amount read %d greater than expected %d' % (retsize, size)
589853
590 data = create_string_buffer(ret, retsize)
591 memmove(buf, data, retsize)
854 ctypes.memmove(buf, ret, retsize)
592855 return retsize
593856
594857 def write(self, path, buf, size, offset, fip):
595 data = string_at(buf, size)
858 data = ctypes.string_at(buf, size)
596859
597860 if self.raw_fi:
598861 fh = fip.contents
639902 def setxattr(self, path, name, value, size, options, *args):
640903 return self.operations('setxattr', path.decode(self.encoding),
641904 name.decode(self.encoding),
642 string_at(value, size), options, *args)
905 ctypes.string_at(value, size), options, *args)
643906
644907 def getxattr(self, path, name, value, size, *args):
645908 ret = self.operations('getxattr', path.decode(self.encoding),
647910
648911 retsize = len(ret)
649912 # allow size queries
650 if not value: return retsize
913 if not value:
914 return retsize
651915
652916 # do not truncate
653 if retsize > size: return -ERANGE
654
655 buf = create_string_buffer(ret, retsize) # Does not add trailing 0
656 memmove(value, buf, retsize)
917 if retsize > size:
918 return -errno.ERANGE
919
920 # Does not add trailing 0
921 buf = ctypes.create_string_buffer(ret, retsize)
922 ctypes.memmove(value, buf, retsize)
657923
658924 return retsize
659925
665931
666932 retsize = len(ret)
667933 # allow size queries
668 if not namebuf: return retsize
934 if not namebuf:
935 return retsize
669936
670937 # do not truncate
671 if retsize > size: return -ERANGE
672
673 buf = create_string_buffer(ret, retsize)
674 memmove(namebuf, buf, retsize)
938 if retsize > size:
939 return -errno.ERANGE
940
941 buf = ctypes.create_string_buffer(ret, retsize)
942 ctypes.memmove(namebuf, buf, retsize)
675943
676944 return retsize
677945
697965 name, attrs, offset = item
698966 if attrs:
699967 st = c_stat()
700 set_st_attrs(st, attrs)
968 set_st_attrs(st, attrs, use_ns=self.use_ns)
701969 else:
702970 st = None
703971
7451013 length, fh)
7461014
7471015 def fgetattr(self, path, buf, fip):
748 memset(buf, 0, sizeof(c_stat))
1016 ctypes.memset(buf, 0, ctypes.sizeof(c_stat))
7491017
7501018 st = buf.contents
7511019 if not fip:
7561024 fh = fip.contents.fh
7571025
7581026 attrs = self.operations('getattr', self._decode_optional_path(path), fh)
759 set_st_attrs(st, attrs)
1027 set_st_attrs(st, attrs, use_ns=self.use_ns)
7601028 return 0
7611029
7621030 def lock(self, path, fip, cmd, lock):
7701038
7711039 def utimens(self, path, buf):
7721040 if buf:
773 atime = time_of_timespec(buf.contents.actime)
774 mtime = time_of_timespec(buf.contents.modtime)
1041 atime = time_of_timespec(buf.contents.actime, use_ns=self.use_ns)
1042 mtime = time_of_timespec(buf.contents.modtime, use_ns=self.use_ns)
7751043 times = (atime, mtime)
7761044 else:
7771045 times = None
7821050 return self.operations('bmap', path.decode(self.encoding), blocksize,
7831051 idx)
7841052
1053 def ioctl(self, path, cmd, arg, fip, flags, data):
1054 if self.raw_fi:
1055 fh = fip.contents
1056 else:
1057 fh = fip.contents.fh
1058
1059 return self.operations('ioctl', path.decode(self.encoding),
1060 cmd, arg, fh, flags, data)
7851061
7861062 class Operations(object):
7871063 '''
7951071
7961072 def __call__(self, op, *args):
7971073 if not hasattr(self, op):
798 raise FuseOSError(EFAULT)
1074 raise FuseOSError(errno.EFAULT)
7991075 return getattr(self, op)(*args)
8001076
8011077 def access(self, path, amode):
8041080 bmap = None
8051081
8061082 def chmod(self, path, mode):
807 raise FuseOSError(EROFS)
1083 raise FuseOSError(errno.EROFS)
8081084
8091085 def chown(self, path, uid, gid):
810 raise FuseOSError(EROFS)
1086 raise FuseOSError(errno.EROFS)
8111087
8121088 def create(self, path, mode, fi=None):
8131089 '''
8181094 and return 0.
8191095 '''
8201096
821 raise FuseOSError(EROFS)
1097 raise FuseOSError(errno.EROFS)
8221098
8231099 def destroy(self, path):
8241100 'Called on filesystem destruction. Path is always /'
8411117
8421118 st_atime, st_mtime and st_ctime should be floats.
8431119
844 NOTE: There is an incombatibility between Linux and Mac OS X
1120 NOTE: There is an incompatibility between Linux and Mac OS X
8451121 concerning st_nlink of directories. Mac OS X counts all files inside
8461122 the directory, while Linux counts only the subdirectories.
8471123 '''
8481124
8491125 if path != '/':
850 raise FuseOSError(ENOENT)
1126 raise FuseOSError(errno.ENOENT)
8511127 return dict(st_mode=(S_IFDIR | 0o755), st_nlink=2)
8521128
8531129 def getxattr(self, path, name, position=0):
8621138
8631139 pass
8641140
1141 def ioctl(self, path, cmd, arg, fip, flags, data):
1142 raise FuseOSError(errno.ENOTTY)
1143
8651144 def link(self, target, source):
8661145 'creates a hard link `target -> source` (e.g. ln source target)'
8671146
868 raise FuseOSError(EROFS)
1147 raise FuseOSError(errno.EROFS)
8691148
8701149 def listxattr(self, path):
8711150 return []
8731152 lock = None
8741153
8751154 def mkdir(self, path, mode):
876 raise FuseOSError(EROFS)
1155 raise FuseOSError(errno.EROFS)
8771156
8781157 def mknod(self, path, mode, dev):
879 raise FuseOSError(EROFS)
1158 raise FuseOSError(errno.EROFS)
8801159
8811160 def open(self, path, flags):
8821161 '''
8991178 def read(self, path, size, offset, fh):
9001179 'Returns a string containing the data requested.'
9011180
902 raise FuseOSError(EIO)
1181 raise FuseOSError(errno.EIO)
9031182
9041183 def readdir(self, path, fh):
9051184 '''
9101189 return ['.', '..']
9111190
9121191 def readlink(self, path):
913 raise FuseOSError(ENOENT)
1192 raise FuseOSError(errno.ENOENT)
9141193
9151194 def release(self, path, fh):
9161195 return 0
9221201 raise FuseOSError(ENOTSUP)
9231202
9241203 def rename(self, old, new):
925 raise FuseOSError(EROFS)
1204 raise FuseOSError(errno.EROFS)
9261205
9271206 def rmdir(self, path):
928 raise FuseOSError(EROFS)
1207 raise FuseOSError(errno.EROFS)
9291208
9301209 def setxattr(self, path, name, value, options, position=0):
9311210 raise FuseOSError(ENOTSUP)
9441223 def symlink(self, target, source):
9451224 'creates a symlink `target -> source` (e.g. ln -s source target)'
9461225
947 raise FuseOSError(EROFS)
1226 raise FuseOSError(errno.EROFS)
9481227
9491228 def truncate(self, path, length, fh=None):
950 raise FuseOSError(EROFS)
1229 raise FuseOSError(errno.EROFS)
9511230
9521231 def unlink(self, path):
953 raise FuseOSError(EROFS)
1232 raise FuseOSError(errno.EROFS)
9541233
9551234 def utimens(self, path, times=None):
9561235 'Times is a (atime, mtime) tuple. If None use current time.'
9581237 return 0
9591238
9601239 def write(self, path, data, offset, fh):
961 raise FuseOSError(EROFS)
1240 raise FuseOSError(errno.EROFS)
9621241
9631242
9641243 class LoggingMixIn:
0 Metadata-Version: 1.1
0 Metadata-Version: 1.2
11 Name: fusepy
2 Version: 2.0.4
2 Version: 3.0.1
33 Summary: Simple ctypes bindings for FUSE
4 Home-page: http://github.com/terencehonles/fusepy
5 Author: Terence Honles
6 Author-email: terence@honles.com
4 Home-page: http://github.com/fusepy/fusepy
5 Author: Giorgos Verigakis
6 Author-email: verigak@gmail.com
7 Maintainer: Terence Honles
8 Maintainer-email: terence@honles.com
79 License: ISC
810 Description: fusepy
911 ======
12
13 **NOTE**: *This project has moved to be under a GitHub organization and can
14 be found at https://github.com/fusepy/fusepy. The project has new
15 maintainers and will be looking to incorporate pull requests in a more
16 timely manner. If you would like to help maintain this package please open
17 a pull request and demonstrate willingness to help (we will leave
18 maintainer criteria up to the current maintainers).*
1019
1120 ``fusepy`` is a Python module that provides a simple interface to FUSE_ and
1221 MacFUSE_. It's just one file and is implemented using ctypes.
4049 .. _`Google Code`: http://code.google.com/p/fusepy/
4150
4251 .. _officially hosted on GitHub: source_
43 .. _download: https://github.com/terencehonles/fusepy/zipball/master
44 .. _source: http://github.com/terencehonles/fusepy
52 .. _download: https://github.com/fusepy/fusepy/zipball/master
53 .. _source: http://github.com/fusepy/fusepy
4554
4655 .. examples
47 .. _memory: http://github.com/terencehonles/fusepy/blob/master/examples/memory.py
48 .. _loopback: http://github.com/terencehonles/fusepy/blob/master/examples/loopback.py
49 .. _context: http://github.com/terencehonles/fusepy/blob/master/examples/context.py
50 .. _sftp: http://github.com/terencehonles/fusepy/blob/master/examples/sftp.py
56 .. _memory: http://github.com/fusepy/fusepy/blob/master/examples/memory.py
57 .. _loopback: http://github.com/fusepy/fusepy/blob/master/examples/loopback.py
58 .. _context: http://github.com/fusepy/fusepy/blob/master/examples/context.py
59 .. _sftp: http://github.com/fusepy/fusepy/blob/master/examples/sftp.py
5160
5261 Platform: UNKNOWN
5362 Classifier: Intended Audience :: Developers
00 [egg_info]
11 tag_build =
22 tag_date = 0
3 tag_svn_revision = 0
43
88
99 setup(
1010 name = 'fusepy',
11 version = '2.0.4',
11 version = '3.0.1',
1212
1313 description = 'Simple ctypes bindings for FUSE',
1414 long_description = documentation,
1818 maintainer_email = 'terence@honles.com',
1919 license = 'ISC',
2020 py_modules=['fuse'],
21 url = 'http://github.com/terencehonles/fusepy',
21 url = 'http://github.com/fusepy/fusepy',
2222
2323 classifiers = [
2424 'Intended Audience :: Developers',