Skip to content

Commit 12500cf

Browse files
authored
Merge pull request #79 from jepler/issue77
When getting string size, count UTF8 bytes
2 parents 2cb2302 + 4129521 commit 12500cf

File tree

6 files changed

+81
-11
lines changed

6 files changed

+81
-11
lines changed

example/xattr.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Example by github @vignedev from https://github.com/libfuse/python-fuse/issues/77
2+
3+
import fuse
4+
import stat, errno
5+
from fuse import Fuse, Stat, Direntry
6+
7+
fuse.fuse_python_api = (0, 2)
8+
9+
BROKEN_FILE = '/utf8_attr'
10+
FATTR_NAME = 'user.xdg.comment'
11+
FATTR_VALUE = 'ああ、メッセージは切り取られていない'
12+
13+
class EmptyStat(Stat):
14+
def __init__(self):
15+
self.st_mode = 0
16+
self.st_ino = 0
17+
self.st_dev = 0
18+
self.st_nlink = 0
19+
self.st_uid = 0
20+
self.st_gid = 0
21+
self.st_size = 0
22+
self.st_atime = 0
23+
self.st_mtime = 0
24+
self.st_ctime = 0
25+
26+
class GetAttrBug(Fuse):
27+
def getattr(self, path):
28+
ret_stat = EmptyStat()
29+
if path == '/':
30+
ret_stat.st_mode = stat.S_IFDIR | int(0e755)
31+
return ret_stat
32+
33+
if path == BROKEN_FILE:
34+
ret_stat.st_mode = stat.S_IFREG | int(0e000)
35+
return ret_stat
36+
37+
return -errno.ENOENT
38+
39+
def readdir(self, path, offset):
40+
yield Direntry('.')
41+
yield Direntry('..')
42+
yield Direntry(BROKEN_FILE[1:])
43+
44+
def open(self, path, flags):
45+
return -errno.EACCES
46+
47+
def read(self, path, size, offset):
48+
return
49+
50+
def listxattr(self, path, size):
51+
if size == 0: return 1
52+
else: return [ FATTR_NAME ]
53+
54+
def getxattr(self, path, attr, size):
55+
if size == 0: return len(FATTR_VALUE.encode('utf8'))
56+
else: return FATTR_VALUE
57+
58+
if __name__ == '__main__':
59+
server = GetAttrBug(dash_s_do='setsingle')
60+
server.parse(errex=1)
61+
server.main()

example/xmp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22

3-
# Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
3+
# Copyright (C) 2001 Jeff Epler <jepler@gmail.com>
44
# Copyright (C) 2006 Csaba Henk <[email protected]>
55
#
66
# This program can be distributed under the terms of the GNU LGPL.

fuse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
2+
# Copyright (C) 2001 Jeff Epler <jepler@gmail.com>
33
# Copyright (C) 2006 Csaba Henk <[email protected]>
44
#
55
# This program can be distributed under the terms of the GNU LGPL.

fuseparts/_fusemodule.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (C) 2001 Jeff Epler <jepler@unpythonic.dhs.org>
2+
Copyright (C) 2001 Jeff Epler <jepler@gmail.com>
33
44
This program can be distributed under the terms of the GNU LGPL.
55
See the file COPYING.
@@ -94,12 +94,16 @@
9494
PyErr_SetString(PyExc_ValueError, "non-decodable filename");
9595
return NULL;
9696
}
97-
97+
static inline Py_ssize_t PyString_Size(PyObject *s) {
98+
Py_ssize_t result = -1;
99+
(void)PyUnicode_AsUTF8AndSize(s, &result);
100+
return result;
101+
}
98102
#else
99103
#define PyString_AsString PyUnicode_AsUTF8
104+
#define PyString_Size PyUnicode_GET_LENGTH
100105
#endif
101106
#define PyString_Check PyUnicode_Check
102-
#define PyString_Size PyUnicode_GET_LENGTH
103107
#endif
104108

105109
#ifdef FIX_PATH_DECODING
@@ -683,14 +687,14 @@ read_func(const char *path, char *buf, size_t s, off_t off)
683687
if(PyObject_CheckBuffer(v)) {
684688
PyObject_GetBuffer(v, &buffer, PyBUF_SIMPLE);
685689

686-
if(buffer.len <= s) {
690+
if((size_t)buffer.len <= s) {
687691
memcpy(buf, buffer.buf, buffer.len);
688692
ret = buffer.len;
689693
}
690694

691695
PyBuffer_Release(&buffer);
692696
} else if(PyBytes_Check(v)) {
693-
if(PyBytes_Size(v) > s)
697+
if((size_t)PyBytes_Size(v) > s)
694698
goto OUT_DECREF;
695699
memcpy(buf, PyBytes_AsString(v), PyBytes_Size(v));
696700
ret = PyBytes_Size(v);
@@ -944,7 +948,7 @@ getxattr_func(const char *path, const char *name, char *value, size_t size)
944948
/* If the size of the value buffer is too small to hold the result, errno
945949
* is set to ERANGE.
946950
*/
947-
if (PyString_Size(v) > size) {
951+
if ((size_t)PyString_Size(v) > size) {
948952
ret = -ERANGE;
949953
goto OUT_DECREF;
950954
}
@@ -980,9 +984,9 @@ listxattr_func(const char *path, char *list, size_t size)
980984
}
981985

982986
for (;;) {
983-
int ilen;
987+
size_t ilen;
984988

985-
w = PyIter_Next(iter);
989+
w = PyIter_Next(iter);
986990
if (!w) {
987991
ret = lx - list;
988992
break;
@@ -1302,7 +1306,9 @@ pyfuse_loop_mt(struct fuse *f)
13021306
#ifdef WITH_THREAD
13031307
PyThreadState *save;
13041308

1309+
#if PY_VERSION_HEX < 0x03070000
13051310
PyEval_InitThreads();
1311+
#endif
13061312
interp = PyThreadState_Get()->interp;
13071313
save = PyEval_SaveThread();
13081314
err = fuse_loop_mt(f);

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def setup(**kwargs):
103103
package_data={'': ['COPYING', 'AUTHORS', 'FAQ', 'INSTALL',
104104
'README.md', 'README.new_fusepy_api.rst',
105105
'README.package_maintainers.rst']},
106-
author = 'Jeff Epler <[email protected]>, Csaba Henk <[email protected]>, Steven James, Miklos Szeredi <[email protected]>, Sébastien Delafond<[email protected]>',
106+
author = 'Csaba Henk <[email protected]>, Steven James, Miklos Szeredi <[email protected]>, Sébastien Delafond<[email protected]>',
107107
maintainer = 'Sébastien Delafond',
108108
maintainer_email = '[email protected]',
109109
ext_modules = [fusemodule],

tests/test_basic.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,6 @@ def test_fioc(filesystem):
6161
fcntl.ioctl(f.fileno(), FIOC_GET_SIZE, b)
6262
assert struct.unpack("L", b)[0] == 42
6363

64+
@pytest.mark.fstype("xattr")
65+
def test_xattr(filesystem):
66+
assert os.getxattr(filesystem / "utf8_attr", "user.xdg.comment").decode("utf-8") == 'ああ、メッセージは切り取られていない'

0 commit comments

Comments
 (0)