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