mercurial/osutil.c
author Patrick Mezard <pmezard@gmail.com>
Sun, 24 May 2009 16:27:50 +0200
changeset 8597 dc1b9e22f288
parent 8330 7de68012f86e
child 8723 b4a1b9012d96
permissions -rw-r--r--
osutil: silence uninitialized variable warning
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     1
/*
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     2
 osutil.c - native operating system services
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     3
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     4
 Copyright 2007 Matt Mackall and others
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     5
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     6
 This software may be used and distributed according to the terms of
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     7
 the GNU General Public License, incorporated herein by reference.
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     8
*/
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     9
5463
3b204881f959 osutil: use fdopendir instead of dirfd
Bryan O'Sullivan <bos@serpentine.com>
parents: 5457
diff changeset
    10
#define _ATFILE_SOURCE
5397
11caa374f497 osutil.c: include Python.h before the other headers
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5396
diff changeset
    11
#include <Python.h>
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    12
#include <fcntl.h>
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    13
#include <stdio.h>
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    14
#include <string.h>
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    15
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    16
#ifdef _WIN32
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    17
# include <windows.h>
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    18
# include <io.h>
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    19
#else
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    20
# include <dirent.h>
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    21
# include <sys/stat.h>
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    22
# include <sys/types.h>
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
    23
# include <unistd.h>
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    24
#endif
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    25
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    26
#ifdef _WIN32
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    27
/*
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    28
stat struct compatible with hg expectations
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    29
Mercurial only uses st_mode, st_size and st_mtime
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    30
the rest is kept to minimize changes between implementations
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    31
*/
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    32
struct hg_stat {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    33
	int st_dev;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    34
	int st_mode;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    35
	int st_nlink;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    36
	__int64 st_size;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    37
	int st_mtime;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    38
	int st_ctime;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    39
};
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    40
struct listdir_stat {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    41
	PyObject_HEAD
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    42
	struct hg_stat st;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    43
};
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    44
#else
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    45
struct listdir_stat {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    46
	PyObject_HEAD
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    47
	struct stat st;
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    48
};
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    49
#endif
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    50
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    51
#define listdir_slot(name) \
7190
aecea6934fdd Some additional space/tab cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7136
diff changeset
    52
	static PyObject *listdir_stat_##name(PyObject *self, void *x) \
aecea6934fdd Some additional space/tab cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7136
diff changeset
    53
	{ \
aecea6934fdd Some additional space/tab cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7136
diff changeset
    54
		return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
aecea6934fdd Some additional space/tab cleanups
Thomas Arendsen Hein <thomas@intevation.de>
parents: 7136
diff changeset
    55
	}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    56
5431
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
    57
listdir_slot(st_dev)
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
    58
listdir_slot(st_mode)
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
    59
