##// END OF EJS Templates
osutil: fix excessive decref on tuple creation failure in listdir()...
Yuya Nishihara -
r45734:f93a4e3d default
parent child Browse files
Show More
@@ -1,1422 +1,1419 b''
1 /*
1 /*
2 osutil.c - native operating system services
2 osutil.c - native operating system services
3
3
4 Copyright 2007 Matt Mackall and others
4 Copyright 2007 Matt Mackall and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #define _ATFILE_SOURCE
10 #define _ATFILE_SOURCE
11 #define PY_SSIZE_T_CLEAN
11 #define PY_SSIZE_T_CLEAN
12 #include <Python.h>
12 #include <Python.h>
13 #include <errno.h>
13 #include <errno.h>
14 #include <fcntl.h>
14 #include <fcntl.h>
15 #include <stdio.h>
15 #include <stdio.h>
16 #include <stdlib.h>
16 #include <stdlib.h>
17 #include <string.h>
17 #include <string.h>
18
18
19 #ifdef _WIN32
19 #ifdef _WIN32
20 #include <io.h>
20 #include <io.h>
21 #include <windows.h>
21 #include <windows.h>
22 #else
22 #else
23 #include <dirent.h>
23 #include <dirent.h>
24 #include <signal.h>
24 #include <signal.h>
25 #include <sys/socket.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
27 #include <sys/types.h>
28 #include <unistd.h>
28 #include <unistd.h>
29 #ifdef HAVE_LINUX_STATFS
29 #ifdef HAVE_LINUX_STATFS
30 #include <linux/magic.h>
30 #include <linux/magic.h>
31 #include <sys/vfs.h>
31 #include <sys/vfs.h>
32 #endif
32 #endif
33 #ifdef HAVE_BSD_STATFS
33 #ifdef HAVE_BSD_STATFS
34 #include <sys/mount.h>
34 #include <sys/mount.h>
35 #include <sys/param.h>
35 #include <sys/param.h>
36 #endif
36 #endif
37 #endif
37 #endif
38
38
39 #ifdef __APPLE__
39 #ifdef __APPLE__
40 #include <sys/attr.h>
40 #include <sys/attr.h>
41 #include <sys/vnode.h>
41 #include <sys/vnode.h>
42 #endif
42 #endif
43
43
44 #include "util.h"
44 #include "util.h"
45
45
46 /* some platforms lack the PATH_MAX definition (eg. GNU/Hurd) */
46 /* some platforms lack the PATH_MAX definition (eg. GNU/Hurd) */
47 #ifndef PATH_MAX
47 #ifndef PATH_MAX
48 #define PATH_MAX 4096
48 #define PATH_MAX 4096
49 #endif
49 #endif
50
50
51 #ifdef _WIN32
51 #ifdef _WIN32
52 /*
52 /*
53 stat struct compatible with hg expectations
53 stat struct compatible with hg expectations
54 Mercurial only uses st_mode, st_size and st_mtime
54 Mercurial only uses st_mode, st_size and st_mtime
55 the rest is kept to minimize changes between implementations
55 the rest is kept to minimize changes between implementations
56 */
56 */
57 struct hg_stat {
57 struct hg_stat {
58 int st_dev;
58 int st_dev;
59 int st_mode;
59 int st_mode;
60 int st_nlink;
60 int st_nlink;
61 __int64 st_size;
61 __int64 st_size;
62 int st_mtime;
62 int st_mtime;
63 int st_ctime;
63 int st_ctime;
64 };
64 };
65 struct listdir_stat {
65 struct listdir_stat {
66 PyObject_HEAD
66 PyObject_HEAD
67 struct hg_stat st;
67 struct hg_stat st;
68 };
68 };
69 #else
69 #else
70 struct listdir_stat {
70 struct listdir_stat {
71 PyObject_HEAD
71 PyObject_HEAD
72 struct stat st;
72 struct stat st;
73 };
73 };
74 #endif
74 #endif
75
75
76 #ifdef IS_PY3K
76 #ifdef IS_PY3K
77 #define listdir_slot(name) \
77 #define listdir_slot(name) \
78 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
78 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
79 { \
79 { \
80 return PyLong_FromLong(((struct listdir_stat *)self)->st.name); \
80 return PyLong_FromLong(((struct listdir_stat *)self)->st.name); \
81 }
81 }
82 #else
82 #else
83 #define listdir_slot(name) \
83 #define listdir_slot(name) \
84 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
84 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
85 { \
85 { \
86 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
86 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
87 }
87 }
88 #endif
88 #endif
89
89
90 listdir_slot(st_dev)
90 listdir_slot(st_dev)
91 listdir_slot(st_mode)
91 listdir_slot(st_mode)
92 listdir_slot(st_nlink)
92 listdir_slot(st_nlink)
93 #ifdef _WIN32
93 #ifdef _WIN32
94 static PyObject *listdir_stat_st_size(PyObject *self, void *x)
94 static PyObject *listdir_stat_st_size(PyObject *self, void *x)
95 {
95 {
96 return PyLong_FromLongLong(
96 return PyLong_FromLongLong(
97 (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
97 (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
98 }
98 }
99 #else
99 #else
100 listdir_slot(st_size)
100 listdir_slot(st_size)
101 #endif
101 #endif
102 listdir_slot(st_mtime)
102 listdir_slot(st_mtime)
103 listdir_slot(st_ctime)
103 listdir_slot(st_ctime)
104
104
105 static struct PyGetSetDef listdir_stat_getsets[] = {
105 static struct PyGetSetDef listdir_stat_getsets[] = {
106 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
106 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
107 {"st_mode", listdir_stat_st_mode, 0, 0, 0},
107 {"st_mode", listdir_stat_st_mode, 0, 0, 0},
108 {"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
108 {"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
109 {"st_size", listdir_stat_st_size, 0, 0, 0},
109 {"st_size", listdir_stat_st_size, 0, 0, 0},
110 {"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
110 {"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
111 {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
111 {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
112 {0, 0, 0, 0, 0}
112 {0, 0, 0, 0, 0}
113 };
113 };
114
114
115 static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
115 static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
116 {
116 {
117 return t->tp_alloc(t, 0);
117 return t->tp_alloc(t, 0);
118 }
118 }
119
119
120 static void listdir_stat_dealloc(PyObject *o)
120 static void listdir_stat_dealloc(PyObject *o)
121 {
121 {
122 o->ob_type->tp_free(o);
122 o->ob_type->tp_free(o);
123 }
123 }
124
124
125 static PyObject *listdir_stat_getitem(PyObject *self, PyObject *key)
125 static PyObject *listdir_stat_getitem(PyObject *self, PyObject *key)
126 {
126 {
127 long index = PyLong_AsLong(key);
127 long index = PyLong_AsLong(key);
128 if (index == -1 && PyErr_Occurred()) {
128 if (index == -1 && PyErr_Occurred()) {
129 return NULL;
129 return NULL;
130 }
130 }
131 if (index != 8) {
131 if (index != 8) {
132 PyErr_Format(PyExc_IndexError, "osutil.stat objects only "
132 PyErr_Format(PyExc_IndexError, "osutil.stat objects only "
133 "support stat.ST_MTIME in "
133 "support stat.ST_MTIME in "
134 "__getitem__");
134 "__getitem__");
135 return NULL;
135 return NULL;
136 }
136 }
137 return listdir_stat_st_mtime(self, NULL);
137 return listdir_stat_st_mtime(self, NULL);
138 }
138 }
139
139
140 static PyMappingMethods listdir_stat_type_mapping_methods = {
140 static PyMappingMethods listdir_stat_type_mapping_methods = {
141 (lenfunc)NULL, /* mp_length */
141 (lenfunc)NULL, /* mp_length */
142 (binaryfunc)listdir_stat_getitem, /* mp_subscript */
142 (binaryfunc)listdir_stat_getitem, /* mp_subscript */
143 (objobjargproc)NULL, /* mp_ass_subscript */
143 (objobjargproc)NULL, /* mp_ass_subscript */
144 };
144 };
145
145
146 static PyTypeObject listdir_stat_type = {
146 static PyTypeObject listdir_stat_type = {
147 PyVarObject_HEAD_INIT(NULL, 0) /* header */
147 PyVarObject_HEAD_INIT(NULL, 0) /* header */
148 "osutil.stat", /*tp_name*/
148 "osutil.stat", /*tp_name*/
149 sizeof(struct listdir_stat), /*tp_basicsize*/
149 sizeof(struct listdir_stat), /*tp_basicsize*/
150 0, /*tp_itemsize*/
150 0, /*tp_itemsize*/
151 (destructor)listdir_stat_dealloc, /*tp_dealloc*/
151 (destructor)listdir_stat_dealloc, /*tp_dealloc*/
152 0, /*tp_print*/
152 0, /*tp_print*/
153 0, /*tp_getattr*/
153 0, /*tp_getattr*/
154 0, /*tp_setattr*/
154 0, /*tp_setattr*/
155 0, /*tp_compare*/
155 0, /*tp_compare*/
156 0, /*tp_repr*/
156 0, /*tp_repr*/
157 0, /*tp_as_number*/
157 0, /*tp_as_number*/
158 0, /*tp_as_sequence*/
158 0, /*tp_as_sequence*/
159 &listdir_stat_type_mapping_methods, /*tp_as_mapping*/
159 &listdir_stat_type_mapping_methods, /*tp_as_mapping*/
160 0, /*tp_hash */
160 0, /*tp_hash */
161 0, /*tp_call*/
161 0, /*tp_call*/
162 0, /*tp_str*/
162 0, /*tp_str*/
163 0, /*tp_getattro*/
163 0, /*tp_getattro*/
164 0, /*tp_setattro*/
164 0, /*tp_setattro*/
165 0, /*tp_as_buffer*/
165 0, /*tp_as_buffer*/
166 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
166 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
167 "stat objects", /* tp_doc */
167 "stat objects", /* tp_doc */
168 0, /* tp_traverse */
168 0, /* tp_traverse */
169 0, /* tp_clear */
169 0, /* tp_clear */
170 0, /* tp_richcompare */
170 0, /* tp_richcompare */
171 0, /* tp_weaklistoffset */
171 0, /* tp_weaklistoffset */
172 0, /* tp_iter */
172 0, /* tp_iter */
173 0, /* tp_iternext */
173 0, /* tp_iternext */
174 0, /* tp_methods */
174 0, /* tp_methods */
175 0, /* tp_members */
175 0, /* tp_members */
176 listdir_stat_getsets, /* tp_getset */
176 listdir_stat_getsets, /* tp_getset */
177 0, /* tp_base */
177 0, /* tp_base */
178 0, /* tp_dict */
178 0, /* tp_dict */
179 0, /* tp_descr_get */
179 0, /* tp_descr_get */
180 0, /* tp_descr_set */
180 0, /* tp_descr_set */
181 0, /* tp_dictoffset */
181 0, /* tp_dictoffset */
182 0, /* tp_init */
182 0, /* tp_init */
183 0, /* tp_alloc */
183 0, /* tp_alloc */
184 listdir_stat_new, /* tp_new */
184 listdir_stat_new, /* tp_new */
185 };
185 };
186
186
187 #ifdef _WIN32
187 #ifdef _WIN32
188
188
189 static int to_python_time(const FILETIME *tm)
189 static int to_python_time(const FILETIME *tm)
190 {
190 {
191 /* number of seconds between epoch and January 1 1601 */
191 /* number of seconds between epoch and January 1 1601 */
192 const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
192 const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
193 /* conversion factor from 100ns to 1s */
193 /* conversion factor from 100ns to 1s */
194 const __int64 a1 = 10000000;
194 const __int64 a1 = 10000000;
195 /* explicit (int) cast to suspend compiler warnings */
195 /* explicit (int) cast to suspend compiler warnings */
196 return (int)((((__int64)tm->dwHighDateTime << 32)
196 return (int)((((__int64)tm->dwHighDateTime << 32)
197 + tm->dwLowDateTime) / a1 - a0);
197 + tm->dwLowDateTime) / a1 - a0);
198 }
198 }
199
199
200 static PyObject *make_item(const WIN32_FIND_DATAA *fd, int wantstat)
200 static PyObject *make_item(const WIN32_FIND_DATAA *fd, int wantstat)
201 {
201 {
202 PyObject *py_st;
202 PyObject *py_st;
203 struct hg_stat *stp;
203 struct hg_stat *stp;
204
204
205 int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
205 int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
206 ? _S_IFDIR : _S_IFREG;
206 ? _S_IFDIR : _S_IFREG;
207
207
208 if (!wantstat)
208 if (!wantstat)
209 return Py_BuildValue(PY23("si", "yi"), fd->cFileName, kind);
209 return Py_BuildValue(PY23("si", "yi"), fd->cFileName, kind);
210
210
211 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
211 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
212 if (!py_st)
212 if (!py_st)
213 return NULL;
213 return NULL;
214
214
215 stp = &((struct listdir_stat *)py_st)->st;
215 stp = &((struct listdir_stat *)py_st)->st;
216 /*
216 /*
217 use kind as st_mode
217 use kind as st_mode
218 rwx bits on Win32 are meaningless
218 rwx bits on Win32 are meaningless
219 and Hg does not use them anyway
219 and Hg does not use them anyway
220 */
220 */
221 stp->st_mode = kind;
221 stp->st_mode = kind;
222 stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
222 stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
223 stp->st_ctime = to_python_time(&fd->ftCreationTime);
223 stp->st_ctime = to_python_time(&fd->ftCreationTime);
224 if (kind == _S_IFREG)
224 if (kind == _S_IFREG)
225 stp->st_size = ((__int64)fd->nFileSizeHigh << 32)
225 stp->st_size = ((__int64)fd->nFileSizeHigh << 32)
226 + fd->nFileSizeLow;
226 + fd->nFileSizeLow;
227 return Py_BuildValue(PY23("siN", "yiN"), fd->cFileName,
227 return Py_BuildValue(PY23("siN", "yiN"), fd->cFileName,
228 kind, py_st);
228 kind, py_st);
229 }
229 }
230
230
231 static PyObject *_listdir(char *path, Py_ssize_t plen, int wantstat, char *skip)
231 static PyObject *_listdir(char *path, Py_ssize_t plen, int wantstat, char *skip)
232 {
232 {
233 PyObject *rval = NULL; /* initialize - return value */
233 PyObject *rval = NULL; /* initialize - return value */
234 PyObject *list;
234 PyObject *list;
235 HANDLE fh;
235 HANDLE fh;
236 WIN32_FIND_DATAA fd;
236 WIN32_FIND_DATAA fd;
237 char *pattern;
237 char *pattern;
238
238
239 /* build the path + \* pattern string */
239 /* build the path + \* pattern string */
240 pattern = PyMem_Malloc(plen + 3); /* path + \* + \0 */
240 pattern = PyMem_Malloc(plen + 3); /* path + \* + \0 */
241 if (!pattern) {
241 if (!pattern) {
242 PyErr_NoMemory();
242 PyErr_NoMemory();
243 goto error_nomem;
243 goto error_nomem;
244 }
244 }
245 memcpy(pattern, path, plen);
245 memcpy(pattern, path, plen);
246
246
247 if (plen > 0) {
247 if (plen > 0) {
248 char c = path[plen-1];
248 char c = path[plen-1];
249 if (c != ':' && c != '/' && c != '\\')
249 if (c != ':' && c != '/' && c != '\\')
250 pattern[plen++] = '\\';
250 pattern[plen++] = '\\';
251 }
251 }
252 pattern[plen++] = '*';
252 pattern[plen++] = '*';
253 pattern[plen] = '\0';
253 pattern[plen] = '\0';
254
254
255 fh = FindFirstFileA(pattern, &fd);
255 fh = FindFirstFileA(pattern, &fd);
256 if (fh == INVALID_HANDLE_VALUE) {
256 if (fh == INVALID_HANDLE_VALUE) {
257 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
257 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
258 goto error_file;
258 goto error_file;
259 }
259 }
260
260
261 list = PyList_New(0);
261 list = PyList_New(0);
262 if (!list)
262 if (!list)
263 goto error_list;
263 goto error_list;
264
264
265 do {
265 do {
266 PyObject *item;
266 PyObject *item;
267
267
268 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
268 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
269 if (!strcmp(fd.cFileName, ".")
269 if (!strcmp(fd.cFileName, ".")
270 || !strcmp(fd.cFileName, ".."))
270 || !strcmp(fd.cFileName, ".."))
271 continue;
271 continue;
272
272
273 if (skip && !strcmp(fd.cFileName, skip)) {
273 if (skip && !strcmp(fd.cFileName, skip)) {
274 rval = PyList_New(0);
274 rval = PyList_New(0);
275 goto error;
275 goto error;
276 }
276 }
277 }
277 }
278
278
279 item = make_item(&fd, wantstat);
279 item = make_item(&fd, wantstat);
280 if (!item)
280 if (!item)
281 goto error;
281 goto error;
282
282
283 if (PyList_Append(list, item)) {
283 if (PyList_Append(list, item)) {
284 Py_XDECREF(item);
284 Py_XDECREF(item);
285 goto error;
285 goto error;
286 }
286 }
287
287
288 Py_XDECREF(item);
288 Py_XDECREF(item);
289 } while (FindNextFileA(fh, &fd));
289 } while (FindNextFileA(fh, &fd));
290
290
291 if (GetLastError() != ERROR_NO_MORE_FILES) {
291 if (GetLastError() != ERROR_NO_MORE_FILES) {
292 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
292 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
293 goto error;
293 goto error;
294 }
294 }
295
295
296 rval = list;
296 rval = list;
297 Py_XINCREF(rval);
297 Py_XINCREF(rval);
298 error:
298 error:
299 Py_XDECREF(list);
299 Py_XDECREF(list);
300 error_list:
300 error_list:
301 FindClose(fh);
301 FindClose(fh);
302 error_file:
302 error_file:
303 PyMem_Free(pattern);
303 PyMem_Free(pattern);
304 error_nomem:
304 error_nomem:
305 return rval;
305 return rval;
306 }
306 }
307
307
308 #else
308 #else
309
309
310 int entkind(struct dirent *ent)
310 int entkind(struct dirent *ent)
311 {
311 {
312 #ifdef DT_REG
312 #ifdef DT_REG
313 switch (ent->d_type) {
313 switch (ent->d_type) {
314 case DT_REG: return S_IFREG;
314 case DT_REG: return S_IFREG;
315 case DT_DIR: return S_IFDIR;
315 case DT_DIR: return S_IFDIR;
316 case DT_LNK: return S_IFLNK;
316 case DT_LNK: return S_IFLNK;
317 case DT_BLK: return S_IFBLK;
317 case DT_BLK: return S_IFBLK;
318 case DT_CHR: return S_IFCHR;
318 case DT_CHR: return S_IFCHR;
319 case DT_FIFO: return S_IFIFO;
319 case DT_FIFO: return S_IFIFO;
320 case DT_SOCK: return S_IFSOCK;
320 case DT_SOCK: return S_IFSOCK;
321 }
321 }
322 #endif
322 #endif
323 return -1;
323 return -1;
324 }
324 }
325
325
326 static PyObject *makestat(const struct stat *st)
326 static PyObject *makestat(const struct stat *st)
327 {
327 {
328 PyObject *stat;
328 PyObject *stat;
329
329
330 stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
330 stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
331 if (stat)
331 if (stat)
332 memcpy(&((struct listdir_stat *)stat)->st, st, sizeof(*st));
332 memcpy(&((struct listdir_stat *)stat)->st, st, sizeof(*st));
333 return stat;
333 return stat;
334 }
334 }
335
335
336 static PyObject *_listdir_stat(char *path, int pathlen, int keepstat,
336 static PyObject *_listdir_stat(char *path, int pathlen, int keepstat,
337 char *skip)
337 char *skip)
338 {
338 {
339 PyObject *list, *elem, *stat = NULL, *ret = NULL;
339 PyObject *list, *elem, *ret = NULL;
340 char fullpath[PATH_MAX + 10];
340 char fullpath[PATH_MAX + 10];
341 int kind, err;
341 int kind, err;
342 struct stat st;
342 struct stat st;
343 struct dirent *ent;
343 struct dirent *ent;
344 DIR *dir;
344 DIR *dir;
345 #ifdef AT_SYMLINK_NOFOLLOW
345 #ifdef AT_SYMLINK_NOFOLLOW
346 int dfd = -1;
346 int dfd = -1;
347 #endif
347 #endif
348
348
349 if (pathlen >= PATH_MAX) {
349 if (pathlen >= PATH_MAX) {
350 errno = ENAMETOOLONG;
350 errno = ENAMETOOLONG;
351 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
351 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
352 goto error_value;
352 goto error_value;
353 }
353 }
354 strncpy(fullpath, path, PATH_MAX);
354 strncpy(fullpath, path, PATH_MAX);
355 fullpath[pathlen] = '/';
355 fullpath[pathlen] = '/';
356
356
357 #ifdef AT_SYMLINK_NOFOLLOW
357 #ifdef AT_SYMLINK_NOFOLLOW
358 dfd = open(path, O_RDONLY);
358 dfd = open(path, O_RDONLY);
359 if (dfd == -1) {
359 if (dfd == -1) {
360 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
360 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
361 goto error_value;
361 goto error_value;
362 }
362 }
363 dir = fdopendir(dfd);
363 dir = fdopendir(dfd);
364 #else
364 #else
365 dir = opendir(path);
365 dir = opendir(path);
366 #endif
366 #endif
367 if (!dir) {
367 if (!dir) {
368 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
368 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
369 goto error_dir;
369 goto error_dir;
370 }
370 }
371
371
372 list = PyList_New(0);
372 list = PyList_New(0);
373 if (!list)
373 if (!list)
374 goto error_list;
374 goto error_list;
375
375
376 while ((ent = readdir(dir))) {
376 while ((ent = readdir(dir))) {
377 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
377 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
378 continue;
378 continue;
379
379
380 kind = entkind(ent);
380 kind = entkind(ent);
381 if (kind == -1 || keepstat) {
381 if (kind == -1 || keepstat) {
382 #ifdef AT_SYMLINK_NOFOLLOW
382 #ifdef AT_SYMLINK_NOFOLLOW
383 err = fstatat(dfd, ent->d_name, &st,
383 err = fstatat(dfd, ent->d_name, &st,
384 AT_SYMLINK_NOFOLLOW);
384 AT_SYMLINK_NOFOLLOW);
385 #else
385 #else
386 strncpy(fullpath + pathlen + 1, ent->d_name,
386 strncpy(fullpath + pathlen + 1, ent->d_name,
387 PATH_MAX - pathlen);
387 PATH_MAX - pathlen);
388 fullpath[PATH_MAX] = '\0';
388 fullpath[PATH_MAX] = '\0';
389 err = lstat(fullpath, &st);
389 err = lstat(fullpath, &st);
390 #endif
390 #endif
391 if (err == -1) {
391 if (err == -1) {
392 /* race with file deletion? */
392 /* race with file deletion? */
393 if (errno == ENOENT)
393 if (errno == ENOENT)
394 continue;
394 continue;
395 strncpy(fullpath + pathlen + 1, ent->d_name,
395 strncpy(fullpath + pathlen + 1, ent->d_name,
396 PATH_MAX - pathlen);
396 PATH_MAX - pathlen);
397 fullpath[PATH_MAX] = 0;
397 fullpath[PATH_MAX] = 0;
398 PyErr_SetFromErrnoWithFilename(PyExc_OSError,
398 PyErr_SetFromErrnoWithFilename(PyExc_OSError,
399 fullpath);
399 fullpath);
400 goto error;
400 goto error;
401 }
401 }
402 kind = st.st_mode & S_IFMT;
402 kind = st.st_mode & S_IFMT;
403 }
403 }
404
404
405 /* quit early? */
405 /* quit early? */
406 if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) {
406 if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) {
407 ret = PyList_New(0);
407 ret = PyList_New(0);
408 goto error;
408 goto error;
409 }
409 }
410
410
411 if (keepstat) {
411 if (keepstat) {
412 stat = makestat(&st);
412 PyObject *stat = makestat(&st);
413 if (!stat)
413 if (!stat)
414 goto error;
414 goto error;
415 elem = Py_BuildValue(PY23("siN", "yiN"), ent->d_name,
415 elem = Py_BuildValue(PY23("siN", "yiN"), ent->d_name,
416 kind, stat);
416 kind, stat);
417 } else
417 } else
418 elem = Py_BuildValue(PY23("si", "yi"), ent->d_name,
418 elem = Py_BuildValue(PY23("si", "yi"), ent->d_name,
419 kind);
419 kind);
420 if (!elem)
420 if (!elem)
421 goto error;
421 goto error;
422 stat = NULL;
423
422
424 PyList_Append(list, elem);
423 PyList_Append(list, elem);
425 Py_DECREF(elem);
424 Py_DECREF(elem);
426 }
425 }
427
426
428 ret = list;
427 ret = list;
429 Py_INCREF(ret);
428 Py_INCREF(ret);
430
429
431 error:
430 error:
432 Py_DECREF(list);
431 Py_DECREF(list);
433 Py_XDECREF(stat);
434 error_list:
432 error_list:
435 closedir(dir);
433 closedir(dir);
436 /* closedir also closes its dirfd */
434 /* closedir also closes its dirfd */
437 goto error_value;
435 goto error_value;
438 error_dir:
436 error_dir:
439 #ifdef AT_SYMLINK_NOFOLLOW
437 #ifdef AT_SYMLINK_NOFOLLOW
440 close(dfd);
438 close(dfd);
441 #endif
439 #endif
442 error_value:
440 error_value:
443 return ret;
441 return ret;
444 }
442 }
445
443
446 #ifdef __APPLE__
444 #ifdef __APPLE__
447
445
448 typedef struct {
446 typedef struct {
449 u_int32_t length;
447 u_int32_t length;
450 attrreference_t name;
448 attrreference_t name;
451 fsobj_type_t obj_type;
449 fsobj_type_t obj_type;
452 struct timespec mtime;
450 struct timespec mtime;
453 #if __LITTLE_ENDIAN__
451 #if __LITTLE_ENDIAN__
454 mode_t access_mask;
452 mode_t access_mask;
455 uint16_t padding;
453 uint16_t padding;
456 #else
454 #else
457 uint16_t padding;
455 uint16_t padding;
458 mode_t access_mask;
456 mode_t access_mask;
459 #endif
457 #endif
460 off_t size;
458 off_t size;
461 } __attribute__((packed)) attrbuf_entry;
459 } __attribute__((packed)) attrbuf_entry;
462
460
463 int attrkind(attrbuf_entry *entry)
461 int attrkind(attrbuf_entry *entry)
464 {
462 {
465 switch (entry->obj_type) {
463 switch (entry->obj_type) {
466 case VREG: return S_IFREG;
464 case VREG: return S_IFREG;
467 case VDIR: return S_IFDIR;
465 case VDIR: return S_IFDIR;
468 case VLNK: return S_IFLNK;
466 case VLNK: return S_IFLNK;
469 case VBLK: return S_IFBLK;
467 case VBLK: return S_IFBLK;
470 case VCHR: return S_IFCHR;
468 case VCHR: return S_IFCHR;
471 case VFIFO: return S_IFIFO;
469 case VFIFO: return S_IFIFO;
472 case VSOCK: return S_IFSOCK;
470 case VSOCK: return S_IFSOCK;
473 }
471 }
474 return -1;
472 return -1;
475 }
473 }
476
474
477 /* get these many entries at a time */
475 /* get these many entries at a time */
478 #define LISTDIR_BATCH_SIZE 50
476 #define LISTDIR_BATCH_SIZE 50
479
477
480 static PyObject *_listdir_batch(char *path, int pathlen, int keepstat,
478 static PyObject *_listdir_batch(char *path, int pathlen, int keepstat,
481 char *skip, bool *fallback)
479 char *skip, bool *fallback)
482 {
480 {
483 PyObject *list, *elem, *stat = NULL, *ret = NULL;
481 PyObject *list, *elem, *ret = NULL;
484 int kind, err;
482 int kind, err;
485 unsigned long index;
483 unsigned long index;
486 unsigned int count, old_state, new_state;
484 unsigned int count, old_state, new_state;
487 bool state_seen = false;
485 bool state_seen = false;
488 attrbuf_entry *entry;
486 attrbuf_entry *entry;
489 /* from the getattrlist(2) man page: a path can be no longer than
487 /* from the getattrlist(2) man page: a path can be no longer than
490 (NAME_MAX * 3 + 1) bytes. Also, "The getattrlist() function will
488 (NAME_MAX * 3 + 1) bytes. Also, "The getattrlist() function will
491 silently truncate attribute data if attrBufSize is too small." So
489 silently truncate attribute data if attrBufSize is too small." So
492 pass in a buffer big enough for the worst case. */
490 pass in a buffer big enough for the worst case. */
493 char attrbuf[LISTDIR_BATCH_SIZE * (sizeof(attrbuf_entry) + NAME_MAX * 3 + 1)];
491 char attrbuf[LISTDIR_BATCH_SIZE * (sizeof(attrbuf_entry) + NAME_MAX * 3 + 1)];
494 unsigned int basep_unused;
492 unsigned int basep_unused;
495
493
496 struct stat st;
494 struct stat st;
497 int dfd = -1;
495 int dfd = -1;
498
496
499 /* these must match the attrbuf_entry struct, otherwise you'll end up
497 /* these must match the attrbuf_entry struct, otherwise you'll end up
500 with garbage */
498 with garbage */
501 struct attrlist requested_attr = {0};
499 struct attrlist requested_attr = {0};
502 requested_attr.bitmapcount = ATTR_BIT_MAP_COUNT;
500 requested_attr.bitmapcount = ATTR_BIT_MAP_COUNT;
503 requested_attr.commonattr = (ATTR_CMN_NAME | ATTR_CMN_OBJTYPE |
501 requested_attr.commonattr = (ATTR_CMN_NAME | ATTR_CMN_OBJTYPE |
504 ATTR_CMN_MODTIME | ATTR_CMN_ACCESSMASK);
502 ATTR_CMN_MODTIME | ATTR_CMN_ACCESSMASK);
505 requested_attr.fileattr = ATTR_FILE_DATALENGTH;
503 requested_attr.fileattr = ATTR_FILE_DATALENGTH;
506
504
507 *fallback = false;
505 *fallback = false;
508
506
509 if (pathlen >= PATH_MAX) {
507 if (pathlen >= PATH_MAX) {
510 errno = ENAMETOOLONG;
508 errno = ENAMETOOLONG;
511 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
509 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
512 goto error_value;
510 goto error_value;
513 }
511 }
514
512
515 dfd = open(path, O_RDONLY);
513 dfd = open(path, O_RDONLY);
516 if (dfd == -1) {
514 if (dfd == -1) {
517 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
515 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
518 goto error_value;
516 goto error_value;
519 }
517 }
520
518
521 list = PyList_New(0);
519 list = PyList_New(0);
522 if (!list)
520 if (!list)
523 goto error_dir;
521 goto error_dir;
524
522
525 do {
523 do {
526 count = LISTDIR_BATCH_SIZE;
524 count = LISTDIR_BATCH_SIZE;
527 err = getdirentriesattr(dfd, &requested_attr, &attrbuf,
525 err = getdirentriesattr(dfd, &requested_attr, &attrbuf,
528 sizeof(attrbuf), &count, &basep_unused,
526 sizeof(attrbuf), &count, &basep_unused,
529 &new_state, 0);
527 &new_state, 0);
530 if (err < 0) {
528 if (err < 0) {
531 if (errno == ENOTSUP) {
529 if (errno == ENOTSUP) {
532 /* We're on a filesystem that doesn't support
530 /* We're on a filesystem that doesn't support
533 getdirentriesattr. Fall back to the
531 getdirentriesattr. Fall back to the
534 stat-based implementation. */
532 stat-based implementation. */
535 *fallback = true;
533 *fallback = true;
536 } else
534 } else
537 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
535 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
538 goto error;
536 goto error;
539 }
537 }
540
538
541 if (!state_seen) {
539 if (!state_seen) {
542 old_state = new_state;
540 old_state = new_state;
543 state_seen = true;
541 state_seen = true;
544 } else if (old_state != new_state) {
542 } else if (old_state != new_state) {
545 /* There's an edge case with getdirentriesattr. Consider
543 /* There's an edge case with getdirentriesattr. Consider
546 the following initial list of files:
544 the following initial list of files:
547
545
548 a
546 a
549 b
547 b
550 <--
548 <--
551 c
549 c
552 d
550 d
553
551
554 If the iteration is paused at the arrow, and b is
552 If the iteration is paused at the arrow, and b is
555 deleted before it is resumed, getdirentriesattr will
553 deleted before it is resumed, getdirentriesattr will
556 not return d at all! Ordinarily we're expected to
554 not return d at all! Ordinarily we're expected to
557 restart the iteration from the beginning. To avoid
555 restart the iteration from the beginning. To avoid
558 getting stuck in a retry loop here, fall back to
556 getting stuck in a retry loop here, fall back to
559 stat. */
557 stat. */
560 *fallback = true;
558 *fallback = true;
561 goto error;
559 goto error;
562 }
560 }
563
561
564 entry = (attrbuf_entry *)attrbuf;
562 entry = (attrbuf_entry *)attrbuf;
565
563
566 for (index = 0; index < count; index++) {
564 for (index = 0; index < count; index++) {
567 char *filename = ((char *)&entry->name) +
565 char *filename = ((char *)&entry->name) +
568 entry->name.attr_dataoffset;
566 entry->name.attr_dataoffset;
569
567
570 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
568 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
571 continue;
569 continue;
572
570
573 kind = attrkind(entry);
571 kind = attrkind(entry);
574 if (kind == -1) {
572 if (kind == -1) {
575 PyErr_Format(PyExc_OSError,
573 PyErr_Format(PyExc_OSError,
576 "unknown object type %u for file "
574 "unknown object type %u for file "
577 "%s%s!",
575 "%s%s!",
578 entry->obj_type, path, filename);
576 entry->obj_type, path, filename);
579 goto error;
577 goto error;
580 }
578 }
581
579
582 /* quit early? */
580 /* quit early? */
583 if (skip && kind == S_IFDIR && !strcmp(filename, skip)) {
581 if (skip && kind == S_IFDIR && !strcmp(filename, skip)) {
584 ret = PyList_New(0);
582 ret = PyList_New(0);
585 goto error;
583 goto error;
586 }
584 }
587
585
588 if (keepstat) {
586 if (keepstat) {
587 PyObject *stat = NULL;
589 /* from the getattrlist(2) man page: "Only the
588 /* from the getattrlist(2) man page: "Only the
590 permission bits ... are valid". */
589 permission bits ... are valid". */
591 st.st_mode = (entry->access_mask & ~S_IFMT) | kind;
590 st.st_mode = (entry->access_mask & ~S_IFMT) | kind;
592 st.st_mtime = entry->mtime.tv_sec;
591 st.st_mtime = entry->mtime.tv_sec;
593 st.st_size = entry->size;
592 st.st_size = entry->size;
594 stat = makestat(&st);
593 stat = makestat(&st);
595 if (!stat)
594 if (!stat)
596 goto error;
595 goto error;
597 elem = Py_BuildValue(PY23("siN", "yiN"),
596 elem = Py_BuildValue(PY23("siN", "yiN"),
598 filename, kind, stat);
597 filename, kind, stat);
599 } else
598 } else
600 elem = Py_BuildValue(PY23("si", "yi"),
599 elem = Py_BuildValue(PY23("si", "yi"),
601 filename, kind);
600 filename, kind);
602 if (!elem)
601 if (!elem)
603 goto error;
602 goto error;
604 stat = NULL;
605
603
606 PyList_Append(list, elem);
604 PyList_Append(list, elem);
607 Py_DECREF(elem);
605 Py_DECREF(elem);
608
606
609 entry = (attrbuf_entry *)((char *)entry + entry->length);
607 entry = (attrbuf_entry *)((char *)entry + entry->length);
610 }
608 }
611 } while (err == 0);
609 } while (err == 0);
612
610
613 ret = list;
611 ret = list;
614 Py_INCREF(ret);
612 Py_INCREF(ret);
615
613
616 error:
614 error:
617 Py_DECREF(list);
615 Py_DECREF(list);
618 Py_XDECREF(stat);
619 error_dir:
616 error_dir:
620 close(dfd);
617 close(dfd);
621 error_value:
618 error_value:
622 return ret;
619 return ret;
623 }
620 }
624
621
625 #endif /* __APPLE__ */
622 #endif /* __APPLE__ */
626
623
627 static PyObject *_listdir(char *path, int pathlen, int keepstat, char *skip)
624 static PyObject *_listdir(char *path, int pathlen, int keepstat, char *skip)
628 {
625 {
629 #ifdef __APPLE__
626 #ifdef __APPLE__
630 PyObject *ret;
627 PyObject *ret;
631 bool fallback = false;
628 bool fallback = false;
632
629
633 ret = _listdir_batch(path, pathlen, keepstat, skip, &fallback);
630 ret = _listdir_batch(path, pathlen, keepstat, skip, &fallback);
634 if (ret != NULL || !fallback)
631 if (ret != NULL || !fallback)
635 return ret;
632 return ret;
636 #endif
633 #endif
637 return _listdir_stat(path, pathlen, keepstat, skip);
634 return _listdir_stat(path, pathlen, keepstat, skip);
638 }
635 }
639
636
640 static PyObject *statfiles(PyObject *self, PyObject *args)
637 static PyObject *statfiles(PyObject *self, PyObject *args)
641 {
638 {
642 PyObject *names, *stats;
639 PyObject *names, *stats;
643 Py_ssize_t i, count;
640 Py_ssize_t i, count;
644
641
645 if (!PyArg_ParseTuple(args, "O:statfiles", &names))
642 if (!PyArg_ParseTuple(args, "O:statfiles", &names))
646 return NULL;
643 return NULL;
647
644
648 count = PySequence_Length(names);
645 count = PySequence_Length(names);
649 if (count == -1) {
646 if (count == -1) {
650 PyErr_SetString(PyExc_TypeError, "not a sequence");
647 PyErr_SetString(PyExc_TypeError, "not a sequence");
651 return NULL;
648 return NULL;
652 }
649 }
653
650
654 stats = PyList_New(count);
651 stats = PyList_New(count);
655 if (stats == NULL)
652 if (stats == NULL)
656 return NULL;
653 return NULL;
657
654
658 for (i = 0; i < count; i++) {
655 for (i = 0; i < count; i++) {
659 PyObject *stat, *pypath;
656 PyObject *stat, *pypath;
660 struct stat st;
657 struct stat st;
661 int ret, kind;
658 int ret, kind;
662 char *path;
659 char *path;
663
660
664 /* With a large file count or on a slow filesystem,
661 /* With a large file count or on a slow filesystem,
665 don't block signals for long (issue4878). */
662 don't block signals for long (issue4878). */
666 if ((i % 1000) == 999 && PyErr_CheckSignals() == -1)
663 if ((i % 1000) == 999 && PyErr_CheckSignals() == -1)
667 goto bail;
664 goto bail;
668
665
669 pypath = PySequence_GetItem(names, i);
666 pypath = PySequence_GetItem(names, i);
670 if (!pypath)
667 if (!pypath)
671 goto bail;
668 goto bail;
672 path = PyBytes_AsString(pypath);
669 path = PyBytes_AsString(pypath);
673 if (path == NULL) {
670 if (path == NULL) {
674 Py_DECREF(pypath);
671 Py_DECREF(pypath);
675 PyErr_SetString(PyExc_TypeError, "not a string");
672 PyErr_SetString(PyExc_TypeError, "not a string");
676 goto bail;
673 goto bail;
677 }
674 }
678 ret = lstat(path, &st);
675 ret = lstat(path, &st);
679 Py_DECREF(pypath);
676 Py_DECREF(pypath);
680 kind = st.st_mode & S_IFMT;
677 kind = st.st_mode & S_IFMT;
681 if (ret != -1 && (kind == S_IFREG || kind == S_IFLNK)) {
678 if (ret != -1 && (kind == S_IFREG || kind == S_IFLNK)) {
682 stat = makestat(&st);
679 stat = makestat(&st);
683 if (stat == NULL)
680 if (stat == NULL)
684 goto bail;
681 goto bail;
685 PyList_SET_ITEM(stats, i, stat);
682 PyList_SET_ITEM(stats, i, stat);
686 } else {
683 } else {
687 Py_INCREF(Py_None);
684 Py_INCREF(Py_None);
688 PyList_SET_ITEM(stats, i, Py_None);
685 PyList_SET_ITEM(stats, i, Py_None);
689 }
686 }
690 }
687 }
691
688
692 return stats;
689 return stats;
693
690
694 bail:
691 bail:
695 Py_DECREF(stats);
692 Py_DECREF(stats);
696 return NULL;
693 return NULL;
697 }
694 }
698
695
699 /*
696 /*
700 * recvfds() simply does not release GIL during blocking io operation because
697 * recvfds() simply does not release GIL during blocking io operation because
701 * command server is known to be single-threaded.
698 * command server is known to be single-threaded.
702 *
699 *
703 * Old systems such as Solaris don't provide CMSG_LEN, msg_control, etc.
700 * Old systems such as Solaris don't provide CMSG_LEN, msg_control, etc.
704 * Currently, recvfds() is not supported on these platforms.
701 * Currently, recvfds() is not supported on these platforms.
705 */
702 */
706 #ifdef CMSG_LEN
703 #ifdef CMSG_LEN
707
704
708 static ssize_t recvfdstobuf(int sockfd, int **rfds, void *cbuf, size_t cbufsize)
705 static ssize_t recvfdstobuf(int sockfd, int **rfds, void *cbuf, size_t cbufsize)
709 {
706 {
710 char dummy[1];
707 char dummy[1];
711 struct iovec iov = {dummy, sizeof(dummy)};
708 struct iovec iov = {dummy, sizeof(dummy)};
712 struct msghdr msgh = {0};
709 struct msghdr msgh = {0};
713 struct cmsghdr *cmsg;
710 struct cmsghdr *cmsg;
714
711
715 msgh.msg_iov = &iov;
712 msgh.msg_iov = &iov;
716 msgh.msg_iovlen = 1;
713 msgh.msg_iovlen = 1;
717 msgh.msg_control = cbuf;
714 msgh.msg_control = cbuf;
718 msgh.msg_controllen = (socklen_t)cbufsize;
715 msgh.msg_controllen = (socklen_t)cbufsize;
719 if (recvmsg(sockfd, &msgh, 0) < 0)
716 if (recvmsg(sockfd, &msgh, 0) < 0)
720 return -1;
717 return -1;
721
718
722 for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg;
719 for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg;
723 cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
720 cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
724 if (cmsg->cmsg_level != SOL_SOCKET ||
721 if (cmsg->cmsg_level != SOL_SOCKET ||
725 cmsg->cmsg_type != SCM_RIGHTS)
722 cmsg->cmsg_type != SCM_RIGHTS)
726 continue;
723 continue;
727 *rfds = (int *)CMSG_DATA(cmsg);
724 *rfds = (int *)CMSG_DATA(cmsg);
728 return (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
725 return (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
729 }
726 }
730
727
731 *rfds = cbuf;
728 *rfds = cbuf;
732 return 0;
729 return 0;
733 }
730 }
734
731
735 static PyObject *recvfds(PyObject *self, PyObject *args)
732 static PyObject *recvfds(PyObject *self, PyObject *args)
736 {
733 {
737 int sockfd;
734 int sockfd;
738 int *rfds = NULL;
735 int *rfds = NULL;
739 ssize_t rfdscount, i;
736 ssize_t rfdscount, i;
740 char cbuf[256];
737 char cbuf[256];
741 PyObject *rfdslist = NULL;
738 PyObject *rfdslist = NULL;
742
739
743 if (!PyArg_ParseTuple(args, "i", &sockfd))
740 if (!PyArg_ParseTuple(args, "i", &sockfd))
744 return NULL;
741 return NULL;
745
742
746 rfdscount = recvfdstobuf(sockfd, &rfds, cbuf, sizeof(cbuf));
743 rfdscount = recvfdstobuf(sockfd, &rfds, cbuf, sizeof(cbuf));
747 if (rfdscount < 0)
744 if (rfdscount < 0)
748 return PyErr_SetFromErrno(PyExc_OSError);
745 return PyErr_SetFromErrno(PyExc_OSError);
749
746
750 rfdslist = PyList_New(rfdscount);
747 rfdslist = PyList_New(rfdscount);
751 if (!rfdslist)
748 if (!rfdslist)
752 goto bail;
749 goto bail;
753 for (i = 0; i < rfdscount; i++) {
750 for (i = 0; i < rfdscount; i++) {
754 PyObject *obj = PyLong_FromLong(rfds[i]);
751 PyObject *obj = PyLong_FromLong(rfds[i]);
755 if (!obj)
752 if (!obj)
756 goto bail;
753 goto bail;
757 PyList_SET_ITEM(rfdslist, i, obj);
754 PyList_SET_ITEM(rfdslist, i, obj);
758 }
755 }
759 return rfdslist;
756 return rfdslist;
760
757
761 bail:
758 bail:
762 Py_XDECREF(rfdslist);
759 Py_XDECREF(rfdslist);
763 return NULL;
760 return NULL;
764 }
761 }
765
762
766 #endif /* CMSG_LEN */
763 #endif /* CMSG_LEN */
767
764
768 /* allow disabling setprocname via compiler flags */
765 /* allow disabling setprocname via compiler flags */
769 #ifndef SETPROCNAME_USE_NONE
766 #ifndef SETPROCNAME_USE_NONE
770 #if defined(HAVE_SETPROCTITLE)
767 #if defined(HAVE_SETPROCTITLE)
771 /* setproctitle is the first choice - available in FreeBSD */
768 /* setproctitle is the first choice - available in FreeBSD */
772 #define SETPROCNAME_USE_SETPROCTITLE
769 #define SETPROCNAME_USE_SETPROCTITLE
773 #elif (defined(__linux__) || defined(__APPLE__)) && PY_MAJOR_VERSION == 2
770 #elif (defined(__linux__) || defined(__APPLE__)) && PY_MAJOR_VERSION == 2
774 /* rewrite the argv buffer in place - works in Linux and OS X. Py_GetArgcArgv
771 /* rewrite the argv buffer in place - works in Linux and OS X. Py_GetArgcArgv
775 * in Python 3 returns the copied wchar_t **argv, thus unsupported. */
772 * in Python 3 returns the copied wchar_t **argv, thus unsupported. */
776 #define SETPROCNAME_USE_ARGVREWRITE
773 #define SETPROCNAME_USE_ARGVREWRITE
777 #else
774 #else
778 #define SETPROCNAME_USE_NONE
775 #define SETPROCNAME_USE_NONE
779 #endif
776 #endif
780 #endif /* ndef SETPROCNAME_USE_NONE */
777 #endif /* ndef SETPROCNAME_USE_NONE */
781
778
782 #ifndef SETPROCNAME_USE_NONE
779 #ifndef SETPROCNAME_USE_NONE
783 static PyObject *setprocname(PyObject *self, PyObject *args)
780 static PyObject *setprocname(PyObject *self, PyObject *args)
784 {
781 {
785 const char *name = NULL;
782 const char *name = NULL;
786 if (!PyArg_ParseTuple(args, PY23("s", "y"), &name))
783 if (!PyArg_ParseTuple(args, PY23("s", "y"), &name))
787 return NULL;
784 return NULL;
788
785
789 #if defined(SETPROCNAME_USE_SETPROCTITLE)
786 #if defined(SETPROCNAME_USE_SETPROCTITLE)
790 setproctitle("%s", name);
787 setproctitle("%s", name);
791 #elif defined(SETPROCNAME_USE_ARGVREWRITE)
788 #elif defined(SETPROCNAME_USE_ARGVREWRITE)
792 {
789 {
793 static char *argvstart = NULL;
790 static char *argvstart = NULL;
794 static size_t argvsize = 0;
791 static size_t argvsize = 0;
795 if (argvstart == NULL) {
792 if (argvstart == NULL) {
796 int argc = 0, i;
793 int argc = 0, i;
797 char **argv = NULL;
794 char **argv = NULL;
798 char *argvend;
795 char *argvend;
799 extern void Py_GetArgcArgv(int *argc, char ***argv);
796 extern void Py_GetArgcArgv(int *argc, char ***argv);
800 Py_GetArgcArgv(&argc, &argv);
797 Py_GetArgcArgv(&argc, &argv);
801 /* Py_GetArgcArgv may not do much if a custom python
798 /* Py_GetArgcArgv may not do much if a custom python
802 * launcher is used that doesn't record the information
799 * launcher is used that doesn't record the information
803 * it needs. Let's handle this gracefully instead of
800 * it needs. Let's handle this gracefully instead of
804 * segfaulting. */
801 * segfaulting. */
805 if (argv != NULL)
802 if (argv != NULL)
806 argvend = argvstart = argv[0];
803 argvend = argvstart = argv[0];
807 else
804 else
808 argvend = argvstart = NULL;
805 argvend = argvstart = NULL;
809
806
810 /* Check the memory we can use. Typically, argv[i] and
807 /* Check the memory we can use. Typically, argv[i] and
811 * argv[i + 1] are continuous. */
808 * argv[i + 1] are continuous. */
812 for (i = 0; i < argc; ++i) {
809 for (i = 0; i < argc; ++i) {
813 size_t len;
810 size_t len;
814 if (argv[i] > argvend || argv[i] < argvstart)
811 if (argv[i] > argvend || argv[i] < argvstart)
815 break; /* not continuous */
812 break; /* not continuous */
816 len = strlen(argv[i]);
813 len = strlen(argv[i]);
817 argvend = argv[i] + len + 1 /* '\0' */;
814 argvend = argv[i] + len + 1 /* '\0' */;
818 }
815 }
819 if (argvend > argvstart) /* sanity check */
816 if (argvend > argvstart) /* sanity check */
820 argvsize = argvend - argvstart;
817 argvsize = argvend - argvstart;
821 }
818 }
822
819
823 if (argvstart && argvsize > 1) {
820 if (argvstart && argvsize > 1) {
824 int n = snprintf(argvstart, argvsize, "%s", name);
821 int n = snprintf(argvstart, argvsize, "%s", name);
825 if (n >= 0 && (size_t)n < argvsize)
822 if (n >= 0 && (size_t)n < argvsize)
826 memset(argvstart + n, 0, argvsize - n);
823 memset(argvstart + n, 0, argvsize - n);
827 }
824 }
828 }
825 }
829 #endif
826 #endif
830
827
831 Py_RETURN_NONE;
828 Py_RETURN_NONE;
832 }
829 }
833 #endif /* ndef SETPROCNAME_USE_NONE */
830 #endif /* ndef SETPROCNAME_USE_NONE */
834
831
835 #if defined(HAVE_BSD_STATFS)
832 #if defined(HAVE_BSD_STATFS)
836 static const char *describefstype(const struct statfs *pbuf)
833 static const char *describefstype(const struct statfs *pbuf)
837 {
834 {
838 /* BSD or OSX provides a f_fstypename field */
835 /* BSD or OSX provides a f_fstypename field */
839 return pbuf->f_fstypename;
836 return pbuf->f_fstypename;
840 }
837 }
841 #elif defined(HAVE_LINUX_STATFS)
838 #elif defined(HAVE_LINUX_STATFS)
842 static const char *describefstype(const struct statfs *pbuf)
839 static const char *describefstype(const struct statfs *pbuf)
843 {
840 {
844 /* Begin of Linux filesystems */
841 /* Begin of Linux filesystems */
845 #ifdef ADFS_SUPER_MAGIC
842 #ifdef ADFS_SUPER_MAGIC
846 if (pbuf->f_type == ADFS_SUPER_MAGIC)
843 if (pbuf->f_type == ADFS_SUPER_MAGIC)
847 return "adfs";
844 return "adfs";
848 #endif
845 #endif
849 #ifdef AFFS_SUPER_MAGIC
846 #ifdef AFFS_SUPER_MAGIC
850 if (pbuf->f_type == AFFS_SUPER_MAGIC)
847 if (pbuf->f_type == AFFS_SUPER_MAGIC)
851 return "affs";
848 return "affs";
852 #endif
849 #endif
853 #ifdef AUTOFS_SUPER_MAGIC
850 #ifdef AUTOFS_SUPER_MAGIC
854 if (pbuf->f_type == AUTOFS_SUPER_MAGIC)
851 if (pbuf->f_type == AUTOFS_SUPER_MAGIC)
855 return "autofs";
852 return "autofs";
856 #endif
853 #endif
857 #ifdef BDEVFS_MAGIC
854 #ifdef BDEVFS_MAGIC
858 if (pbuf->f_type == BDEVFS_MAGIC)
855 if (pbuf->f_type == BDEVFS_MAGIC)
859 return "bdevfs";
856 return "bdevfs";
860 #endif
857 #endif
861 #ifdef BEFS_SUPER_MAGIC
858 #ifdef BEFS_SUPER_MAGIC
862 if (pbuf->f_type == BEFS_SUPER_MAGIC)
859 if (pbuf->f_type == BEFS_SUPER_MAGIC)
863 return "befs";
860 return "befs";
864 #endif
861 #endif
865 #ifdef BFS_MAGIC
862 #ifdef BFS_MAGIC
866 if (pbuf->f_type == BFS_MAGIC)
863 if (pbuf->f_type == BFS_MAGIC)
867 return "bfs";
864 return "bfs";
868 #endif
865 #endif
869 #ifdef BINFMTFS_MAGIC
866 #ifdef BINFMTFS_MAGIC
870 if (pbuf->f_type == BINFMTFS_MAGIC)
867 if (pbuf->f_type == BINFMTFS_MAGIC)
871 return "binfmtfs";
868 return "binfmtfs";
872 #endif
869 #endif
873 #ifdef BTRFS_SUPER_MAGIC
870 #ifdef BTRFS_SUPER_MAGIC
874 if (pbuf->f_type == BTRFS_SUPER_MAGIC)
871 if (pbuf->f_type == BTRFS_SUPER_MAGIC)
875 return "btrfs";
872 return "btrfs";
876 #endif
873 #endif
877 #ifdef CGROUP_SUPER_MAGIC
874 #ifdef CGROUP_SUPER_MAGIC
878 if (pbuf->f_type == CGROUP_SUPER_MAGIC)
875 if (pbuf->f_type == CGROUP_SUPER_MAGIC)
879 return "cgroup";
876 return "cgroup";
880 #endif
877 #endif
881 #ifdef CIFS_MAGIC_NUMBER
878 #ifdef CIFS_MAGIC_NUMBER
882 if (pbuf->f_type == CIFS_MAGIC_NUMBER)
879 if (pbuf->f_type == CIFS_MAGIC_NUMBER)
883 return "cifs";
880 return "cifs";
884 #endif
881 #endif
885 #ifdef CODA_SUPER_MAGIC
882 #ifdef CODA_SUPER_MAGIC
886 if (pbuf->f_type == CODA_SUPER_MAGIC)
883 if (pbuf->f_type == CODA_SUPER_MAGIC)
887 return "coda";
884 return "coda";
888 #endif
885 #endif
889 #ifdef COH_SUPER_MAGIC
886 #ifdef COH_SUPER_MAGIC
890 if (pbuf->f_type == COH_SUPER_MAGIC)
887 if (pbuf->f_type == COH_SUPER_MAGIC)
891 return "coh";
888 return "coh";
892 #endif
889 #endif
893 #ifdef CRAMFS_MAGIC
890 #ifdef CRAMFS_MAGIC
894 if (pbuf->f_type == CRAMFS_MAGIC)
891 if (pbuf->f_type == CRAMFS_MAGIC)
895 return "cramfs";
892 return "cramfs";
896 #endif
893 #endif
897 #ifdef DEBUGFS_MAGIC
894 #ifdef DEBUGFS_MAGIC
898 if (pbuf->f_type == DEBUGFS_MAGIC)
895 if (pbuf->f_type == DEBUGFS_MAGIC)
899 return "debugfs";
896 return "debugfs";
900 #endif
897 #endif
901 #ifdef DEVFS_SUPER_MAGIC
898 #ifdef DEVFS_SUPER_MAGIC
902 if (pbuf->f_type == DEVFS_SUPER_MAGIC)
899 if (pbuf->f_type == DEVFS_SUPER_MAGIC)
903 return "devfs";
900 return "devfs";
904 #endif
901 #endif
905 #ifdef DEVPTS_SUPER_MAGIC
902 #ifdef DEVPTS_SUPER_MAGIC
906 if (pbuf->f_type == DEVPTS_SUPER_MAGIC)
903 if (pbuf->f_type == DEVPTS_SUPER_MAGIC)
907 return "devpts";
904 return "devpts";
908 #endif
905 #endif
909 #ifdef EFIVARFS_MAGIC
906 #ifdef EFIVARFS_MAGIC
910 if (pbuf->f_type == EFIVARFS_MAGIC)
907 if (pbuf->f_type == EFIVARFS_MAGIC)
911 return "efivarfs";
908 return "efivarfs";
912 #endif
909 #endif
913 #ifdef EFS_SUPER_MAGIC
910 #ifdef EFS_SUPER_MAGIC
914 if (pbuf->f_type == EFS_SUPER_MAGIC)
911 if (pbuf->f_type == EFS_SUPER_MAGIC)
915 return "efs";
912 return "efs";
916 #endif
913 #endif
917 #ifdef EXT_SUPER_MAGIC
914 #ifdef EXT_SUPER_MAGIC
918 if (pbuf->f_type == EXT_SUPER_MAGIC)
915 if (pbuf->f_type == EXT_SUPER_MAGIC)
919 return "ext";
916 return "ext";
920 #endif
917 #endif
921 #ifdef EXT2_OLD_SUPER_MAGIC
918 #ifdef EXT2_OLD_SUPER_MAGIC
922 if (pbuf->f_type == EXT2_OLD_SUPER_MAGIC)
919 if (pbuf->f_type == EXT2_OLD_SUPER_MAGIC)
923 return "ext2";
920 return "ext2";
924 #endif
921 #endif
925 #ifdef EXT2_SUPER_MAGIC
922 #ifdef EXT2_SUPER_MAGIC
926 if (pbuf->f_type == EXT2_SUPER_MAGIC)
923 if (pbuf->f_type == EXT2_SUPER_MAGIC)
927 return "ext2";
924 return "ext2";
928 #endif
925 #endif
929 #ifdef EXT3_SUPER_MAGIC
926 #ifdef EXT3_SUPER_MAGIC
930 if (pbuf->f_type == EXT3_SUPER_MAGIC)
927 if (pbuf->f_type == EXT3_SUPER_MAGIC)
931 return "ext3";
928 return "ext3";
932 #endif
929 #endif
933 #ifdef EXT4_SUPER_MAGIC
930 #ifdef EXT4_SUPER_MAGIC
934 if (pbuf->f_type == EXT4_SUPER_MAGIC)
931 if (pbuf->f_type == EXT4_SUPER_MAGIC)
935 return "ext4";
932 return "ext4";
936 #endif
933 #endif
937 #ifdef F2FS_SUPER_MAGIC
934 #ifdef F2FS_SUPER_MAGIC
938 if (pbuf->f_type == F2FS_SUPER_MAGIC)
935 if (pbuf->f_type == F2FS_SUPER_MAGIC)
939 return "f2fs";
936 return "f2fs";
940 #endif
937 #endif
941 #ifdef FUSE_SUPER_MAGIC
938 #ifdef FUSE_SUPER_MAGIC
942 if (pbuf->f_type == FUSE_SUPER_MAGIC)
939 if (pbuf->f_type == FUSE_SUPER_MAGIC)
943 return "fuse";
940 return "fuse";
944 #endif
941 #endif
945 #ifdef FUTEXFS_SUPER_MAGIC
942 #ifdef FUTEXFS_SUPER_MAGIC
946 if (pbuf->f_type == FUTEXFS_SUPER_MAGIC)
943 if (pbuf->f_type == FUTEXFS_SUPER_MAGIC)
947 return "futexfs";
944 return "futexfs";
948 #endif
945 #endif
949 #ifdef HFS_SUPER_MAGIC
946 #ifdef HFS_SUPER_MAGIC
950 if (pbuf->f_type == HFS_SUPER_MAGIC)
947 if (pbuf->f_type == HFS_SUPER_MAGIC)
951 return "hfs";
948 return "hfs";
952 #endif
949 #endif
953 #ifdef HOSTFS_SUPER_MAGIC
950 #ifdef HOSTFS_SUPER_MAGIC
954 if (pbuf->f_type == HOSTFS_SUPER_MAGIC)
951 if (pbuf->f_type == HOSTFS_SUPER_MAGIC)
955 return "hostfs";
952 return "hostfs";
956 #endif
953 #endif
957 #ifdef HPFS_SUPER_MAGIC
954 #ifdef HPFS_SUPER_MAGIC
958 if (pbuf->f_type == HPFS_SUPER_MAGIC)
955 if (pbuf->f_type == HPFS_SUPER_MAGIC)
959 return "hpfs";
956 return "hpfs";
960 #endif
957 #endif
961 #ifdef HUGETLBFS_MAGIC
958 #ifdef HUGETLBFS_MAGIC
962 if (pbuf->f_type == HUGETLBFS_MAGIC)
959 if (pbuf->f_type == HUGETLBFS_MAGIC)
963 return "hugetlbfs";
960 return "hugetlbfs";
964 #endif
961 #endif
965 #ifdef ISOFS_SUPER_MAGIC
962 #ifdef ISOFS_SUPER_MAGIC
966 if (pbuf->f_type == ISOFS_SUPER_MAGIC)
963 if (pbuf->f_type == ISOFS_SUPER_MAGIC)
967 return "isofs";
964 return "isofs";
968 #endif
965 #endif
969 #ifdef JFFS2_SUPER_MAGIC
966 #ifdef JFFS2_SUPER_MAGIC
970 if (pbuf->f_type == JFFS2_SUPER_MAGIC)
967 if (pbuf->f_type == JFFS2_SUPER_MAGIC)
971 return "jffs2";
968 return "jffs2";
972 #endif
969 #endif
973 #ifdef JFS_SUPER_MAGIC
970 #ifdef JFS_SUPER_MAGIC
974 if (pbuf->f_type == JFS_SUPER_MAGIC)
971 if (pbuf->f_type == JFS_SUPER_MAGIC)
975 return "jfs";
972 return "jfs";
976 #endif
973 #endif
977 #ifdef MINIX_SUPER_MAGIC
974 #ifdef MINIX_SUPER_MAGIC
978 if (pbuf->f_type == MINIX_SUPER_MAGIC)
975 if (pbuf->f_type == MINIX_SUPER_MAGIC)
979 return "minix";
976 return "minix";
980 #endif
977 #endif
981 #ifdef MINIX2_SUPER_MAGIC
978 #ifdef MINIX2_SUPER_MAGIC
982 if (pbuf->f_type == MINIX2_SUPER_MAGIC)
979 if (pbuf->f_type == MINIX2_SUPER_MAGIC)
983 return "minix2";
980 return "minix2";
984 #endif
981 #endif
985 #ifdef MINIX3_SUPER_MAGIC
982 #ifdef MINIX3_SUPER_MAGIC
986 if (pbuf->f_type == MINIX3_SUPER_MAGIC)
983 if (pbuf->f_type == MINIX3_SUPER_MAGIC)
987 return "minix3";
984 return "minix3";
988 #endif
985 #endif
989 #ifdef MQUEUE_MAGIC
986 #ifdef MQUEUE_MAGIC
990 if (pbuf->f_type == MQUEUE_MAGIC)
987 if (pbuf->f_type == MQUEUE_MAGIC)
991 return "mqueue";
988 return "mqueue";
992 #endif
989 #endif
993 #ifdef MSDOS_SUPER_MAGIC
990 #ifdef MSDOS_SUPER_MAGIC
994 if (pbuf->f_type == MSDOS_SUPER_MAGIC)
991 if (pbuf->f_type == MSDOS_SUPER_MAGIC)
995 return "msdos";
992 return "msdos";
996 #endif
993 #endif
997 #ifdef NCP_SUPER_MAGIC
994 #ifdef NCP_SUPER_MAGIC
998 if (pbuf->f_type == NCP_SUPER_MAGIC)
995 if (pbuf->f_type == NCP_SUPER_MAGIC)
999 return "ncp";
996 return "ncp";
1000 #endif
997 #endif
1001 #ifdef NFS_SUPER_MAGIC
998 #ifdef NFS_SUPER_MAGIC
1002 if (pbuf->f_type == NFS_SUPER_MAGIC)
999 if (pbuf->f_type == NFS_SUPER_MAGIC)
1003 return "nfs";
1000 return "nfs";
1004 #endif
1001 #endif
1005 #ifdef NILFS_SUPER_MAGIC
1002 #ifdef NILFS_SUPER_MAGIC
1006 if (pbuf->f_type == NILFS_SUPER_MAGIC)
1003 if (pbuf->f_type == NILFS_SUPER_MAGIC)
1007 return "nilfs";
1004 return "nilfs";
1008 #endif
1005 #endif
1009 #ifdef NTFS_SB_MAGIC
1006 #ifdef NTFS_SB_MAGIC
1010 if (pbuf->f_type == NTFS_SB_MAGIC)
1007 if (pbuf->f_type == NTFS_SB_MAGIC)
1011 return "ntfs-sb";
1008 return "ntfs-sb";
1012 #endif
1009 #endif
1013 #ifdef OCFS2_SUPER_MAGIC
1010 #ifdef OCFS2_SUPER_MAGIC
1014 if (pbuf->f_type == OCFS2_SUPER_MAGIC)
1011 if (pbuf->f_type == OCFS2_SUPER_MAGIC)
1015 return "ocfs2";
1012 return "ocfs2";
1016 #endif
1013 #endif
1017 #ifdef OPENPROM_SUPER_MAGIC
1014 #ifdef OPENPROM_SUPER_MAGIC
1018 if (pbuf->f_type == OPENPROM_SUPER_MAGIC)
1015 if (pbuf->f_type == OPENPROM_SUPER_MAGIC)
1019 return "openprom";
1016 return "openprom";
1020 #endif
1017 #endif
1021 #ifdef OVERLAYFS_SUPER_MAGIC
1018 #ifdef OVERLAYFS_SUPER_MAGIC
1022 if (pbuf->f_type == OVERLAYFS_SUPER_MAGIC)
1019 if (pbuf->f_type == OVERLAYFS_SUPER_MAGIC)
1023 return "overlay";
1020 return "overlay";
1024 #endif
1021 #endif
1025 #ifdef PIPEFS_MAGIC
1022 #ifdef PIPEFS_MAGIC
1026 if (pbuf->f_type == PIPEFS_MAGIC)
1023 if (pbuf->f_type == PIPEFS_MAGIC)
1027 return "pipefs";
1024 return "pipefs";
1028 #endif
1025 #endif
1029 #ifdef PROC_SUPER_MAGIC
1026 #ifdef PROC_SUPER_MAGIC
1030 if (pbuf->f_type == PROC_SUPER_MAGIC)
1027 if (pbuf->f_type == PROC_SUPER_MAGIC)
1031 return "proc";
1028 return "proc";
1032 #endif
1029 #endif
1033 #ifdef PSTOREFS_MAGIC
1030 #ifdef PSTOREFS_MAGIC
1034 if (pbuf->f_type == PSTOREFS_MAGIC)
1031 if (pbuf->f_type == PSTOREFS_MAGIC)
1035 return "pstorefs";
1032 return "pstorefs";
1036 #endif
1033 #endif
1037 #ifdef QNX4_SUPER_MAGIC
1034 #ifdef QNX4_SUPER_MAGIC
1038 if (pbuf->f_type == QNX4_SUPER_MAGIC)
1035 if (pbuf->f_type == QNX4_SUPER_MAGIC)
1039 return "qnx4";
1036 return "qnx4";
1040 #endif
1037 #endif
1041 #ifdef QNX6_SUPER_MAGIC
1038 #ifdef QNX6_SUPER_MAGIC
1042 if (pbuf->f_type == QNX6_SUPER_MAGIC)
1039 if (pbuf->f_type == QNX6_SUPER_MAGIC)
1043 return "qnx6";
1040 return "qnx6";
1044 #endif
1041 #endif
1045 #ifdef RAMFS_MAGIC
1042 #ifdef RAMFS_MAGIC
1046 if (pbuf->f_type == RAMFS_MAGIC)
1043 if (pbuf->f_type == RAMFS_MAGIC)
1047 return "ramfs";
1044 return "ramfs";
1048 #endif
1045 #endif
1049 #ifdef REISERFS_SUPER_MAGIC
1046 #ifdef REISERFS_SUPER_MAGIC
1050 if (pbuf->f_type == REISERFS_SUPER_MAGIC)
1047 if (pbuf->f_type == REISERFS_SUPER_MAGIC)
1051 return "reiserfs";
1048 return "reiserfs";
1052 #endif
1049 #endif
1053 #ifdef ROMFS_MAGIC
1050 #ifdef ROMFS_MAGIC
1054 if (pbuf->f_type == ROMFS_MAGIC)
1051 if (pbuf->f_type == ROMFS_MAGIC)
1055 return "romfs";
1052 return "romfs";
1056 #endif
1053 #endif
1057 #ifdef SECURITYFS_MAGIC
1054 #ifdef SECURITYFS_MAGIC
1058 if (pbuf->f_type == SECURITYFS_MAGIC)
1055 if (pbuf->f_type == SECURITYFS_MAGIC)
1059 return "securityfs";
1056 return "securityfs";
1060 #endif
1057 #endif
1061 #ifdef SELINUX_MAGIC
1058 #ifdef SELINUX_MAGIC
1062 if (pbuf->f_type == SELINUX_MAGIC)
1059 if (pbuf->f_type == SELINUX_MAGIC)
1063 return "selinux";
1060 return "selinux";
1064 #endif
1061 #endif
1065 #ifdef SMACK_MAGIC
1062 #ifdef SMACK_MAGIC
1066 if (pbuf->f_type == SMACK_MAGIC)
1063 if (pbuf->f_type == SMACK_MAGIC)
1067 return "smack";
1064 return "smack";
1068 #endif
1065 #endif
1069 #ifdef SMB_SUPER_MAGIC
1066 #ifdef SMB_SUPER_MAGIC
1070 if (pbuf->f_type == SMB_SUPER_MAGIC)
1067 if (pbuf->f_type == SMB_SUPER_MAGIC)
1071 return "smb";
1068 return "smb";
1072 #endif
1069 #endif
1073 #ifdef SOCKFS_MAGIC
1070 #ifdef SOCKFS_MAGIC
1074 if (pbuf->f_type == SOCKFS_MAGIC)
1071 if (pbuf->f_type == SOCKFS_MAGIC)
1075 return "sockfs";
1072 return "sockfs";
1076 #endif
1073 #endif
1077 #ifdef SQUASHFS_MAGIC
1074 #ifdef SQUASHFS_MAGIC
1078 if (pbuf->f_type == SQUASHFS_MAGIC)
1075 if (pbuf->f_type == SQUASHFS_MAGIC)
1079 return "squashfs";
1076 return "squashfs";
1080 #endif
1077 #endif
1081 #ifdef SYSFS_MAGIC
1078 #ifdef SYSFS_MAGIC
1082 if (pbuf->f_type == SYSFS_MAGIC)
1079 if (pbuf->f_type == SYSFS_MAGIC)
1083 return "sysfs";
1080 return "sysfs";
1084 #endif
1081 #endif
1085 #ifdef SYSV2_SUPER_MAGIC
1082 #ifdef SYSV2_SUPER_MAGIC
1086 if (pbuf->f_type == SYSV2_SUPER_MAGIC)
1083 if (pbuf->f_type == SYSV2_SUPER_MAGIC)
1087 return "sysv2";
1084 return "sysv2";
1088 #endif
1085 #endif
1089 #ifdef SYSV4_SUPER_MAGIC
1086 #ifdef SYSV4_SUPER_MAGIC
1090 if (pbuf->f_type == SYSV4_SUPER_MAGIC)
1087 if (pbuf->f_type == SYSV4_SUPER_MAGIC)
1091 return "sysv4";
1088 return "sysv4";
1092 #endif
1089 #endif
1093 #ifdef TMPFS_MAGIC
1090 #ifdef TMPFS_MAGIC
1094 if (pbuf->f_type == TMPFS_MAGIC)
1091 if (pbuf->f_type == TMPFS_MAGIC)
1095 return "tmpfs";
1092 return "tmpfs";
1096 #endif
1093 #endif
1097 #ifdef UDF_SUPER_MAGIC
1094 #ifdef UDF_SUPER_MAGIC
1098 if (pbuf->f_type == UDF_SUPER_MAGIC)
1095 if (pbuf->f_type == UDF_SUPER_MAGIC)
1099 return "udf";
1096 return "udf";
1100 #endif
1097 #endif
1101 #ifdef UFS_MAGIC
1098 #ifdef UFS_MAGIC
1102 if (pbuf->f_type == UFS_MAGIC)
1099 if (pbuf->f_type == UFS_MAGIC)
1103 return "ufs";
1100 return "ufs";
1104 #endif
1101 #endif
1105 #ifdef USBDEVICE_SUPER_MAGIC
1102 #ifdef USBDEVICE_SUPER_MAGIC
1106 if (pbuf->f_type == USBDEVICE_SUPER_MAGIC)
1103 if (pbuf->f_type == USBDEVICE_SUPER_MAGIC)
1107 return "usbdevice";
1104 return "usbdevice";
1108 #endif
1105 #endif
1109 #ifdef V9FS_MAGIC
1106 #ifdef V9FS_MAGIC
1110 if (pbuf->f_type == V9FS_MAGIC)
1107 if (pbuf->f_type == V9FS_MAGIC)
1111 return "v9fs";
1108 return "v9fs";
1112 #endif
1109 #endif
1113 #ifdef VXFS_SUPER_MAGIC
1110 #ifdef VXFS_SUPER_MAGIC
1114 if (pbuf->f_type == VXFS_SUPER_MAGIC)
1111 if (pbuf->f_type == VXFS_SUPER_MAGIC)
1115 return "vxfs";
1112 return "vxfs";
1116 #endif
1113 #endif
1117 #ifdef XENFS_SUPER_MAGIC
1114 #ifdef XENFS_SUPER_MAGIC
1118 if (pbuf->f_type == XENFS_SUPER_MAGIC)
1115 if (pbuf->f_type == XENFS_SUPER_MAGIC)
1119 return "xenfs";
1116 return "xenfs";
1120 #endif
1117 #endif
1121 #ifdef XENIX_SUPER_MAGIC
1118 #ifdef XENIX_SUPER_MAGIC
1122 if (pbuf->f_type == XENIX_SUPER_MAGIC)
1119 if (pbuf->f_type == XENIX_SUPER_MAGIC)
1123 return "xenix";
1120 return "xenix";
1124 #endif
1121 #endif
1125 #ifdef XFS_SUPER_MAGIC
1122 #ifdef XFS_SUPER_MAGIC
1126 if (pbuf->f_type == XFS_SUPER_MAGIC)
1123 if (pbuf->f_type == XFS_SUPER_MAGIC)
1127 return "xfs";
1124 return "xfs";
1128 #endif
1125 #endif
1129 /* End of Linux filesystems */
1126 /* End of Linux filesystems */
1130 return NULL;
1127 return NULL;
1131 }
1128 }
1132 #endif /* def HAVE_LINUX_STATFS */
1129 #endif /* def HAVE_LINUX_STATFS */
1133
1130
1134 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1131 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1135 /* given a directory path, return filesystem type name (best-effort) */
1132 /* given a directory path, return filesystem type name (best-effort) */
1136 static PyObject *getfstype(PyObject *self, PyObject *args)
1133 static PyObject *getfstype(PyObject *self, PyObject *args)
1137 {
1134 {
1138 const char *path = NULL;
1135 const char *path = NULL;
1139 struct statfs buf;
1136 struct statfs buf;
1140 int r;
1137 int r;
1141 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1138 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1142 return NULL;
1139 return NULL;
1143
1140
1144 memset(&buf, 0, sizeof(buf));
1141 memset(&buf, 0, sizeof(buf));
1145 r = statfs(path, &buf);
1142 r = statfs(path, &buf);
1146 if (r != 0)
1143 if (r != 0)
1147 return PyErr_SetFromErrno(PyExc_OSError);
1144 return PyErr_SetFromErrno(PyExc_OSError);
1148 return Py_BuildValue(PY23("s", "y"), describefstype(&buf));
1145 return Py_BuildValue(PY23("s", "y"), describefstype(&buf));
1149 }
1146 }
1150 #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */
1147 #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */
1151
1148
1152 #if defined(HAVE_BSD_STATFS)
1149 #if defined(HAVE_BSD_STATFS)
1153 /* given a directory path, return filesystem mount point (best-effort) */
1150 /* given a directory path, return filesystem mount point (best-effort) */
1154 static PyObject *getfsmountpoint(PyObject *self, PyObject *args)
1151 static PyObject *getfsmountpoint(PyObject *self, PyObject *args)
1155 {
1152 {
1156 const char *path = NULL;
1153 const char *path = NULL;
1157 struct statfs buf;
1154 struct statfs buf;
1158 int r;
1155 int r;
1159 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1156 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1160 return NULL;
1157 return NULL;
1161
1158
1162 memset(&buf, 0, sizeof(buf));
1159 memset(&buf, 0, sizeof(buf));
1163 r = statfs(path, &buf);
1160 r = statfs(path, &buf);
1164 if (r != 0)
1161 if (r != 0)
1165 return PyErr_SetFromErrno(PyExc_OSError);
1162 return PyErr_SetFromErrno(PyExc_OSError);
1166 return Py_BuildValue(PY23("s", "y"), buf.f_mntonname);
1163 return Py_BuildValue(PY23("s", "y"), buf.f_mntonname);
1167 }
1164 }
1168 #endif /* defined(HAVE_BSD_STATFS) */
1165 #endif /* defined(HAVE_BSD_STATFS) */
1169
1166
1170 static PyObject *unblocksignal(PyObject *self, PyObject *args)
1167 static PyObject *unblocksignal(PyObject *self, PyObject *args)
1171 {
1168 {
1172 int sig = 0;
1169 int sig = 0;
1173 sigset_t set;
1170 sigset_t set;
1174 int r;
1171 int r;
1175 if (!PyArg_ParseTuple(args, "i", &sig))
1172 if (!PyArg_ParseTuple(args, "i", &sig))
1176 return NULL;
1173 return NULL;
1177 r = sigemptyset(&set);
1174 r = sigemptyset(&set);
1178 if (r != 0)
1175 if (r != 0)
1179 return PyErr_SetFromErrno(PyExc_OSError);
1176 return PyErr_SetFromErrno(PyExc_OSError);
1180 r = sigaddset(&set, sig);
1177 r = sigaddset(&set, sig);
1181 if (r != 0)
1178 if (r != 0)
1182 return PyErr_SetFromErrno(PyExc_OSError);
1179 return PyErr_SetFromErrno(PyExc_OSError);
1183 r = sigprocmask(SIG_UNBLOCK, &set, NULL);
1180 r = sigprocmask(SIG_UNBLOCK, &set, NULL);
1184 if (r != 0)
1181 if (r != 0)
1185 return PyErr_SetFromErrno(PyExc_OSError);
1182 return PyErr_SetFromErrno(PyExc_OSError);
1186 Py_RETURN_NONE;
1183 Py_RETURN_NONE;
1187 }
1184 }
1188
1185
1189 #endif /* ndef _WIN32 */
1186 #endif /* ndef _WIN32 */
1190
1187
1191 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
1188 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
1192 {
1189 {
1193 PyObject *statobj = NULL; /* initialize - optional arg */
1190 PyObject *statobj = NULL; /* initialize - optional arg */
1194 PyObject *skipobj = NULL; /* initialize - optional arg */
1191 PyObject *skipobj = NULL; /* initialize - optional arg */
1195 char *path, *skip = NULL;
1192 char *path, *skip = NULL;
1196 Py_ssize_t plen;
1193 Py_ssize_t plen;
1197 int wantstat;
1194 int wantstat;
1198
1195
1199 static char *kwlist[] = {"path", "stat", "skip", NULL};
1196 static char *kwlist[] = {"path", "stat", "skip", NULL};
1200
1197
1201 if (!PyArg_ParseTupleAndKeywords(args, kwargs, PY23("s#|OO:listdir",
1198 if (!PyArg_ParseTupleAndKeywords(args, kwargs, PY23("s#|OO:listdir",
1202 "y#|OO:listdir"),
1199 "y#|OO:listdir"),
1203 kwlist, &path, &plen, &statobj, &skipobj))
1200 kwlist, &path, &plen, &statobj, &skipobj))
1204 return NULL;
1201 return NULL;
1205
1202
1206 wantstat = statobj && PyObject_IsTrue(statobj);
1203 wantstat = statobj && PyObject_IsTrue(statobj);
1207
1204
1208 if (skipobj && skipobj != Py_None) {
1205 if (skipobj && skipobj != Py_None) {
1209 skip = PyBytes_AsString(skipobj);
1206 skip = PyBytes_AsString(skipobj);
1210 if (!skip)
1207 if (!skip)
1211 return NULL;
1208 return NULL;
1212 }
1209 }
1213
1210
1214 return _listdir(path, plen, wantstat, skip);
1211 return _listdir(path, plen, wantstat, skip);
1215 }
1212 }
1216
1213
1217 #ifdef _WIN32
1214 #ifdef _WIN32
1218 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
1215 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
1219 {
1216 {
1220 static char *kwlist[] = {"name", "mode", "buffering", NULL};
1217 static char *kwlist[] = {"name", "mode", "buffering", NULL};
1221 PyObject *file_obj = NULL;
1218 PyObject *file_obj = NULL;
1222 char *name = NULL;
1219 char *name = NULL;
1223 char *mode = "rb";
1220 char *mode = "rb";
1224 DWORD access = 0;
1221 DWORD access = 0;
1225 DWORD creation;
1222 DWORD creation;
1226 HANDLE handle;
1223 HANDLE handle;
1227 int fd, flags = 0;
1224 int fd, flags = 0;
1228 int bufsize = -1;
1225 int bufsize = -1;
1229 char m0, m1, m2;
1226 char m0, m1, m2;
1230 char fpmode[4];
1227 char fpmode[4];
1231 int fppos = 0;
1228 int fppos = 0;
1232 int plus;
1229 int plus;
1233 #ifndef IS_PY3K
1230 #ifndef IS_PY3K
1234 FILE *fp;
1231 FILE *fp;
1235 #endif
1232 #endif
1236
1233
1237 if (!PyArg_ParseTupleAndKeywords(args, kwds, PY23("et|si:posixfile",
1234 if (!PyArg_ParseTupleAndKeywords(args, kwds, PY23("et|si:posixfile",
1238 "et|yi:posixfile"),
1235 "et|yi:posixfile"),
1239 kwlist,
1236 kwlist,
1240 Py_FileSystemDefaultEncoding,
1237 Py_FileSystemDefaultEncoding,
1241 &name, &mode, &bufsize))
1238 &name, &mode, &bufsize))
1242 return NULL;
1239 return NULL;
1243
1240
1244 m0 = mode[0];
1241 m0 = mode[0];
1245 m1 = m0 ? mode[1] : '\0';
1242 m1 = m0 ? mode[1] : '\0';
1246 m2 = m1 ? mode[2] : '\0';
1243 m2 = m1 ? mode[2] : '\0';
1247 plus = m1 == '+' || m2 == '+';
1244 plus = m1 == '+' || m2 == '+';
1248
1245
1249 fpmode[fppos++] = m0;
1246 fpmode[fppos++] = m0;
1250 if (m1 == 'b' || m2 == 'b') {
1247 if (m1 == 'b' || m2 == 'b') {
1251 flags = _O_BINARY;
1248 flags = _O_BINARY;
1252 fpmode[fppos++] = 'b';
1249 fpmode[fppos++] = 'b';
1253 }
1250 }
1254 else
1251 else
1255 flags = _O_TEXT;
1252 flags = _O_TEXT;
1256 if (m0 == 'r' && !plus) {
1253 if (m0 == 'r' && !plus) {
1257 flags |= _O_RDONLY;
1254 flags |= _O_RDONLY;
1258 access = GENERIC_READ;
1255 access = GENERIC_READ;
1259 } else {
1256 } else {
1260 /*
1257 /*
1261 work around http://support.microsoft.com/kb/899149 and
1258 work around http://support.microsoft.com/kb/899149 and
1262 set _O_RDWR for 'w' and 'a', even if mode has no '+'
1259 set _O_RDWR for 'w' and 'a', even if mode has no '+'
1263 */
1260 */
1264 flags |= _O_RDWR;
1261 flags |= _O_RDWR;
1265 access = GENERIC_READ | GENERIC_WRITE;
1262 access = GENERIC_READ | GENERIC_WRITE;
1266 fpmode[fppos++] = '+';
1263 fpmode[fppos++] = '+';
1267 }
1264 }
1268 fpmode[fppos++] = '\0';
1265 fpmode[fppos++] = '\0';
1269
1266
1270 switch (m0) {
1267 switch (m0) {
1271 case 'r':
1268 case 'r':
1272 creation = OPEN_EXISTING;
1269 creation = OPEN_EXISTING;
1273 break;
1270 break;
1274 case 'w':
1271 case 'w':
1275 creation = CREATE_ALWAYS;
1272 creation = CREATE_ALWAYS;
1276 break;
1273 break;
1277 case 'a':
1274 case 'a':
1278 creation = OPEN_ALWAYS;
1275 creation = OPEN_ALWAYS;
1279 flags |= _O_APPEND;
1276 flags |= _O_APPEND;
1280 break;
1277 break;
1281 default:
1278 default:
1282 PyErr_Format(PyExc_ValueError,
1279 PyErr_Format(PyExc_ValueError,
1283 "mode string must begin with one of 'r', 'w', "
1280 "mode string must begin with one of 'r', 'w', "
1284 "or 'a', not '%c'", m0);
1281 "or 'a', not '%c'", m0);
1285 goto bail;
1282 goto bail;
1286 }
1283 }
1287
1284
1288 handle = CreateFile(name, access,
1285 handle = CreateFile(name, access,
1289 FILE_SHARE_READ | FILE_SHARE_WRITE |
1286 FILE_SHARE_READ | FILE_SHARE_WRITE |
1290 FILE_SHARE_DELETE,
1287 FILE_SHARE_DELETE,
1291 NULL,
1288 NULL,
1292 creation,
1289 creation,
1293 FILE_ATTRIBUTE_NORMAL,
1290 FILE_ATTRIBUTE_NORMAL,
1294 0);
1291 0);
1295
1292
1296 if (handle == INVALID_HANDLE_VALUE) {
1293 if (handle == INVALID_HANDLE_VALUE) {
1297 PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
1294 PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
1298 goto bail;
1295 goto bail;
1299 }
1296 }
1300
1297
1301 fd = _open_osfhandle((intptr_t)handle, flags);
1298 fd = _open_osfhandle((intptr_t)handle, flags);
1302
1299
1303 if (fd == -1) {
1300 if (fd == -1) {
1304 CloseHandle(handle);
1301 CloseHandle(handle);
1305 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1302 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1306 goto bail;
1303 goto bail;
1307 }
1304 }
1308 #ifndef IS_PY3K
1305 #ifndef IS_PY3K
1309 fp = _fdopen(fd, fpmode);
1306 fp = _fdopen(fd, fpmode);
1310 if (fp == NULL) {
1307 if (fp == NULL) {
1311 _close(fd);
1308 _close(fd);
1312 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1309 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1313 goto bail;
1310 goto bail;
1314 }
1311 }
1315
1312
1316 file_obj = PyFile_FromFile(fp, name, mode, fclose);
1313 file_obj = PyFile_FromFile(fp, name, mode, fclose);
1317 if (file_obj == NULL) {
1314 if (file_obj == NULL) {
1318 fclose(fp);
1315 fclose(fp);
1319 goto bail;
1316 goto bail;
1320 }
1317 }
1321
1318
1322 PyFile_SetBufSize(file_obj, bufsize);
1319 PyFile_SetBufSize(file_obj, bufsize);
1323 #else
1320 #else
1324 file_obj = PyFile_FromFd(fd, name, mode, bufsize, NULL, NULL, NULL, 1);
1321 file_obj = PyFile_FromFd(fd, name, mode, bufsize, NULL, NULL, NULL, 1);
1325 if (file_obj == NULL)
1322 if (file_obj == NULL)
1326 goto bail;
1323 goto bail;
1327 #endif
1324 #endif
1328 bail:
1325 bail:
1329 PyMem_Free(name);
1326 PyMem_Free(name);
1330 return file_obj;
1327 return file_obj;
1331 }
1328 }
1332 #endif
1329 #endif
1333
1330
1334 #ifdef __APPLE__
1331 #ifdef __APPLE__
1335 #include <ApplicationServices/ApplicationServices.h>
1332 #include <ApplicationServices/ApplicationServices.h>
1336
1333
1337 static PyObject *isgui(PyObject *self)
1334 static PyObject *isgui(PyObject *self)
1338 {
1335 {
1339 CFDictionaryRef dict = CGSessionCopyCurrentDictionary();
1336 CFDictionaryRef dict = CGSessionCopyCurrentDictionary();
1340
1337
1341 if (dict != NULL) {
1338 if (dict != NULL) {
1342 CFRelease(dict);
1339 CFRelease(dict);
1343 Py_RETURN_TRUE;
1340 Py_RETURN_TRUE;
1344 } else {
1341 } else {
1345 Py_RETURN_FALSE;
1342 Py_RETURN_FALSE;
1346 }
1343 }
1347 }
1344 }
1348 #endif
1345 #endif
1349
1346
1350 static char osutil_doc[] = "Native operating system services.";
1347 static char osutil_doc[] = "Native operating system services.";
1351
1348
1352 static PyMethodDef methods[] = {
1349 static PyMethodDef methods[] = {
1353 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
1350 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
1354 "list a directory\n"},
1351 "list a directory\n"},
1355 #ifdef _WIN32
1352 #ifdef _WIN32
1356 {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
1353 {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
1357 "Open a file with POSIX-like semantics.\n"
1354 "Open a file with POSIX-like semantics.\n"
1358 "On error, this function may raise either a WindowsError or an IOError."},
1355 "On error, this function may raise either a WindowsError or an IOError."},
1359 #else
1356 #else
1360 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
1357 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
1361 "stat a series of files or symlinks\n"
1358 "stat a series of files or symlinks\n"
1362 "Returns None for non-existent entries and entries of other types.\n"},
1359 "Returns None for non-existent entries and entries of other types.\n"},
1363 #ifdef CMSG_LEN
1360 #ifdef CMSG_LEN
1364 {"recvfds", (PyCFunction)recvfds, METH_VARARGS,
1361 {"recvfds", (PyCFunction)recvfds, METH_VARARGS,
1365 "receive list of file descriptors via socket\n"},
1362 "receive list of file descriptors via socket\n"},
1366 #endif
1363 #endif
1367 #ifndef SETPROCNAME_USE_NONE
1364 #ifndef SETPROCNAME_USE_NONE
1368 {"setprocname", (PyCFunction)setprocname, METH_VARARGS,
1365 {"setprocname", (PyCFunction)setprocname, METH_VARARGS,
1369 "set process title (best-effort)\n"},
1366 "set process title (best-effort)\n"},
1370 #endif
1367 #endif
1371 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1368 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1372 {"getfstype", (PyCFunction)getfstype, METH_VARARGS,
1369 {"getfstype", (PyCFunction)getfstype, METH_VARARGS,
1373 "get filesystem type (best-effort)\n"},
1370 "get filesystem type (best-effort)\n"},
1374 #endif
1371 #endif
1375 #if defined(HAVE_BSD_STATFS)
1372 #if defined(HAVE_BSD_STATFS)
1376 {"getfsmountpoint", (PyCFunction)getfsmountpoint, METH_VARARGS,
1373 {"getfsmountpoint", (PyCFunction)getfsmountpoint, METH_VARARGS,
1377 "get filesystem mount point (best-effort)\n"},
1374 "get filesystem mount point (best-effort)\n"},
1378 #endif
1375 #endif
1379 {"unblocksignal", (PyCFunction)unblocksignal, METH_VARARGS,
1376 {"unblocksignal", (PyCFunction)unblocksignal, METH_VARARGS,
1380 "change signal mask to unblock a given signal\n"},
1377 "change signal mask to unblock a given signal\n"},
1381 #endif /* ndef _WIN32 */
1378 #endif /* ndef _WIN32 */
1382 #ifdef __APPLE__
1379 #ifdef __APPLE__
1383 {
1380 {
1384 "isgui", (PyCFunction)isgui, METH_NOARGS,
1381 "isgui", (PyCFunction)isgui, METH_NOARGS,
1385 "Is a CoreGraphics session available?"
1382 "Is a CoreGraphics session available?"
1386 },
1383 },
1387 #endif
1384 #endif
1388 {NULL, NULL}
1385 {NULL, NULL}
1389 };
1386 };
1390
1387
1391 static const int version = 4;
1388 static const int version = 4;
1392
1389
1393 #ifdef IS_PY3K
1390 #ifdef IS_PY3K
1394 static struct PyModuleDef osutil_module = {
1391 static struct PyModuleDef osutil_module = {
1395 PyModuleDef_HEAD_INIT,
1392 PyModuleDef_HEAD_INIT,
1396 "osutil",
1393 "osutil",
1397 osutil_doc,
1394 osutil_doc,
1398 -1,
1395 -1,
1399 methods
1396 methods
1400 };
1397 };
1401
1398
1402 PyMODINIT_FUNC PyInit_osutil(void)
1399 PyMODINIT_FUNC PyInit_osutil(void)
1403 {
1400 {
1404 PyObject *m;
1401 PyObject *m;
1405 if (PyType_Ready(&listdir_stat_type) < 0)
1402 if (PyType_Ready(&listdir_stat_type) < 0)
1406 return NULL;
1403 return NULL;
1407
1404
1408 m = PyModule_Create(&osutil_module);
1405 m = PyModule_Create(&osutil_module);
1409 PyModule_AddIntConstant(m, "version", version);
1406 PyModule_AddIntConstant(m, "version", version);
1410 return m;
1407 return m;
1411 }
1408 }
1412 #else
1409 #else
1413 PyMODINIT_FUNC initosutil(void)
1410 PyMODINIT_FUNC initosutil(void)
1414 {
1411 {
1415 PyObject *m;
1412 PyObject *m;
1416 if (PyType_Ready(&listdir_stat_type) == -1)
1413 if (PyType_Ready(&listdir_stat_type) == -1)
1417 return;
1414 return;
1418
1415
1419 m = Py_InitModule3("osutil", methods, osutil_doc);
1416 m = Py_InitModule3("osutil", methods, osutil_doc);
1420 PyModule_AddIntConstant(m, "version", version);
1417 PyModule_AddIntConstant(m, "version", version);
1421 }
1418 }
1422 #endif
1419 #endif
General Comments 0
You need to be logged in to leave comments. Login now