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 */
51 #endif /* USE_GUSI1 */
52 #include <sys/types.h>
55 #if TARGET_API_MAC_OS8
75 /* Optional routines, for some compiler/runtime combinations */
76 #if defined(USE_GUSI) || !defined(__MWERKS__)
79 #if defined(MPW) || defined(USE_GUSI)
94 #define MAXPATHLEN 1024
97 /* Prototypes for Unix simulation on Mac */
101 int chdir(const char *path
);
102 int mkdir(const char *path
, int mode
);
103 DIR * opendir(char *);
104 void closedir(DIR *);
105 struct dirent
* readdir(DIR *);
106 int rmdir(const char *path
);
109 int unlink(const char *);
111 #endif /* USE_GUSI */
114 char *getbootvol(void);
117 /* Set a MAC-specific error from errno, and return NULL */
122 return PyErr_SetFromErrno(PyExc_OSError
);
125 /* MAC generic methods */
130 int (*func
)(const char *);
134 if (!PyArg_ParseTuple(args
, "s", &path1
))
136 Py_BEGIN_ALLOW_THREADS
137 res
= (*func
)(path1
);
148 int (*func
)(const char *, const char *);
152 if (!PyArg_ParseTuple(args
, "ss", &path1
, &path2
))
154 Py_BEGIN_ALLOW_THREADS
155 res
= (*func
)(path1
, path2
);
164 mac_strint(args
, func
)
166 int (*func
)(const char *, int);
171 if (!PyArg_ParseTuple(args
, "si", &path
, &i
))
173 Py_BEGIN_ALLOW_THREADS
174 res
= (*func
)(path
, i
);
183 mac_chdir(self
, args
)
190 /* Change MacOS's idea of wd too */
191 rv
= mac_1str(args
, chdir
);
195 return mac_1str(args
, chdir
);
201 mac_close(self
, args
)
206 if (!PyArg_ParseTuple(args
, "i", &fd
))
208 Py_BEGIN_ALLOW_THREADS
212 /* GUSI gives surious errors here? */
228 if (!PyArg_ParseTuple(args
, "i", &fd
))
230 Py_BEGIN_ALLOW_THREADS
235 return PyInt_FromLong((long)fd
);
242 mac_fdopen(self
, args
)
246 extern int fclose(FILE *);
250 if (!PyArg_ParseTuple(args
, "is", &fd
, &mode
))
252 Py_BEGIN_ALLOW_THREADS
253 fp
= fdopen(fd
, mode
);
257 return PyFile_FromFile(fp
, "(fdopen)", mode
, fclose
);
261 #if TARGET_API_MAC_OS8
263 mac_getbootvol(self
, args
)
268 if (!PyArg_ParseTuple(args
, ""))
270 Py_BEGIN_ALLOW_THREADS
275 return PyString_FromString(res
);
280 mac_getcwd(self
, args
)
284 char path
[MAXPATHLEN
];
286 if (!PyArg_ParseTuple(args
, ""))
288 Py_BEGIN_ALLOW_THREADS
290 res
= getcwd(path
, sizeof path
);
298 return PyString_FromString(res
);
302 mac_listdir(self
, args
)
310 if (!PyArg_ParseTuple(args
, "s", &name
))
313 /* Work around a bug in GUSI: if you opendir() a file it will
314 ** actually opendir() the parent directory.
320 res
= stat(name
, &stb
);
323 if (!S_ISDIR(stb
.st_mode
) ) {
330 Py_BEGIN_ALLOW_THREADS
331 if ((dirp
= opendir(name
)) == NULL
) {
335 if ((d
= PyList_New(0)) == NULL
) {
340 while ((ep
= readdir(dirp
)) != NULL
) {
341 v
= PyString_FromString(ep
->d_name
);
347 if (PyList_Append(d
, v
) != 0) {
362 mac_lseek(self
, args
)
370 if (!PyArg_ParseTuple(args
, "iii", &fd
, &where
, &how
))
372 Py_BEGIN_ALLOW_THREADS
373 res
= lseek(fd
, (long)where
, how
);
377 return PyInt_FromLong(res
);
381 mac_mkdir(self
, args
)
387 int mode
= 0777; /* Unused */
388 if (!PyArg_ParseTuple(args
, "s|i", &path
, &mode
))
390 Py_BEGIN_ALLOW_THREADS
394 res
= mkdir(path
, mode
);
410 int perm
; /* Accepted but ignored */
412 if (!PyArg_ParseTuple(args
, "si|i", &path
, &mode
, &perm
))
414 Py_BEGIN_ALLOW_THREADS
415 fd
= open(path
, mode
);
419 return PyInt_FromLong((long)fd
);
429 if (!PyArg_ParseTuple(args
, "ii", &fd
, &size
))
431 buffer
= PyString_FromStringAndSize((char *)NULL
, size
);
434 Py_BEGIN_ALLOW_THREADS
435 size
= read(fd
, PyString_AsString(buffer
), size
);
441 _PyString_Resize(&buffer
, size
);
446 mac_rename(self
, args
)
450 return mac_2str(args
, rename
);
454 mac_rmdir(self
, args
)
458 return mac_1str(args
, rmdir
);
461 static char stat_result__doc__
[] =
462 "stat_result: Result from stat or lstat.\n\n\
463 This object may be accessed either as a tuple of\n\
464 (mode,ino,dev,nlink,uid,gid,size,atime,mtime,ctime)\n\
465 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
467 See os.stat for more information.\n";
469 #define COMMON_STAT_RESULT_FIELDS \
470 { "st_mode", "protection bits" }, \
471 { "st_ino", "inode" }, \
472 { "st_dev", "device" }, \
473 { "st_nlink", "number of hard links" }, \
474 { "st_uid", "user ID of owner" }, \
475 { "st_gid", "group ID of owner" }, \
476 { "st_size", "total size, in bytes" }, \
477 { "st_atime", "time of last access" }, \
478 { "st_mtime", "time of last modification" }, \
479 { "st_ctime", "time of last change" },
483 static PyStructSequence_Field stat_result_fields
[] = {
484 COMMON_STAT_RESULT_FIELDS
488 static PyStructSequence_Desc stat_result_desc
= {
495 static PyTypeObject StatResultType
;
497 #ifdef TARGET_API_MAC_OS8
498 static PyStructSequence_Field xstat_result_fields
[] = {
499 COMMON_STAT_RESULT_FIELDS
506 static PyStructSequence_Desc xstat_result_desc
= {
513 static PyTypeObject XStatResultType
;
517 _pystat_from_struct_stat(struct stat st
, void* _mst
)
521 #if TARGET_API_MAC_OS8
525 v
= PyStructSequence_New(&XStatResultType
);
528 v
= PyStructSequence_New(&StatResultType
);
529 PyStructSequence_SET_ITEM(v
, 0, PyInt_FromLong((long)st
.st_mode
));
530 PyStructSequence_SET_ITEM(v
, 1, PyInt_FromLong((long)st
.st_ino
));
531 PyStructSequence_SET_ITEM(v
, 2, PyInt_FromLong((long)st
.st_dev
));
532 PyStructSequence_SET_ITEM(v
, 3, PyInt_FromLong((long)st
.st_nlink
));
533 PyStructSequence_SET_ITEM(v
, 4, PyInt_FromLong((long)st
.st_uid
));
534 PyStructSequence_SET_ITEM(v
, 5, PyInt_FromLong((long)st
.st_gid
));
535 PyStructSequence_SET_ITEM(v
, 6, PyInt_FromLong((long)st
.st_size
));
536 PyStructSequence_SET_ITEM(v
, 7,
537 PyFloat_FromDouble((double)st
.st_atime
));
538 PyStructSequence_SET_ITEM(v
, 8,
539 PyFloat_FromDouble((double)st
.st_mtime
));
540 PyStructSequence_SET_ITEM(v
, 9,
541 PyFloat_FromDouble((double)st
.st_ctime
));
542 #if TARGET_API_MAC_OS8
544 mst
= (struct macstat
*) _mst
;
545 PyStructSequence_SET_ITEM(v
, 10,
546 PyInt_FromLong((long)mst
->st_rsize
));
547 PyStructSequence_SET_ITEM(v
, 11,
548 PyString_FromStringAndSize(mst
->st_creator
,
550 PyStructSequence_SET_ITEM(v
, 12,
551 PyString_FromStringAndSize(mst
->st_type
,
556 if (PyErr_Occurred()) {
573 if (!PyArg_ParseTuple(args
, "s", &path
))
575 Py_BEGIN_ALLOW_THREADS
576 res
= stat(path
, &st
);
581 return _pystat_from_struct_stat(st
, NULL
);
586 mac_fstat(self
, args
)
593 if (!PyArg_ParseTuple(args
, "l", &fd
))
595 Py_BEGIN_ALLOW_THREADS
596 res
= fstat((int)fd
, &st
);
601 return _pystat_from_struct_stat(st
, NULL
);
603 #endif /* WEHAVE_FSTAT */
605 #if TARGET_API_MAC_OS8
607 mac_xstat(self
, args
)
615 if (!PyArg_ParseTuple(args
, "s", &path
))
618 ** Convoluted: we want stat() and xstat() to agree, so we call both
619 ** stat and macstat, and use the latter only for values not provided by
622 Py_BEGIN_ALLOW_THREADS
623 res
= macstat(path
, &mst
);
627 Py_BEGIN_ALLOW_THREADS
628 res
= stat(path
, &st
);
633 return _pystat_from_struct_stat(st
, (void*) &mst
);
643 if (!PyArg_ParseTuple(args
, ""))
645 Py_BEGIN_ALLOW_THREADS
655 mac_unlink(self
, args
)
659 return mac_1str(args
, (int (*)(const char *))unlink
);
663 mac_write(self
, args
)
669 if (!PyArg_ParseTuple(args
, "is#", &fd
, &buffer
, &size
))
671 Py_BEGIN_ALLOW_THREADS
672 size
= write(fd
, buffer
, size
);
676 return PyInt_FromLong((long)size
);
679 #ifdef USE_MALLOC_DEBUG
680 void *mstats(char *);
683 mac_mstats(self
, args
)
691 #endif /* USE_MALLOC_DEBUG */
693 static struct PyMethodDef mac_methods
[] = {
694 {"chdir", mac_chdir
, 1},
695 {"close", mac_close
, 1},
700 {"fdopen", mac_fdopen
, 1},
703 {"fstat", mac_fstat
, 1},
705 #if TARGET_API_MAC_OS8
706 {"getbootvol", mac_getbootvol
, 1}, /* non-standard */
708 {"getcwd", mac_getcwd
, 1},
709 {"listdir", mac_listdir
, 1},
710 {"lseek", mac_lseek
, 1},
711 {"mkdir", mac_mkdir
, 1},
712 {"open", mac_open
, 1},
713 {"read", mac_read
, 1},
714 {"rename", mac_rename
, 1},
715 {"rmdir", mac_rmdir
, 1},
716 {"stat", mac_stat
, 1},
717 #if TARGET_API_MAC_OS8
718 {"xstat", mac_xstat
, 1},
720 {"sync", mac_sync
, 1},
721 {"remove", mac_unlink
, 1},
722 {"unlink", mac_unlink
, 1},
723 {"write", mac_write
, 1},
724 #ifdef USE_MALLOC_DEBUG
725 {"mstats", mac_mstats
, 1},
728 {NULL
, NULL
} /* Sentinel */
732 ins(PyObject
*d
, char *symbol
, long value
)
734 PyObject
* v
= PyInt_FromLong(value
);
735 if (!v
|| PyDict_SetItemString(d
, symbol
, v
) < 0)
736 return -1; /* triggers fatal error */
746 if (ins(d
, "F_OK", (long)F_OK
)) return -1;
749 if (ins(d
, "R_OK", (long)R_OK
)) return -1;
752 if (ins(d
, "W_OK", (long)W_OK
)) return -1;
755 if (ins(d
, "X_OK", (long)X_OK
)) return -1;
758 if (ins(d
, "NGROUPS_MAX", (long)NGROUPS_MAX
)) return -1;
761 if (ins(d
, "TMP_MAX", (long)TMP_MAX
)) return -1;
764 if (ins(d
, "WNOHANG", (long)WNOHANG
)) return -1;
767 if (ins(d
, "O_RDONLY", (long)O_RDONLY
)) return -1;
770 if (ins(d
, "O_WRONLY", (long)O_WRONLY
)) return -1;
773 if (ins(d
, "O_RDWR", (long)O_RDWR
)) return -1;
776 if (ins(d
, "O_NDELAY", (long)O_NDELAY
)) return -1;
779 if (ins(d
, "O_NONBLOCK", (long)O_NONBLOCK
)) return -1;
782 if (ins(d
, "O_APPEND", (long)O_APPEND
)) return -1;
785 if (ins(d
, "O_DSYNC", (long)O_DSYNC
)) return -1;
788 if (ins(d
, "O_RSYNC", (long)O_RSYNC
)) return -1;
791 if (ins(d
, "O_SYNC", (long)O_SYNC
)) return -1;
794 if (ins(d
, "O_NOCTTY", (long)O_NOCTTY
)) return -1;
797 if (ins(d
, "O_CREAT", (long)O_CREAT
)) return -1;
800 if (ins(d
, "O_EXCL", (long)O_EXCL
)) return -1;
803 if (ins(d
, "O_TRUNC", (long)O_TRUNC
)) return -1;
806 if (ins(d
, "O_BINARY", (long)O_BINARY
)) return -1;
809 if (ins(d
, "O_TEXT", (long)O_TEXT
)) return -1;
813 if (ins(d
, "P_WAIT", (long)_P_WAIT
)) return -1;
814 if (ins(d
, "P_NOWAIT", (long)_P_NOWAIT
)) return -1;
815 if (ins(d
, "P_OVERLAY", (long)_OLD_P_OVERLAY
)) return -1;
816 if (ins(d
, "P_NOWAITO", (long)_P_NOWAITO
)) return -1;
817 if (ins(d
, "P_DETACH", (long)_P_DETACH
)) return -1;
820 #if defined(PYOS_OS2)
821 if (insertvalues(d
)) return -1;
832 m
= Py_InitModule("mac", mac_methods
);
833 d
= PyModule_GetDict(m
);
838 /* Initialize mac.error exception */
839 PyDict_SetItemString(d
, "error", PyExc_OSError
);
841 PyStructSequence_InitType(&StatResultType
, &stat_result_desc
);
842 PyDict_SetItemString(d
, "stat_result", (PyObject
*) &StatResultType
);
844 #if TARGET_API_MAC_OS8
845 PyStructSequence_InitType(&XStatResultType
, &xstat_result_desc
);
846 PyDict_SetItemString(d
, "xstat_result", (PyObject
*) &XStatResultType
);