summaryrefslogtreecommitdiff
path: root/demo
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2012-06-17 15:28:22 +0200
committerArmin Rigo <arigo@tunes.org>2012-06-17 15:28:22 +0200
commit800fd444c1bcbb277102864cc224b47d08db3887 (patch)
tree4dfdee562a298e7d94e07f47b97ad8c79624090e /demo
parentbe0cf814f049281bb17ee4448c0875b2e473a5f1 (diff)
downloadcffi-800fd444c1bcbb277102864cc224b47d08db3887.tar.gz
Add another example. This one segfaults CPython on a bogus
reference count issue. Needs to investigate.
Diffstat (limited to 'demo')
-rw-r--r--demo/bsdopendirtype.py62
1 files changed, 62 insertions, 0 deletions
diff --git a/demo/bsdopendirtype.py b/demo/bsdopendirtype.py
new file mode 100644
index 0000000..6c2dadd
--- /dev/null
+++ b/demo/bsdopendirtype.py
@@ -0,0 +1,62 @@
+from cffi import FFI
+
+ffi = FFI()
+ffi.cdef("""
+ typedef ... DIR;
+ struct dirent {
+ unsigned char d_type; /* type of file */
+ char d_name[]; /* filename */
+ ...;
+ };
+ DIR *opendir(const char *name);
+ int closedir(DIR *dirp);
+ struct dirent *readdir(DIR *dirp);
+ static const int DT_BLK, DT_CHR, DT_DIR, DT_FIFO, DT_LNK, DT_REG, DT_SOCK;
+""")
+lib = ffi.verify("""
+ #include <sys/types.h>
+ #include <dirent.h>
+""")
+
+
+def _posix_error():
+ raise OSError(ffi.errno, os.strerror(ffi.errno))
+
+_dtype_to_smode = {
+ lib.DT_BLK: 0060000,
+ lib.DT_CHR: 0020000,
+ lib.DT_DIR: 0040000,
+ lib.DT_FIFO: 0010000,
+ lib.DT_LNK: 0120000,
+ lib.DT_REG: 0100000,
+ lib.DT_SOCK: 0140000,
+}
+
+def opendir(dir):
+ if len(dir) == 0:
+ dir = '.'
+ dirname = dir
+ if not dirname.endswith('/'):
+ dirname += '/'
+ dirp = lib.opendir(dir)
+ if dirp == None:
+ raise _posix_error()
+ try:
+ while True:
+ ffi.errno = 0
+ dirent = lib.readdir(dirp)
+ if dirent == None:
+ if ffi.errno != 0:
+ raise _posix_error()
+ return
+ name = str(dirent.d_name)
+ if name == '.' or name == '..':
+ continue
+ name = dirname + name
+ try:
+ smode = _dtype_to_smode[dirent.d_type]
+ except KeyError:
+ smode = os.lstat(name).st_mode
+ yield name, smode
+ finally:
+ lib.closedir(dirp)