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