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