1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
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 */
28 #include "structseq.h"
35 #if TARGET_API_MAC_OS8
41 /* Remove defines from macstat.h */
49 #include <sys/types.h>
52 #if TARGET_API_MAC_OS8
69 /* Optional routines, for some compiler/runtime combinations */
70 #if defined(USE_GUSI) || !defined(__MWERKS__)
73 #if defined(MPW) || defined(USE_GUSI)
88 #define MAXPATHLEN 1024
91 /* Prototypes for Unix simulation on Mac */
95 int chdir(const char *path
);
96 int mkdir(const char *path
, int mode
);
97 DIR * opendir(char *);
99 struct dirent
* readdir(DIR *);
100 int rmdir(const char *path
);
103 int unlink(const char *);
105 #endif /* USE_GUSI */
108 char *getbootvol(void);
111 /* Set a MAC-specific error from errno, and return NULL */
116 return PyErr_SetFromErrno(PyExc_OSError
);
119 /* MAC generic methods */
124 int (*func
)(const char *);
128 if (!PyArg_ParseTuple(args
, "s", &path1
))
130 Py_BEGIN_ALLOW_THREADS
131 res
= (*func
)(path1
);
142 int (*func
)(const char *, const char *);
146 if (!PyArg_ParseTuple(args
, "ss", &path1
, &path2
))
148 Py_BEGIN_ALLOW_THREADS
149 res
= (*func
)(path1
, path2
);
158 mac_strint(args
, func
)
160 int (*func
)(const char *, int);
165 if (!PyArg_ParseTuple(args
, "si", &path
, &i
))
167 Py_BEGIN_ALLOW_THREADS
168 res
= (*func
)(path
, i
);
177 mac_chdir(self
, args
)
181 return mac_1str(args
, chdir
);
185 mac_close(self
, args
)
190 if (!PyArg_ParseTuple(args
, "i", &fd
))
192 Py_BEGIN_ALLOW_THREADS
209 if (!PyArg_ParseTuple(args
, "i", &fd
))
211 Py_BEGIN_ALLOW_THREADS
216 return PyInt_FromLong((long)fd
);
223 mac_fdopen(self
, args
)
227 extern int fclose(FILE *);
231 if (!PyArg_ParseTuple(args
, "is", &fd
, &mode
))
233 Py_BEGIN_ALLOW_THREADS
234 fp
= fdopen(fd
, mode
);
238 return PyFile_FromFile(fp
, "(fdopen)", mode
, fclose
);
242 #if TARGET_API_MAC_OS8
244 mac_getbootvol(self
, args
)
249 if (!PyArg_ParseTuple(args
, ""))
251 Py_BEGIN_ALLOW_THREADS
256 return PyString_FromString(res
);
261 mac_getcwd(self
, args
)
265 char path
[MAXPATHLEN
];
267 if (!PyArg_ParseTuple(args
, ""))
269 Py_BEGIN_ALLOW_THREADS
271 res
= getcwd(path
, sizeof path
);
279 return PyString_FromString(res
);
283 mac_listdir(self
, args
)
291 if (!PyArg_ParseTuple(args
, "s", &name
))
294 /* Work around a bug in GUSI: if you opendir() a file it will
295 ** actually opendir() the parent directory.
301 res
= stat(name
, &stb
);
304 if (!S_ISDIR(stb
.st_mode
) ) {
311 Py_BEGIN_ALLOW_THREADS
312 if ((dirp
= opendir(name
)) == NULL
) {
316 if ((d
= PyList_New(0)) == NULL
) {
321 while ((ep
= readdir(dirp
)) != NULL
) {
322 v
= PyString_FromString(ep
->d_name
);
328 if (PyList_Append(d
, v
) != 0) {
343 mac_lseek(self
, args
)
351 if (!PyArg_ParseTuple(args
, "iii", &fd
, &where
, &how
))
353 Py_BEGIN_ALLOW_THREADS
354 res
= lseek(fd
, (long)where
, how
);
358 return PyInt_FromLong(res
);
362 mac_mkdir(self
, args
)
368 int mode
= 0777; /* Unused */
369 if (!PyArg_ParseTuple(args
, "s|i", &path
, &mode
))
371 Py_BEGIN_ALLOW_THREADS
372 res
= mkdir(path
, mode
);
387 int perm
; /* Accepted but ignored */
389 if (!PyArg_ParseTuple(args
, "si|i", &path
, &mode
, &perm
))
391 Py_BEGIN_ALLOW_THREADS
392 fd
= open(path
, mode
);
396 return PyInt_FromLong((long)fd
);
406 if (!PyArg_ParseTuple(args
, "ii", &fd
, &size
))
408 buffer
= PyString_FromStringAndSize((char *)NULL
, size
);
411 Py_BEGIN_ALLOW_THREADS
412 size
= read(fd
, PyString_AsString(buffer
), size
);
418 _PyString_Resize(&buffer
, size
);
423 mac_rename(self
, args
)
427 return mac_2str(args
, rename
);
431 mac_rmdir(self
, args
)
435 return mac_1str(args
, rmdir
);
438 static char stat_result__doc__
[] =
439 "stat_result: Result from stat or lstat.\n\n\
440 This object may be accessed either as a tuple of\n\
441 (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
442 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
444 See os.stat for more information.\n";
446 #define COMMON_STAT_RESULT_FIELDS \
447 { "st_mode", "protection bits" }, \
448 { "st_ino", "inode" }, \
449 { "st_dev", "device" }, \
450 { "st_nlink", "number of hard links" }, \
451 { "st_uid", "user ID of owner" }, \
452 { "st_gid", "group ID of owner" }, \
453 { "st_size", "total size, in bytes" }, \
454 { "st_atime", "time of last access" }, \
455 { "st_mtime", "time of last modification" }, \
456 { "st_ctime", "time of last change" },
460 static PyStructSequence_Field stat_result_fields
[] = {
461 COMMON_STAT_RESULT_FIELDS
465 static PyStructSequence_Desc stat_result_desc
= {
472 static PyTypeObject StatResultType
;
474 #ifdef TARGET_API_MAC_OS8
475 static PyStructSequence_Field xstat_result_fields
[] = {
476 COMMON_STAT_RESULT_FIELDS
483 static PyStructSequence_Desc xstat_result_desc
= {
490 static PyTypeObject XStatResultType
;
494 _pystat_from_struct_stat(struct stat st
, void* _mst
)
498 #if TARGET_API_MAC_OS8
502 v
= PyStructSequence_New(&XStatResultType
);
505 v
= PyStructSequence_New(&StatResultType
);
506 PyStructSequence_SET_ITEM(v
, 0, PyInt_FromLong((long)st
.st_mode
));
507 PyStructSequence_SET_ITEM(v
, 1, PyInt_FromLong((long)st
.st_ino
));
508 PyStructSequence_SET_ITEM(v
, 2, PyInt_FromLong((long)st
.st_dev
));
509 PyStructSequence_SET_ITEM(v
, 3, PyInt_FromLong((long)st
.st_nlink
));
510 PyStructSequence_SET_ITEM(v
, 4, PyInt_FromLong((long)st
.st_uid
));
511 PyStructSequence_SET_ITEM(v
, 5, PyInt_FromLong((long)st
.st_gid
));
512 PyStructSequence_SET_ITEM(v
, 6, PyInt_FromLong((long)st
.st_size
));
513 PyStructSequence_SET_ITEM(v
, 7,
514 PyFloat_FromDouble((double)st
.st_atime
));
515 PyStructSequence_SET_ITEM(v
, 8,
516 PyFloat_FromDouble((double)st
.st_mtime
));
517 PyStructSequence_SET_ITEM(v
, 9,
518 PyFloat_FromDouble((double)st
.st_ctime
));
519 #if TARGET_API_MAC_OS8
521 mst
= (struct macstat
*) _mst
;
522 PyStructSequence_SET_ITEM(v
, 10,
523 PyInt_FromLong((long)mst
->st_rsize
));
524 PyStructSequence_SET_ITEM(v
, 11,
525 PyString_FromStringAndSize(mst
->st_creator
,
527 PyStructSequence_SET_ITEM(v
, 12,
528 PyString_FromStringAndSize(mst
->st_type
,
533 if (PyErr_Occurred()) {
550 if (!PyArg_ParseTuple(args
, "s", &path
))
552 Py_BEGIN_ALLOW_THREADS
553 res
= stat(path
, &st
);
558 return _pystat_from_struct_stat(st
, NULL
);
563 mac_fstat(self
, args
)
570 if (!PyArg_ParseTuple(args
, "l", &fd
))
572 Py_BEGIN_ALLOW_THREADS
573 res
= fstat((int)fd
, &st
);
578 return _pystat_from_struct_stat(st
, NULL
);
580 #endif /* WEHAVE_FSTAT */
582 #if TARGET_API_MAC_OS8
584 mac_xstat(self
, args
)
592 if (!PyArg_ParseTuple(args
, "s", &path
))
595 ** Convoluted: we want stat() and xstat() to agree, so we call both
596 ** stat and macstat, and use the latter only for values not provided by
599 Py_BEGIN_ALLOW_THREADS
600 res
= macstat(path
, &mst
);
604 Py_BEGIN_ALLOW_THREADS
605 res
= stat(path
, &st
);
610 return _pystat_from_struct_stat(st
, (void*) &mst
);
620 if (!PyArg_ParseTuple(args
, ""))
622 Py_BEGIN_ALLOW_THREADS
637 mac_unlink(self
, args
)
641 return mac_1str(args
, (int (*)(const char *))unlink
);
645 mac_write(self
, args
)
651 if (!PyArg_ParseTuple(args
, "is#", &fd
, &buffer
, &size
))
653 Py_BEGIN_ALLOW_THREADS
654 size
= write(fd
, buffer
, size
);
658 return PyInt_FromLong((long)size
);
661 #ifdef USE_MALLOC_DEBUG
662 void *mstats(char *);
665 mac_mstats(self
, args
)
673 #endif /* USE_MALLOC_DEBUG */
675 static struct PyMethodDef mac_methods
[] = {
676 {"chdir", mac_chdir
, 1},
677 {"close", mac_close
, 1},
682 {"fdopen", mac_fdopen
, 1},
685 {"fstat", mac_fstat
, 1},
687 #if TARGET_API_MAC_OS8
688 {"getbootvol", mac_getbootvol
, 1}, /* non-standard */
690 {"getcwd", mac_getcwd
, 1},
691 {"listdir", mac_listdir
, 1},
692 {"lseek", mac_lseek
, 1},
693 {"mkdir", mac_mkdir
, 1},
694 {"open", mac_open
, 1},
695 {"read", mac_read
, 1},
696 {"rename", mac_rename
, 1},
697 {"rmdir", mac_rmdir
, 1},
698 {"stat", mac_stat
, 1},
699 #if TARGET_API_MAC_OS8
700 {"xstat", mac_xstat
, 1},
702 {"sync", mac_sync
, 1},
703 {"remove", mac_unlink
, 1},
704 {"unlink", mac_unlink
, 1},
705 {"write", mac_write
, 1},
706 #ifdef USE_MALLOC_DEBUG
707 {"mstats", mac_mstats
, 1},
710 {NULL
, NULL
} /* Sentinel */
714 ins(PyObject
*d
, char *symbol
, long value
)
716 PyObject
* v
= PyInt_FromLong(value
);
717 if (!v
|| PyDict_SetItemString(d
, symbol
, v
) < 0)
718 return -1; /* triggers fatal error */
728 if (ins(d
, "F_OK", (long)F_OK
)) return -1;
731 if (ins(d
, "R_OK", (long)R_OK
)) return -1;
734 if (ins(d
, "W_OK", (long)W_OK
)) return -1;
737 if (ins(d
, "X_OK", (long)X_OK
)) return -1;
740 if (ins(d
, "NGROUPS_MAX", (long)NGROUPS_MAX
)) return -1;
743 if (ins(d
, "TMP_MAX", (long)TMP_MAX
)) return -1;
746 if (ins(d
, "WNOHANG", (long)WNOHANG
)) return -1;
749 if (ins(d
, "O_RDONLY", (long)O_RDONLY
)) return -1;
752 if (ins(d
, "O_WRONLY", (long)O_WRONLY
)) return -1;
755 if (ins(d
, "O_RDWR", (long)O_RDWR
)) return -1;
758 if (ins(d
, "O_NDELAY", (long)O_NDELAY
)) return -1;
761 if (ins(d
, "O_NONBLOCK", (long)O_NONBLOCK
)) return -1;
764 if (ins(d
, "O_APPEND", (long)O_APPEND
)) return -1;
767 if (ins(d
, "O_DSYNC", (long)O_DSYNC
)) return -1;
770 if (ins(d
, "O_RSYNC", (long)O_RSYNC
)) return -1;
773 if (ins(d
, "O_SYNC", (long)O_SYNC
)) return -1;
776 if (ins(d
, "O_NOCTTY", (long)O_NOCTTY
)) return -1;
779 if (ins(d
, "O_CREAT", (long)O_CREAT
)) return -1;
782 if (ins(d
, "O_EXCL", (long)O_EXCL
)) return -1;
785 if (ins(d
, "O_TRUNC", (long)O_TRUNC
)) return -1;
788 if (ins(d
, "O_BINARY", (long)O_BINARY
)) return -1;
791 if (ins(d
, "O_TEXT", (long)O_TEXT
)) return -1;
795 if (ins(d
, "P_WAIT", (long)_P_WAIT
)) return -1;
796 if (ins(d
, "P_NOWAIT", (long)_P_NOWAIT
)) return -1;
797 if (ins(d
, "P_OVERLAY", (long)_OLD_P_OVERLAY
)) return -1;
798 if (ins(d
, "P_NOWAITO", (long)_P_NOWAITO
)) return -1;
799 if (ins(d
, "P_DETACH", (long)_P_DETACH
)) return -1;
802 #if defined(PYOS_OS2)
803 if (insertvalues(d
)) return -1;
814 m
= Py_InitModule("mac", mac_methods
);
815 d
= PyModule_GetDict(m
);
820 /* Initialize mac.error exception */
821 PyDict_SetItemString(d
, "error", PyExc_OSError
);
823 PyStructSequence_InitType(&StatResultType
, &stat_result_desc
);
824 PyDict_SetItemString(d
, "stat_result", (PyObject
*) &StatResultType
);
826 #if TARGET_API_MAC_OS8
827 PyStructSequence_InitType(&XStatResultType
, &xstat_result_desc
);
828 PyDict_SetItemString(d
, "xstat_result", (PyObject
*) &XStatResultType
);