listdir_slot(st_nlink)
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    60
#ifdef _WIN32
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    61
static PyObject *listdir_stat_st_size(PyObject *self, void *x)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    62
{
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    63
	return PyLong_FromLongLong(
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    64
		(PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    65
}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    66
#else
5431
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
    67
listdir_slot(st_size)
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
    68
#endif
5431
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
    69
listdir_slot(st_mtime)
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
    70
listdir_slot(st_ctime)
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    71
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    72
static struct PyGetSetDef listdir_stat_getsets[] = {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    73
	{"st_dev", listdir_stat_st_dev, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    74
	{"st_mode", listdir_stat_st_mode, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    75
	{"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    76
	{"st_size", listdir_stat_st_size, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    77
	{"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    78
	{"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    79
	{0, 0, 0, 0, 0}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    80
};
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    81
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    82
static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    83
{
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    84
	return t->tp_alloc(t, 0);
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    85
}
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    86
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    87
static void listdir_stat_dealloc(PyObject *o)
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    88
{
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    89
	o->ob_type->tp_free(o);
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    90
}
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    91
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    92
static PyTypeObject listdir_stat_type = {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    93
	PyObject_HEAD_INIT(NULL)
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    94
	0,                         /*ob_size*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    95
	"osutil.stat",             /*tp_name*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    96
	sizeof(struct listdir_stat), /*tp_basicsize*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    97
	0,                         /*tp_itemsize*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    98
	(destructor)listdir_stat_dealloc, /*tp_dealloc*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
    99
	0,                         /*tp_print*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   100
	0,                         /*tp_getattr*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   101
	0,                         /*tp_setattr*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   102
	0,                         /*tp_compare*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   103
	0,                         /*tp_repr*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   104
	0,                         /*tp_as_number*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   105
	0,                         /*tp_as_sequence*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   106
	0,                         /*tp_as_mapping*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   107
	0,                         /*tp_hash */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   108
	0,                         /*tp_call*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   109
	0,                         /*tp_str*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   110
	0,                         /*tp_getattro*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   111
	0,                         /*tp_setattro*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   112
	0,                         /*tp_as_buffer*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   113
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   114
	"stat objects",            /* tp_doc */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   115
	0,                         /* tp_traverse */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   116
	0,                         /* tp_clear */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   117
	0,                         /* tp_richcompare */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   118
	0,                         /* tp_weaklistoffset */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   119
	0,                         /* tp_iter */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   120
	0,                         /* tp_iternext */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   121
	0,                         /* tp_methods */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   122
	0,                         /* tp_members */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   123
	listdir_stat_getsets,      /* tp_getset */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   124
	0,                         /* tp_base */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   125
	0,                         /* tp_dict */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   126
	0,                         /* tp_descr_get */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   127
	0,                         /* tp_descr_set */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   128
	0,                         /* tp_dictoffset */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   129
	0,                         /* tp_init */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   130
	0,                         /* tp_alloc */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   131
	listdir_stat_new,          /* tp_new */
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   132
};
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   133
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   134
#ifdef _WIN32
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   135
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   136
static int to_python_time(const FILETIME *tm)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   137
{
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   138
	/* number of seconds between epoch and January 1 1601 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   139
	const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   140
	/* conversion factor from 100ns to 1s */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   141
	const __int64 a1 = 10000000;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   142
	/* explicit (int) cast to suspend compiler warnings */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   143
	return (int)((((__int64)tm->dwHighDateTime << 32)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   144
			+ tm->dwLowDateTime) / a1 - a0);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   145
}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   146
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   147
static PyObject *make_item(const WIN32_FIND_DATAA *fd, int wantstat)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   148
{
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   149
	PyObject *py_st;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   150
	struct hg_stat *stp;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   151
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   152
	int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   153
		? _S_IFDIR : _S_IFREG;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   154
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   155
	if (!wantstat)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   156
		return Py_BuildValue("si", fd->cFileName, kind);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   157
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   158
	py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   159
	if (!py_st)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   160
		return NULL;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   161
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   162
	stp = &((struct listdir_stat *)py_st)->st;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   163
	/*
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   164
	use kind as st_mode
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   165
	rwx bits on Win32 are meaningless
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   166
	and Hg does not use them anyway
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   167
	*/
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   168
	stp->st_mode  = kind;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   169
	stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   170
	stp->st_ctime = to_python_time(&fd->ftCreationTime);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   171
	if (kind == _S_IFREG)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   172
		stp->st_size =	((__int64)fd->nFileSizeHigh << 32)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   173
				+ fd->nFileSizeLow;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   174
	return Py_BuildValue("siN", fd->cFileName,
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   175
		kind, py_st);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   176
}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   177
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   178
static PyObject *_listdir(char *path, int plen, int wantstat, char *skip)
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   179
{
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   180
	PyObject *rval = NULL; /* initialize - return value */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   181
	PyObject *list;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   182
	HANDLE fh;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   183
	WIN32_FIND_DATAA fd;
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   184
	char *pattern;
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   185
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   186
	/* build the path + \* pattern string */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   187
	pattern = malloc(plen+3); /* path + \* + \0 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   188
	if (!pattern) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   189
		PyErr_NoMemory();
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   190
		goto error_nomem;
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   191
	}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   192
	strcpy(pattern, path);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   193
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   194
	if (plen > 0) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   195
		char c = path[plen-1];
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   196
		if (c != ':' && c != '/' && c != '\\')
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   197
			pattern[plen++] = '\\';
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   198
	}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   199
	strcpy(pattern + plen, "*");
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   200
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   201
	fh = FindFirstFileA(pattern, &fd);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   202
	if (fh == INVALID_HANDLE_VALUE) {
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
   203
		PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   204
		goto error_file;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   205
	}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   206
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   207
	list = PyList_New(0);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   208
	if (!list)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   209
		goto error_list;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   210
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   211
	do {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   212
		PyObject *item;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   213
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   214
		if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   215
			if (!strcmp(fd.cFileName, ".")
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   216
			|| !strcmp(fd.cFileName, ".."))
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   217
				continue;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   218
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   219
			if (skip && !strcmp(fd.cFileName, skip)) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   220
				rval = PyList_New(0);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   221
				goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   222
			}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   223
		}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   224
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   225
		item = make_item(&fd, wantstat);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   226
		if (!item)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   227
			goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   228
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   229
		if (PyList_Append(list, item)) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   230
			Py_XDECREF(item);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   231
			goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   232
		}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   233
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   234
		Py_XDECREF(item);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   235
	} while (FindNextFileA(fh, &fd));
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   236
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   237
	if (GetLastError() != ERROR_NO_MORE_FILES) {
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
   238
		PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   239
		goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   240
	}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   241
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   242
	rval = list;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   243
	Py_XINCREF(rval);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   244
error:
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   245
	Py_XDECREF(list);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   246
error_list:
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   247
	FindClose(fh);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   248
error_file:
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   249
	free(pattern);
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   250
error_nomem:
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   251
	return rval;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   252
}
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   253
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   254
#else
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   255
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   256
int entkind(struct dirent *ent)
5425
830f6e280c90 osutils: pull file stat loop into its own function
Matt Mackall <mpm@selenic.com>
parents: 5424
diff changeset
   257
{
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   258
#ifdef DT_REG
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   259
	switch (ent->d_type) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   260
	case DT_REG: return S_IFREG;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   261
	case DT_DIR: return S_IFDIR;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   262
	case DT_LNK: return S_IFLNK;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   263
	case DT_BLK: return S_IFBLK;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   264
	case DT_CHR: return S_IFCHR;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   265
	case DT_FIFO: return S_IFIFO;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   266
	case DT_SOCK: return S_IFSOCK;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   267
	}
5463
3b204881f959 osutil: use fdopendir instead of dirfd
Bryan O'Sullivan <bos@serpentine.com>
parents: 5457
diff changeset
   268
#endif
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   269
	return -1;
5425
830f6e280c90 osutils: pull file stat loop into its own function
Matt Mackall <mpm@selenic.com>
parents: 5424
diff changeset
   270
}
830f6e280c90 osutils: pull file stat loop into its own function
Matt Mackall <mpm@selenic.com>
parents: 5424
diff changeset
   271
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   272
static PyObject *_listdir(char *path, int pathlen, int keepstat, char *skip)
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   273
{
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   274
	PyObject *list, *elem, *stat, *ret = NULL;
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   275
	char fullpath[PATH_MAX + 10];
7136
d834ed27199f _listdir only uses dfd if AT_SYMLINK_NOFOLLOW is defined
Brendan Cully <brendan@kublai.com>
parents: 7098
diff changeset
   276
	int kind, err;
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   277
	struct stat st;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   278
	struct dirent *ent;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   279
	DIR *dir;
7136
d834ed27199f _listdir only uses dfd if AT_SYMLINK_NOFOLLOW is defined
Brendan Cully <brendan@kublai.com>
parents: 7098
diff changeset
   280
#ifdef AT_SYMLINK_NOFOLLOW
d834ed27199f _listdir only uses dfd if AT_SYMLINK_NOFOLLOW is defined
Brendan Cully <brendan@kublai.com>
parents: 7098
diff changeset
   281
	int dfd = -1;
d834ed27199f _listdir only uses dfd if AT_SYMLINK_NOFOLLOW is defined
Brendan Cully <brendan@kublai.com>
parents: 7098
diff changeset
   282
#endif
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   283
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
   284
	if (pathlen >= PATH_MAX) {
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
   285
		PyErr_SetString(PyExc_ValueError, "path too long");
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   286
		goto error_value;
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
   287
	}
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   288
	strncpy(fullpath, path, PATH_MAX);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   289
	fullpath[pathlen] = '/';
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   290
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   291
#ifdef AT_SYMLINK_NOFOLLOW
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   292
	dfd = open(path, O_RDONLY);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   293
	if (dfd == -1) {
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   294
		PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   295
		goto error_value;
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   296
	}
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   297
	dir = fdopendir(dfd);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   298
#else
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   299
	dir = opendir(path);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   300
#endif
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   301
	if (!dir) {
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   302
		PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   303
		goto error_dir;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   304
 	}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   305
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   306
	list = PyList_New(0);
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   307
	if (!list)
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   308
		goto error_list;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   309
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   310
	while ((ent = readdir(dir))) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   311
		if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   312
			continue;
5416
ca890c0c3f1f osutil.c: style fix - delete trailing end-of-line spaces
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 5398
diff changeset
   313
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   314
		kind = entkind(ent);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   315
		if (kind == -1 || keepstat) {
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   316
#ifdef AT_SYMLINK_NOFOLLOW
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   317
			err = fstatat(dfd, ent->d_name, &st,
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   318
				      AT_SYMLINK_NOFOLLOW);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   319
#else
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   320
			strncpy(fullpath + pathlen + 1, ent->d_name,
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   321
				PATH_MAX - pathlen);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   322
			fullpath[PATH_MAX] = 0;
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   323
			err = lstat(fullpath, &st);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   324
#endif
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   325
			if (err == -1) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   326
				strncpy(fullpath + pathlen + 1, ent->d_name,
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   327
					PATH_MAX - pathlen);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   328
				fullpath[PATH_MAX] = 0;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   329
				PyErr_SetFromErrnoWithFilename(PyExc_OSError,
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   330
							       fullpath);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   331
				goto error;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   332
			}
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   333
			kind = st.st_mode & S_IFMT;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   334
		}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   335
7034
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
   336
		/* quit early? */
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
   337
		if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) {
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
   338
			ret = PyList_New(0);
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
   339
			goto error;
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
   340
		}
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
   341
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   342
		if (keepstat) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   343
			stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   344
			if (!stat)
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   345
				goto error;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   346
			memcpy(&((struct listdir_stat *)stat)->st, &st, sizeof(st));
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   347
			elem = Py_BuildValue("siN", ent->d_name, kind, stat);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   348
		} else
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   349
			elem = Py_BuildValue("si", ent->d_name, kind);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   350
		if (!elem)
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   351
			goto error;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   352
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   353
		PyList_Append(list, elem);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   354
		Py_DECREF(elem);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   355
	}
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   356
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   357
	ret = list;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   358
	Py_INCREF(ret);
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   359
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   360
error:
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   361
	Py_DECREF(list);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   362
error_list:
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   363
	closedir(dir);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   364
error_dir:
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   365
#ifdef AT_SYMLINK_NOFOLLOW
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   366
	close(dfd);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
   367
#endif
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   368
error_value:
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
   369
	return ret;
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   370
}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   371
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   372
#endif /* ndef _WIN32 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
   373
7098
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   374
static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   375
{
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   376
	PyObject *statobj = NULL; /* initialize - optional arg */
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   377
	PyObject *skipobj = NULL; /* initialize - optional arg */
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   378
	char *path, *skip = NULL;
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   379
	int wantstat, plen;
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   380
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   381
	static char *kwlist[] = {"path", "stat", "skip", NULL};
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   382
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   383
	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|OO:listdir",
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   384
			kwlist, &path, &plen, &statobj, &skipobj))
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   385
		return NULL;
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   386
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   387
	wantstat = statobj && PyObject_IsTrue(statobj);
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   388
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   389
	if (skipobj && skipobj != Py_None) {
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   390
		skip = PyString_AsString(skipobj);
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   391
		if (!skip)
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   392
			return NULL;
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   393
	}
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   394
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   395
	return _listdir(path, plen, wantstat, skip);
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   396
}
8a5c88c7e97b osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 7059
diff changeset
   397
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   398
#ifdef _WIN32
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   399
static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   400
{
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   401
	static char *kwlist[] = {"name", "mode", "buffering", NULL};
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   402
	PyObject *file_obj = NULL;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   403
	char *name = NULL;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   404
	char *mode = "rb";
8597
dc1b9e22f288 osutil: silence uninitialized variable warning
Patrick Mezard <pmezard@gmail.com>
parents: 8330
diff changeset
   405
	DWORD access = 0;
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   406
	DWORD creation;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   407
	HANDLE handle;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   408
	int fd, flags = 0;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   409
	int bufsize = -1;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   410
	char m0, m1, m2;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   411
	char fpmode[4];
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   412
	int fppos = 0;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   413
	int plus;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   414
	FILE *fp;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   415
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   416
	if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:posixfile", kwlist,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   417
					 Py_FileSystemDefaultEncoding,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   418
					 &name, &mode, &bufsize))
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   419
		return NULL;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   420
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   421
	m0 = mode[0];
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   422
	m1 = m0 ? mode[1] : '\0';
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   423
	m2 = m1 ? mode[2] : '\0';
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   424
	plus = m1 == '+' || m2 == '+';
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   425
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   426
	fpmode[fppos++] = m0;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   427
	if (m1 == 'b' || m2 == 'b') {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   428
		flags = _O_BINARY;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   429
		fpmode[fppos++] = 'b';
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   430
	}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   431
	else
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   432
		flags = _O_TEXT;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   433
	if (plus) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   434
		flags |= _O_RDWR;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   435
		access = GENERIC_READ | GENERIC_WRITE;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   436
		fpmode[fppos++] = '+';
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   437
	}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   438
	fpmode[fppos++] = '\0';
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   439
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   440
	switch (m0) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   441
	case 'r':
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   442
		creation = OPEN_EXISTING;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   443
		if (!plus) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   444
			flags |= _O_RDONLY;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   445
			access = GENERIC_READ;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   446
		}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   447
		break;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   448
	case 'w':
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   449
		creation = CREATE_ALWAYS;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   450
		if (!plus) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   451
			access = GENERIC_WRITE;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   452
			flags |= _O_WRONLY;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   453
		}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   454
		break;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   455
	case 'a':
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   456
		creation = OPEN_ALWAYS;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   457
		flags |= _O_APPEND;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   458
		if (!plus) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   459
			flags |= _O_WRONLY;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   460
			access = GENERIC_WRITE;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   461
		}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   462
		break;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   463
	default:
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   464
		PyErr_Format(PyExc_ValueError,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   465
			     "mode string must begin with one of 'r', 'w', "
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   466
			     "or 'a', not '%c'", m0);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   467
		goto bail;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   468
	}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   469
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   470
	handle = CreateFile(name, access,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   471
			    FILE_SHARE_READ | FILE_SHARE_WRITE |
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   472
			    FILE_SHARE_DELETE,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   473
			    NULL,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   474
			    creation,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   475
			    FILE_ATTRIBUTE_NORMAL,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   476
			    0);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   477
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   478
	if (handle == INVALID_HANDLE_VALUE) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   479
		PyErr_SetFromWindowsErrWithFilename(GetLastError(), name);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   480
		goto bail;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   481
	}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   482
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   483
	fd = _open_osfhandle((intptr_t) handle, flags);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   484
	if (fd == -1) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   485
		CloseHandle(handle);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   486
		PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   487
		goto bail;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   488
	}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   489
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   490
	fp = _fdopen(fd, fpmode);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   491
	if (fp == NULL) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   492
		_close(fd);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   493
		PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   494
		goto bail;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   495
	}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   496
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   497
	file_obj = PyFile_FromFile(fp, name, mode, fclose);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   498
	if (file_obj == NULL) {
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   499
		fclose(fp);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   500
		goto bail;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   501
	}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   502
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   503
	PyFile_SetBufSize(file_obj, bufsize);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   504
bail:
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   505
	PyMem_Free(name);
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   506
	return file_obj;
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   507
}
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   508
#endif
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   509
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   510
static char osutil_doc[] = "Native operating system services.";
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   511
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   512
static PyMethodDef methods[] = {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   513
	{"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   514
	 "list a directory\n"},
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   515
#ifdef _WIN32
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   516
	{"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   517
	 "Open a file with POSIX-like semantics.\n"
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   518
"On error, this function may raise either a WindowsError or an IOError."},
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 7190
diff changeset
   519
#endif
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   520
	{NULL, NULL}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   521
};
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   522
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   523
PyMODINIT_FUNC initosutil(void)
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   524
{
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   525
	if (PyType_Ready(&listdir_stat_type) == -1)
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   526
		return;
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   527
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
   528
	Py_InitModule3("osutil", methods, osutil_doc);
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   529
}