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