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