##// END OF EJS Templates
statfs: avoid static allocation...
Jun Wu -
r31623:a01e1132 default
parent child Browse files
Show More
@@ -1,1318 +1,1314 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, return filesystem type (best-effort), or None */
798 /* given a directory path and a zero-initialized statfs buffer, return
799 const char *getfstype(const char *path) {
799 * filesystem type name (best-effort), or NULL. */
800 #ifdef HAVE_BSD_STATFS
800 const char *getfstype(const char *path, struct statfs *pbuf) {
801 /* need to return a string field */
802 static struct statfs buf;
803 #else
804 struct statfs buf;
805 #endif
806 int r;
801 int r;
807 memset(&buf, 0, sizeof(buf));
802 r = statfs(path, pbuf);
808 r = statfs(path, &buf);
809 if (r != 0)
803 if (r != 0)
810 return NULL;
804 return NULL;
811 #if defined(HAVE_BSD_STATFS)
805 #if defined(HAVE_BSD_STATFS)
812 /* BSD or OSX provides a f_fstypename field */
806 /* BSD or OSX provides a f_fstypename field */
813 return buf.f_fstypename;
807 return pbuf->f_fstypename;
814 #elif defined(HAVE_LINUX_STATFS)
808 #elif defined(HAVE_LINUX_STATFS)
815 /* Begin of Linux filesystems */
809 /* Begin of Linux filesystems */
816 #ifdef ADFS_SUPER_MAGIC
810 #ifdef ADFS_SUPER_MAGIC
817 if (buf.f_type == ADFS_SUPER_MAGIC)
811 if (pbuf->f_type == ADFS_SUPER_MAGIC)
818 return "adfs";
812 return "adfs";
819 #endif
813 #endif
820 #ifdef AFFS_SUPER_MAGIC
814 #ifdef AFFS_SUPER_MAGIC
821 if (buf.f_type == AFFS_SUPER_MAGIC)
815 if (pbuf->f_type == AFFS_SUPER_MAGIC)
822 return "affs";
816 return "affs";
823 #endif
817 #endif
824 #ifdef BDEVFS_MAGIC
818 #ifdef BDEVFS_MAGIC
825 if (buf.f_type == BDEVFS_MAGIC)
819 if (pbuf->f_type == BDEVFS_MAGIC)
826 return "bdevfs";
820 return "bdevfs";
827 #endif
821 #endif
828 #ifdef BEFS_SUPER_MAGIC
822 #ifdef BEFS_SUPER_MAGIC
829 if (buf.f_type == BEFS_SUPER_MAGIC)
823 if (pbuf->f_type == BEFS_SUPER_MAGIC)
830 return "befs";
824 return "befs";
831 #endif
825 #endif
832 #ifdef BFS_MAGIC
826 #ifdef BFS_MAGIC
833 if (buf.f_type == BFS_MAGIC)
827 if (pbuf->f_type == BFS_MAGIC)
834 return "bfs";
828 return "bfs";
835 #endif
829 #endif
836 #ifdef BINFMTFS_MAGIC
830 #ifdef BINFMTFS_MAGIC
837 if (buf.f_type == BINFMTFS_MAGIC)
831 if (pbuf->f_type == BINFMTFS_MAGIC)
838 return "binfmtfs";
832 return "binfmtfs";
839 #endif
833 #endif
840 #ifdef BTRFS_SUPER_MAGIC
834 #ifdef BTRFS_SUPER_MAGIC
841 if (buf.f_type == BTRFS_SUPER_MAGIC)
835 if (pbuf->f_type == BTRFS_SUPER_MAGIC)
842 return "btrfs";
836 return "btrfs";
843 #endif
837 #endif
844 #ifdef CGROUP_SUPER_MAGIC
838 #ifdef CGROUP_SUPER_MAGIC
845 if (buf.f_type == CGROUP_SUPER_MAGIC)
839 if (pbuf->f_type == CGROUP_SUPER_MAGIC)
846 return "cgroup";
840 return "cgroup";
847 #endif
841 #endif
848 #ifdef CIFS_MAGIC_NUMBER
842 #ifdef CIFS_MAGIC_NUMBER
849 if (buf.f_type == CIFS_MAGIC_NUMBER)
843 if (pbuf->f_type == CIFS_MAGIC_NUMBER)
850 return "cifs";
844 return "cifs";
851 #endif
845 #endif
852 #ifdef CODA_SUPER_MAGIC
846 #ifdef CODA_SUPER_MAGIC
853 if (buf.f_type == CODA_SUPER_MAGIC)
847 if (pbuf->f_type == CODA_SUPER_MAGIC)
854 return "coda";
848 return "coda";
855 #endif
849 #endif
856 #ifdef COH_SUPER_MAGIC
850 #ifdef COH_SUPER_MAGIC
857 if (buf.f_type == COH_SUPER_MAGIC)
851 if (pbuf->f_type == COH_SUPER_MAGIC)
858 return "coh";
852 return "coh";
859 #endif
853 #endif
860 #ifdef CRAMFS_MAGIC
854 #ifdef CRAMFS_MAGIC
861 if (buf.f_type == CRAMFS_MAGIC)
855 if (pbuf->f_type == CRAMFS_MAGIC)
862 return "cramfs";
856 return "cramfs";
863 #endif
857 #endif
864 #ifdef DEBUGFS_MAGIC
858 #ifdef DEBUGFS_MAGIC
865 if (buf.f_type == DEBUGFS_MAGIC)
859 if (pbuf->f_type == DEBUGFS_MAGIC)
866 return "debugfs";
860 return "debugfs";
867 #endif
861 #endif
868 #ifdef DEVFS_SUPER_MAGIC
862 #ifdef DEVFS_SUPER_MAGIC
869 if (buf.f_type == DEVFS_SUPER_MAGIC)
863 if (pbuf->f_type == DEVFS_SUPER_MAGIC)
870 return "devfs";
864 return "devfs";
871 #endif
865 #endif
872 #ifdef DEVPTS_SUPER_MAGIC
866 #ifdef DEVPTS_SUPER_MAGIC
873 if (buf.f_type == DEVPTS_SUPER_MAGIC)
867 if (pbuf->f_type == DEVPTS_SUPER_MAGIC)
874 return "devpts";
868 return "devpts";
875 #endif
869 #endif
876 #ifdef EFIVARFS_MAGIC
870 #ifdef EFIVARFS_MAGIC
877 if (buf.f_type == EFIVARFS_MAGIC)
871 if (pbuf->f_type == EFIVARFS_MAGIC)
878 return "efivarfs";
872 return "efivarfs";
879 #endif
873 #endif
880 #ifdef EFS_SUPER_MAGIC
874 #ifdef EFS_SUPER_MAGIC
881 if (buf.f_type == EFS_SUPER_MAGIC)
875 if (pbuf->f_type == EFS_SUPER_MAGIC)
882 return "efs";
876 return "efs";
883 #endif
877 #endif
884 #ifdef EXT_SUPER_MAGIC
878 #ifdef EXT_SUPER_MAGIC
885 if (buf.f_type == EXT_SUPER_MAGIC)
879 if (pbuf->f_type == EXT_SUPER_MAGIC)
886 return "ext";
880 return "ext";
887 #endif
881 #endif
888 #ifdef EXT2_OLD_SUPER_MAGIC
882 #ifdef EXT2_OLD_SUPER_MAGIC
889 if (buf.f_type == EXT2_OLD_SUPER_MAGIC)
883 if (pbuf->f_type == EXT2_OLD_SUPER_MAGIC)
890 return "ext2";
884 return "ext2";
891 #endif
885 #endif
892 #ifdef EXT2_SUPER_MAGIC
886 #ifdef EXT2_SUPER_MAGIC
893 if (buf.f_type == EXT2_SUPER_MAGIC)
887 if (pbuf->f_type == EXT2_SUPER_MAGIC)
894 return "ext2";
888 return "ext2";
895 #endif
889 #endif
896 #ifdef EXT3_SUPER_MAGIC
890 #ifdef EXT3_SUPER_MAGIC
897 if (buf.f_type == EXT3_SUPER_MAGIC)
891 if (pbuf->f_type == EXT3_SUPER_MAGIC)
898 return "ext3";
892 return "ext3";
899 #endif
893 #endif
900 #ifdef EXT4_SUPER_MAGIC
894 #ifdef EXT4_SUPER_MAGIC
901 if (buf.f_type == EXT4_SUPER_MAGIC)
895 if (pbuf->f_type == EXT4_SUPER_MAGIC)
902 return "ext4";
896 return "ext4";
903 #endif
897 #endif
904 #ifdef FUSE_SUPER_MAGIC
898 #ifdef FUSE_SUPER_MAGIC
905 if (buf.f_type == FUSE_SUPER_MAGIC)
899 if (pbuf->f_type == FUSE_SUPER_MAGIC)
906 return "fuse";
900 return "fuse";
907 #endif
901 #endif
908 #ifdef FUTEXFS_SUPER_MAGIC
902 #ifdef FUTEXFS_SUPER_MAGIC
909 if (buf.f_type == FUTEXFS_SUPER_MAGIC)
903 if (pbuf->f_type == FUTEXFS_SUPER_MAGIC)
910 return "futexfs";
904 return "futexfs";
911 #endif
905 #endif
912 #ifdef HFS_SUPER_MAGIC
906 #ifdef HFS_SUPER_MAGIC
913 if (buf.f_type == HFS_SUPER_MAGIC)
907 if (pbuf->f_type == HFS_SUPER_MAGIC)
914 return "hfs";
908 return "hfs";
915 #endif
909 #endif
916 #ifdef HOSTFS_SUPER_MAGIC
910 #ifdef HOSTFS_SUPER_MAGIC
917 if (buf.f_type == HOSTFS_SUPER_MAGIC)
911 if (pbuf->f_type == HOSTFS_SUPER_MAGIC)
918 return "hostfs";
912 return "hostfs";
919 #endif
913 #endif
920 #ifdef HPFS_SUPER_MAGIC
914 #ifdef HPFS_SUPER_MAGIC
921 if (buf.f_type == HPFS_SUPER_MAGIC)
915 if (pbuf->f_type == HPFS_SUPER_MAGIC)
922 return "hpfs";
916 return "hpfs";
923 #endif
917 #endif
924 #ifdef HUGETLBFS_MAGIC
918 #ifdef HUGETLBFS_MAGIC
925 if (buf.f_type == HUGETLBFS_MAGIC)
919 if (pbuf->f_type == HUGETLBFS_MAGIC)
926 return "hugetlbfs";
920 return "hugetlbfs";
927 #endif
921 #endif
928 #ifdef ISOFS_SUPER_MAGIC
922 #ifdef ISOFS_SUPER_MAGIC
929 if (buf.f_type == ISOFS_SUPER_MAGIC)
923 if (pbuf->f_type == ISOFS_SUPER_MAGIC)
930 return "isofs";
924 return "isofs";
931 #endif
925 #endif
932 #ifdef JFFS2_SUPER_MAGIC
926 #ifdef JFFS2_SUPER_MAGIC
933 if (buf.f_type == JFFS2_SUPER_MAGIC)
927 if (pbuf->f_type == JFFS2_SUPER_MAGIC)
934 return "jffs2";
928 return "jffs2";
935 #endif
929 #endif
936 #ifdef JFS_SUPER_MAGIC
930 #ifdef JFS_SUPER_MAGIC
937 if (buf.f_type == JFS_SUPER_MAGIC)
931 if (pbuf->f_type == JFS_SUPER_MAGIC)
938 return "jfs";
932 return "jfs";
939 #endif
933 #endif
940 #ifdef MINIX_SUPER_MAGIC
934 #ifdef MINIX_SUPER_MAGIC
941 if (buf.f_type == MINIX_SUPER_MAGIC)
935 if (pbuf->f_type == MINIX_SUPER_MAGIC)
942 return "minix";
936 return "minix";
943 #endif
937 #endif
944 #ifdef MINIX2_SUPER_MAGIC
938 #ifdef MINIX2_SUPER_MAGIC
945 if (buf.f_type == MINIX2_SUPER_MAGIC)
939 if (pbuf->f_type == MINIX2_SUPER_MAGIC)
946 return "minix2";
940 return "minix2";
947 #endif
941 #endif
948 #ifdef MINIX3_SUPER_MAGIC
942 #ifdef MINIX3_SUPER_MAGIC
949 if (buf.f_type == MINIX3_SUPER_MAGIC)
943 if (pbuf->f_type == MINIX3_SUPER_MAGIC)
950 return "minix3";
944 return "minix3";
951 #endif
945 #endif
952 #ifdef MQUEUE_MAGIC
946 #ifdef MQUEUE_MAGIC
953 if (buf.f_type == MQUEUE_MAGIC)
947 if (pbuf->f_type == MQUEUE_MAGIC)
954 return "mqueue";
948 return "mqueue";
955 #endif
949 #endif
956 #ifdef MSDOS_SUPER_MAGIC
950 #ifdef MSDOS_SUPER_MAGIC
957 if (buf.f_type == MSDOS_SUPER_MAGIC)
951 if (pbuf->f_type == MSDOS_SUPER_MAGIC)
958 return "msdos";
952 return "msdos";
959 #endif
953 #endif
960 #ifdef NCP_SUPER_MAGIC
954 #ifdef NCP_SUPER_MAGIC
961 if (buf.f_type == NCP_SUPER_MAGIC)
955 if (pbuf->f_type == NCP_SUPER_MAGIC)
962 return "ncp";
956 return "ncp";
963 #endif
957 #endif
964 #ifdef NFS_SUPER_MAGIC
958 #ifdef NFS_SUPER_MAGIC
965 if (buf.f_type == NFS_SUPER_MAGIC)
959 if (pbuf->f_type == NFS_SUPER_MAGIC)
966 return "nfs";
960 return "nfs";
967 #endif
961 #endif
968 #ifdef NILFS_SUPER_MAGIC
962 #ifdef NILFS_SUPER_MAGIC
969 if (buf.f_type == NILFS_SUPER_MAGIC)
963 if (pbuf->f_type == NILFS_SUPER_MAGIC)
970 return "nilfs";
964 return "nilfs";
971 #endif
965 #endif
972 #ifdef NTFS_SB_MAGIC
966 #ifdef NTFS_SB_MAGIC
973 if (buf.f_type == NTFS_SB_MAGIC)
967 if (pbuf->f_type == NTFS_SB_MAGIC)
974 return "ntfs-sb";
968 return "ntfs-sb";
975 #endif
969 #endif
976 #ifdef OCFS2_SUPER_MAGIC
970 #ifdef OCFS2_SUPER_MAGIC
977 if (buf.f_type == OCFS2_SUPER_MAGIC)
971 if (pbuf->f_type == OCFS2_SUPER_MAGIC)
978 return "ocfs2";
972 return "ocfs2";
979 #endif
973 #endif
980 #ifdef OPENPROM_SUPER_MAGIC
974 #ifdef OPENPROM_SUPER_MAGIC
981 if (buf.f_type == OPENPROM_SUPER_MAGIC)
975 if (pbuf->f_type == OPENPROM_SUPER_MAGIC)
982 return "openprom";
976 return "openprom";
983 #endif
977 #endif
984 #ifdef PIPEFS_MAGIC
978 #ifdef PIPEFS_MAGIC
985 if (buf.f_type == PIPEFS_MAGIC)
979 if (pbuf->f_type == PIPEFS_MAGIC)
986 return "pipefs";
980 return "pipefs";
987 #endif
981 #endif
988 #ifdef PROC_SUPER_MAGIC
982 #ifdef PROC_SUPER_MAGIC
989 if (buf.f_type == PROC_SUPER_MAGIC)
983 if (pbuf->f_type == PROC_SUPER_MAGIC)
990 return "proc";
984 return "proc";
991 #endif
985 #endif
992 #ifdef PSTOREFS_MAGIC
986 #ifdef PSTOREFS_MAGIC
993 if (buf.f_type == PSTOREFS_MAGIC)
987 if (pbuf->f_type == PSTOREFS_MAGIC)
994 return "pstorefs";
988 return "pstorefs";
995 #endif
989 #endif
996 #ifdef QNX4_SUPER_MAGIC
990 #ifdef QNX4_SUPER_MAGIC
997 if (buf.f_type == QNX4_SUPER_MAGIC)
991 if (pbuf->f_type == QNX4_SUPER_MAGIC)
998 return "qnx4";
992 return "qnx4";
999 #endif
993 #endif
1000 #ifdef QNX6_SUPER_MAGIC
994 #ifdef QNX6_SUPER_MAGIC
1001 if (buf.f_type == QNX6_SUPER_MAGIC)
995 if (pbuf->f_type == QNX6_SUPER_MAGIC)
1002 return "qnx6";
996 return "qnx6";
1003 #endif
997 #endif
1004 #ifdef RAMFS_MAGIC
998 #ifdef RAMFS_MAGIC
1005 if (buf.f_type == RAMFS_MAGIC)
999 if (pbuf->f_type == RAMFS_MAGIC)
1006 return "ramfs";
1000 return "ramfs";
1007 #endif
1001 #endif
1008 #ifdef REISERFS_SUPER_MAGIC
1002 #ifdef REISERFS_SUPER_MAGIC
1009 if (buf.f_type == REISERFS_SUPER_MAGIC)
1003 if (pbuf->f_type == REISERFS_SUPER_MAGIC)
1010 return "reiserfs";
1004 return "reiserfs";
1011 #endif
1005 #endif
1012 #ifdef ROMFS_MAGIC
1006 #ifdef ROMFS_MAGIC
1013 if (buf.f_type == ROMFS_MAGIC)
1007 if (pbuf->f_type == ROMFS_MAGIC)
1014 return "romfs";
1008 return "romfs";
1015 #endif
1009 #endif
1016 #ifdef SELINUX_MAGIC
1010 #ifdef SELINUX_MAGIC
1017 if (buf.f_type == SELINUX_MAGIC)
1011 if (pbuf->f_type == SELINUX_MAGIC)
1018 return "selinux";
1012 return "selinux";
1019 #endif
1013 #endif
1020 #ifdef SMACK_MAGIC
1014 #ifdef SMACK_MAGIC
1021 if (buf.f_type == SMACK_MAGIC)
1015 if (pbuf->f_type == SMACK_MAGIC)
1022 return "smack";
1016 return "smack";
1023 #endif
1017 #endif
1024 #ifdef SMB_SUPER_MAGIC
1018 #ifdef SMB_SUPER_MAGIC
1025 if (buf.f_type == SMB_SUPER_MAGIC)
1019 if (pbuf->f_type == SMB_SUPER_MAGIC)
1026 return "smb";
1020 return "smb";
1027 #endif
1021 #endif
1028 #ifdef SOCKFS_MAGIC
1022 #ifdef SOCKFS_MAGIC
1029 if (buf.f_type == SOCKFS_MAGIC)
1023 if (pbuf->f_type == SOCKFS_MAGIC)
1030 return "sockfs";
1024 return "sockfs";
1031 #endif
1025 #endif
1032 #ifdef SQUASHFS_MAGIC
1026 #ifdef SQUASHFS_MAGIC
1033 if (buf.f_type == SQUASHFS_MAGIC)
1027 if (pbuf->f_type == SQUASHFS_MAGIC)
1034 return "squashfs";
1028 return "squashfs";
1035 #endif
1029 #endif
1036 #ifdef SYSFS_MAGIC
1030 #ifdef SYSFS_MAGIC
1037 if (buf.f_type == SYSFS_MAGIC)
1031 if (pbuf->f_type == SYSFS_MAGIC)
1038 return "sysfs";
1032 return "sysfs";
1039 #endif
1033 #endif
1040 #ifdef SYSV2_SUPER_MAGIC
1034 #ifdef SYSV2_SUPER_MAGIC
1041 if (buf.f_type == SYSV2_SUPER_MAGIC)
1035 if (pbuf->f_type == SYSV2_SUPER_MAGIC)
1042 return "sysv2";
1036 return "sysv2";
1043 #endif
1037 #endif
1044 #ifdef SYSV4_SUPER_MAGIC
1038 #ifdef SYSV4_SUPER_MAGIC
1045 if (buf.f_type == SYSV4_SUPER_MAGIC)
1039 if (pbuf->f_type == SYSV4_SUPER_MAGIC)
1046 return "sysv4";
1040 return "sysv4";
1047 #endif
1041 #endif
1048 #ifdef TMPFS_MAGIC
1042 #ifdef TMPFS_MAGIC
1049 if (buf.f_type == TMPFS_MAGIC)
1043 if (pbuf->f_type == TMPFS_MAGIC)
1050 return "tmpfs";
1044 return "tmpfs";
1051 #endif
1045 #endif
1052 #ifdef UDF_SUPER_MAGIC
1046 #ifdef UDF_SUPER_MAGIC
1053 if (buf.f_type == UDF_SUPER_MAGIC)
1047 if (pbuf->f_type == UDF_SUPER_MAGIC)
1054 return "udf";
1048 return "udf";
1055 #endif
1049 #endif
1056 #ifdef UFS_MAGIC
1050 #ifdef UFS_MAGIC
1057 if (buf.f_type == UFS_MAGIC)
1051 if (pbuf->f_type == UFS_MAGIC)
1058 return "ufs";
1052 return "ufs";
1059 #endif
1053 #endif
1060 #ifdef USBDEVICE_SUPER_MAGIC
1054 #ifdef USBDEVICE_SUPER_MAGIC
1061 if (buf.f_type == USBDEVICE_SUPER_MAGIC)
1055 if (pbuf->f_type == USBDEVICE_SUPER_MAGIC)
1062 return "usbdevice";
1056 return "usbdevice";
1063 #endif
1057 #endif
1064 #ifdef V9FS_MAGIC
1058 #ifdef V9FS_MAGIC
1065 if (buf.f_type == V9FS_MAGIC)
1059 if (pbuf->f_type == V9FS_MAGIC)
1066 return "v9fs";
1060 return "v9fs";
1067 #endif
1061 #endif
1068 #ifdef VXFS_SUPER_MAGIC
1062 #ifdef VXFS_SUPER_MAGIC
1069 if (buf.f_type == VXFS_SUPER_MAGIC)
1063 if (pbuf->f_type == VXFS_SUPER_MAGIC)
1070 return "vxfs";
1064 return "vxfs";
1071 #endif
1065 #endif
1072 #ifdef XENFS_SUPER_MAGIC
1066 #ifdef XENFS_SUPER_MAGIC
1073 if (buf.f_type == XENFS_SUPER_MAGIC)
1067 if (pbuf->f_type == XENFS_SUPER_MAGIC)
1074 return "xenfs";
1068 return "xenfs";
1075 #endif
1069 #endif
1076 #ifdef XENIX_SUPER_MAGIC
1070 #ifdef XENIX_SUPER_MAGIC
1077 if (buf.f_type == XENIX_SUPER_MAGIC)
1071 if (pbuf->f_type == XENIX_SUPER_MAGIC)
1078 return "xenix";
1072 return "xenix";
1079 #endif
1073 #endif
1080 #ifdef XFS_SUPER_MAGIC
1074 #ifdef XFS_SUPER_MAGIC
1081 if (buf.f_type == XFS_SUPER_MAGIC)
1075 if (pbuf->f_type == XFS_SUPER_MAGIC)
1082 return "xfs";
1076 return "xfs";
1083 #endif
1077 #endif
1084 /* End of Linux filesystems */
1078 /* End of Linux filesystems */
1085 #endif /* def HAVE_LINUX_STATFS */
1079 #endif /* def HAVE_LINUX_STATFS */
1086 return NULL;
1080 return NULL;
1087 }
1081 }
1088
1082
1089 static PyObject *pygetfstype(PyObject *self, PyObject *args)
1083 static PyObject *pygetfstype(PyObject *self, PyObject *args)
1090 {
1084 {
1091 const char *path = NULL;
1085 const char *path = NULL;
1086 struct statfs buf;
1092 if (!PyArg_ParseTuple(args, "s", &path))
1087 if (!PyArg_ParseTuple(args, "s", &path))
1093 return NULL;
1088 return NULL;
1094
1089
1095 const char *type = getfstype(path);
1090 memset(&buf, 0, sizeof(buf));
1091 const char *type = getfstype(path, &buf);
1096 if (type == NULL)
1092 if (type == NULL)
1097 Py_RETURN_NONE;
1093 Py_RETURN_NONE;
1098
1094
1099 PyObject *result = Py_BuildValue("s", type);
1095 PyObject *result = Py_BuildValue("s", type);
1100 return result;
1096 return result;
1101 }
1097 }
1102 #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */
1098 #endif /* defined(HAVE_LINUX_STATFS) || defined(HAVE_BSD_STATFS) */
1103
1099
1104 #endif /* ndef _WIN32 */
1100 #endif /* ndef _WIN32 */
1105
1101
1106 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
1102 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
1107 {
1103 {
1108 PyObject *statobj = NULL; /* initialize - optional arg */
1104 PyObject *statobj = NULL; /* initialize - optional arg */
1109 PyObject *skipobj = NULL; /* initialize - optional arg */
1105 PyObject *skipobj = NULL; /* initialize - optional arg */
1110 char *path, *skip = NULL;
1106 char *path, *skip = NULL;
1111 int wantstat, plen;
1107 int wantstat, plen;
1112
1108
1113 static char *kwlist[] = {"path", "stat", "skip", NULL};
1109 static char *kwlist[] = {"path", "stat", "skip", NULL};
1114
1110
1115 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|OO:listdir",
1111 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|OO:listdir",
1116 kwlist, &path, &plen, &statobj, &skipobj))
1112 kwlist, &path, &plen, &statobj, &skipobj))
1117 return NULL;
1113 return NULL;
1118
1114
1119 wantstat = statobj && PyObject_IsTrue(statobj);
1115 wantstat = statobj && PyObject_IsTrue(statobj);
1120
1116
1121 if (skipobj && skipobj != Py_None) {
1117 if (skipobj && skipobj != Py_None) {
1122 skip = PyBytes_AsString(skipobj);
1118 skip = PyBytes_AsString(skipobj);
1123 if (!skip)
1119 if (!skip)
1124 return NULL;
1120 return NULL;
1125 }
1121 }
1126
1122
1127 return _listdir(path, plen, wantstat, skip);
1123 return _listdir(path, plen, wantstat, skip);
1128 }
1124 }
1129
1125
1130 #ifdef _WIN32
1126 #ifdef _WIN32
1131 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
1127 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
1132 {
1128 {
1133 static char *kwlist[] = {"name", "mode", "buffering", NULL};
1129 static char *kwlist[] = {"name", "mode", "buffering", NULL};
1134 PyObject *file_obj = NULL;
1130 PyObject *file_obj = NULL;
1135 char *name = NULL;
1131 char *name = NULL;
1136 char *mode = "rb";
1132 char *mode = "rb";
1137 DWORD access = 0;
1133 DWORD access = 0;
1138 DWORD creation;
1134 DWORD creation;
1139 HANDLE handle;
1135 HANDLE handle;
1140 int fd, flags = 0;
1136 int fd, flags = 0;
1141 int bufsize = -1;
1137 int bufsize = -1;
1142 char m0, m1, m2;
1138 char m0, m1, m2;
1143 char fpmode[4];
1139 char fpmode[4];
1144 int fppos = 0;
1140 int fppos = 0;
1145 int plus;
1141 int plus;
1146 FILE *fp;
1142 FILE *fp;
1147
1143
1148 if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:posixfile", kwlist,
1144 if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:posixfile", kwlist,
1149 Py_FileSystemDefaultEncoding,
1145 Py_FileSystemDefaultEncoding,
1150 &name, &mode, &bufsize))
1146 &name, &mode, &bufsize))
1151 return NULL;
1147 return NULL;
1152
1148
1153 m0 = mode[0];
1149 m0 = mode[0];
1154 m1 = m0 ? mode[1] : '\0';
1150 m1 = m0 ? mode[1] : '\0';
1155 m2 = m1 ? mode[2] : '\0';
1151 m2 = m1 ? mode[2] : '\0';
1156 plus = m1 == '+' || m2 == '+';
1152 plus = m1 == '+' || m2 == '+';
1157
1153
1158 fpmode[fppos++] = m0;
1154 fpmode[fppos++] = m0;
1159 if (m1 == 'b' || m2 == 'b') {
1155 if (m1 == 'b' || m2 == 'b') {
1160 flags = _O_BINARY;
1156 flags = _O_BINARY;
1161 fpmode[fppos++] = 'b';
1157 fpmode[fppos++] = 'b';
1162 }
1158 }
1163 else
1159 else
1164 flags = _O_TEXT;
1160 flags = _O_TEXT;
1165 if (m0 == 'r' && !plus) {
1161 if (m0 == 'r' && !plus) {
1166 flags |= _O_RDONLY;
1162 flags |= _O_RDONLY;
1167 access = GENERIC_READ;
1163 access = GENERIC_READ;
1168 } else {
1164 } else {
1169 /*
1165 /*
1170 work around http://support.microsoft.com/kb/899149 and
1166 work around http://support.microsoft.com/kb/899149 and
1171 set _O_RDWR for 'w' and 'a', even if mode has no '+'
1167 set _O_RDWR for 'w' and 'a', even if mode has no '+'
1172 */
1168 */
1173 flags |= _O_RDWR;
1169 flags |= _O_RDWR;
1174 access = GENERIC_READ | GENERIC_WRITE;
1170 access = GENERIC_READ | GENERIC_WRITE;
1175 fpmode[fppos++] = '+';
1171 fpmode[fppos++] = '+';
1176 }
1172 }
1177 fpmode[fppos++] = '\0';
1173 fpmode[fppos++] = '\0';
1178
1174
1179 switch (m0) {
1175 switch (m0) {
1180 case 'r':
1176 case 'r':
1181 creation = OPEN_EXISTING;
1177 creation = OPEN_EXISTING;
1182 break;
1178 break;
1183 case 'w':
1179 case 'w':
1184 creation = CREATE_ALWAYS;
1180 creation = CREATE_ALWAYS;
1185 break;
1181 break;
1186 case 'a':
1182 case 'a':
1187 creation = OPEN_ALWAYS;
1183 creation = OPEN_ALWAYS;
1188 flags |= _O_APPEND;
1184 flags |= _O_APPEND;
1189 break;
1185 break;
1190 default:
1186 default:
1191 PyErr_Format(PyExc_ValueError,
1187 PyErr_Format(PyExc_ValueError,
1192 "mode string must begin with one of 'r', 'w', "
1188 "mode string must begin with one of 'r', 'w', "
1193 "or 'a', not '%c'", m0);
1189 "or 'a', not '%c'", m0);
1194 goto bail;
1190 goto bail;
1195 }
1191 }
1196
1192
1197 handle = CreateFile(name, access,
1193 handle = CreateFile(name, access,
1198 FILE_SHARE_READ | FILE_SHARE_WRITE |
1194 FILE_SHARE_READ | FILE_SHARE_WRITE |
1199 FILE_SHARE_DELETE,
1195 FILE_SHARE_DELETE,
1200 NULL,
1196 NULL,
1201 creation,
1197 creation,
1202 FILE_ATTRIBUTE_NORMAL,
1198 FILE_ATTRIBUTE_NORMAL,
1203 0);
1199 0);
1204
1200
1205 if (handle == INVALID_HANDLE_VALUE) {
1201 if (handle == INVALID_HANDLE_VALUE) {
1206 PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
1202 PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
1207 goto bail;
1203 goto bail;
1208 }
1204 }
1209
1205
1210 fd = _open_osfhandle((intptr_t)handle, flags);
1206 fd = _open_osfhandle((intptr_t)handle, flags);
1211
1207
1212 if (fd == -1) {
1208 if (fd == -1) {
1213 CloseHandle(handle);
1209 CloseHandle(handle);
1214 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1210 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1215 goto bail;
1211 goto bail;
1216 }
1212 }
1217 #ifndef IS_PY3K
1213 #ifndef IS_PY3K
1218 fp = _fdopen(fd, fpmode);
1214 fp = _fdopen(fd, fpmode);
1219 if (fp == NULL) {
1215 if (fp == NULL) {
1220 _close(fd);
1216 _close(fd);
1221 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1217 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
1222 goto bail;
1218 goto bail;
1223 }
1219 }
1224
1220
1225 file_obj = PyFile_FromFile(fp, name, mode, fclose);
1221 file_obj = PyFile_FromFile(fp, name, mode, fclose);
1226 if (file_obj == NULL) {
1222 if (file_obj == NULL) {
1227 fclose(fp);
1223 fclose(fp);
1228 goto bail;
1224 goto bail;
1229 }
1225 }
1230
1226
1231 PyFile_SetBufSize(file_obj, bufsize);
1227 PyFile_SetBufSize(file_obj, bufsize);
1232 #else
1228 #else
1233 file_obj = PyFile_FromFd(fd, name, mode, bufsize, NULL, NULL, NULL, 1);
1229 file_obj = PyFile_FromFd(fd, name, mode, bufsize, NULL, NULL, NULL, 1);
1234 if (file_obj == NULL)
1230 if (file_obj == NULL)
1235 goto bail;
1231 goto bail;
1236 #endif
1232 #endif
1237 bail:
1233 bail:
1238 PyMem_Free(name);
1234 PyMem_Free(name);
1239 return file_obj;
1235 return file_obj;
1240 }
1236 }
1241 #endif
1237 #endif
1242
1238
1243 #ifdef __APPLE__
1239 #ifdef __APPLE__
1244 #include <ApplicationServices/ApplicationServices.h>
1240 #include <ApplicationServices/ApplicationServices.h>
1245
1241
1246 static PyObject *isgui(PyObject *self)
1242 static PyObject *isgui(PyObject *self)
1247 {
1243 {
1248 CFDictionaryRef dict = CGSessionCopyCurrentDictionary();
1244 CFDictionaryRef dict = CGSessionCopyCurrentDictionary();
1249
1245
1250 if (dict != NULL) {
1246 if (dict != NULL) {
1251 CFRelease(dict);
1247 CFRelease(dict);
1252 Py_RETURN_TRUE;
1248 Py_RETURN_TRUE;
1253 } else {
1249 } else {
1254 Py_RETURN_FALSE;
1250 Py_RETURN_FALSE;
1255 }
1251 }
1256 }
1252 }
1257 #endif
1253 #endif
1258
1254
1259 static char osutil_doc[] = "Native operating system services.";
1255 static char osutil_doc[] = "Native operating system services.";
1260
1256
1261 static PyMethodDef methods[] = {
1257 static PyMethodDef methods[] = {
1262 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
1258 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
1263 "list a directory\n"},
1259 "list a directory\n"},
1264 #ifdef _WIN32
1260 #ifdef _WIN32
1265 {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
1261 {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
1266 "Open a file with POSIX-like semantics.\n"
1262 "Open a file with POSIX-like semantics.\n"
1267 "On error, this function may raise either a WindowsError or an IOError."},
1263 "On error, this function may raise either a WindowsError or an IOError."},
1268 #else
1264 #else
1269 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
1265 {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS,
1270 "stat a series of files or symlinks\n"
1266 "stat a series of files or symlinks\n"
1271 "Returns None for non-existent entries and entries of other types.\n"},
1267 "Returns None for non-existent entries and entries of other types.\n"},
1272 #ifdef CMSG_LEN
1268 #ifdef CMSG_LEN
1273 {"recvfds", (PyCFunction)recvfds, METH_VARARGS,
1269 {"recvfds", (PyCFunction)recvfds, METH_VARARGS,
1274 "receive list of file descriptors via socket\n"},
1270 "receive list of file descriptors via socket\n"},
1275 #endif
1271 #endif
1276 #ifndef SETPROCNAME_USE_NONE
1272 #ifndef SETPROCNAME_USE_NONE
1277 {"setprocname", (PyCFunction)setprocname, METH_VARARGS,
1273 {"setprocname", (PyCFunction)setprocname, METH_VARARGS,
1278 "set process title (best-effort)\n"},
1274 "set process title (best-effort)\n"},
1279 #endif
1275 #endif
1280 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1276 #if defined(HAVE_BSD_STATFS) || defined(HAVE_LINUX_STATFS)
1281 {"getfstype", (PyCFunction)pygetfstype, METH_VARARGS,
1277 {"getfstype", (PyCFunction)pygetfstype, METH_VARARGS,
1282 "get filesystem type (best-effort)\n"},
1278 "get filesystem type (best-effort)\n"},
1283 #endif
1279 #endif
1284 #endif /* ndef _WIN32 */
1280 #endif /* ndef _WIN32 */
1285 #ifdef __APPLE__
1281 #ifdef __APPLE__
1286 {
1282 {
1287 "isgui", (PyCFunction)isgui, METH_NOARGS,
1283 "isgui", (PyCFunction)isgui, METH_NOARGS,
1288 "Is a CoreGraphics session available?"
1284 "Is a CoreGraphics session available?"
1289 },
1285 },
1290 #endif
1286 #endif
1291 {NULL, NULL}
1287 {NULL, NULL}
1292 };
1288 };
1293
1289
1294 #ifdef IS_PY3K
1290 #ifdef IS_PY3K
1295 static struct PyModuleDef osutil_module = {
1291 static struct PyModuleDef osutil_module = {
1296 PyModuleDef_HEAD_INIT,
1292 PyModuleDef_HEAD_INIT,
1297 "osutil",
1293 "osutil",
1298 osutil_doc,
1294 osutil_doc,
1299 -1,
1295 -1,
1300 methods
1296 methods
1301 };
1297 };
1302
1298
1303 PyMODINIT_FUNC PyInit_osutil(void)
1299 PyMODINIT_FUNC PyInit_osutil(void)
1304 {
1300 {
1305 if (PyType_Ready(&listdir_stat_type) < 0)
1301 if (PyType_Ready(&listdir_stat_type) < 0)
1306 return NULL;
1302 return NULL;
1307
1303
1308 return PyModule_Create(&osutil_module);
1304 return PyModule_Create(&osutil_module);
1309 }
1305 }
1310 #else
1306 #else
1311 PyMODINIT_FUNC initosutil(void)
1307 PyMODINIT_FUNC initosutil(void)
1312 {
1308 {
1313 if (PyType_Ready(&listdir_stat_type) == -1)
1309 if (PyType_Ready(&listdir_stat_type) == -1)
1314 return;
1310 return;
1315
1311
1316 Py_InitModule3("osutil", methods, osutil_doc);
1312 Py_InitModule3("osutil", methods, osutil_doc);
1317 }
1313 }
1318 #endif
1314 #endif
General Comments 0
You need to be logged in to leave comments. Login now