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