The 0.5 release happened on 2/15, not on 2/14. :-)
[python/dscho.git] / Mac / Modules / macmodule.c
blob910f69051ce0796096be796f1d541887971f2227
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Mac module implementation */
27 #include "Python.h"
28 #include "ceval.h"
30 #include <stdio.h>
31 #include <string.h>
32 #include <errno.h>
34 #ifdef THINK_C
35 #include "unix.h"
36 #undef S_IFMT
37 #undef S_IFDIR
38 #undef S_IFCHR
39 #undef S_IFBLK
40 #undef S_IFREG
41 #undef S_ISDIR
42 #undef S_ISREG
43 #endif
45 #include "macstat.h"
46 #ifdef USE_GUSI
47 /* Remove defines from macstat.h */
48 #undef S_IFMT
49 #undef S_IFDIR
50 #undef S_IFREG
51 #undef S_IREAD
52 #undef S_IWRITE
53 #undef S_IEXEC
55 #include <GUSI.h>
56 #include <sys/types.h>
57 #include <stat.h>
58 #else
59 #define stat macstat
60 #endif
62 #ifdef __MWERKS__
63 #include <unix.h>
64 #else
65 #include <fcntl.h>
66 #endif
68 /* Optional routines, for some compiler/runtime combinations */
69 #if defined(USE_GUSI) || !defined(__MWERKS__)
70 #define WEHAVE_FDOPEN
71 #endif
72 #if defined(MPW) || defined(USE_GUSI)
73 #define WEHAVE_DUP
74 #endif
75 #if defined(USE_GUSI)
76 #define WEHAVE_FSTAT
77 #endif
79 #include "macdefs.h"
80 #ifdef USE_GUSI
81 #include <dirent.h>
82 #else
83 #include "dirent.h"
84 #endif
86 #ifndef MAXPATHLEN
87 #define MAXPATHLEN 1024
88 #endif
90 /* Prototypes for Unix simulation on Mac */
92 #ifndef USE_GUSI
94 int chdir Py_PROTO((const char *path));
95 int mkdir Py_PROTO((const char *path, int mode));
96 DIR * opendir Py_PROTO((char *));
97 void closedir Py_PROTO((DIR *));
98 struct dirent * readdir Py_PROTO((DIR *));
99 int rmdir Py_PROTO((const char *path));
100 int sync Py_PROTO((void));
102 #if defined(THINK_C) || defined(__SC__)
103 int unlink Py_PROTO((char *));
104 #else
105 int unlink Py_PROTO((const char *));
106 #endif
108 #endif /* USE_GUSI */
110 char *getwd Py_PROTO((char *));
111 char *getbootvol Py_PROTO((void));
114 static PyObject *MacError; /* Exception mac.error */
116 /* Set a MAC-specific error from errno, and return NULL */
118 static PyObject *
119 mac_error()
121 return PyErr_SetFromErrno(MacError);
124 /* MAC generic methods */
126 static PyObject *
127 mac_1str(args, func)
128 PyObject *args;
129 int (*func) Py_FPROTO((const char *));
131 char *path1;
132 int res;
133 if (!PyArg_Parse(args, "s", &path1))
134 return NULL;
135 Py_BEGIN_ALLOW_THREADS
136 res = (*func)(path1);
137 Py_END_ALLOW_THREADS
138 if (res < 0)
139 return mac_error();
140 Py_INCREF(Py_None);
141 return Py_None;
144 static PyObject *
145 mac_2str(args, func)
146 PyObject *args;
147 int (*func) Py_FPROTO((const char *, const char *));
149 char *path1, *path2;
150 int res;
151 if (!PyArg_Parse(args, "(ss)", &path1, &path2))
152 return NULL;
153 Py_BEGIN_ALLOW_THREADS
154 res = (*func)(path1, path2);
155 Py_END_ALLOW_THREADS
156 if (res < 0)
157 return mac_error();
158 Py_INCREF(Py_None);
159 return Py_None;
162 static PyObject *
163 mac_strint(args, func)
164 PyObject *args;
165 int (*func) Py_FPROTO((const char *, int));
167 char *path;
168 int i;
169 int res;
170 if (!PyArg_Parse(args, "(si)", &path, &i))
171 return NULL;
172 Py_BEGIN_ALLOW_THREADS
173 res = (*func)(path, i);
174 Py_END_ALLOW_THREADS
175 if (res < 0)
176 return mac_error();
177 Py_INCREF(Py_None);
178 return Py_None;
181 static PyObject *
182 mac_chdir(self, args)
183 PyObject *self;
184 PyObject *args;
186 #ifdef USE_GUSI
187 PyObject *rv;
189 /* Change MacOS's idea of wd too */
190 rv = mac_1str(args, chdir);
191 PyMac_FixGUSIcd();
192 return rv;
193 #else
194 return mac_1str(args, chdir);
195 #endif
199 static PyObject *
200 mac_close(self, args)
201 PyObject *self;
202 PyObject *args;
204 int fd, res;
205 if (!PyArg_Parse(args, "i", &fd))
206 return NULL;
207 Py_BEGIN_ALLOW_THREADS
208 res = close(fd);
209 Py_END_ALLOW_THREADS
210 #ifndef USE_GUSI
211 /* GUSI gives surious errors here? */
212 if (res < 0)
213 return mac_error();
214 #endif
215 Py_INCREF(Py_None);
216 return Py_None;
219 #ifdef WEHAVE_DUP
221 static PyObject *
222 mac_dup(self, args)
223 PyObject *self;
224 PyObject *args;
226 int fd;
227 if (!PyArg_Parse(args, "i", &fd))
228 return NULL;
229 Py_BEGIN_ALLOW_THREADS
230 fd = dup(fd);
231 Py_END_ALLOW_THREADS
232 if (fd < 0)
233 return mac_error();
234 return PyInt_FromLong((long)fd);
237 #endif
239 #ifdef WEHAVE_FDOPEN
240 static PyObject *
241 mac_fdopen(self, args)
242 PyObject *self;
243 PyObject *args;
245 extern int fclose Py_PROTO((FILE *));
246 int fd;
247 char *mode;
248 FILE *fp;
249 if (!PyArg_Parse(args, "(is)", &fd, &mode))
250 return NULL;
251 Py_BEGIN_ALLOW_THREADS
252 fp = fdopen(fd, mode);
253 Py_END_ALLOW_THREADS
254 if (fp == NULL)
255 return mac_error();
256 return PyFile_FromFile(fp, "(fdopen)", mode, fclose);
258 #endif
260 static PyObject *
261 mac_getbootvol(self, args)
262 PyObject *self;
263 PyObject *args;
265 char *res;
266 if (!PyArg_NoArgs(args))
267 return NULL;
268 Py_BEGIN_ALLOW_THREADS
269 res = getbootvol();
270 Py_END_ALLOW_THREADS
271 if (res == NULL)
272 return mac_error();
273 return PyString_FromString(res);
276 static PyObject *
277 mac_getcwd(self, args)
278 PyObject *self;
279 PyObject *args;
281 char path[MAXPATHLEN];
282 char *res;
283 if (!PyArg_NoArgs(args))
284 return NULL;
285 Py_BEGIN_ALLOW_THREADS
286 #ifdef USE_GUSI
287 res = getcwd(path, sizeof path);
288 #else
289 res = getwd(path);
290 #endif
291 Py_END_ALLOW_THREADS
292 if (res == NULL) {
293 PyErr_SetString(MacError, path);
294 return NULL;
296 return PyString_FromString(res);
299 static PyObject *
300 mac_listdir(self, args)
301 PyObject *self;
302 PyObject *args;
304 char *name;
305 PyObject *d, *v;
306 DIR *dirp;
307 struct dirent *ep;
308 if (!PyArg_Parse(args, "s", &name))
309 return NULL;
310 Py_BEGIN_ALLOW_THREADS
311 if ((dirp = opendir(name)) == NULL) {
312 Py_BLOCK_THREADS
313 return mac_error();
315 if ((d = PyList_New(0)) == NULL) {
316 closedir(dirp);
317 Py_BLOCK_THREADS
318 return NULL;
320 while ((ep = readdir(dirp)) != NULL) {
321 v = PyString_FromString(ep->d_name);
322 if (v == NULL) {
323 Py_DECREF(d);
324 d = NULL;
325 break;
327 if (PyList_Append(d, v) != 0) {
328 Py_DECREF(v);
329 Py_DECREF(d);
330 d = NULL;
331 break;
333 Py_DECREF(v);
335 closedir(dirp);
336 Py_END_ALLOW_THREADS
338 return d;
341 static PyObject *
342 mac_lseek(self, args)
343 PyObject *self;
344 PyObject *args;
346 int fd;
347 int where;
348 int how;
349 long res;
350 if (!PyArg_Parse(args, "(iii)", &fd, &where, &how))
351 return NULL;
352 Py_BEGIN_ALLOW_THREADS
353 res = lseek(fd, (long)where, how);
354 Py_END_ALLOW_THREADS
355 if (res < 0)
356 return mac_error();
357 return PyInt_FromLong(res);
360 static PyObject *
361 mac_mkdir(self, args)
362 PyObject *self;
363 PyObject *args;
365 int res;
366 char *path;
367 int mode = 0777; /* Unused */
368 if (!PyArg_ParseTuple(args, "s|i", &path, &mode))
369 return NULL;
370 Py_BEGIN_ALLOW_THREADS
371 #ifdef USE_GUSI
372 res = mkdir(path);
373 #else
374 res = mkdir(path, mode);
375 #endif
376 Py_END_ALLOW_THREADS
377 if (res < 0)
378 return mac_error();
379 Py_INCREF(Py_None);
380 return Py_None;
383 static PyObject *
384 mac_open(self, args)
385 PyObject *self;
386 PyObject *args;
388 char *path;
389 int mode;
390 int fd;
391 if (!PyArg_Parse(args, "(si)", &path, &mode))
392 return NULL;
393 Py_BEGIN_ALLOW_THREADS
394 fd = open(path, mode);
395 Py_END_ALLOW_THREADS
396 if (fd < 0)
397 return mac_error();
398 return PyInt_FromLong((long)fd);
401 static PyObject *
402 mac_read(self, args)
403 PyObject *self;
404 PyObject *args;
406 int fd, size;
407 PyObject *buffer;
408 if (!PyArg_Parse(args, "(ii)", &fd, &size))
409 return NULL;
410 buffer = PyString_FromStringAndSize((char *)NULL, size);
411 if (buffer == NULL)
412 return NULL;
413 Py_BEGIN_ALLOW_THREADS
414 size = read(fd, PyString_AsString(buffer), size);
415 Py_END_ALLOW_THREADS
416 if (size < 0) {
417 Py_DECREF(buffer);
418 return mac_error();
420 _PyString_Resize(&buffer, size);
421 return buffer;
424 static PyObject *
425 mac_rename(self, args)
426 PyObject *self;
427 PyObject *args;
429 return mac_2str(args, rename);
432 static PyObject *
433 mac_rmdir(self, args)
434 PyObject *self;
435 PyObject *args;
437 return mac_1str(args, rmdir);
440 static PyObject *
441 mac_stat(self, args)
442 PyObject *self;
443 PyObject *args;
445 struct stat st;
446 char *path;
447 int res;
448 if (!PyArg_Parse(args, "s", &path))
449 return NULL;
450 Py_BEGIN_ALLOW_THREADS
451 res = stat(path, &st);
452 Py_END_ALLOW_THREADS
453 if (res != 0)
454 return mac_error();
455 return Py_BuildValue("(lllllllddd)",
456 (long)st.st_mode,
457 (long)st.st_ino,
458 (long)st.st_dev,
459 (long)st.st_nlink,
460 (long)st.st_uid,
461 (long)st.st_gid,
462 (long)st.st_size,
463 (double)st.st_atime,
464 (double)st.st_mtime,
465 (double)st.st_ctime);
468 #ifdef WEHAVE_FSTAT
469 static PyObject *
470 mac_fstat(self, args)
471 PyObject *self;
472 PyObject *args;
474 struct stat st;
475 long fd;
476 int res;
477 if (!PyArg_Parse(args, "l", &fd))
478 return NULL;
479 Py_BEGIN_ALLOW_THREADS
480 res = fstat((int)fd, &st);
481 Py_END_ALLOW_THREADS
482 if (res != 0)
483 return mac_error();
484 return Py_BuildValue("(lllllllddd)",
485 (long)st.st_mode,
486 (long)st.st_ino,
487 (long)st.st_dev,
488 (long)st.st_nlink,
489 (long)st.st_uid,
490 (long)st.st_gid,
491 (long)st.st_size,
492 (double)st.st_atime,
493 (double)st.st_mtime,
494 (double)st.st_ctime);
496 #endif /* WEHAVE_FSTAT */
498 static PyObject *
499 mac_xstat(self, args)
500 PyObject *self;
501 PyObject *args;
503 struct macstat mst;
504 struct stat st;
505 char *path;
506 int res;
507 if (!PyArg_Parse(args, "s", &path))
508 return NULL;
510 ** Convoluted: we want stat() and xstat() to agree, so we call both
511 ** stat and macstat, and use the latter only for values not provided by
512 ** the former.
514 Py_BEGIN_ALLOW_THREADS
515 res = macstat(path, &mst);
516 Py_END_ALLOW_THREADS
517 if (res != 0)
518 return mac_error();
519 Py_BEGIN_ALLOW_THREADS
520 res = stat(path, &st);
521 Py_END_ALLOW_THREADS
522 if (res != 0)
523 return mac_error();
524 return Py_BuildValue("(llllllldddls#s#)",
525 (long)st.st_mode,
526 (long)st.st_ino,
527 (long)st.st_dev,
528 (long)st.st_nlink,
529 (long)st.st_uid,
530 (long)st.st_gid,
531 (long)st.st_size,
532 (double)st.st_atime,
533 (double)st.st_mtime,
534 (double)st.st_ctime,
535 (long)mst.st_rsize,
536 mst.st_creator, 4,
537 mst.st_type, 4);
540 static PyObject *
541 mac_sync(self, args)
542 PyObject *self;
543 PyObject *args;
545 int res;
546 if (!PyArg_NoArgs(args))
547 return NULL;
548 Py_BEGIN_ALLOW_THREADS
549 res = sync();
550 Py_END_ALLOW_THREADS
551 if (res != 0)
552 return mac_error();
553 Py_INCREF(Py_None);
554 return Py_None;
557 static PyObject *
558 mac_unlink(self, args)
559 PyObject *self;
560 PyObject *args;
562 return mac_1str(args, (int (*)(const char *))unlink);
565 static PyObject *
566 mac_write(self, args)
567 PyObject *self;
568 PyObject *args;
570 int fd, size;
571 char *buffer;
572 if (!PyArg_Parse(args, "(is#)", &fd, &buffer, &size))
573 return NULL;
574 Py_BEGIN_ALLOW_THREADS
575 size = write(fd, buffer, size);
576 Py_END_ALLOW_THREADS
577 if (size < 0)
578 return mac_error();
579 return PyInt_FromLong((long)size);
582 #ifdef USE_MALLOC_DEBUG
583 static PyObject *
584 mac_mstats(self, args)
585 PyObject*self;
586 PyObject *args;
588 mstats("python");
589 Py_INCREF(Py_None);
590 return Py_None;
592 #endif /* USE_MALLOC_DEBUG */
594 static struct PyMethodDef mac_methods[] = {
595 {"chdir", mac_chdir},
596 {"close", mac_close},
597 #ifdef WEHAVE_DUP
598 {"dup", mac_dup},
599 #endif
600 #ifdef WEHAVE_FDOPEN
601 {"fdopen", mac_fdopen},
602 #endif
603 #ifdef WEHAVE_FSTAT
604 {"fstat", mac_fstat},
605 #endif
606 {"getbootvol", mac_getbootvol}, /* non-standard */
607 {"getcwd", mac_getcwd},
608 {"listdir", mac_listdir, 0},
609 {"lseek", mac_lseek},
610 {"mkdir", mac_mkdir, 1},
611 {"open", mac_open},
612 {"read", mac_read},
613 {"rename", mac_rename},
614 {"rmdir", mac_rmdir},
615 {"stat", mac_stat},
616 {"xstat", mac_xstat},
617 {"sync", mac_sync},
618 {"remove", mac_unlink},
619 {"unlink", mac_unlink},
620 {"write", mac_write},
621 #ifdef USE_MALLOC_DEBUG
622 {"mstats", mac_mstats},
623 #endif
625 {NULL, NULL} /* Sentinel */
629 void
630 initmac()
632 PyObject *m, *d;
634 m = Py_InitModule("mac", mac_methods);
635 d = PyModule_GetDict(m);
637 /* Initialize mac.error exception */
638 MacError = PyErr_NewException("mac.error", NULL, NULL);
639 PyDict_SetItemString(d, "error", MacError);