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