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