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