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