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