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