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