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