annotate mercurial/osutil.c @ 7059:6a76cf980999

Improve error handling in osutil.c 1) In posix part set error when path is too long so instead of SystemError: error returned without exception set it will raise ValueError: path too long 2) In Win32 part replace generic PyErr_SetExcFromWindowsErrWithFilename by PyErr_SetFromWindowsErrWithFilename The exception returned is WinError(based on OSError) and some rudimentary errno translation is performed from Windows error range to errno module friendly range so errors like ENOENT can be handled via symbolic constant and consistently between Win32 and Posix.
author Petr Kodl <petrkodl@gmail.com>
date Wed, 01 Oct 2008 08:41:18 -0400
parents 2c1f18b88b6a
children 8a5c88c7e97b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
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>
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
12 #ifdef _WIN32
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
13 #include <windows.h>
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
14 #else
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
15 #include <dirent.h>
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
16 #include <fcntl.h>
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
17 #include <string.h>
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
18 #include <sys/stat.h>
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
19 #include <sys/types.h>
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
20 #include <unistd.h>
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
21 #endif
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
22
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
23 #ifdef _WIN32
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
24 /*
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
25 stat struct compatible with hg expectations
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
26 Mercurial only uses st_mode, st_size and st_mtime
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
27 the rest is kept to minimize changes between implementations
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
28 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
29 struct hg_stat {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
30 int st_dev;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
31 int st_mode;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
32 int st_nlink;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
33 __int64 st_size;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
34 int st_mtime;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
35 int st_ctime;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
36 };
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
37 struct listdir_stat {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
38 PyObject_HEAD
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
39 struct hg_stat st;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
40 };
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
41 #else
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
42 struct listdir_stat {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
43 PyObject_HEAD
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
44 struct stat st;
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
45 };
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
46 #endif
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
47
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
48 #define listdir_slot(name) \
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
49 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
50 { \
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
51 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
52 }
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
53
5431
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
54 listdir_slot(st_dev)
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
55 listdir_slot(st_mode)
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
56 listdir_slot(st_nlink)
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
57 #ifdef _WIN32
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
58 static PyObject *listdir_stat_st_size(PyObject *self, void *x)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
59 {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
60 return PyLong_FromLongLong(
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
61 (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
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 #else
5431
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
64 listdir_slot(st_size)
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
65 #endif
5431
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
66 listdir_slot(st_mtime)
a7c832abd29c Fix build error with Sun C compiler.
Bryan O'Sullivan <bos@serpentine.com>
parents: 5430
diff changeset
67 listdir_slot(st_ctime)
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
68
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
69 static struct PyGetSetDef listdir_stat_getsets[] = {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
70 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
71 {"st_mode", listdir_stat_st_mode, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
72 {"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
73 {"st_size", listdir_stat_st_size, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
74 {"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
75 {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
76 {0, 0, 0, 0, 0}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
77 };
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
78
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
79 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
80 {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
81 return t->tp_alloc(t, 0);
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
82 }
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
83
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
84 static void listdir_stat_dealloc(PyObject *o)
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
85 {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
86 o->ob_type->tp_free(o);
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
87 }
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
88
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
89 static PyTypeObject listdir_stat_type = {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
90 PyObject_HEAD_INIT(NULL)
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
91 0, /*ob_size*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
92 "osutil.stat", /*tp_name*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
93 sizeof(struct listdir_stat), /*tp_basicsize*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
94 0, /*tp_itemsize*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
95 (destructor)listdir_stat_dealloc, /*tp_dealloc*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
96 0, /*tp_print*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
97 0, /*tp_getattr*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
98 0, /*tp_setattr*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
99 0, /*tp_compare*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
100 0, /*tp_repr*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
101 0, /*tp_as_number*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
102 0, /*tp_as_sequence*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
103 0, /*tp_as_mapping*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
104 0, /*tp_hash */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
105 0, /*tp_call*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
106 0, /*tp_str*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
107 0, /*tp_getattro*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
108 0, /*tp_setattro*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
109 0, /*tp_as_buffer*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
110 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
111 "stat objects", /* tp_doc */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
112 0, /* tp_traverse */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
113 0, /* tp_clear */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
114 0, /* tp_richcompare */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
115 0, /* tp_weaklistoffset */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
116 0, /* tp_iter */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
117 0, /* tp_iternext */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
118 0, /* tp_methods */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
119 0, /* tp_members */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
120 listdir_stat_getsets, /* tp_getset */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
121 0, /* tp_base */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
122 0, /* tp_dict */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
123 0, /* tp_descr_get */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
124 0, /* tp_descr_set */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
125 0, /* tp_dictoffset */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
126 0, /* tp_init */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
127 0, /* tp_alloc */
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
128 listdir_stat_new, /* tp_new */
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
129 };
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
130
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
131 #ifdef _WIN32
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
132
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
133 static int to_python_time(const FILETIME *tm)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
134 {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
135 /* number of seconds between epoch and January 1 1601 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
136 const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
137 /* conversion factor from 100ns to 1s */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
138 const __int64 a1 = 10000000;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
139 /* explicit (int) cast to suspend compiler warnings */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
140 return (int)((((__int64)tm->dwHighDateTime << 32)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
141 + tm->dwLowDateTime) / a1 - a0);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
142 }
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
143
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
144 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
145 {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
146 PyObject *py_st;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
147 struct hg_stat *stp;
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 int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
150 ? _S_IFDIR : _S_IFREG;
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 if (!wantstat)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
153 return Py_BuildValue("si", fd->cFileName, kind);
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 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
156 if (!py_st)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
157 return NULL;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
158
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
159 stp = &((struct listdir_stat *)py_st)->st;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
160 /*
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
161 use kind as st_mode
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
162 rwx bits on Win32 are meaningless
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
163 and Hg does not use them anyway
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
164 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
165 stp->st_mode = kind;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
166 stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
167 stp->st_ctime = to_python_time(&fd->ftCreationTime);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
168 if (kind == _S_IFREG)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
169 stp->st_size = ((__int64)fd->nFileSizeHigh << 32)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
170 + fd->nFileSizeLow;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
171 return Py_BuildValue("siN", fd->cFileName,
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
172 kind, py_st);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
173 }
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
174
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
175 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
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 PyObject *rval = NULL; /* initialize - return value */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
178 PyObject *statobj = NULL; /* initialize - optional arg */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
179 PyObject *list;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
180 HANDLE fh;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
181 WIN32_FIND_DATAA fd;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
182 char *path, *pattern, *skip = NULL;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
183 int plen, wantstat;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
184
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
185 static char *kwlist[] = {"path", "stat", "skip", NULL};
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
186
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
187 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|Os:listdir",
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
188 kwlist, &path, &plen, &statobj, &skip))
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
189 goto error_parse;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
190
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
191 wantstat = statobj && PyObject_IsTrue(statobj);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
192
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
193 /* build the path + \* pattern string */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
194 pattern = malloc(plen+3); /* path + \* + \0 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
195 if (!pattern) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
196 PyErr_NoMemory();
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
197 goto error_parse;
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, path);
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 if (plen > 0) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
202 char c = path[plen-1];
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
203 if (c != ':' && c != '/' && c != '\\')
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
204 pattern[plen++] = '\\';
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 strcpy(pattern + plen, "*");
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
207
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
208 fh = FindFirstFileA(pattern, &fd);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
209 if (fh == INVALID_HANDLE_VALUE) {
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
210 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
211 goto error_file;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
212 }
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 list = PyList_New(0);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
215 if (!list)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
216 goto error_list;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
217
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
218 do {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
219 PyObject *item;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
220
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
221 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
222 if (!strcmp(fd.cFileName, ".")
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
223 || !strcmp(fd.cFileName, ".."))
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
224 continue;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
225
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
226 if (skip && !strcmp(fd.cFileName, skip)) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
227 rval = PyList_New(0);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
228 goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
229 }
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
230 }
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
231
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
232 item = make_item(&fd, wantstat);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
233 if (!item)
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
234 goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
235
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
236 if (PyList_Append(list, item)) {
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
237 Py_XDECREF(item);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
238 goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
239 }
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 Py_XDECREF(item);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
242 } while (FindNextFileA(fh, &fd));
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
243
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
244 if (GetLastError() != ERROR_NO_MORE_FILES) {
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
245 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
246 goto error;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
247 }
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
248
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
249 rval = list;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
250 Py_XINCREF(rval);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
251 error:
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
252 Py_XDECREF(list);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
253 error_list:
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
254 FindClose(fh);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
255 error_file:
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
256 free(pattern);
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
257 error_parse:
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
258 return rval;
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
259 }
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
260
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
261 #else
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
262
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
263 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
264 {
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
265 #ifdef DT_REG
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
266 switch (ent->d_type) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
267 case DT_REG: return S_IFREG;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
268 case DT_DIR: return S_IFDIR;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
269 case DT_LNK: return S_IFLNK;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
270 case DT_BLK: return S_IFBLK;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
271 case DT_CHR: return S_IFCHR;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
272 case DT_FIFO: return S_IFIFO;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
273 case DT_SOCK: return S_IFSOCK;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
274 }
5463
3b204881f959 osutil: use fdopendir instead of dirfd
Bryan O'Sullivan <bos@serpentine.com>
parents: 5457
diff changeset
275 #endif
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
276 return -1;
5425
830f6e280c90 osutils: pull file stat loop into its own function
Matt Mackall <mpm@selenic.com>
parents: 5424
diff changeset
277 }
830f6e280c90 osutils: pull file stat loop into its own function
Matt Mackall <mpm@selenic.com>
parents: 5424
diff changeset
278
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
279 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
280 {
7034
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
281 static char *kwlist[] = { "path", "stat", "skip", NULL };
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
282 PyObject *statflag = NULL, *list, *elem, *stat, *ret = NULL;
7034
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
283 char fullpath[PATH_MAX + 10], *path, *skip = NULL;
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
284 int pathlen, keepstat, kind, dfd = -1, err;
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
285 struct stat st;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
286 struct dirent *ent;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
287 DIR *dir;
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
288
7034
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
289 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|Os:listdir", kwlist,
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
290 &path, &pathlen, &statflag, &skip))
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
291 goto error_parse;
7034
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
292
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
293 if (pathlen >= PATH_MAX) {
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
294 PyErr_SetString(PyExc_ValueError, "path too long");
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
295 goto error_parse;
7059
6a76cf980999 Improve error handling in osutil.c
Petr Kodl <petrkodl@gmail.com>
parents: 7056
diff changeset
296 }
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
297 strncpy(fullpath, path, PATH_MAX);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
298 fullpath[pathlen] = '/';
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
299 keepstat = statflag && PyObject_IsTrue(statflag);
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
300
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
301 #ifdef AT_SYMLINK_NOFOLLOW
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
302 dfd = open(path, O_RDONLY);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
303 if (dfd == -1) {
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
304 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
305 goto error_parse;
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
306 }
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
307 dir = fdopendir(dfd);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
308 #else
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
309 dir = opendir(path);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
310 #endif
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
311 if (!dir) {
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
312 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
313 goto error_dir;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
314 }
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
315
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
316 list = PyList_New(0);
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
317 if (!list)
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
318 goto error_list;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
319
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
320 while ((ent = readdir(dir))) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
321 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
322 continue;
5416
ca890c0c3f1f osutil.c: style fix - delete trailing end-of-line spaces
Giorgos Keramidas <keramida@ceid.upatras.gr>
parents: 5398
diff changeset
323
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
324 kind = entkind(ent);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
325 if (kind == -1 || keepstat) {
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
326 #ifdef AT_SYMLINK_NOFOLLOW
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
327 err = fstatat(dfd, ent->d_name, &st,
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
328 AT_SYMLINK_NOFOLLOW);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
329 #else
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
330 strncpy(fullpath + pathlen + 1, ent->d_name,
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
331 PATH_MAX - pathlen);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
332 fullpath[PATH_MAX] = 0;
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
333 err = lstat(fullpath, &st);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
334 #endif
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
335 if (err == -1) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
336 strncpy(fullpath + pathlen + 1, ent->d_name,
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
337 PATH_MAX - pathlen);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
338 fullpath[PATH_MAX] = 0;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
339 PyErr_SetFromErrnoWithFilename(PyExc_OSError,
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
340 fullpath);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
341 goto error;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
342 }
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
343 kind = st.st_mode & S_IFMT;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
344 }
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
345
7034
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
346 /* quit early? */
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
347 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
348 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
349 goto error;
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
350 }
0d513661d6c2 listdir: add support for aborting if a certain path is found
Matt Mackall <mpm@selenic.com>
parents: 7033
diff changeset
351
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
352 if (keepstat) {
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
353 stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
354 if (!stat)
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
355 goto error;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
356 memcpy(&((struct listdir_stat *)stat)->st, &st, sizeof(st));
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
357 elem = Py_BuildValue("siN", ent->d_name, kind, stat);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
358 } else
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
359 elem = Py_BuildValue("si", ent->d_name, kind);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
360 if (!elem)
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
361 goto error;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
362
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
363 PyList_Append(list, elem);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
364 Py_DECREF(elem);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
365 }
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
366
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
367 ret = list;
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
368 Py_INCREF(ret);
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
369
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
370 error:
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
371 Py_DECREF(list);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
372 error_list:
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
373 closedir(dir);
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
374 error_dir:
7033
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
375 #ifdef AT_SYMLINK_NOFOLLOW
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
376 close(dfd);
892d27fb04a5 osutil: fix some braindamage
Matt Mackall <mpm@selenic.com>
parents: 7031
diff changeset
377 #endif
7031
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
378 error_parse:
19e8d034932e osutil: major listdir cleanup
Matt Mackall <mpm@selenic.com>
parents: 7022
diff changeset
379 return ret;
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
380 }
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
381
7056
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
382 #endif /* ndef _WIN32 */
2c1f18b88b6a osutil: implementation for Win32
Petr Kodl <petrkodl@gmail.com>
parents: 7034
diff changeset
383
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
384 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
385
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
386 static PyMethodDef methods[] = {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
387 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
388 "list a directory\n"},
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
389 {NULL, NULL}
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
390 };
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
391
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
392 PyMODINIT_FUNC initosutil(void)
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
393 {
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
394 if (PyType_Ready(&listdir_stat_type) == -1)
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
395 return;
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
396
5421
9b5d626be8ba osutil: cleanups
Matt Mackall <mpm@selenic.com>
parents: 5416
diff changeset
397 Py_InitModule3("osutil", methods, osutil_doc);
5396
5105b119edd2 Add osutil module, containing a listdir function.
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
398 }