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