##// END OF EJS Templates
osutil: allow disabling setprocname via a define passed to the compiler...
Kyle Lippincott -
r43231:460f8bf5 default
parent child Browse files
Show More
@@ -1,1411 +1,1414 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, *stat = NULL, *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 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;
422 stat = NULL;
423
423
424 PyList_Append(list, elem);
424 PyList_Append(list, elem);
425 Py_DECREF(elem);
425 Py_DECREF(elem);
426 }
426 }
427
427
428 ret = list;
428 ret = list;
429 Py_INCREF(ret);
429 Py_INCREF(ret);
430
430
431 error:
431 error:
432 Py_DECREF(list);
432 Py_DECREF(list);
433 Py_XDECREF(stat);
433 Py_XDECREF(stat);
434 error_list:
434 error_list:
435 closedir(dir);
435 closedir(dir);
436 /* closedir also closes its dirfd */
436 /* closedir also closes its dirfd */
437 goto error_value;
437 goto error_value;
438 error_dir:
438 error_dir:
439 #ifdef AT_SYMLINK_NOFOLLOW
439 #ifdef AT_SYMLINK_NOFOLLOW
440 close(dfd);
440 close(dfd);
441 #endif
441 #endif
442 error_value:
442 error_value:
443 return ret;
443 return ret;
444 }
444 }
445
445
446 #ifdef __APPLE__
446 #ifdef __APPLE__
447
447
448 typedef struct {
448 typedef struct {
449 u_int32_t length;
449 u_int32_t length;
450 attrreference_t name;
450 attrreference_t name;
451 fsobj_type_t obj_type;
451 fsobj_type_t obj_type;
452 struct timespec mtime;
452 struct timespec mtime;
453 #if __LITTLE_ENDIAN__
453 #if __LITTLE_ENDIAN__
454 mode_t access_mask;
454 mode_t access_mask;
455 uint16_t padding;
455 uint16_t padding;
456 #else
456 #else
457 uint16_t padding;
457 uint16_t padding;
458 mode_t access_mask;
458 mode_t access_mask;
459 #endif
459 #endif
460 off_t size;
460 off_t size;
461 } __attribute__((packed)) attrbuf_entry;
461 } __attribute__((packed)) attrbuf_entry;
462
462
463 int attrkind(attrbuf_entry *entry)
463 int attrkind(attrbuf_entry *entry)
464 {
464 {
465 switch (entry->obj_type) {
465 switch (entry->obj_type) {
466 case VREG: return S_IFREG;
466 case VREG: return S_IFREG;
467 case VDIR: return S_IFDIR;
467 case VDIR: return S_IFDIR;
468 case VLNK: return S_IFLNK;
468 case VLNK: return S_IFLNK;
469 case VBLK: return S_IFBLK;
469 case VBLK: return S_IFBLK;
470 case VCHR: return S_IFCHR;
470 case VCHR: return S_IFCHR;
471 case VFIFO: return S_IFIFO;
471 case VFIFO: return S_IFIFO;
472 case VSOCK: return S_IFSOCK;
472 case VSOCK: return S_IFSOCK;
473 }
473 }
474 return -1;
474 return -1;
475 }
475 }
476
476
477 /* get these many entries at a time */
477 /* get these many entries at a time */
478 #define LISTDIR_BATCH_SIZE 50
478 #define LISTDIR_BATCH_SIZE 50
479
479
480 static PyObject *_listdir_batch(char *path, int pathlen, int keepstat,
480 static PyObject *_listdir_batch(char *path, int pathlen, int keepstat,
481 char *skip, bool *fallback)
481 char *skip, bool *fallback)
482 {
482 {
483 PyObject *list, *elem, *stat = NULL, *ret = NULL;
483 PyObject *list, *elem, *stat = NULL, *ret = NULL;
484 int kind, err;
484 int kind, err;
485 unsigned long index;
485 unsigned long index;
486 unsigned int count, old_state, new_state;
486 unsigned int count, old_state, new_state;
487 bool state_seen = false;
487 bool state_seen = false;
488 attrbuf_entry *entry;
488 attrbuf_entry *entry;
489 /* 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
490 (NAME_MAX * 3 + 1) bytes. Also, "The getattrlist() function will
490 (NAME_MAX * 3 + 1) bytes. Also, "The getattrlist() function will
491 silently truncate attribute data if attrBufSize is too small." So
491 silently truncate attribute data if attrBufSize is too small." So
492 pass in a buffer big enough for the worst case. */
492 pass in a buffer big enough for the worst case. */
493 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)];
494 unsigned int basep_unused;
494 unsigned int basep_unused;
495
495
496 struct stat st;
496 struct stat st;
497 int dfd = -1;
497 int dfd = -1;
498
498
499 /* 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
500 with garbage */
500 with garbage */
501 struct attrlist requested_attr = {0};
501 struct attrlist requested_attr = {0};
502 requested_attr.bitmapcount = ATTR_BIT_MAP_COUNT;
502 requested_attr.bitmapcount = ATTR_BIT_MAP_COUNT;
503 requested_attr.commonattr = (ATTR_CMN_NAME | ATTR_CMN_OBJTYPE |
503 requested_attr.commonattr = (ATTR_CMN_NAME | ATTR_CMN_OBJTYPE |
504 ATTR_CMN_MODTIME | ATTR_CMN_ACCESSMASK);
504 ATTR_CMN_MODTIME | ATTR_CMN_ACCESSMASK);
505 requested_attr.fileattr = ATTR_FILE_DATALENGTH;
505 requested_attr.fileattr = ATTR_FILE_DATALENGTH;
506
506
507 *fallback = false;
507 *fallback = false;
508
508
509 if (pathlen >= PATH_MAX) {
509 if (pathlen >= PATH_MAX) {
510 errno = ENAMETOOLONG;
510 errno = ENAMETOOLONG;
511 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
511 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
512 goto error_value;
512 goto error_value;
513 }
513 }
514
514
515 dfd = open(path, O_RDONLY);
515 dfd = open(path, O_RDONLY);
516 if (dfd == -1) {
516 if (dfd == -1) {
517 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
517 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
518 goto error_value;
518 goto error_value;
519 }
519 }
520
520
521 list = PyList_New(0);
521 list = PyList_New(0);
522 if (!list)
522 if (!list)
523 goto error_dir;
523 goto error_dir;
524
524
525 do {
525 do {
526 count = LISTDIR_BATCH_SIZE;
526 count = LISTDIR_BATCH_SIZE;
527 err = getdirentriesattr(dfd, &requested_attr, &attrbuf,
527 err = getdirentriesattr(dfd, &requested_attr, &attrbuf,
528 sizeof(attrbuf), &count, &basep_unused,
528 sizeof(attrbuf), &count, &basep_unused,
529 &new_state, 0);
529 &new_state, 0);
530 if (err < 0) {
530 if (err < 0) {
531 if (errno == ENOTSUP) {
531 if (errno == ENOTSUP) {
532 /* We're on a filesystem that doesn't support
532 /* We're on a filesystem that doesn't support
533 getdirentriesattr. Fall back to the
533 getdirentriesattr. Fall back to the
534 stat-based implementation. */
534 stat-based implementation. */
535 *fallback = true;
535 *fallback = true;
536 } else
536 } else
537 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
537 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
538 goto error;
538 goto error;
539 }
539 }
540
540
541 if (!state_seen) {
541 if (!state_seen) {
542 old_state = new_state;
542 old_state = new_state;
543 state_seen = true;
543 state_seen = true;
544 } else if (old_state != new_state) {
544 } else if (old_state != new_state) {
545 /* There's an edge case with getdirentriesattr. Consider
545 /* There's an edge case with getdirentriesattr. Consider
546 the following initial list of files:
546 the following initial list of files:
547
547
548 a
548 a
549 b
549 b
550 <--
550 <--
551 c
551 c
552 d
552 d
553
553
554 If the iteration is paused at the arrow, and b is
554 If the iteration is paused at the arrow, and b is
555 deleted before it is resumed, getdirentriesattr will
555 deleted before it is resumed, getdirentriesattr will
556 not return d at all! Ordinarily we're expected to
556 not return d at all! Ordinarily we're expected to
557 restart the iteration from the beginning. To avoid
557 restart the iteration from the beginning. To avoid
558 getting stuck in a retry loop here, fall back to
558 getting stuck in a retry loop here, fall back to
559 stat. */
559 stat. */
560 *fallback = true;
560 *fallback = true;
561 goto error;
561 goto error;
562 }
562 }
563
563
564 entry = (attrbuf_entry *)attrbuf;
564 entry = (attrbuf_entry *)attrbuf;
565
565
566 for (index = 0; index < count; index++) {
566 for (index = 0; index < count; index++) {
567 char *filename = ((char *)&entry->name) +
567 char *filename = ((char *)&entry->name) +
568 entry->name.attr_dataoffset;
568 entry->name.attr_dataoffset;
569
569
570 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
570 if (!strcmp(filename, ".") || !strcmp(filename, ".."))
571 continue;
571 continue;
572
572
573 kind = attrkind(entry);
573 kind = attrkind(entry);
574 if (kind == -1) {
574 if (kind == -1) {
575 PyErr_Format(PyExc_OSError,
575 PyErr_Format(PyExc_OSError,
576 "unknown object type %u for file "
576 "unknown object type %u for file "
577 "%s%s!",
577 "%s%s!",
578 entry->obj_type, path, filename);
578 entry->obj_type, path, filename);
579 goto error;
579 goto error;
580 }
580 }
581
581
582 /* quit early? */
582 /* quit early? */
583 if (skip && kind == S_IFDIR && !strcmp(filename, skip)) {
583 if (skip && kind == S_IFDIR && !strcmp(filename, skip)) {
584 ret = PyList_New(0);
584 ret = PyList_New(0);
585 goto error;
585 goto error;
586 }
586 }
587
587
588 if (keepstat) {
588 if (keepstat) {
589 /* from the getattrlist(2) man page: "Only the
589 /* from the getattrlist(2) man page: "Only the
590 permission bits ... are valid". */
590 permission bits ... are valid". */
591 st.st_mode = (entry->access_mask & ~S_IFMT) | kind;
591 st.st_mode = (entry->access_mask & ~S_IFMT) | kind;
592 st.st_mtime = entry->mtime.tv_sec;
592 st.st_mtime = entry->mtime.tv_sec;
593 st.st_size = entry->size;
593 st.st_size = entry->size;
594 stat = makestat(&st);
594 stat = makestat(&st);
595 if (!stat)
595 if (!stat)
596 goto error;
596 goto error;
597 elem = Py_BuildValue(PY23("siN", "yiN"),
597 elem = Py_BuildValue(PY23("siN", "yiN"),
598 filename, kind, stat);
598 filename, kind, stat);
599 } else
599 } else
600 elem = Py_BuildValue(PY23("si", "yi"),
600 elem = Py_BuildValue(PY23("si", "yi"),
601 filename, kind);
601 filename, kind);
602 if (!elem)
602 if (!elem)
603 goto error;
603 goto error;
604 stat = NULL;
604 stat = NULL;
605
605
606 PyList_Append(list, elem);
606 PyList_Append(list, elem);
607 Py_DECREF(elem);
607 Py_DECREF(elem);
608
608
609 entry = (attrbuf_entry *)((char *)entry + entry->length);
609 entry = (attrbuf_entry *)((char *)entry + entry->length);
610 }
610 }
611 } while (err == 0);
611 } while (err == 0);
612
612
613 ret = list;
613 ret = list;
614 Py_INCREF(ret);
614 Py_INCREF(ret);
615
615
616 error:
616 error:
617 Py_DECREF(list);
617 Py_DECREF(list);
618 Py_XDECREF(stat);
618 Py_XDECREF(stat);
619 error_dir:
619 error_dir:
620 close(dfd);
620 close(dfd);
621 error_value:
621 error_value:
622 return ret;
622 return ret;
623 }
623 }
624
624
625 #endif /* __APPLE__ */
625 #endif /* __APPLE__ */
626
626
627 static PyObject *_listdir(char *path, int pathlen, int keepstat, char *skip)
627 static PyObject *_listdir(char *path, int pathlen, int keepstat, char *skip)
628 {
628 {
629 #ifdef __APPLE__
629 #ifdef __APPLE__
630 PyObject *ret;
630 PyObject *ret;
631 bool fallback = false;
631 bool fallback = false;
632
632
633 ret = _listdir_batch(path, pathlen, keepstat, skip, &fallback);
633 ret = _listdir_batch(path, pathlen, keepstat, skip, &fallback);
634 if (ret != NULL || !fallback)
634 if (ret != NULL || !fallback)
635 return ret;
635 return ret;
636 #endif
636 #endif
637 return _listdir_stat(path, pathlen, keepstat, skip);
637 return _listdir_stat(path, pathlen, keepstat, skip);
638 }
638 }
639
639
640 static PyObject *statfiles(PyObject *self, PyObject *args)
640 static PyObject *statfiles(PyObject *self, PyObject *args)
641 {
641 {
642 PyObject *names, *stats;
642 PyObject *names, *stats;
643 Py_ssize_t i, count;
643 Py_ssize_t i, count;
644
644
645 if (!PyArg_ParseTuple(args, "O:statfiles", &names))
645 if (!PyArg_ParseTuple(args, "O:statfiles", &names))
646 return NULL;
646 return NULL;
647
647
648 count = PySequence_Length(names);
648 count = PySequence_Length(names);
649 if (count == -1) {
649 if (count == -1) {
650 PyErr_SetString(PyExc_TypeError, "not a sequence");
650 PyErr_SetString(PyExc_TypeError, "not a sequence");
651 return NULL;
651 return NULL;
652 }
652 }
653
653
654 stats = PyList_New(count);
654 stats = PyList_New(count);
655 if (stats == NULL)
655 if (stats == NULL)
656 return NULL;
656 return NULL;
657
657
658 for (i = 0; i < count; i++) {
658 for (i = 0; i < count; i++) {
659 PyObject *stat, *pypath;
659 PyObject *stat, *pypath;
660 struct stat st;
660 struct stat st;
661 int ret, kind;
661 int ret, kind;
662 char *path;
662 char *path;
663
663
664 /* With a large file count or on a slow filesystem,
664 /* With a large file count or on a slow filesystem,
665 don't block signals for long (issue4878). */
665 don't block signals for long (issue4878). */
666 if ((i % 1000) == 999 && PyErr_CheckSignals() == -1)
666 if ((i % 1000) == 999 && PyErr_CheckSignals() == -1)
667 goto bail;
667 goto bail;
668
668
669 pypath = PySequence_GetItem(names, i);
669 pypath = PySequence_GetItem(names, i);
670 if (!pypath)
670 if (!pypath)
671 goto bail;
671 goto bail;
672 path = PyBytes_AsString(pypath);
672 path = PyBytes_AsString(pypath);
673 if (path == NULL) {
673 if (path == NULL) {
674 Py_DECREF(pypath);
674 Py_DECREF(pypath);
675 PyErr_SetString(PyExc_TypeError, "not a string");
675 PyErr_SetString(PyExc_TypeError, "not a string");
676 goto bail;
676 goto bail;
677 }
677 }
678 ret = lstat(path, &st);
678 ret = lstat(path, &st);
679 Py_DECREF(pypath);
679 Py_DECREF(pypath);
680 kind = st.st_mode & S_IFMT;
680 kind = st.st_mode & S_IFMT;
681 if (ret != -1 && (kind == S_IFREG || kind == S_IFLNK)) {
681 if (ret != -1 && (kind == S_IFREG || kind == S_IFLNK)) {
682 stat = makestat(&st);
682 stat = makestat(&st);
683 if (stat == NULL)
683 if (stat == NULL)
684 goto bail;
684 goto bail;
685 PyList_SET_ITEM(stats, i, stat);
685 PyList_SET_ITEM(stats, i, stat);
686 } else {
686 } else {
687 Py_INCREF(Py_None);
687 Py_INCREF(Py_None);
688 PyList_SET_ITEM(stats, i, Py_None);
688 PyList_SET_ITEM(stats, i, Py_None);
689 }
689 }
690 }
690 }
691
691
692 return stats;
692 return stats;
693
693
694 bail:
694 bail:
695 Py_DECREF(stats);
695 Py_DECREF(stats);
696 return NULL;
696 return NULL;
697 }
697 }
698
698
699 /*
699 /*
700 * recvfds() simply does not release GIL during blocking io operation because
700 * recvfds() simply does not release GIL during blocking io operation because
701 * command server is known to be single-threaded.
701 * command server is known to be single-threaded.
702 *
702 *
703 * 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.
704 * Currently, recvfds() is not supported on these platforms.
704 * Currently, recvfds() is not supported on these platforms.
705 */
705 */
706 #ifdef CMSG_LEN
706 #ifdef CMSG_LEN
707
707
708 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)
709 {
709 {
710 char dummy[1];
710 char dummy[1];
711 struct iovec iov = {dummy, sizeof(dummy)};
711 struct iovec iov = {dummy, sizeof(dummy)};
712 struct msghdr msgh = {0};
712 struct msghdr msgh = {0};
713 struct cmsghdr *cmsg;
713 struct cmsghdr *cmsg;
714
714
715 msgh.msg_iov = &iov;
715 msgh.msg_iov = &iov;
716 msgh.msg_iovlen = 1;
716 msgh.msg_iovlen = 1;
717 msgh.msg_control = cbuf;
717 msgh.msg_control = cbuf;
718 msgh.msg_controllen = (socklen_t)cbufsize;
718 msgh.msg_controllen = (socklen_t)cbufsize;
719 if (recvmsg(sockfd, &msgh, 0) < 0)
719 if (recvmsg(sockfd, &msgh, 0) < 0)
720 return -1;
720 return -1;
721
721
722 for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg;
722 for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg;
723 cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
723 cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
724 if (cmsg->cmsg_level != SOL_SOCKET ||
724 if (cmsg->cmsg_level != SOL_SOCKET ||
725 cmsg->cmsg_type != SCM_RIGHTS)
725 cmsg->cmsg_type != SCM_RIGHTS)
726 continue;
726 continue;
727 *rfds = (int *)CMSG_DATA(cmsg);
727 *rfds = (int *)CMSG_DATA(cmsg);
728 return (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
728 return (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
729 }
729 }
730
730
731 *rfds = cbuf;
731 *rfds = cbuf;
732 return 0;
732 return 0;
733 }
733 }
734
734
735 static PyObject *recvfds(PyObject *self, PyObject *args)
735 static PyObject *recvfds(PyObject *self, PyObject *args)
736 {
736 {
737 int sockfd;
737 int sockfd;
738 int *rfds = NULL;
738 int *rfds = NULL;
739 ssize_t rfdscount, i;
739 ssize_t rfdscount, i;
740 char cbuf[256];
740 char cbuf[256];
741 PyObject *rfdslist = NULL;
741 PyObject *rfdslist = NULL;
742
742
743 if (!PyArg_ParseTuple(args, "i", &sockfd))
743 if (!PyArg_ParseTuple(args, "i", &sockfd))
744 return NULL;
744 return NULL;
745
745
746 rfdscount = recvfdstobuf(sockfd, &rfds, cbuf, sizeof(cbuf));
746 rfdscount = recvfdstobuf(sockfd, &rfds, cbuf, sizeof(cbuf));
747 if (rfdscount < 0)
747 if (rfdscount < 0)
748 return PyErr_SetFromErrno(PyExc_OSError);
748 return PyErr_SetFromErrno(PyExc_OSError);
749
749
750 rfdslist = PyList_New(rfdscount);
750 rfdslist = PyList_New(rfdscount);
751 if (!rfdslist)
751 if (!rfdslist)
752 goto bail;
752 goto bail;
753 for (i = 0; i < rfdscount; i++) {
753 for (i = 0; i < rfdscount; i++) {
754 PyObject *obj = PyLong_FromLong(rfds[i]);
754 PyObject *obj = PyLong_FromLong(rfds[i]);
755 if (!obj)
755 if (!obj)
756 goto bail;
756 goto bail;
757 PyList_SET_ITEM(rfdslist, i, obj);
757 PyList_SET_ITEM(rfdslist, i, obj);
758 }
758 }
759 return rfdslist;
759 return rfdslist;
760
760
761 bail:
761 bail:
762 Py_XDECREF(rfdslist);
762 Py_XDECREF(rfdslist);
763 return NULL;
763 return NULL;
764 }
764 }
765
765
766 #endif /* CMSG_LEN */
766 #endif /* CMSG_LEN */
767
767
768 /* allow disabling setprocname via compiler flags */
769 #ifndef SETPROCNAME_USE_NONE
768 #if defined(HAVE_SETPROCTITLE)
770 #if defined(HAVE_SETPROCTITLE)
769 /* setproctitle is the first choice - available in FreeBSD */
771 /* setproctitle is the first choice - available in FreeBSD */
770 #define SETPROCNAME_USE_SETPROCTITLE
772 #define SETPROCNAME_USE_SETPROCTITLE
771 #elif (defined(__linux__) || defined(__APPLE__)) && PY_MAJOR_VERSION == 2
773 #elif (defined(__linux__) || defined(__APPLE__)) && PY_MAJOR_VERSION == 2
772 /* rewrite the argv buffer in place - works in Linux and OS X. Py_GetArgcArgv
774 /* rewrite the argv buffer in place - works in Linux and OS X. Py_GetArgcArgv
773 * in Python 3 returns the copied wchar_t **argv, thus unsupported. */
775 * in Python 3 returns the copied wchar_t **argv, thus unsupported. */
774 #define SETPROCNAME_USE_ARGVREWRITE
776 #define SETPROCNAME_USE_ARGVREWRITE
775 #else
777 #else
776 #define SETPROCNAME_USE_NONE
778 #define SETPROCNAME_USE_NONE
777 #endif
779 #endif
780 #endif /* ndef SETPROCNAME_USE_NONE */
778
781
779 #ifndef SETPROCNAME_USE_NONE
782 #ifndef SETPROCNAME_USE_NONE
780 static PyObject *setprocname(PyObject *self, PyObject *args)
783 static PyObject *setprocname(PyObject *self, PyObject *args)
781 {
784 {
782 const char *name = NULL;
785 const char *name = NULL;
783 if (!PyArg_ParseTuple(args, PY23("s", "y"), &name))
786 if (!PyArg_ParseTuple(args, PY23("s", "y"), &name))
784 return NULL;
787 return NULL;
785
788
786 #if defined(SETPROCNAME_USE_SETPROCTITLE)
789 #if defined(SETPROCNAME_USE_SETPROCTITLE)
787 setproctitle("%s", name);
790 setproctitle("%s", name);
788 #elif defined(SETPROCNAME_USE_ARGVREWRITE)
791 #elif defined(SETPROCNAME_USE_ARGVREWRITE)
789 {
792 {
790 static char *argvstart = NULL;
793 static char *argvstart = NULL;
791 static size_t argvsize = 0;
794 static size_t argvsize = 0;
792 if (argvstart == NULL) {
795 if (argvstart == NULL) {
793 int argc = 0, i;
796 int argc = 0, i;
794 char **argv = NULL;
797 char **argv = NULL;
795 char *argvend;
798 char *argvend;
796 extern void Py_GetArgcArgv(int *argc, char ***argv);
799 extern void Py_GetArgcArgv(int *argc, char ***argv);
797 Py_GetArgcArgv(&argc, &argv);
800 Py_GetArgcArgv(&argc, &argv);
798
801
799 /* Check the memory we can use. Typically, argv[i] and
802 /* Check the memory we can use. Typically, argv[i] and
800 * argv[i + 1] are continuous. */
803 * argv[i + 1] are continuous. */
801 argvend = argvstart = argv[0];
804 argvend = argvstart = argv[0];
802 for (i = 0; i < argc; ++i) {
805 for (i = 0; i < argc; ++i) {
803 if (argv[i] > argvend || argv[i] < argvstart)
806 if (argv[i] > argvend || argv[i] < argvstart)
804 break; /* not continuous */
807 break; /* not continuous */
805 size_t len = strlen(argv[i]);
808 size_t len = strlen(argv[i]);
806 argvend = argv[i] + len + 1 /* '\0' */;
809 argvend = argv[i] + len + 1 /* '\0' */;
807 }
810 }
808 if (argvend > argvstart) /* sanity check */
811 if (argvend > argvstart) /* sanity check */
809 argvsize = argvend - argvstart;
812 argvsize = argvend - argvstart;
810 }
813 }
811
814
812 if (argvstart && argvsize > 1) {
815 if (argvstart && argvsize > 1) {
813 int n = snprintf(argvstart, argvsize, "%s", name);
816 int n = snprintf(argvstart, argvsize, "%s", name);
814 if (n >= 0 && (size_t)n < argvsize)
817 if (n >= 0 && (size_t)n < argvsize)
815 memset(argvstart + n, 0, argvsize - n);
818 memset(argvstart + n, 0, argvsize - n);
816 }
819 }
817 }
820 }
818 #endif
821 #endif
819
822
820 Py_RETURN_NONE;
823 Py_RETURN_NONE;
821 }
824 }
822 #endif /* ndef SETPROCNAME_USE_NONE */
825 #endif /* ndef SETPROCNAME_USE_NONE */
823
826
824 #if defined(HAVE_BSD_STATFS)
827 #if defined(HAVE_BSD_STATFS)
825 static const char *describefstype(const struct statfs *pbuf)
828 static const char *describefstype(const struct statfs *pbuf)
826 {
829 {
827 /* BSD or OSX provides a f_fstypename field */
830 /* BSD or OSX provides a f_fstypename field */
828 return pbuf->f_fstypename;
831 return pbuf->f_fstypename;
829 }
832 }
830 #elif defined(HAVE_LINUX_STATFS)
833 #elif defined(HAVE_LINUX_STATFS)
831 static const char *describefstype(const struct statfs *pbuf)
834 static const char *describefstype(const struct statfs *pbuf)
832 {
835 {
833 /* Begin of Linux filesystems */
836 /* Begin of Linux filesystems */
834 #ifdef ADFS_SUPER_MAGIC
837 #ifdef ADFS_SUPER_MAGIC
835 if (pbuf->f_type == ADFS_SUPER_MAGIC)
838 if (pbuf->f_type == ADFS_SUPER_MAGIC)
836 return "adfs";
839 return "adfs";
837 #endif
840 #endif
838 #ifdef AFFS_SUPER_MAGIC
841 #ifdef AFFS_SUPER_MAGIC
839 if (pbuf->f_type == AFFS_SUPER_MAGIC)
842 if (pbuf->f_type == AFFS_SUPER_MAGIC)
840 return "affs";
843 return "affs";
841 #endif
844 #endif
842 #ifdef AUTOFS_SUPER_MAGIC
845 #ifdef AUTOFS_SUPER_MAGIC
843 if (pbuf->f_type == AUTOFS_SUPER_MAGIC)
846 if (pbuf->f_type == AUTOFS_SUPER_MAGIC)
844 return "autofs";
847 return "autofs";
845 #endif
848 #endif
846 #ifdef BDEVFS_MAGIC
849 #ifdef BDEVFS_MAGIC
847 if (pbuf->f_type == BDEVFS_MAGIC)
850 if (pbuf->f_type == BDEVFS_MAGIC)
848 return "bdevfs";
851 return "bdevfs";
849 #endif
852 #endif
850 #ifdef BEFS_SUPER_MAGIC
853 #ifdef BEFS_SUPER_MAGIC
851 if (pbuf->f_type == BEFS_SUPER_MAGIC)
854 if (pbuf->f_type == BEFS_SUPER_MAGIC)
852 return "befs";
855 return "befs";
853 #endif
856 #endif
854 #ifdef BFS_MAGIC
857 #ifdef BFS_MAGIC
855 if (pbuf->f_type == BFS_MAGIC)
858 if (pbuf->f_type == BFS_MAGIC)
856 return "bfs";
859 return "bfs";
857 #endif
860 #endif
858 #ifdef BINFMTFS_MAGIC
861 #ifdef BINFMTFS_MAGIC
859 if (pbuf->f_type == BINFMTFS_MAGIC)
862 if (pbuf->f_type == BINFMTFS_MAGIC)
860 return "binfmtfs";
863 return "binfmtfs";
861 #endif
864 #endif
862 #ifdef BTRFS_SUPER_MAGIC
865 #ifdef BTRFS_SUPER_MAGIC
863 if (pbuf->f_type == BTRFS_SUPER_MAGIC)
866 if (pbuf->f_type == BTRFS_SUPER_MAGIC)
864 return "btrfs";
867 return "btrfs";
865 #endif
868 #endif
866 #ifdef CGROUP_SUPER_MAGIC
869 #ifdef CGROUP_SUPER_MAGIC
867 if (pbuf->f_type == CGROUP_SUPER_MAGIC)
870 if (pbuf->f_type == CGROUP_SUPER_MAGIC)
868 return "cgroup";
871 return "cgroup";
869 #endif
872 #endif
870 #ifdef CIFS_MAGIC_NUMBER
873 #ifdef CIFS_MAGIC_NUMBER
871 if (pbuf->f_type == CIFS_MAGIC_NUMBER)
874 if (pbuf->f_type == CIFS_MAGIC_NUMBER)
872 return "cifs";
875 return "cifs";
873 #endif
876 #endif
874 #ifdef CODA_SUPER_MAGIC
877 #ifdef CODA_SUPER_MAGIC
875 if (pbuf->f_type == CODA_SUPER_MAGIC)
878 if (pbuf->f_type == CODA_SUPER_MAGIC)
876 return "coda";
879 return "coda";
877 #endif
880 #endif
878 #ifdef COH_SUPER_MAGIC
881 #ifdef COH_SUPER_MAGIC
879 if (pbuf->f_type == COH_SUPER_MAGIC)
882 if (pbuf->f_type == COH_SUPER_MAGIC)
880 return "coh";
883 return "coh";
881 #endif
884 #endif
882 #ifdef CRAMFS_MAGIC
885 #ifdef CRAMFS_MAGIC
883 if (pbuf->f_type == CRAMFS_MAGIC)
886 if (pbuf->f_type == CRAMFS_MAGIC)
884 return "cramfs";
887 return "cramfs";
885 #endif
888 #endif
886 #ifdef DEBUGFS_MAGIC
889 #ifdef DEBUGFS_MAGIC
887 if (pbuf->f_type == DEBUGFS_MAGIC)
890 if (pbuf->f_type == DEBUGFS_MAGIC)
888 return "debugfs";
891 return "debugfs";
889 #endif
892 #endif
890 #ifdef DEVFS_SUPER_MAGIC
893 #ifdef DEVFS_SUPER_MAGIC
891 if (pbuf->f_type == DEVFS_SUPER_MAGIC)
894 if (pbuf->f_type == DEVFS_SUPER_MAGIC)
892 return "devfs";
895 return "devfs";
893 #endif
896 #endif
894 #ifdef DEVPTS_SUPER_MAGIC
897 #ifdef DEVPTS_SUPER_MAGIC
895 if (pbuf->f_type == DEVPTS_SUPER_MAGIC)
898 if (pbuf->f_type == DEVPTS_SUPER_MAGIC)
896 return "devpts";
899 return "devpts";
897 #endif
900 #endif
898 #ifdef EFIVARFS_MAGIC
901 #ifdef EFIVARFS_MAGIC
899 if (pbuf->f_type == EFIVARFS_MAGIC)
902 if (pbuf->f_type == EFIVARFS_MAGIC)
900 return "efivarfs";
903 return "efivarfs";
901 #endif
904 #endif
902 #ifdef EFS_SUPER_MAGIC
905 #ifdef EFS_SUPER_MAGIC
903 if (pbuf->f_type == EFS_SUPER_MAGIC)
906 if (pbuf->f_type == EFS_SUPER_MAGIC)
904 return "efs";
907 return "efs";
905 #endif
908 #endif
906 #ifdef EXT_SUPER_MAGIC
909 #ifdef EXT_SUPER_MAGIC
907 if (pbuf->f_type == EXT_SUPER_MAGIC)
910 if (pbuf->f_type == EXT_SUPER_MAGIC)
908 return "ext";
911 return "ext";
909 #endif
912 #endif
910 #ifdef EXT2_OLD_SUPER_MAGIC
913 #ifdef EXT2_OLD_SUPER_MAGIC
911 if (pbuf->f_type == EXT2_OLD_SUPER_MAGIC)
914 if (pbuf->f_type == EXT2_OLD_SUPER_MAGIC)
912 return "ext2";
915 return "ext2";
913 #endif
916 #endif
914 #ifdef EXT2_SUPER_MAGIC
917 #ifdef EXT2_SUPER_MAGIC
915 if (pbuf->f_type == EXT2_SUPER_MAGIC)
918 if (pbuf->f_type == EXT2_SUPER_MAGIC)
916 return "ext2";
919 return "ext2";
917 #endif
920 #endif
918 #ifdef EXT3_SUPER_MAGIC
921 #ifdef EXT3_SUPER_MAGIC
919 if (pbuf->f_type == EXT3_SUPER_MAGIC)
922 if (pbuf->f_type == EXT3_SUPER_MAGIC)
920 return "ext3";
923 return "ext3";
921 #endif
924 #endif
922 #ifdef EXT4_SUPER_MAGIC
925 #ifdef EXT4_SUPER_MAGIC
923 if (pbuf->f_type == EXT4_SUPER_MAGIC)
926 if (pbuf->f_type == EXT4_SUPER_MAGIC)
924 return "ext4";
927 return "ext4";
925 #endif
928 #endif
926 #ifdef F2FS_SUPER_MAGIC
929 #ifdef F2FS_SUPER_MAGIC
927 if (pbuf->f_type == F2FS_SUPER_MAGIC)
930 if (pbuf->f_type == F2FS_SUPER_MAGIC)
928 return "f2fs";
931 return "f2fs";
929 #endif
932 #endif
930 #ifdef FUSE_SUPER_MAGIC
933 #ifdef FUSE_SUPER_MAGIC
931 if (pbuf->f_type == FUSE_SUPER_MAGIC)
934 if (pbuf->f_type == FUSE_SUPER_MAGIC)
932 return "fuse";
935 return "fuse";
933 #endif
936 #endif
934 #ifdef FUTEXFS_SUPER_MAGIC
937 #ifdef FUTEXFS_SUPER_MAGIC
935 if (pbuf->f_type == FUTEXFS_SUPER_MAGIC)
938 if (pbuf->f_type == FUTEXFS_SUPER_MAGIC)
936 return "futexfs";
939 return "futexfs";
937 #endif
940 #endif
938 #ifdef HFS_SUPER_MAGIC
941 #ifdef HFS_SUPER_MAGIC
939 if (pbuf->f_type == HFS_SUPER_MAGIC)
942 if (pbuf->f_type == HFS_SUPER_MAGIC)
940 return "hfs";
943 return "hfs";
941 #endif
944 #endif
942 #ifdef HOSTFS_SUPER_MAGIC
945 #ifdef HOSTFS_SUPER_MAGIC
943 if (pbuf->f_type == HOSTFS_SUPER_MAGIC)
946 if (pbuf->f_type == HOSTFS_SUPER_MAGIC)
944 return "hostfs";
947 return "hostfs";
945 #endif
948 #endif
946 #ifdef HPFS_SUPER_MAGIC
949 #ifdef HPFS_SUPER_MAGIC
947 if (pbuf->f_type == HPFS_SUPER_MAGIC)
950 if (pbuf->f_type == HPFS_SUPER_MAGIC)
948 return "hpfs";
951 return "hpfs";
949 #endif
952 #endif
950 #ifdef HUGETLBFS_MAGIC
953 #ifdef HUGETLBFS_MAGIC
951 if (pbuf->f_type == HUGETLBFS_MAGIC)
954 if (pbuf->f_type == HUGETLBFS_MAGIC)
952 return "hugetlbfs";
955 return "hugetlbfs";
953 #endif
956 #endif
954 #ifdef ISOFS_SUPER_MAGIC
957 #ifdef ISOFS_SUPER_MAGIC
955 if (pbuf->f_type == ISOFS_SUPER_MAGIC)
958 if (pbuf->f_type == ISOFS_SUPER_MAGIC)
956 return "isofs";
959 return "isofs";
957 #endif
960 #endif
958 #ifdef JFFS2_SUPER_MAGIC
961 #ifdef JFFS2_SUPER_MAGIC
959 if (pbuf->f_type == JFFS2_SUPER_MAGIC)
962 if (pbuf->f_type == JFFS2_SUPER_MAGIC)
960 return "jffs2";
963 return "jffs2";
961 #endif
964 #endif
962 #ifdef JFS_SUPER_MAGIC
965 #ifdef JFS_SUPER_MAGIC
963 if (pbuf->f_type == JFS_SUPER_MAGIC)
966 if (pbuf->f_type == JFS_SUPER_MAGIC)
964 return "jfs";
967 return "jfs";
965 #endif
968 #endif
966 #ifdef MINIX_SUPER_MAGIC
969 #ifdef MINIX_SUPER_MAGIC
967 if (pbuf->f_type == MINIX_SUPER_MAGIC)
970 if (pbuf->f_type == MINIX_SUPER_MAGIC)
968 return "minix";
971 return "minix";
969 #endif
972 #endif
970 #ifdef MINIX2_SUPER_MAGIC
973 #ifdef MINIX2_SUPER_MAGIC
971 if (pbuf->f_type == MINIX2_SUPER_MAGIC)
974 if (pbuf->f_type == MINIX2_SUPER_MAGIC)
972 return "minix2";
975 return "minix2";
973 #endif
976 #endif
974 #ifdef MINIX3_SUPER_MAGIC
977 #ifdef MINIX3_SUPER_MAGIC
975 if (pbuf->f_type == MINIX3_SUPER_MAGIC)
978 if (pbuf->f_type == MINIX3_SUPER_MAGIC)
976 return "minix3";
979 return "minix3";
977 #endif
980 #endif
978 #ifdef MQUEUE_MAGIC
981 #ifdef MQUEUE_MAGIC
979 if (pbuf->f_type == MQUEUE_MAGIC)
982 if (pbuf->f_type == MQUEUE_MAGIC)
980 return "mqueue";
983 return "mqueue";
981 #endif
984 #endif
982 #ifdef MSDOS_SUPER_MAGIC
985 #ifdef MSDOS_SUPER_MAGIC
983 if (pbuf->f_type == MSDOS_SUPER_MAGIC)
986 if (pbuf->f_type == MSDOS_SUPER_MAGIC)
984 return "msdos";
987 return "msdos";
985 #endif
988 #endif
986 #ifdef NCP_SUPER_MAGIC
989 #ifdef NCP_SUPER_MAGIC
987 if (pbuf->f_type == NCP_SUPER_MAGIC)
990 if (pbuf->f_type == NCP_SUPER_MAGIC)
988 return "ncp";
991 return "ncp";
989 #endif
992 #endif
990 #ifdef NFS_SUPER_MAGIC
993 #ifdef NFS_SUPER_MAGIC
991 if (pbuf->f_type == NFS_SUPER_MAGIC)
994 if (pbuf->f_type == NFS_SUPER_MAGIC)
992 return "nfs";
995 return "nfs";
993 #endif
996 #endif
994 #ifdef NILFS_SUPER_MAGIC
997 #ifdef NILFS_SUPER_MAGIC
995 if (pbuf->f_type == NILFS_SUPER_MAGIC)
998 if (pbuf->f_type == NILFS_SUPER_MAGIC)
996 return "nilfs";
999 return "nilfs";
997 #endif
1000 #endif
998 #ifdef NTFS_SB_MAGIC
1001 #ifdef NTFS_SB_MAGIC
999 if (pbuf->f_type == NTFS_SB_MAGIC)
1002 if (pbuf->f_type == NTFS_SB_MAGIC)
1000 return "ntfs-sb";
1003 return "ntfs-sb";
1001 #endif
1004 #endif
1002 #ifdef OCFS2_SUPER_MAGIC
1005 #ifdef OCFS2_SUPER_MAGIC
1003 if (pbuf->f_type == OCFS2_SUPER_MAGIC)
1006 if (pbuf->f_type == OCFS2_SUPER_MAGIC)
1004 return "ocfs2";
1007 return "ocfs2";
1005 #endif
1008 #endif
1006 #ifdef OPENPROM_SUPER_MAGIC
1009 #ifdef OPENPROM_SUPER_MAGIC
1007 if (pbuf->f_type == OPENPROM_SUPER_MAGIC)
1010 if (pbuf->f_type == OPENPROM_SUPER_MAGIC)
1008 return "openprom";
1011 return "openprom";
1009 #endif
1012 #endif
1010 #ifdef OVERLAYFS_SUPER_MAGIC
1013 #ifdef OVERLAYFS_SUPER_MAGIC
1011 if (pbuf->f_type == OVERLAYFS_SUPER_MAGIC)
1014 if (pbuf->f_type == OVERLAYFS_SUPER_MAGIC)
1012 return "overlay";
1015 return "overlay";
1013 #endif
1016 #endif
1014 #ifdef PIPEFS_MAGIC
1017 #ifdef PIPEFS_MAGIC
1015 if (pbuf->f_type == PIPEFS_MAGIC)
1018 if (pbuf->f_type == PIPEFS_MAGIC)
1016 return "pipefs";
1019 return "pipefs";
1017 #endif
1020 #endif
1018 #ifdef PROC_SUPER_MAGIC
1021 #ifdef PROC_SUPER_MAGIC
1019 if (pbuf->f_type == PROC_SUPER_MAGIC)
1022 if (pbuf->f_type == PROC_SUPER_MAGIC)
1020 return "proc";
1023 return "proc";
1021 #endif
1024 #endif
1022 #ifdef PSTOREFS_MAGIC
1025 #ifdef PSTOREFS_MAGIC
1023 if (pbuf->f_type == PSTOREFS_MAGIC)
1026 if (pbuf->f_type == PSTOREFS_MAGIC)
1024 return "pstorefs";
1027 return "pstorefs";
1025 #endif
1028 #endif
1026 #ifdef QNX4_SUPER_MAGIC
1029 #ifdef QNX4_SUPER_MAGIC
1027 if (pbuf->f_type == QNX4_SUPER_MAGIC)
1030 if (pbuf->f_type == QNX4_SUPER_MAGIC)
1028 return "qnx4";
1031 return "qnx4";
1029 #endif
1032 #endif
1030 #ifdef QNX6_SUPER_MAGIC
1033 #ifdef QNX6_SUPER_MAGIC
1031 if (pbuf->f_type == QNX6_SUPER_MAGIC)
1034 if (pbuf->f_type == QNX6_SUPER_MAGIC)
1032 return "qnx6";
1035 return "qnx6";
1033 #endif
1036 #endif
1034 #ifdef RAMFS_MAGIC
1037 #ifdef RAMFS_MAGIC
1035 if (pbuf->f_type == RAMFS_MAGIC)
1038 if (pbuf->f_type == RAMFS_MAGIC)
1036 return "ramfs";
1039 return "ramfs";
1037 #endif
1040 #endif
1038 #ifdef REISERFS_SUPER_MAGIC
1041 #ifdef REISERFS_SUPER_MAGIC
1039 if (pbuf->f_type == REISERFS_SUPER_MAGIC)
1042 if (pbuf->f_type == REISERFS_SUPER_MAGIC)
1040 return "reiserfs";
1043 return "reiserfs";
1041 #endif
1044 #endif
1042 #ifdef ROMFS_MAGIC
1045 #ifdef ROMFS_MAGIC
1043 if (pbuf->f_type == ROMFS_MAGIC)
1046 if (pbuf->f_type == ROMFS_MAGIC)
1044 return "romfs";
1047 return "romfs";
1045 #endif
1048 #endif
1046 #ifdef SECURITYFS_MAGIC
1049 #ifdef SECURITYFS_MAGIC
1047 if (pbuf->f_type == SECURITYFS_MAGIC)
1050 if (pbuf->f_type == SECURITYFS_MAGIC)
1048 return "securityfs";
1051 return "securityfs";
1049 #endif
1052 #endif
1050 #ifdef SELINUX_MAGIC
1053 #ifdef SELINUX_MAGIC
1051 if (pbuf->f_type == SELINUX_MAGIC)
1054 if (pbuf->f_type == SELINUX_MAGIC)
1052 return "selinux";
1055 return "selinux";
1053 #endif
1056 #endif
1054 #ifdef SMACK_MAGIC
1057 #ifdef SMACK_MAGIC
1055 if (pbuf->f_type == SMACK_MAGIC)
1058 if (pbuf->f_type == SMACK_MAGIC)
1056 return "smack";
1059 return "smack";
1057 #endif
1060 #endif
1058 #ifdef SMB_SUPER_MAGIC
1061 #ifdef SMB_SUPER_MAGIC
1059 if (pbuf->f_type == SMB_SUPER_MAGIC)
1062 if (pbuf->f_type == SMB_SUPER_MAGIC)
1060 return "smb";
1063 return "smb";
1061 #endif
1064 #endif
1062 #ifdef SOCKFS_MAGIC
1065 #ifdef SOCKFS_MAGIC
1063 if (pbuf->f_type == SOCKFS_MAGIC)
1066 if (pbuf->f_type == SOCKFS_MAGIC)
1064 return "sockfs";
1067 return "sockfs";
1065 #endif
1068 #endif
1066 #ifdef SQUASHFS_MAGIC
1069 #ifdef SQUASHFS_MAGIC
1067 if (pbuf->f_type == SQUASHFS_MAGIC)
1070 if (pbuf->f_type == SQUASHFS_MAGIC)
1068 return "squashfs";
1071 return "squashfs";
1069 #endif
1072 #endif
1070 #ifdef SYSFS_MAGIC
1073 #ifdef SYSFS_MAGIC
1071 if (pbuf->f_type == SYSFS_MAGIC)
1074 if (pbuf->f_type == SYSFS_MAGIC)
1072 return "sysfs";
1075 return "sysfs";
1073 #endif
1076 #endif
1074 #ifdef SYSV2_SUPER_MAGIC
1077 #ifdef SYSV2_SUPER_MAGIC
1075 if (pbuf->f_type == SYSV2_SUPER_MAGIC)
1078 if (pbuf->f_type == SYSV2_SUPER_MAGIC)
1076 return "sysv2";
1079 return "sysv2";
1077 #endif
1080 #endif
1078 #ifdef SYSV4_SUPER_MAGIC
1081 #ifdef SYSV4_SUPER_MAGIC
1079 if (pbuf->f_type == SYSV4_SUPER_MAGIC)
1082 if (pbuf->f_type == SYSV4_SUPER_MAGIC)
1080 return "sysv4";
1083 return "sysv4";
1081 #endif
1084 #endif
1082 #ifdef TMPFS_MAGIC
1085 #ifdef TMPFS_MAGIC
1083 if (pbuf->f_type == TMPFS_MAGIC)
1086 if (pbuf->f_type == TMPFS_MAGIC)
1084 return "tmpfs";
1087 return "tmpfs";
1085 #endif
1088 #endif
1086 #ifdef UDF_SUPER_MAGIC
1089 #ifdef UDF_SUPER_MAGIC
1087 if (pbuf->f_type == UDF_SUPER_MAGIC)
1090 if (pbuf->f_type == UDF_SUPER_MAGIC)
1088 return "udf";
1091 return "udf";
1089 #endif
1092 #endif
1090 #ifdef UFS_MAGIC
1093 #ifdef UFS_MAGIC
1091 if (pbuf->f_type == UFS_MAGIC)
1094 if (pbuf->f_type == UFS_MAGIC)
1092 return "ufs";
1095 return "ufs";
1093 #endif
1096 #endif
1094 #ifdef USBDEVICE_SUPER_MAGIC
1097 #ifdef USBDEVICE_SUPER_MAGIC
1095 if (pbuf->f_type == USBDEVICE_SUPER_MAGIC)
1098 if (pbuf->f_type == USBDEVICE_SUPER_MAGIC)
1096 return "usbdevice";
1099 return "usbdevice";
1097 #endif
1100 #endif
1098 #ifdef V9FS_MAGIC
1101 #ifdef V9FS_MAGIC
1099 if (pbuf->f_type == V9FS_MAGIC)
1102 if (pbuf->f_type == V9FS_MAGIC)
1100 return "v9fs";
1103 return "v9fs";
1101 #endif
1104 #endif
1102 #ifdef VXFS_SUPER_MAGIC
1105 #ifdef VXFS_SUPER_MAGIC
1103 if (pbuf->f_type == VXFS_SUPER_MAGIC)
1106 if (pbuf->f_type == VXFS_SUPER_MAGIC)
1104 return "vxfs";
1107 return "vxfs";
1105 #endif
1108 #endif
1106 #ifdef XENFS_SUPER_MAGIC
1109 #ifdef XENFS_SUPER_MAGIC
1107 if (pbuf->f_type == XENFS_SUPER_MAGIC)
1110 if (pbuf->f_type == XENFS_SUPER_MAGIC)
1108 return "xenfs";
1111 return "xenfs";
1109 #endif
1112 #endif
1110 #ifdef XENIX_SUPER_MAGIC
1113 #ifdef XENIX_SUPER_MAGIC
1111 if (pbuf->f_type == XENIX_SUPER_MAGIC)
1114 if (pbuf->f_type == XENIX_SUPER_MAGIC)
1112 return "xenix";
1115 return "xenix";
1113 #endif
1116 #endif
1114 #ifdef XFS_SUPER_MAGIC
1117 #ifdef XFS_SUPER_MAGIC
1115 if (pbuf->f_type == XFS_SUPER_MAGIC)
1118 if (pbuf->f_type == XFS_SUPER_MAGIC)
1116 return "xfs";
1119 return "xfs";
1117 #endif
1120 #endif
1118 /* End of Linux filesystems */
1121 /* End of Linux filesystems */
1119 return NULL;
1122 return NULL;
1120 }
1123 }
1121 #endif /* def HAVE_LINUX_STATFS */
1124 #endif /* def HAVE_LINUX_STATFS */
1122
1125
1123 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1126 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1124 /* given a directory path, return filesystem type name (best-effort) */
1127 /* given a directory path, return filesystem type name (best-effort) */
1125 static PyObject *getfstype(PyObject *self, PyObject *args)
1128 static PyObject *getfstype(PyObject *self, PyObject *args)
1126 {
1129 {
1127 const char *path = NULL;
1130 const char *path = NULL;
1128 struct statfs buf;
1131 struct statfs buf;
1129 int r;
1132 int r;
1130 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1133 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1131 return NULL;
1134 return NULL;
1132
1135
1133 memset(&buf, 0, sizeof(buf));
1136 memset(&buf, 0, sizeof(buf));
1134 r = statfs(path, &buf);
1137 r = statfs(path, &buf);
1135 if (r != 0)
1138 if (r != 0)
1136 return PyErr_SetFromErrno(PyExc_OSError);
1139 return PyErr_SetFromErrno(PyExc_OSError);
1137 return Py_BuildValue(PY23("s", "y"), describefstype(&buf));
1140 return Py_BuildValue(PY23("s", "y"), describefstype(&buf));
1138 }
1141 }
1139 #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */
1142 #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */
1140
1143
1141 #if defined(HAVE_BSD_STATFS)
1144 #if defined(HAVE_BSD_STATFS)
1142 /* given a directory path, return filesystem mount point (best-effort) */
1145 /* given a directory path, return filesystem mount point (best-effort) */
1143 static PyObject *getfsmountpoint(PyObject *self, PyObject *args)
1146 static PyObject *getfsmountpoint(PyObject *self, PyObject *args)
1144 {
1147 {
1145 const char *path = NULL;
1148 const char *path = NULL;
1146 struct statfs buf;
1149 struct statfs buf;
1147 int r;
1150 int r;
1148 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1151 if (!PyArg_ParseTuple(args, PY23("s", "y"), &path))
1149 return NULL;
1152 return NULL;
1150
1153
1151 memset(&buf, 0, sizeof(buf));
1154 memset(&buf, 0, sizeof(buf));
1152 r = statfs(path, &buf);
1155 r = statfs(path, &buf);
1153 if (r != 0)
1156 if (r != 0)
1154 return PyErr_SetFromErrno(PyExc_OSError);
1157 return PyErr_SetFromErrno(PyExc_OSError);
1155 return Py_BuildValue(PY23("s", "y"), buf.f_mntonname);
1158 return Py_BuildValue(PY23("s", "y"), buf.f_mntonname);
1156 }
1159 }
1157 #endif /* defined(HAVE_BSD_STATFS) */
1160 #endif /* defined(HAVE_BSD_STATFS) */
1158
1161
1159 static PyObject *unblocksignal(PyObject *self, PyObject *args)
1162 static PyObject *unblocksignal(PyObject *self, PyObject *args)
1160 {
1163 {
1161 int sig = 0;
1164 int sig = 0;
1162 int r;
1165 int r;
1163 if (!PyArg_ParseTuple(args, "i", &sig))
1166 if (!PyArg_ParseTuple(args, "i", &sig))
1164 return NULL;
1167 return NULL;
1165 sigset_t set;
1168 sigset_t set;
1166 r = sigemptyset(&set);
1169 r = sigemptyset(&set);
1167 if (r != 0)
1170 if (r != 0)
1168 return PyErr_SetFromErrno(PyExc_OSError);
1171 return PyErr_SetFromErrno(PyExc_OSError);
1169 r = sigaddset(&set, sig);
1172 r = sigaddset(&set, sig);
1170 if (r != 0)
1173 if (r != 0)
1171 return PyErr_SetFromErrno(PyExc_OSError);
1174 return PyErr_SetFromErrno(PyExc_OSError);
1172 r = sigprocmask(SIG_UNBLOCK, &set, NULL);
1175 r = sigprocmask(SIG_UNBLOCK, &set, NULL);
1173 if (r != 0)
1176 if (r != 0)
1174 return PyErr_SetFromErrno(PyExc_OSError);
1177 return PyErr_SetFromErrno(PyExc_OSError);
1175 Py_RETURN_NONE;
1178 Py_RETURN_NONE;
1176 }
1179 }
1177
1180
1178 #endif /* ndef _WIN32 */
1181 #endif /* ndef _WIN32 */
1179
1182
1180 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
1183 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
1181 {
1184 {
1182 PyObject *statobj = NULL; /* initialize - optional arg */
1185 PyObject *statobj = NULL; /* initialize - optional arg */
1183 PyObject *skipobj = NULL; /* initialize - optional arg */
1186 PyObject *skipobj = NULL; /* initialize - optional arg */
1184 char *path, *skip = NULL;
1187 char *path, *skip = NULL;
1185 Py_ssize_t plen;
1188 Py_ssize_t plen;
1186 int wantstat;
1189 int wantstat;
1187
1190
1188 static char *kwlist[] = {"path", "stat", "skip", NULL};
1191 static char *kwlist[] = {"path", "stat", "skip", NULL};
1189
1192
1190 if (!PyArg_ParseTupleAndKeywords(args, kwargs, PY23("s#|OO:listdir",
1193 if (!PyArg_ParseTupleAndKeywords(args, kwargs, PY23("s#|OO:listdir",
1191 "y#|OO:listdir"),
1194 "y#|OO:listdir"),
1192 kwlist, &path, &plen, &statobj, &skipobj))
1195 kwlist, &path, &plen, &statobj, &skipobj))
1193 return NULL;
1196 return NULL;
1194
1197
1195 wantstat = statobj && PyObject_IsTrue(statobj);
1198 wantstat = statobj && PyObject_IsTrue(statobj);
1196
1199
1197 if (skipobj && skipobj != Py_None) {
1200 if (skipobj && skipobj != Py_None) {
1198 skip = PyBytes_AsString(skipobj);
1201 skip = PyBytes_AsString(skipobj);
1199 if (!skip)
1202 if (!skip)
1200 return NULL;
1203 return NULL;
1201 }
1204 }
1202
1205
1203 return _listdir(path, plen, wantstat, skip);
1206 return _listdir(path, plen, wantstat, skip);
1204 }
1207 }
1205
1208
1206 #ifdef _WIN32
1209 #ifdef _WIN32
1207 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
1210 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
1208 {
1211 {
1209 static char *kwlist[] = {"name", "mode", "buffering", NULL};
1212 static char *kwlist[] = {"name", "mode", "buffering", NULL};
1210 PyObject *file_obj = NULL;
1213 PyObject *file_obj = NULL;
1211 char *name = NULL;
1214 char *name = NULL;
1212 char *mode = "rb";
1215 char *mode = "rb";
1213 DWORD access = 0;
1216 DWORD access = 0;
1214 DWORD creation;
1217 DWORD creation;
1215 HANDLE handle;
1218 HANDLE handle;
1216 int fd, flags = 0;
1219 int fd, flags = 0;
1217 int bufsize = -1;
1220 int bufsize = -1;
1218 char m0, m1, m2;
1221 char m0, m1, m2;
1219 char fpmode[4];
1222 char fpmode[4];
1220 int fppos = 0;
1223 int fppos = 0;
1221 int plus;
1224 int plus;
1222 #ifndef IS_PY3K
1225 #ifndef IS_PY3K
1223 FILE *fp;
1226 FILE *fp;
1224 #endif
1227 #endif
1225
1228
1226 if (!PyArg_ParseTupleAndKeywords(args, kwds, PY23("et|si:posixfile",
1229 if (!PyArg_ParseTupleAndKeywords(args, kwds, PY23("et|si:posixfile",
1227 "et|yi:posixfile"),
1230 "et|yi:posixfile"),
1228 kwlist,
1231 kwlist,
1229 Py_FileSystemDefaultEncoding,
1232 Py_FileSystemDefaultEncoding,
1230 &name, &mode, &bufsize))
1233 &name, &mode, &bufsize))
1231 return NULL;
1234 return NULL;
1232
1235
1233 m0 = mode[0];
1236 m0 = mode[0];
1234 m1 = m0 ? mode[1] : '\0';
1237 m1 = m0 ? mode[1] : '\0';
1235 m2 = m1 ? mode[2] : '\0';
1238 m2 = m1 ? mode[2] : '\0';
1236 plus = m1 == '+' || m2 == '+';
1239 plus = m1 == '+' || m2 == '+';
1237
1240
1238 fpmode[fppos++] = m0;
1241 fpmode[fppos++] = m0;
1239 if (m1 == 'b' || m2 == 'b') {
1242 if (m1 == 'b' || m2 == 'b') {
1240 flags = _O_BINARY;
1243 flags = _O_BINARY;
1241 fpmode[fppos++] = 'b';
1244 fpmode[fppos++] = 'b';
1242 }
1245 }
1243 else
1246 else
1244 flags = _O_TEXT;
1247 flags = _O_TEXT;
1245 if (m0 == 'r' && !plus) {
1248 if (m0 == 'r' && !plus) {
1246 flags |= _O_RDONLY;
1249 flags |= _O_RDONLY;
1247 access = GENERIC_READ;
1250 access = GENERIC_READ;
1248 } else {
1251 } else {
1249 /*
1252 /*
1250 work around http://support.microsoft.com/kb/899149 and
1253 work around http://support.microsoft.com/kb/899149 and
1251 set _O_RDWR for 'w' and 'a', even if mode has no '+'
1254 set _O_RDWR for 'w' and 'a', even if mode has no '+'
1252 */
1255 */
1253 flags |= _O_RDWR;
1256 flags |= _O_RDWR;
1254 access = GENERIC_READ | GENERIC_WRITE;
1257 access = GENERIC_READ | GENERIC_WRITE;
1255 fpmode[fppos++] = '+';
1258 fpmode[fppos++] = '+';
1256 }
1259 }
1257 fpmode[fppos++] = '\0';
1260 fpmode[fppos++] = '\0';
1258
1261
1259 switch (m0) {
1262 switch (m0) {
1260 case 'r':
1263 case 'r':
1261 creation = OPEN_EXISTING;
1264 creation = OPEN_EXISTING;
1262 break;
1265 break;
1263 case 'w':
1266 case 'w':
1264 creation = CREATE_ALWAYS;
1267 creation = CREATE_ALWAYS;
1265 break;
1268 break;
1266 case 'a':
1269 case 'a':
1267 creation = OPEN_ALWAYS;
1270 creation = OPEN_ALWAYS;
1268 flags |= _O_APPEND;
1271 flags |= _O_APPEND;
1269 break;
1272 break;
1270 default:
1273 default:
1271 PyErr_Format(PyExc_ValueError,
1274 PyErr_Format(PyExc_ValueError,
1272 "mode string must begin with one of 'r', 'w', "
1275 "mode string must begin with one of 'r', 'w', "
1273 "or 'a', not '%c'", m0);
1276 "or 'a', not '%c'", m0);
1274 goto bail;
1277 goto bail;
1275 }
1278 }
1276
1279
1277 handle = CreateFile(name, access,
1280 handle = CreateFile(name, access,
1278 FILE_SHARE_READ | FILE_SHARE_WRITE |
1281 FILE_SHARE_READ | FILE_SHARE_WRITE |
1279 FILE_SHARE_DELETE,
1282 FILE_SHARE_DELETE,
1280 NULL,
1283 NULL,
1281 creation,
1284 creation,
1282 FILE_ATTRIBUTE_NORMAL,
1285 FILE_ATTRIBUTE_NORMAL,
1283 0);
1286 0);
1284
1287
1285 if (handle == INVALID_HANDLE_VALUE) {
1288 if (handle == INVALID_HANDLE_VALUE) {
1286 PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
1289 PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
1287 goto bail;
1290 goto bail;
1288 }
1291 }
1289
1292
1290 fd = _open_osfhandle((intptr_t)handle, flags);
1293 fd = _open_osfhandle((intptr_t)handle, flags);
1291
1294
1292 if (fd == -1) {
1295 if (fd == -1) {
1293 CloseHandle(handle);
1296 CloseHandle(handle);
1294 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1297 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1295 goto bail;
1298 goto bail;
1296 }
1299 }
1297 #ifndef IS_PY3K
1300 #ifndef IS_PY3K
1298 fp = _fdopen(fd, fpmode);
1301 fp = _fdopen(fd, fpmode);
1299 if (fp == NULL) {
1302 if (fp == NULL) {
1300 _close(fd);
1303 _close(fd);
1301 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1304 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1302 goto bail;
1305 goto bail;
1303 }
1306 }
1304
1307
1305 file_obj = PyFile_FromFile(fp, name, mode, fclose);
1308 file_obj = PyFile_FromFile(fp, name, mode, fclose);
1306 if (file_obj == NULL) {
1309 if (file_obj == NULL) {
1307 fclose(fp);
1310 fclose(fp);
1308 goto bail;
1311 goto bail;
1309 }
1312 }
1310
1313
1311 PyFile_SetBufSize(file_obj, bufsize);
1314 PyFile_SetBufSize(file_obj, bufsize);
1312 #else
1315 #else
1313 file_obj = PyFile_FromFd(fd, name, mode, bufsize, NULL, NULL, NULL, 1);
1316 file_obj = PyFile_FromFd(fd, name, mode, bufsize, NULL, NULL, NULL, 1);
1314 if (file_obj == NULL)
1317 if (file_obj == NULL)
1315 goto bail;
1318 goto bail;
1316 #endif
1319 #endif
1317 bail:
1320 bail:
1318 PyMem_Free(name);
1321 PyMem_Free(name);
1319 return file_obj;
1322 return file_obj;
1320 }
1323 }
1321 #endif
1324 #endif
1322
1325
1323 #ifdef __APPLE__
1326 #ifdef __APPLE__
1324 #include <ApplicationServices/ApplicationServices.h>
1327 #include <ApplicationServices/ApplicationServices.h>
1325
1328
1326 static PyObject *isgui(PyObject *self)
1329 static PyObject *isgui(PyObject *self)
1327 {
1330 {
1328 CFDictionaryRef dict = CGSessionCopyCurrentDictionary();
1331 CFDictionaryRef dict = CGSessionCopyCurrentDictionary();
1329
1332
1330 if (dict != NULL) {
1333 if (dict != NULL) {
1331 CFRelease(dict);
1334 CFRelease(dict);
1332 Py_RETURN_TRUE;
1335 Py_RETURN_TRUE;
1333 } else {
1336 } else {
1334 Py_RETURN_FALSE;
1337 Py_RETURN_FALSE;
1335 }
1338 }
1336 }
1339 }
1337 #endif
1340 #endif
1338
1341
1339 static char osutil_doc[] = "Native operating system services.";
1342 static char osutil_doc[] = "Native operating system services.";
1340
1343
1341 static PyMethodDef methods[] = {
1344 static PyMethodDef methods[] = {
1342 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
1345 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
1343 "list a directory\n"},
1346 "list a directory\n"},
1344 #ifdef _WIN32
1347 #ifdef _WIN32
1345 {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
1348 {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
1346 "Open a file with POSIX-like semantics.\n"
1349 "Open a file with POSIX-like semantics.\n"
1347 "On error, this function may raise either a WindowsError or an IOError."},
1350 "On error, this function may raise either a WindowsError or an IOError."},
1348 #else
1351 #else
1349 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
1352 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
1350 "stat a series of files or symlinks\n"
1353 "stat a series of files or symlinks\n"
1351 "Returns None for non-existent entries and entries of other types.\n"},
1354 "Returns None for non-existent entries and entries of other types.\n"},
1352 #ifdef CMSG_LEN
1355 #ifdef CMSG_LEN
1353 {"recvfds", (PyCFunction)recvfds, METH_VARARGS,
1356 {"recvfds", (PyCFunction)recvfds, METH_VARARGS,
1354 "receive list of file descriptors via socket\n"},
1357 "receive list of file descriptors via socket\n"},
1355 #endif
1358 #endif
1356 #ifndef SETPROCNAME_USE_NONE
1359 #ifndef SETPROCNAME_USE_NONE
1357 {"setprocname", (PyCFunction)setprocname, METH_VARARGS,
1360 {"setprocname", (PyCFunction)setprocname, METH_VARARGS,
1358 "set process title (best-effort)\n"},
1361 "set process title (best-effort)\n"},
1359 #endif
1362 #endif
1360 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1363 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1361 {"getfstype", (PyCFunction)getfstype, METH_VARARGS,
1364 {"getfstype", (PyCFunction)getfstype, METH_VARARGS,
1362 "get filesystem type (best-effort)\n"},
1365 "get filesystem type (best-effort)\n"},
1363 #endif
1366 #endif
1364 #if defined(HAVE_BSD_STATFS)
1367 #if defined(HAVE_BSD_STATFS)
1365 {"getfsmountpoint", (PyCFunction)getfsmountpoint, METH_VARARGS,
1368 {"getfsmountpoint", (PyCFunction)getfsmountpoint, METH_VARARGS,
1366 "get filesystem mount point (best-effort)\n"},
1369 "get filesystem mount point (best-effort)\n"},
1367 #endif
1370 #endif
1368 {"unblocksignal", (PyCFunction)unblocksignal, METH_VARARGS,
1371 {"unblocksignal", (PyCFunction)unblocksignal, METH_VARARGS,
1369 "change signal mask to unblock a given signal\n"},
1372 "change signal mask to unblock a given signal\n"},
1370 #endif /* ndef _WIN32 */
1373 #endif /* ndef _WIN32 */
1371 #ifdef __APPLE__
1374 #ifdef __APPLE__
1372 {
1375 {
1373 "isgui", (PyCFunction)isgui, METH_NOARGS,
1376 "isgui", (PyCFunction)isgui, METH_NOARGS,
1374 "Is a CoreGraphics session available?"
1377 "Is a CoreGraphics session available?"
1375 },
1378 },
1376 #endif
1379 #endif
1377 {NULL, NULL}
1380 {NULL, NULL}
1378 };
1381 };
1379
1382
1380 static const int version = 4;
1383 static const int version = 4;
1381
1384
1382 #ifdef IS_PY3K
1385 #ifdef IS_PY3K
1383 static struct PyModuleDef osutil_module = {
1386 static struct PyModuleDef osutil_module = {
1384 PyModuleDef_HEAD_INIT,
1387 PyModuleDef_HEAD_INIT,
1385 "osutil",
1388 "osutil",
1386 osutil_doc,
1389 osutil_doc,
1387 -1,
1390 -1,
1388 methods
1391 methods
1389 };
1392 };
1390
1393
1391 PyMODINIT_FUNC PyInit_osutil(void)
1394 PyMODINIT_FUNC PyInit_osutil(void)
1392 {
1395 {
1393 PyObject *m;
1396 PyObject *m;
1394 if (PyType_Ready(&listdir_stat_type) < 0)
1397 if (PyType_Ready(&listdir_stat_type) < 0)
1395 return NULL;
1398 return NULL;
1396
1399
1397 m = PyModule_Create(&osutil_module);
1400 m = PyModule_Create(&osutil_module);
1398 PyModule_AddIntConstant(m, "version", version);
1401 PyModule_AddIntConstant(m, "version", version);
1399 return m;
1402 return m;
1400 }
1403 }
1401 #else
1404 #else
1402 PyMODINIT_FUNC initosutil(void)
1405 PyMODINIT_FUNC initosutil(void)
1403 {
1406 {
1404 PyObject *m;
1407 PyObject *m;
1405 if (PyType_Ready(&listdir_stat_type) == -1)
1408 if (PyType_Ready(&listdir_stat_type) == -1)
1406 return;
1409 return;
1407
1410
1408 m = Py_InitModule3("osutil", methods, osutil_doc);
1411 m = Py_InitModule3("osutil", methods, osutil_doc);
1409 PyModule_AddIntConstant(m, "version", version);
1412 PyModule_AddIntConstant(m, "version", version);
1410 }
1413 }
1411 #endif
1414 #endif
General Comments 0
You need to be logged in to leave comments. Login now