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