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