Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
djrandom-py
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ale
djrandom-py
Commits
a5ced330
Commit
a5ced330
authored
13 years ago
by
ale
Browse files
Options
Downloads
Patches
Plain Diff
bundle Giorgos Verigakis's fuse.py wrapper
parent
fcea6ba5
No related branches found
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
client/djrandom_client/fuse/fuse.py
+650
-0
650 additions, 0 deletions
client/djrandom_client/fuse/fuse.py
with
650 additions
and
0 deletions
client/djrandom_client/fuse/fuse.py
0 → 100644
+
650
−
0
View file @
a5ced330
# Copyright (c) 2008 Giorgos Verigakis <verigak@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from
__future__
import
division
from
ctypes
import
*
from
ctypes.util
import
find_library
from
errno
import
*
from
functools
import
partial
from
os
import
strerror
from
platform
import
machine
,
system
from
stat
import
S_IFDIR
from
traceback
import
print_exc
class
c_timespec
(
Structure
):
_fields_
=
[(
'
tv_sec
'
,
c_long
),
(
'
tv_nsec
'
,
c_long
)]
class
c_utimbuf
(
Structure
):
_fields_
=
[(
'
actime
'
,
c_timespec
),
(
'
modtime
'
,
c_timespec
)]
class
c_stat
(
Structure
):
pass
# Platform dependent
_system
=
system
()
if
_system
in
(
'
Darwin
'
,
'
FreeBSD
'
):
_libiconv
=
CDLL
(
find_library
(
"
iconv
"
),
RTLD_GLOBAL
)
# libfuse dependency
ENOTSUP
=
45
c_dev_t
=
c_int32
c_fsblkcnt_t
=
c_ulong
c_fsfilcnt_t
=
c_ulong
c_gid_t
=
c_uint32
c_mode_t
=
c_uint16
c_off_t
=
c_int64
c_pid_t
=
c_int32
c_uid_t
=
c_uint32
setxattr_t
=
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
,
c_int
,
c_uint32
)
getxattr_t
=
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
,
c_uint32
)
c_stat
.
_fields_
=
[
(
'
st_dev
'
,
c_dev_t
),
(
'
st_ino
'
,
c_uint32
),
(
'
st_mode
'
,
c_mode_t
),
(
'
st_nlink
'
,
c_uint16
),
(
'
st_uid
'
,
c_uid_t
),
(
'
st_gid
'
,
c_gid_t
),
(
'
st_rdev
'
,
c_dev_t
),
(
'
st_atimespec
'
,
c_timespec
),
(
'
st_mtimespec
'
,
c_timespec
),
(
'
st_ctimespec
'
,
c_timespec
),
(
'
st_size
'
,
c_off_t
),
(
'
st_blocks
'
,
c_int64
),
(
'
st_blksize
'
,
c_int32
)]
elif
_system
==
'
Linux
'
:
ENOTSUP
=
95
c_dev_t
=
c_ulonglong
c_fsblkcnt_t
=
c_ulonglong
c_fsfilcnt_t
=
c_ulonglong
c_gid_t
=
c_uint
c_mode_t
=
c_uint
c_off_t
=
c_longlong
c_pid_t
=
c_int
c_uid_t
=
c_uint
setxattr_t
=
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
,
c_int
)
getxattr_t
=
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
)
_machine
=
machine
()
if
_machine
==
'
x86_64
'
:
c_stat
.
_fields_
=
[
(
'
st_dev
'
,
c_dev_t
),
(
'
st_ino
'
,
c_ulong
),
(
'
st_nlink
'
,
c_ulong
),
(
'
st_mode
'
,
c_mode_t
),
(
'
st_uid
'
,
c_uid_t
),
(
'
st_gid
'
,
c_gid_t
),
(
'
__pad0
'
,
c_int
),
(
'
st_rdev
'
,
c_dev_t
),
(
'
st_size
'
,
c_off_t
),
(
'
st_blksize
'
,
c_long
),
(
'
st_blocks
'
,
c_long
),
(
'
st_atimespec
'
,
c_timespec
),
(
'
st_mtimespec
'
,
c_timespec
),
(
'
st_ctimespec
'
,
c_timespec
)]
elif
_machine
==
'
ppc
'
:
c_stat
.
_fields_
=
[
(
'
st_dev
'
,
c_dev_t
),
(
'
st_ino
'
,
c_ulonglong
),
(
'
st_mode
'
,
c_mode_t
),
(
'
st_nlink
'
,
c_uint
),
(
'
st_uid
'
,
c_uid_t
),
(
'
st_gid
'
,
c_gid_t
),
(
'
st_rdev
'
,
c_dev_t
),
(
'
__pad2
'
,
c_ushort
),
(
'
st_size
'
,
c_off_t
),
(
'
st_blksize
'
,
c_long
),
(
'
st_blocks
'
,
c_longlong
),
(
'
st_atimespec
'
,
c_timespec
),
(
'
st_mtimespec
'
,
c_timespec
),
(
'
st_ctimespec
'
,
c_timespec
)]
else
:
# i686, use as fallback for everything else
c_stat
.
_fields_
=
[
(
'
st_dev
'
,
c_dev_t
),
(
'
__pad1
'
,
c_ushort
),
(
'
__st_ino
'
,
c_ulong
),
(
'
st_mode
'
,
c_mode_t
),
(
'
st_nlink
'
,
c_uint
),
(
'
st_uid
'
,
c_uid_t
),
(
'
st_gid
'
,
c_gid_t
),
(
'
st_rdev
'
,
c_dev_t
),
(
'
__pad2
'
,
c_ushort
),
(
'
st_size
'
,
c_off_t
),
(
'
st_blksize
'
,
c_long
),
(
'
st_blocks
'
,
c_longlong
),
(
'
st_atimespec
'
,
c_timespec
),
(
'
st_mtimespec
'
,
c_timespec
),
(
'
st_ctimespec
'
,
c_timespec
),
(
'
st_ino
'
,
c_ulonglong
)]
else
:
raise
NotImplementedError
(
'
%s is not supported.
'
%
_system
)
class
c_statvfs
(
Structure
):
_fields_
=
[
(
'
f_bsize
'
,
c_ulong
),
(
'
f_frsize
'
,
c_ulong
),
(
'
f_blocks
'
,
c_fsblkcnt_t
),
(
'
f_bfree
'
,
c_fsblkcnt_t
),
(
'
f_bavail
'
,
c_fsblkcnt_t
),
(
'
f_files
'
,
c_fsfilcnt_t
),
(
'
f_ffree
'
,
c_fsfilcnt_t
),
(
'
f_favail
'
,
c_fsfilcnt_t
)]
if
_system
==
'
FreeBSD
'
:
c_fsblkcnt_t
=
c_uint64
c_fsfilcnt_t
=
c_uint64
setxattr_t
=
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
,
c_int
)
getxattr_t
=
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
)
class
c_statvfs
(
Structure
):
_fields_
=
[
(
'
f_bavail
'
,
c_fsblkcnt_t
),
(
'
f_bfree
'
,
c_fsblkcnt_t
),
(
'
f_blocks
'
,
c_fsblkcnt_t
),
(
'
f_favail
'
,
c_fsfilcnt_t
),
(
'
f_ffree
'
,
c_fsfilcnt_t
),
(
'
f_files
'
,
c_fsfilcnt_t
),
(
'
f_bsize
'
,
c_ulong
),
(
'
f_flag
'
,
c_ulong
),
(
'
f_frsize
'
,
c_ulong
)]
class
fuse_file_info
(
Structure
):
_fields_
=
[
(
'
flags
'
,
c_int
),
(
'
fh_old
'
,
c_ulong
),
(
'
writepage
'
,
c_int
),
(
'
direct_io
'
,
c_uint
,
1
),
(
'
keep_cache
'
,
c_uint
,
1
),
(
'
flush
'
,
c_uint
,
1
),
(
'
padding
'
,
c_uint
,
29
),
(
'
fh
'
,
c_uint64
),
(
'
lock_owner
'
,
c_uint64
)]
class
fuse_context
(
Structure
):
_fields_
=
[
(
'
fuse
'
,
c_voidp
),
(
'
uid
'
,
c_uid_t
),
(
'
gid
'
,
c_gid_t
),
(
'
pid
'
,
c_pid_t
),
(
'
private_data
'
,
c_voidp
)]
class
fuse_operations
(
Structure
):
_fields_
=
[
(
'
getattr
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_stat
))),
(
'
readlink
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
)),
(
'
getdir
'
,
c_voidp
),
# Deprecated, use readdir
(
'
mknod
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_mode_t
,
c_dev_t
)),
(
'
mkdir
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_mode_t
)),
(
'
unlink
'
,
CFUNCTYPE
(
c_int
,
c_char_p
)),
(
'
rmdir
'
,
CFUNCTYPE
(
c_int
,
c_char_p
)),
(
'
symlink
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
)),
(
'
rename
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
)),
(
'
link
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
)),
(
'
chmod
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_mode_t
)),
(
'
chown
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_uid_t
,
c_gid_t
)),
(
'
truncate
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_off_t
)),
(
'
utime
'
,
c_voidp
),
# Deprecated, use utimens
(
'
open
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
fuse_file_info
))),
(
'
read
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
,
c_off_t
,
POINTER
(
fuse_file_info
))),
(
'
write
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
,
c_off_t
,
POINTER
(
fuse_file_info
))),
(
'
statfs
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_statvfs
))),
(
'
flush
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
fuse_file_info
))),
(
'
release
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
fuse_file_info
))),
(
'
fsync
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_int
,
POINTER
(
fuse_file_info
))),
(
'
setxattr
'
,
setxattr_t
),
(
'
getxattr
'
,
getxattr_t
),
(
'
listxattr
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_byte
),
c_size_t
)),
(
'
removexattr
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_char_p
)),
(
'
opendir
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
fuse_file_info
))),
(
'
readdir
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_voidp
,
CFUNCTYPE
(
c_int
,
c_voidp
,
c_char_p
,
POINTER
(
c_stat
),
c_off_t
),
c_off_t
,
POINTER
(
fuse_file_info
))),
(
'
releasedir
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
fuse_file_info
))),
(
'
fsyncdir
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_int
,
POINTER
(
fuse_file_info
))),
(
'
init
'
,
CFUNCTYPE
(
c_voidp
,
c_voidp
)),
(
'
destroy
'
,
CFUNCTYPE
(
c_voidp
,
c_voidp
)),
(
'
access
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_int
)),
(
'
create
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_mode_t
,
POINTER
(
fuse_file_info
))),
(
'
ftruncate
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_off_t
,
POINTER
(
fuse_file_info
))),
(
'
fgetattr
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_stat
),
POINTER
(
fuse_file_info
))),
(
'
lock
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
fuse_file_info
),
c_int
,
c_voidp
)),
(
'
utimens
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
POINTER
(
c_utimbuf
))),
(
'
bmap
'
,
CFUNCTYPE
(
c_int
,
c_char_p
,
c_size_t
,
POINTER
(
c_ulonglong
)))]
def
time_of_timespec
(
ts
):
return
ts
.
tv_sec
+
ts
.
tv_nsec
/
10
**
9
def
set_st_attrs
(
st
,
attrs
):
for
key
,
val
in
attrs
.
items
():
if
key
in
(
'
st_atime
'
,
'
st_mtime
'
,
'
st_ctime
'
):
timespec
=
getattr
(
st
,
key
+
'
spec
'
)
timespec
.
tv_sec
=
int
(
val
)
timespec
.
tv_nsec
=
int
((
val
-
timespec
.
tv_sec
)
*
10
**
9
)
elif
hasattr
(
st
,
key
):
setattr
(
st
,
key
,
val
)
_libfuse_path
=
find_library
(
'
fuse
'
)
if
not
_libfuse_path
:
raise
EnvironmentError
(
'
Unable to find libfuse
'
)
_libfuse
=
CDLL
(
_libfuse_path
)
_libfuse
.
fuse_get_context
.
restype
=
POINTER
(
fuse_context
)
def
fuse_get_context
():
"""
Returns a (uid, gid, pid) tuple
"""
ctxp
=
_libfuse
.
fuse_get_context
()
ctx
=
ctxp
.
contents
return
ctx
.
uid
,
ctx
.
gid
,
ctx
.
pid
class
FuseOSError
(
OSError
):
def
__init__
(
self
,
errno
):
super
(
FuseOSError
,
self
).
__init__
(
errno
,
strerror
(
errno
))
class
FUSE
(
object
):
"""
This class is the lower level interface and should not be subclassed
under normal use. Its methods are called by fuse.
Assumes API version 2.6 or later.
"""
def
__init__
(
self
,
operations
,
mountpoint
,
raw_fi
=
False
,
**
kwargs
):
"""
Setting raw_fi to True will cause FUSE to pass the fuse_file_info
class as is to Operations, instead of just the fh field.
This gives you access to direct_io, keep_cache, etc.
"""
self
.
operations
=
operations
self
.
raw_fi
=
raw_fi
args
=
[
'
fuse
'
]
if
kwargs
.
pop
(
'
foreground
'
,
False
):
args
.
append
(
'
-f
'
)
if
kwargs
.
pop
(
'
debug
'
,
False
):
args
.
append
(
'
-d
'
)
if
kwargs
.
pop
(
'
nothreads
'
,
False
):
args
.
append
(
'
-s
'
)
kwargs
.
setdefault
(
'
fsname
'
,
operations
.
__class__
.
__name__
)
args
.
append
(
'
-o
'
)
args
.
append
(
'
,
'
.
join
(
key
if
val
==
True
else
'
%s=%s
'
%
(
key
,
val
)
for
key
,
val
in
kwargs
.
items
()))
args
.
append
(
mountpoint
)
argv
=
(
c_char_p
*
len
(
args
))(
*
args
)
fuse_ops
=
fuse_operations
()
for
name
,
prototype
in
fuse_operations
.
_fields_
:
if
prototype
!=
c_voidp
and
getattr
(
operations
,
name
,
None
):
op
=
partial
(
self
.
_wrapper_
,
getattr
(
self
,
name
))
setattr
(
fuse_ops
,
name
,
prototype
(
op
))
err
=
_libfuse
.
fuse_main_real
(
len
(
args
),
argv
,
pointer
(
fuse_ops
),
sizeof
(
fuse_ops
),
None
)
del
self
.
operations
# Invoke the destructor
if
err
:
raise
RuntimeError
(
err
)
def
_wrapper_
(
self
,
func
,
*
args
,
**
kwargs
):
"""
Decorator for the methods that follow
"""
try
:
return
func
(
*
args
,
**
kwargs
)
or
0
except
OSError
,
e
:
return
-
(
e
.
errno
or
EFAULT
)
except
:
print_exc
()
return
-
EFAULT
def
getattr
(
self
,
path
,
buf
):
return
self
.
fgetattr
(
path
,
buf
,
None
)
def
readlink
(
self
,
path
,
buf
,
bufsize
):
ret
=
self
.
operations
(
'
readlink
'
,
path
)
data
=
create_string_buffer
(
ret
[:
bufsize
-
1
])
memmove
(
buf
,
data
,
len
(
data
))
return
0
def
mknod
(
self
,
path
,
mode
,
dev
):
return
self
.
operations
(
'
mknod
'
,
path
,
mode
,
dev
)
def
mkdir
(
self
,
path
,
mode
):
return
self
.
operations
(
'
mkdir
'
,
path
,
mode
)
def
unlink
(
self
,
path
):
return
self
.
operations
(
'
unlink
'
,
path
)
def
rmdir
(
self
,
path
):
return
self
.
operations
(
'
rmdir
'
,
path
)
def
symlink
(
self
,
source
,
target
):
return
self
.
operations
(
'
symlink
'
,
target
,
source
)
def
rename
(
self
,
old
,
new
):
return
self
.
operations
(
'
rename
'
,
old
,
new
)
def
link
(
self
,
source
,
target
):
return
self
.
operations
(
'
link
'
,
target
,
source
)
def
chmod
(
self
,
path
,
mode
):
return
self
.
operations
(
'
chmod
'
,
path
,
mode
)
def
chown
(
self
,
path
,
uid
,
gid
):
# Check if any of the arguments is a -1 that has overflowed
if
c_uid_t
(
uid
+
1
).
value
==
0
:
uid
=
-
1
if
c_gid_t
(
gid
+
1
).
value
==
0
:
gid
=
-
1
return
self
.
operations
(
'
chown
'
,
path
,
uid
,
gid
)
def
truncate
(
self
,
path
,
length
):
return
self
.
operations
(
'
truncate
'
,
path
,
length
)
def
open
(
self
,
path
,
fip
):
fi
=
fip
.
contents
if
self
.
raw_fi
:
return
self
.
operations
(
'
open
'
,
path
,
fi
)
else
:
fi
.
fh
=
self
.
operations
(
'
open
'
,
path
,
fi
.
flags
)
return
0
def
read
(
self
,
path
,
buf
,
size
,
offset
,
fip
):
fh
=
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
ret
=
self
.
operations
(
'
read
'
,
path
,
size
,
offset
,
fh
)
if
not
ret
:
return
0
data
=
create_string_buffer
(
ret
[:
size
],
size
)
memmove
(
buf
,
data
,
size
)
return
size
def
write
(
self
,
path
,
buf
,
size
,
offset
,
fip
):
data
=
string_at
(
buf
,
size
)
fh
=
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
return
self
.
operations
(
'
write
'
,
path
,
data
,
offset
,
fh
)
def
statfs
(
self
,
path
,
buf
):
stv
=
buf
.
contents
attrs
=
self
.
operations
(
'
statfs
'
,
path
)
for
key
,
val
in
attrs
.
items
():
if
hasattr
(
stv
,
key
):
setattr
(
stv
,
key
,
val
)
return
0
def
flush
(
self
,
path
,
fip
):
fh
=
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
return
self
.
operations
(
'
flush
'
,
path
,
fh
)
def
release
(
self
,
path
,
fip
):
fh
=
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
return
self
.
operations
(
'
release
'
,
path
,
fh
)
def
fsync
(
self
,
path
,
datasync
,
fip
):
fh
=
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
return
self
.
operations
(
'
fsync
'
,
path
,
datasync
,
fh
)
def
setxattr
(
self
,
path
,
name
,
value
,
size
,
options
,
*
args
):
data
=
string_at
(
value
,
size
)
return
self
.
operations
(
'
setxattr
'
,
path
,
name
,
data
,
options
,
*
args
)
def
getxattr
(
self
,
path
,
name
,
value
,
size
,
*
args
):
ret
=
self
.
operations
(
'
getxattr
'
,
path
,
name
,
*
args
)
retsize
=
len
(
ret
)
buf
=
create_string_buffer
(
ret
,
retsize
)
# Does not add trailing 0
if
bool
(
value
):
if
retsize
>
size
:
return
-
ERANGE
memmove
(
value
,
buf
,
retsize
)
return
retsize
def
listxattr
(
self
,
path
,
namebuf
,
size
):
ret
=
self
.
operations
(
'
listxattr
'
,
path
)
buf
=
create_string_buffer
(
'
\x00
'
.
join
(
ret
))
if
ret
else
''
bufsize
=
len
(
buf
)
if
bool
(
namebuf
):
if
bufsize
>
size
:
return
-
ERANGE
memmove
(
namebuf
,
buf
,
bufsize
)
return
bufsize
def
removexattr
(
self
,
path
,
name
):
return
self
.
operations
(
'
removexattr
'
,
path
,
name
)
def
opendir
(
self
,
path
,
fip
):
# Ignore raw_fi
fip
.
contents
.
fh
=
self
.
operations
(
'
opendir
'
,
path
)
return
0
def
readdir
(
self
,
path
,
buf
,
filler
,
offset
,
fip
):
# Ignore raw_fi
for
item
in
self
.
operations
(
'
readdir
'
,
path
,
fip
.
contents
.
fh
):
if
isinstance
(
item
,
str
):
name
,
st
,
offset
=
item
,
None
,
0
else
:
name
,
attrs
,
offset
=
item
if
attrs
:
st
=
c_stat
()
set_st_attrs
(
st
,
attrs
)
else
:
st
=
None
if
filler
(
buf
,
name
,
st
,
offset
)
!=
0
:
break
return
0
def
releasedir
(
self
,
path
,
fip
):
# Ignore raw_fi
return
self
.
operations
(
'
releasedir
'
,
path
,
fip
.
contents
.
fh
)
def
fsyncdir
(
self
,
path
,
datasync
,
fip
):
# Ignore raw_fi
return
self
.
operations
(
'
fsyncdir
'
,
path
,
datasync
,
fip
.
contents
.
fh
)
def
init
(
self
,
conn
):
return
self
.
operations
(
'
init
'
,
'
/
'
)
def
destroy
(
self
,
private_data
):
return
self
.
operations
(
'
destroy
'
,
'
/
'
)
def
access
(
self
,
path
,
amode
):
return
self
.
operations
(
'
access
'
,
path
,
amode
)
def
create
(
self
,
path
,
mode
,
fip
):
fi
=
fip
.
contents
if
self
.
raw_fi
:
return
self
.
operations
(
'
create
'
,
path
,
mode
,
fi
)
else
:
fi
.
fh
=
self
.
operations
(
'
create
'
,
path
,
mode
)
return
0
def
ftruncate
(
self
,
path
,
length
,
fip
):
fh
=
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
return
self
.
operations
(
'
truncate
'
,
path
,
length
,
fh
)
def
fgetattr
(
self
,
path
,
buf
,
fip
):
memset
(
buf
,
0
,
sizeof
(
c_stat
))
st
=
buf
.
contents
fh
=
fip
and
(
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
)
attrs
=
self
.
operations
(
'
getattr
'
,
path
,
fh
)
set_st_attrs
(
st
,
attrs
)
return
0
def
lock
(
self
,
path
,
fip
,
cmd
,
lock
):
fh
=
fip
.
contents
if
self
.
raw_fi
else
fip
.
contents
.
fh
return
self
.
operations
(
'
lock
'
,
path
,
fh
,
cmd
,
lock
)
def
utimens
(
self
,
path
,
buf
):
if
buf
:
atime
=
time_of_timespec
(
buf
.
contents
.
actime
)
mtime
=
time_of_timespec
(
buf
.
contents
.
modtime
)
times
=
(
atime
,
mtime
)
else
:
times
=
None
return
self
.
operations
(
'
utimens
'
,
path
,
times
)
def
bmap
(
self
,
path
,
blocksize
,
idx
):
return
self
.
operations
(
'
bmap
'
,
path
,
blocksize
,
idx
)
class
Operations
(
object
):
"""
This class should be subclassed and passed as an argument to FUSE on
initialization. All operations should raise a FuseOSError exception
on error.
When in doubt of what an operation should do, check the FUSE header
file or the corresponding system call man page.
"""
def
__call__
(
self
,
op
,
*
args
):
if
not
hasattr
(
self
,
op
):
raise
FuseOSError
(
EFAULT
)
return
getattr
(
self
,
op
)(
*
args
)
def
access
(
self
,
path
,
amode
):
return
0
bmap
=
None
def
chmod
(
self
,
path
,
mode
):
raise
FuseOSError
(
EROFS
)
def
chown
(
self
,
path
,
uid
,
gid
):
raise
FuseOSError
(
EROFS
)
def
create
(
self
,
path
,
mode
,
fi
=
None
):
"""
When raw_fi is False (default case), fi is None and create should
return a numerical file handle.
When raw_fi is True the file handle should be set directly by create
and return 0.
"""
raise
FuseOSError
(
EROFS
)
def
destroy
(
self
,
path
):
"""
Called on filesystem destruction. Path is always /
"""
pass
def
flush
(
self
,
path
,
fh
):
return
0
def
fsync
(
self
,
path
,
datasync
,
fh
):
return
0
def
fsyncdir
(
self
,
path
,
datasync
,
fh
):
return
0
def
getattr
(
self
,
path
,
fh
=
None
):
"""
Returns a dictionary with keys identical to the stat C structure
of stat(2).
st_atime, st_mtime and st_ctime should be floats.
NOTE: There is an incombatibility between Linux and Mac OS X concerning
st_nlink of directories. Mac OS X counts all files inside the directory,
while Linux counts only the subdirectories.
"""
if
path
!=
'
/
'
:
raise
FuseOSError
(
ENOENT
)
return
dict
(
st_mode
=
(
S_IFDIR
|
0755
),
st_nlink
=
2
)
def
getxattr
(
self
,
path
,
name
,
position
=
0
):
raise
FuseOSError
(
ENOTSUP
)
def
init
(
self
,
path
):
"""
Called on filesystem initialization. Path is always /
Use it instead of __init__ if you start threads on initialization.
"""
pass
def
link
(
self
,
target
,
source
):
raise
FuseOSError
(
EROFS
)
def
listxattr
(
self
,
path
):
return
[]
lock
=
None
def
mkdir
(
self
,
path
,
mode
):
raise
FuseOSError
(
EROFS
)
def
mknod
(
self
,
path
,
mode
,
dev
):
raise
FuseOSError
(
EROFS
)
def
open
(
self
,
path
,
flags
):
"""
When raw_fi is False (default case), open should return a numerical
file handle.
When raw_fi is True the signature of open becomes:
open(self, path, fi)
and the file handle should be set directly.
"""
return
0
def
opendir
(
self
,
path
):
"""
Returns a numerical file handle.
"""
return
0
def
read
(
self
,
path
,
size
,
offset
,
fh
):
"""
Returns a string containing the data requested.
"""
raise
FuseOSError
(
EIO
)
def
readdir
(
self
,
path
,
fh
):
"""
Can return either a list of names, or a list of (name, attrs, offset)
tuples. attrs is a dict as in getattr.
"""
return
[
'
.
'
,
'
..
'
]
def
readlink
(
self
,
path
):
raise
FuseOSError
(
ENOENT
)
def
release
(
self
,
path
,
fh
):
return
0
def
releasedir
(
self
,
path
,
fh
):
return
0
def
removexattr
(
self
,
path
,
name
):
raise
FuseOSError
(
ENOTSUP
)
def
rename
(
self
,
old
,
new
):
raise
FuseOSError
(
EROFS
)
def
rmdir
(
self
,
path
):
raise
FuseOSError
(
EROFS
)
def
setxattr
(
self
,
path
,
name
,
value
,
options
,
position
=
0
):
raise
FuseOSError
(
ENOTSUP
)
def
statfs
(
self
,
path
):
"""
Returns a dictionary with keys identical to the statvfs C structure
of statvfs(3).
On Mac OS X f_bsize and f_frsize must be a power of 2 (minimum 512).
"""
return
{}
def
symlink
(
self
,
target
,
source
):
raise
FuseOSError
(
EROFS
)
def
truncate
(
self
,
path
,
length
,
fh
=
None
):
raise
FuseOSError
(
EROFS
)
def
unlink
(
self
,
path
):
raise
FuseOSError
(
EROFS
)
def
utimens
(
self
,
path
,
times
=
None
):
"""
Times is a (atime, mtime) tuple. If None use current time.
"""
return
0
def
write
(
self
,
path
,
data
,
offset
,
fh
):
raise
FuseOSError
(
EROFS
)
class
LoggingMixIn
:
def
__call__
(
self
,
op
,
path
,
*
args
):
print
'
->
'
,
op
,
path
,
repr
(
args
)
ret
=
'
[Unhandled Exception]
'
try
:
ret
=
getattr
(
self
,
op
)(
path
,
*
args
)
return
ret
except
OSError
,
e
:
ret
=
str
(
e
)
raise
finally
:
print
'
<-
'
,
op
,
repr
(
ret
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment