Bump version to 0.9.1.
[python/dscho.git] / Mac / Modules / macmodule.c
blobd553f30c3825956080b424609d9acf40d2921840
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 #if !TARGET_API_MAC_CARBON_NOTYET
35 /* XXXX Skip for Carbon, for now */
36 #include "macstat.h"
37 #endif
39 #ifdef USE_GUSI
40 /* Remove defines from macstat.h */
41 #undef S_IFMT
42 #undef S_IFDIR
43 #undef S_IFREG
44 #undef S_IREAD
45 #undef S_IWRITE
46 #undef S_IEXEC
48 #ifdef USE_GUSI1
49 #include <GUSI.h>
50 #endif /* USE_GUSI1 */
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #else /* USE_GUSI */
54 #if !TARGET_API_MAC_CARBON_NOTYET
55 #define stat macstat
56 #endif
57 #endif /* USE_GUSI */
59 #ifdef USE_GUSI2
60 #define sync bad_sync
61 #include <unistd.h>
62 #include <fcntl.h>
63 #undef sync
64 int sync(void);
65 #else
66 #define mode_t int
67 #include <fcntl.h>
68 #ifdef _POSIX
69 #include <unistd.h>
70 #include <stat.h>
71 #endif
72 #endif
74 /* Optional routines, for some compiler/runtime combinations */
75 #if defined(USE_GUSI) || !defined(__MWERKS__)
76 #define WEHAVE_FDOPEN
77 #endif
78 #if defined(MPW) || defined(USE_GUSI)
79 #define WEHAVE_DUP
80 #endif
81 #if defined(USE_GUSI)
82 #define WEHAVE_FSTAT
83 #endif
85 #include "macdefs.h"
86 #ifdef USE_GUSI
87 #include <dirent.h>
88 #else
89 #include "dirent.h"
90 #endif
92 #ifndef MAXPATHLEN
93 #define MAXPATHLEN 1024
94 #endif
96 /* Prototypes for Unix simulation on Mac */
98 #ifndef USE_GUSI
100 int chdir(const char *path);
101 int mkdir(const char *path, int mode);
102 DIR * opendir(char *);
103 void closedir(DIR *);
104 struct dirent * readdir(DIR *);
105 int rmdir(const char *path);
106 int sync(void);
108 int unlink(const char *);
110 #endif /* USE_GUSI */
112 char *getwd(char *);
113 char *getbootvol(void);
116 static PyObject *MacError; /* Exception mac.error */
118 /* Set a MAC-specific error from errno, and return NULL */
120 static PyObject *
121 mac_error()
123 return PyErr_SetFromErrno(MacError);
126 /* MAC generic methods */
128 static PyObject *
129 mac_1str(args, func)
130 PyObject *args;
131 int (*func)(const char *);
133 char *path1;
134 int res;
135 if (!PyArg_Parse(args, "s", &path1))
136 return NULL;
137 Py_BEGIN_ALLOW_THREADS
138 res = (*func)(path1);
139 Py_END_ALLOW_THREADS
140 if (res < 0)
141 return mac_error();
142 Py_INCREF(Py_None);
143 return Py_None;
146 static PyObject *
147 mac_2str(args, func)
148 PyObject *args;
149 int (*func)(const char *, const char *);
151 char *path1, *path2;
152 int res;
153 if (!PyArg_Parse(args, "(ss)", &path1, &path2))
154 return NULL;
155 Py_BEGIN_ALLOW_THREADS
156 res = (*func)(path1, path2);
157 Py_END_ALLOW_THREADS
158 if (res < 0)
159 return mac_error();
160 Py_INCREF(Py_None);
161 return Py_None;
164 static PyObject *
165 mac_strint(args, func)
166 PyObject *args;
167 int (*func)(const char *, int);
169 char *path;
170 int i;
171 int res;
172 if (!PyArg_Parse(args, "(si)", &path, &i))
173 return NULL;
174 Py_BEGIN_ALLOW_THREADS
175 res = (*func)(path, i);
176 Py_END_ALLOW_THREADS
177 if (res < 0)
178 return mac_error();
179 Py_INCREF(Py_None);
180 return Py_None;
183 static PyObject *
184 mac_chdir(self, args)
185 PyObject *self;
186 PyObject *args;
188 #ifdef USE_GUSI1
189 PyObject *rv;
191 /* Change MacOS's idea of wd too */
192 rv = mac_1str(args, chdir);
193 PyMac_FixGUSIcd();
194 return rv;
195 #else
196 return mac_1str(args, chdir);
197 #endif
201 static PyObject *
202 mac_close(self, args)
203 PyObject *self;
204 PyObject *args;
206 int fd, res;
207 if (!PyArg_Parse(args, "i", &fd))
208 return NULL;
209 Py_BEGIN_ALLOW_THREADS
210 res = close(fd);
211 Py_END_ALLOW_THREADS
212 #ifndef USE_GUSI1
213 /* GUSI gives surious errors here? */
214 if (res < 0)
215 return mac_error();
216 #endif
217 Py_INCREF(Py_None);
218 return Py_None;
221 #ifdef WEHAVE_DUP
223 static PyObject *
224 mac_dup(self, args)
225 PyObject *self;
226 PyObject *args;
228 int fd;
229 if (!PyArg_Parse(args, "i", &fd))
230 return NULL;
231 Py_BEGIN_ALLOW_THREADS
232 fd = dup(fd);
233 Py_END_ALLOW_THREADS
234 if (fd < 0)
235 return mac_error();
236 return PyInt_FromLong((long)fd);
239 #endif
241 #ifdef WEHAVE_FDOPEN
242 static PyObject *
243 mac_fdopen(self, args)
244 PyObject *self;
245 PyObject *args;
247 extern int fclose(FILE *);
248 int fd;
249 char *mode;
250 FILE *fp;
251 if (!PyArg_Parse(args, "(is)", &fd, &mode))
252 return NULL;
253 Py_BEGIN_ALLOW_THREADS
254 fp = fdopen(fd, mode);
255 Py_END_ALLOW_THREADS
256 if (fp == NULL)
257 return mac_error();
258 return PyFile_FromFile(fp, "(fdopen)", mode, fclose);
260 #endif
262 #if !TARGET_API_MAC_CARBON
263 static PyObject *
264 mac_getbootvol(self, args)
265 PyObject *self;
266 PyObject *args;
268 char *res;
269 if (!PyArg_NoArgs(args))
270 return NULL;
271 Py_BEGIN_ALLOW_THREADS
272 res = getbootvol();
273 Py_END_ALLOW_THREADS
274 if (res == NULL)
275 return mac_error();
276 return PyString_FromString(res);
278 #endif
280 static PyObject *
281 mac_getcwd(self, args)
282 PyObject *self;
283 PyObject *args;
285 char path[MAXPATHLEN];
286 char *res;
287 if (!PyArg_NoArgs(args))
288 return NULL;
289 Py_BEGIN_ALLOW_THREADS
290 #ifdef USE_GUSI
291 res = getcwd(path, sizeof path);
292 #else
293 res = getwd(path);
294 #endif
295 Py_END_ALLOW_THREADS
296 if (res == NULL) {
297 PyErr_SetString(MacError, path);
298 return NULL;
300 return PyString_FromString(res);
303 static PyObject *
304 mac_listdir(self, args)
305 PyObject *self;
306 PyObject *args;
308 char *name;
309 PyObject *d, *v;
310 DIR *dirp;
311 struct dirent *ep;
312 if (!PyArg_Parse(args, "s", &name))
313 return NULL;
314 Py_BEGIN_ALLOW_THREADS
315 if ((dirp = opendir(name)) == NULL) {
316 Py_BLOCK_THREADS
317 return mac_error();
319 if ((d = PyList_New(0)) == NULL) {
320 closedir(dirp);
321 Py_BLOCK_THREADS
322 return NULL;
324 while ((ep = readdir(dirp)) != NULL) {
325 v = PyString_FromString(ep->d_name);
326 if (v == NULL) {
327 Py_DECREF(d);
328 d = NULL;
329 break;
331 if (PyList_Append(d, v) != 0) {
332 Py_DECREF(v);
333 Py_DECREF(d);
334 d = NULL;
335 break;
337 Py_DECREF(v);
339 closedir(dirp);
340 Py_END_ALLOW_THREADS
342 return d;
345 static PyObject *
346 mac_lseek(self, args)
347 PyObject *self;
348 PyObject *args;
350 int fd;
351 int where;
352 int how;
353 long res;
354 if (!PyArg_Parse(args, "(iii)", &fd, &where, &how))
355 return NULL;
356 Py_BEGIN_ALLOW_THREADS
357 res = lseek(fd, (long)where, how);
358 Py_END_ALLOW_THREADS
359 if (res < 0)
360 return mac_error();
361 return PyInt_FromLong(res);
364 static PyObject *
365 mac_mkdir(self, args)
366 PyObject *self;
367 PyObject *args;
369 int res;
370 char *path;
371 int mode = 0777; /* Unused */
372 if (!PyArg_ParseTuple(args, "s|i", &path, &mode))
373 return NULL;
374 Py_BEGIN_ALLOW_THREADS
375 #ifdef USE_GUSI1
376 res = mkdir(path);
377 #else
378 res = mkdir(path, mode);
379 #endif
380 Py_END_ALLOW_THREADS
381 if (res < 0)
382 return mac_error();
383 Py_INCREF(Py_None);
384 return Py_None;
387 static PyObject *
388 mac_open(self, args)
389 PyObject *self;
390 PyObject *args;
392 char *path;
393 int mode;
394 int fd;
395 if (!PyArg_Parse(args, "(si)", &path, &mode))
396 return NULL;
397 Py_BEGIN_ALLOW_THREADS
398 fd = open(path, mode);
399 Py_END_ALLOW_THREADS
400 if (fd < 0)
401 return mac_error();
402 return PyInt_FromLong((long)fd);
405 static PyObject *
406 mac_read(self, args)
407 PyObject *self;
408 PyObject *args;
410 int fd, size;
411 PyObject *buffer;
412 if (!PyArg_Parse(args, "(ii)", &fd, &size))
413 return NULL;
414 buffer = PyString_FromStringAndSize((char *)NULL, size);
415 if (buffer == NULL)
416 return NULL;
417 Py_BEGIN_ALLOW_THREADS
418 size = read(fd, PyString_AsString(buffer), size);
419 Py_END_ALLOW_THREADS
420 if (size < 0) {
421 Py_DECREF(buffer);
422 return mac_error();
424 _PyString_Resize(&buffer, size);
425 return buffer;
428 static PyObject *
429 mac_rename(self, args)
430 PyObject *self;
431 PyObject *args;
433 return mac_2str(args, rename);
436 static PyObject *
437 mac_rmdir(self, args)
438 PyObject *self;
439 PyObject *args;
441 return mac_1str(args, rmdir);
444 static PyObject *
445 mac_stat(self, args)
446 PyObject *self;
447 PyObject *args;
449 struct stat st;
450 char *path;
451 int res;
452 if (!PyArg_Parse(args, "s", &path))
453 return NULL;
454 Py_BEGIN_ALLOW_THREADS
455 res = stat(path, &st);
456 Py_END_ALLOW_THREADS
457 if (res != 0)
458 return mac_error();
459 return Py_BuildValue("(lllllllddd)",
460 (long)st.st_mode,
461 (long)st.st_ino,
462 (long)st.st_dev,
463 (long)st.st_nlink,
464 (long)st.st_uid,
465 (long)st.st_gid,
466 (long)st.st_size,
467 (double)st.st_atime,
468 (double)st.st_mtime,
469 (double)st.st_ctime);
472 #ifdef WEHAVE_FSTAT
473 static PyObject *
474 mac_fstat(self, args)
475 PyObject *self;
476 PyObject *args;
478 struct stat st;
479 long fd;
480 int res;
481 if (!PyArg_Parse(args, "l", &fd))
482 return NULL;
483 Py_BEGIN_ALLOW_THREADS
484 res = fstat((int)fd, &st);
485 Py_END_ALLOW_THREADS
486 if (res != 0)
487 return mac_error();
488 return Py_BuildValue("(lllllllddd)",
489 (long)st.st_mode,
490 (long)st.st_ino,
491 (long)st.st_dev,
492 (long)st.st_nlink,
493 (long)st.st_uid,
494 (long)st.st_gid,
495 (long)st.st_size,
496 (double)st.st_atime,
497 (double)st.st_mtime,
498 (double)st.st_ctime);
500 #endif /* WEHAVE_FSTAT */
502 #if !TARGET_API_MAC_CARBON_NOTYET
503 static PyObject *
504 mac_xstat(self, args)
505 PyObject *self;
506 PyObject *args;
508 struct macstat mst;
509 struct stat st;
510 char *path;
511 int res;
512 if (!PyArg_Parse(args, "s", &path))
513 return NULL;
515 ** Convoluted: we want stat() and xstat() to agree, so we call both
516 ** stat and macstat, and use the latter only for values not provided by
517 ** the former.
519 Py_BEGIN_ALLOW_THREADS
520 res = macstat(path, &mst);
521 Py_END_ALLOW_THREADS
522 if (res != 0)
523 return mac_error();
524 Py_BEGIN_ALLOW_THREADS
525 res = stat(path, &st);
526 Py_END_ALLOW_THREADS
527 if (res != 0)
528 return mac_error();
529 return Py_BuildValue("(llllllldddls#s#)",
530 (long)st.st_mode,
531 (long)st.st_ino,
532 (long)st.st_dev,
533 (long)st.st_nlink,
534 (long)st.st_uid,
535 (long)st.st_gid,
536 (long)st.st_size,
537 (double)st.st_atime,
538 (double)st.st_mtime,
539 (double)st.st_ctime,
540 (long)mst.st_rsize,
541 mst.st_creator, 4,
542 mst.st_type, 4);
544 #endif
546 static PyObject *
547 mac_sync(self, args)
548 PyObject *self;
549 PyObject *args;
551 int res;
552 if (!PyArg_NoArgs(args))
553 return NULL;
554 Py_BEGIN_ALLOW_THREADS
555 res = sync();
556 Py_END_ALLOW_THREADS
557 if (res != 0)
558 return mac_error();
559 Py_INCREF(Py_None);
560 return Py_None;
563 static PyObject *
564 mac_unlink(self, args)
565 PyObject *self;
566 PyObject *args;
568 return mac_1str(args, (int (*)(const char *))unlink);
571 static PyObject *
572 mac_write(self, args)
573 PyObject *self;
574 PyObject *args;
576 int fd, size;
577 char *buffer;
578 if (!PyArg_Parse(args, "(is#)", &fd, &buffer, &size))
579 return NULL;
580 Py_BEGIN_ALLOW_THREADS
581 size = write(fd, buffer, size);
582 Py_END_ALLOW_THREADS
583 if (size < 0)
584 return mac_error();
585 return PyInt_FromLong((long)size);
588 #ifdef USE_MALLOC_DEBUG
589 static PyObject *
590 mac_mstats(self, args)
591 PyObject*self;
592 PyObject *args;
594 mstats("python");
595 Py_INCREF(Py_None);
596 return Py_None;
598 #endif /* USE_MALLOC_DEBUG */
600 static struct PyMethodDef mac_methods[] = {
601 {"chdir", mac_chdir},
602 {"close", mac_close},
603 #ifdef WEHAVE_DUP
604 {"dup", mac_dup},
605 #endif
606 #ifdef WEHAVE_FDOPEN
607 {"fdopen", mac_fdopen},
608 #endif
609 #ifdef WEHAVE_FSTAT
610 {"fstat", mac_fstat},
611 #endif
612 #if !TARGET_API_MAC_CARBON
613 {"getbootvol", mac_getbootvol}, /* non-standard */
614 #endif
615 {"getcwd", mac_getcwd},
616 {"listdir", mac_listdir, 0},
617 {"lseek", mac_lseek},
618 {"mkdir", mac_mkdir, 1},
619 {"open", mac_open},
620 {"read", mac_read},
621 {"rename", mac_rename},
622 {"rmdir", mac_rmdir},
623 {"stat", mac_stat},
624 #if !TARGET_API_MAC_CARBON_NOTYET
625 {"xstat", mac_xstat},
626 #endif
627 {"sync", mac_sync},
628 {"remove", mac_unlink},
629 {"unlink", mac_unlink},
630 {"write", mac_write},
631 #ifdef USE_MALLOC_DEBUG
632 {"mstats", mac_mstats},
633 #endif
635 {NULL, NULL} /* Sentinel */
639 void
640 initmac()
642 PyObject *m, *d;
644 m = Py_InitModule("mac", mac_methods);
645 d = PyModule_GetDict(m);
647 /* Initialize mac.error exception */
648 MacError = PyErr_NewException("mac.error", NULL, NULL);
649 PyDict_SetItemString(d, "error", MacError);