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