##// END OF EJS Templates
Windows: improve performance via buffered I/O...
Bryan O'Sullivan -
r8330:7de68012 default
parent child Browse files
Show More
@@ -9,15 +9,18 b''
9
9
10 #define _ATFILE_SOURCE
10 #define _ATFILE_SOURCE
11 #include <Python.h>
11 #include <Python.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <string.h>
15
12 #ifdef _WIN32
16 #ifdef _WIN32
13 #include <windows.h>
17 # include <windows.h>
18 # include <io.h>
14 #else
19 #else
15 #include <dirent.h>
20 # include <dirent.h>
16 #include <fcntl.h>
21 # include <sys/stat.h>
17 #include <string.h>
22 # include <sys/types.h>
18 #include <sys/stat.h>
23 # include <unistd.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #endif
24 #endif
22
25
23 #ifdef _WIN32
26 #ifdef _WIN32
@@ -392,11 +395,128 b' static PyObject *listdir(PyObject *self,'
392 return _listdir(path, plen, wantstat, skip);
395 return _listdir(path, plen, wantstat, skip);
393 }
396 }
394
397
398 #ifdef _WIN32
399 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
400 {
401 static char *kwlist[] = {"name", "mode", "buffering", NULL};
402 PyObject *file_obj = NULL;
403 char *name = NULL;
404 char *mode = "rb";
405 DWORD access;
406 DWORD creation;
407 HANDLE handle;
408 int fd, flags = 0;
409 int bufsize = -1;
410 char m0, m1, m2;
411 char fpmode[4];
412 int fppos = 0;
413 int plus;
414 FILE *fp;
415
416 if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:posixfile", kwlist,
417 Py_FileSystemDefaultEncoding,
418 &name, &mode, &bufsize))
419 return NULL;
420
421 m0 = mode[0];
422 m1 = m0 ? mode[1] : '\0';
423 m2 = m1 ? mode[2] : '\0';
424 plus = m1 == '+' || m2 == '+';
425
426 fpmode[fppos++] = m0;
427 if (m1 == 'b' || m2 == 'b') {
428 flags = _O_BINARY;
429 fpmode[fppos++] = 'b';
430 }
431 else
432 flags = _O_TEXT;
433 if (plus) {
434 flags |= _O_RDWR;
435 access = GENERIC_READ | GENERIC_WRITE;
436 fpmode[fppos++] = '+';
437 }
438 fpmode[fppos++] = '\0';
439
440 switch (m0) {
441 case 'r':
442 creation = OPEN_EXISTING;
443 if (!plus) {
444 flags |= _O_RDONLY;
445 access = GENERIC_READ;
446 }
447 break;
448 case 'w':
449 creation = CREATE_ALWAYS;
450 if (!plus) {
451 access = GENERIC_WRITE;
452 flags |= _O_WRONLY;
453 }
454 break;
455 case 'a':
456 creation = OPEN_ALWAYS;
457 flags |= _O_APPEND;
458 if (!plus) {
459 flags |= _O_WRONLY;
460 access = GENERIC_WRITE;
461 }
462 break;
463 default:
464 PyErr_Format(PyExc_ValueError,
465 "mode string must begin with one of 'r', 'w', "
466 "or 'a', not '%c'", m0);
467 goto bail;
468 }
469
470 handle = CreateFile(name, access,
471 FILE_SHARE_READ | FILE_SHARE_WRITE |
472 FILE_SHARE_DELETE,
473 NULL,
474 creation,
475 FILE_ATTRIBUTE_NORMAL,
476 0);
477
478 if (handle == INVALID_HANDLE_VALUE) {
479 PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
480 goto bail;
481 }
482
483 fd = _open_osfhandle((intptr_t) handle, flags);
484 if (fd == -1) {
485 CloseHandle(handle);
486 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
487 goto bail;
488 }
489
490 fp = _fdopen(fd, fpmode);
491 if (fp == NULL) {
492 _close(fd);
493 PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
494 goto bail;
495 }
496
497 file_obj = PyFile_FromFile(fp, name, mode, fclose);
498 if (file_obj == NULL) {
499 fclose(fp);
500 goto bail;
501 }
502
503 PyFile_SetBufSize(file_obj, bufsize);
504 bail:
505 PyMem_Free(name);
506 return file_obj;
507 }
508 #endif
509
395 static char osutil_doc[] = "Native operating system services.";
510 static char osutil_doc[] = "Native operating system services.";
396
511
397 static PyMethodDef methods[] = {
512 static PyMethodDef methods[] = {
398 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
513 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
399 "list a directory\n"},
514 "list a directory\n"},
515 #ifdef _WIN32
516 {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
517 "Open a file with POSIX-like semantics.\n"
518 "On error, this function may raise either a WindowsError or an IOError."},
519 #endif
400 {NULL, NULL}
520 {NULL, NULL}
401 };
521 };
402
522
@@ -240,12 +240,23 b' def groupname(gid=None):'
240 If gid is None, return the name of the current group."""
240 If gid is None, return the name of the current group."""
241 return None
241 return None
242
242
243 posixfile = file
244 try:
243 try:
245 # override functions with win32 versions if possible
244 # override functions with win32 versions if possible
246 from win32 import *
245 from win32 import *
247 if not _is_win_9x():
246 if not _is_win_9x():
248 posixfile = posixfile_nt
247 posixfile = posixfile_nt
248 try:
249 # fast, buffered POSIX-like file support
250 from osutil import posixfile as _posixfile
251 def posixfile(name, mode='r', buffering=-1):
252 # wrap osutil.posixfile to provide friendlier exceptions
253 try:
254 return _posixfile(name, mode, buffering)
255 except WindowsError, err:
256 raise WinIOError(err)
257 posixfile.__doc__ = _posixfile.__doc__
258 except ImportError:
259 # slow, unbuffered POSIX-like file support
260 posixfile = posixfile_nt
249 except ImportError:
261 except ImportError:
250 pass
262 posixfile = file
251
General Comments 0
You need to be logged in to leave comments. Login now