blob: 5b02aae2fe39fe395e548bbdf7b12600334ae014 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* POSIX module implementation */
26
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000027#ifdef AMOEBA
28#define NO_LSTAT
29#define SYSV
30#endif
31
Guido van Rossum0ee42cd1991-04-08 21:01:03 +000032#ifdef MSDOS
33#define NO_LSTAT
34#endif
35
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000036#include <signal.h>
37#include <string.h>
38#include <setjmp.h>
39#include <sys/types.h>
40#include <sys/stat.h>
Guido van Rossum0ee42cd1991-04-08 21:01:03 +000041
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000042#ifdef SYSV
Guido van Rossum0ee42cd1991-04-08 21:01:03 +000043
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000044#define UTIME_STRUCT
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000045#include <dirent.h>
46#define direct dirent
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000047#ifdef i386
48#define mode_t int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000049#endif
Guido van Rossum0ee42cd1991-04-08 21:01:03 +000050
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000051#else /* !SYSV */
Guido van Rossum0ee42cd1991-04-08 21:01:03 +000052
53#ifndef MSDOS
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000054#include <sys/dir.h>
Guido van Rossum0ee42cd1991-04-08 21:01:03 +000055#endif
56
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000057#endif /* !SYSV */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000058
Guido van Rossum3f5da241990-12-20 15:06:42 +000059#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000060#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000061
Guido van Rossum7f77e2d1990-10-30 13:34:38 +000062extern char *strerror PROTO((int));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000063
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000064
65/* Return a dictionary corresponding to the POSIX environment table */
66
67extern char **environ;
68
69static object *
70convertenviron()
71{
72 object *d;
73 char **e;
74 d = newdictobject();
75 if (d == NULL)
76 return NULL;
77 if (environ == NULL)
78 return d;
79 /* XXX This part ignores errors */
80 for (e = environ; *e != NULL; e++) {
81 object *v;
82 char *p = strchr(*e, '=');
83 if (p == NULL)
84 continue;
85 v = newstringobject(p+1);
86 if (v == NULL)
87 continue;
88 *p = '\0';
89 (void) dictinsert(d, *e, v);
90 *p = '=';
91 DECREF(v);
92 }
93 return d;
94}
95
96
97static object *PosixError; /* Exception posix.error */
98
99/* Set a POSIX-specific error from errno, and return NULL */
100
Guido van Rossum9a1581c1990-10-21 13:12:47 +0000101static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000102posix_error()
103{
Guido van Rossume8f305a1990-10-14 20:04:28 +0000104 return err_errno(PosixError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000105}
106
107
108/* POSIX generic methods */
109
110static object *
111posix_1str(args, func)
112 object *args;
113 int (*func) FPROTO((const char *));
114{
115 object *path1;
116 if (!getstrarg(args, &path1))
117 return NULL;
118 if ((*func)(getstringvalue(path1)) < 0)
119 return posix_error();
120 INCREF(None);
121 return None;
122}
123
124static object *
125posix_2str(args, func)
126 object *args;
127 int (*func) FPROTO((const char *, const char *));
128{
129 object *path1, *path2;
130 if (!getstrstrarg(args, &path1, &path2))
131 return NULL;
132 if ((*func)(getstringvalue(path1), getstringvalue(path2)) < 0)
133 return posix_error();
134 INCREF(None);
135 return None;
136}
137
138static object *
139posix_strint(args, func)
140 object *args;
141 int (*func) FPROTO((const char *, int));
142{
143 object *path1;
144 int i;
145 if (!getstrintarg(args, &path1, &i))
146 return NULL;
147 if ((*func)(getstringvalue(path1), i) < 0)
148 return posix_error();
149 INCREF(None);
150 return None;
151}
152
153static object *
154posix_do_stat(self, args, statfunc)
155 object *self;
156 object *args;
157 int (*statfunc) FPROTO((const char *, struct stat *));
158{
159 struct stat st;
160 object *path;
161 object *v;
162 if (!getstrarg(args, &path))
163 return NULL;
164 if ((*statfunc)(getstringvalue(path), &st) != 0)
165 return posix_error();
166 v = newtupleobject(10);
167 if (v == NULL)
168 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000169#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
170 SET(0, st_mode);
171 SET(1, st_ino);
172 SET(2, st_dev);
173 SET(3, st_nlink);
174 SET(4, st_uid);
175 SET(5, st_gid);
176 SET(6, st_size);
177 SET(7, st_atime);
178 SET(8, st_mtime);
179 SET(9, st_ctime);
180#undef SET
Guido van Rossum3f5da241990-12-20 15:06:42 +0000181 if (err_occurred()) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182 DECREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000183 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000184 }
185 return v;
186}
187
188
189/* POSIX methods */
190
191static object *
192posix_chdir(self, args)
193 object *self;
194 object *args;
195{
196 extern int chdir PROTO((const char *));
197 return posix_1str(args, chdir);
198}
199
200static object *
201posix_chmod(self, args)
202 object *self;
203 object *args;
204{
205 extern int chmod PROTO((const char *, mode_t));
206 return posix_strint(args, chmod);
207}
208
209static object *
210posix_getcwd(self, args)
211 object *self;
212 object *args;
213{
214 char buf[1026];
215 extern char *getcwd PROTO((char *, int));
216 if (!getnoarg(args))
217 return NULL;
218 if (getcwd(buf, sizeof buf) == NULL)
219 return posix_error();
220 return newstringobject(buf);
221}
222
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000223#ifndef MSDOS
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000224static object *
225posix_link(self, args)
226 object *self;
227 object *args;
228{
229 extern int link PROTO((const char *, const char *));
230 return posix_2str(args, link);
231}
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000232#endif /* !MSDOS */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000233
234static object *
235posix_listdir(self, args)
236 object *self;
237 object *args;
238{
239 object *name, *d, *v;
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000240
241#ifdef MSDOS
242 struct ffblk ep;
243 int rv;
244 if (!getstrarg(args, &name))
245 return NULL;
246
247 if (findfirst((char *) getstringvalue(name), &ep, 0) == -1)
248 return posix_error();
249 if ((d = newlistobject(0)) == NULL)
250 return NULL;
251 do {
252 v = newstringobject(ep.ff_name);
253 if (v == NULL) {
254 DECREF(d);
255 d = NULL;
256 break;
257 }
258 if (addlistitem(d, v) != 0) {
259 DECREF(v);
260 DECREF(d);
261 d = NULL;
262 break;
263 }
264 DECREF(v);
265 } while ((rv = findnext(&ep)) == 0);
266#else /* !MSDOS */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000267 DIR *dirp;
268 struct direct *ep;
269 if (!getstrarg(args, &name))
270 return NULL;
271 if ((dirp = opendir(getstringvalue(name))) == NULL)
272 return posix_error();
273 if ((d = newlistobject(0)) == NULL) {
274 closedir(dirp);
275 return NULL;
276 }
277 while ((ep = readdir(dirp)) != NULL) {
278 v = newstringobject(ep->d_name);
279 if (v == NULL) {
280 DECREF(d);
281 d = NULL;
282 break;
283 }
284 if (addlistitem(d, v) != 0) {
285 DECREF(v);
286 DECREF(d);
287 d = NULL;
288 break;
289 }
290 DECREF(v);
291 }
292 closedir(dirp);
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000293#endif /* !MSDOS */
294
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000295 return d;
296}
297
298static object *
299posix_mkdir(self, args)
300 object *self;
301 object *args;
302{
303 extern int mkdir PROTO((const char *, mode_t));
304 return posix_strint(args, mkdir);
305}
306
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000307#ifdef i386
308int
309rename(from, to)
310 char *from;
311 char *to;
312{
313 int status;
314 /* XXX Shouldn't this unlink the destination first? */
315 status = link(from, to);
316 if (status != 0)
317 return status;
318 return unlink(from);
319}
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000320#endif /* i386 */
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000321
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000322static object *
323posix_rename(self, args)
324 object *self;
325 object *args;
326{
327 extern int rename PROTO((const char *, const char *));
328 return posix_2str(args, rename);
329}
330
331static object *
332posix_rmdir(self, args)
333 object *self;
334 object *args;
335{
336 extern int rmdir PROTO((const char *));
337 return posix_1str(args, rmdir);
338}
339
340static object *
341posix_stat(self, args)
342 object *self;
343 object *args;
344{
345 extern int stat PROTO((const char *, struct stat *));
346 return posix_do_stat(self, args, stat);
347}
348
349static object *
350posix_system(self, args)
351 object *self;
352 object *args;
353{
354 object *command;
355 int sts;
356 if (!getstrarg(args, &command))
357 return NULL;
358 sts = system(getstringvalue(command));
359 return newintobject((long)sts);
360}
361
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000362#ifndef MSDOS
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000363static object *
364posix_umask(self, args)
365 object *self;
366 object *args;
367{
368 int i;
369 if (!getintarg(args, &i))
370 return NULL;
371 i = umask(i);
372 if (i < 0)
373 return posix_error();
374 return newintobject((long)i);
375}
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000376#endif /* !MSDOS */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000377
378static object *
379posix_unlink(self, args)
380 object *self;
381 object *args;
382{
383 extern int unlink PROTO((const char *));
384 return posix_1str(args, unlink);
385}
386
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000387#ifdef UTIME_STRUCT
388#include <utime.h>
389#endif
390
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000391static object *
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000392posix_utime(self, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000393 object *self;
394 object *args;
395{
396 object *path;
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000397
398#ifdef UTIME_STRUCT
399 struct utimbuf buf;
400#define ATIME buf.actime
401#define MTIME buf.modtime
402#define UTIME_ARG &buf
403
404#else
405 time_t buf[2];
406#define ATIME buf[0]
407#define MTIME buf[1]
408#define UTIME_ARG buf
409#endif
410
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000411 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
412 err_badarg();
413 return NULL;
414 }
415 if (!getstrarg(gettupleitem(args, 0), &path) ||
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000416 !getlonglongargs(gettupleitem(args, 1), &ATIME, &MTIME))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000417 return NULL;
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000418 if (utime(getstringvalue(path), UTIME_ARG) < 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000419 return posix_error();
420 INCREF(None);
421 return None;
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000422#undef UTIME_ARG
423#undef ATIME
424#undef MTIME
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000425}
426
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000427#ifndef NO_LSTAT
428
429static object *
430posix_lstat(self, args)
431 object *self;
432 object *args;
433{
434 extern int lstat PROTO((const char *, struct stat *));
435 return posix_do_stat(self, args, lstat);
436}
437
438static object *
439posix_readlink(self, args)
440 object *self;
441 object *args;
442{
443 char buf[1024]; /* XXX Should use MAXPATHLEN */
444 object *path;
445 int n;
446 if (!getstrarg(args, &path))
447 return NULL;
448 n = readlink(getstringvalue(path), buf, sizeof buf);
449 if (n < 0)
450 return posix_error();
451 return newsizedstringobject(buf, n);
452}
453
454static object *
455posix_symlink(self, args)
456 object *self;
457 object *args;
458{
459 extern int symlink PROTO((const char *, const char *));
460 return posix_2str(args, symlink);
461}
462
463#endif /* NO_LSTAT */
464
465
466static struct methodlist posix_methods[] = {
467 {"chdir", posix_chdir},
468 {"chmod", posix_chmod},
469 {"getcwd", posix_getcwd},
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000470#ifndef MSDOS
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000471 {"link", posix_link},
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000472#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000473 {"listdir", posix_listdir},
474 {"mkdir", posix_mkdir},
475 {"rename", posix_rename},
476 {"rmdir", posix_rmdir},
477 {"stat", posix_stat},
478 {"system", posix_system},
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000479#ifndef MSDOS
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000480 {"umask", posix_umask},
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000481#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000482 {"unlink", posix_unlink},
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000483 {"utime", posix_utime},
484 {"utimes", posix_utime}, /* XXX for compatibility only */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000485#ifndef NO_LSTAT
486 {"lstat", posix_lstat},
487 {"readlink", posix_readlink},
488 {"symlink", posix_symlink},
489#endif
490 {NULL, NULL} /* Sentinel */
491};
492
493
494void
495initposix()
496{
497 object *m, *d, *v;
498
499 m = initmodule("posix", posix_methods);
500 d = getmoduledict(m);
501
502 /* Initialize posix.environ dictionary */
503 v = convertenviron();
504 if (v == NULL || dictinsert(d, "environ", v) != 0)
505 fatal("can't define posix.environ");
506 DECREF(v);
507
508 /* Initialize posix.error exception */
509 PosixError = newstringobject("posix.error");
510 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
511 fatal("can't define posix.error");
512}
Guido van Rossum0ee42cd1991-04-08 21:01:03 +0000513
514#ifdef MSDOS
515
516/* A small "compatibility library" for TurboC under MS-DOS */
517
518#include <sir.h>
519#include <io.h>
520#include <dos.h>
521#include <fcntl.h>
522
523int
524chmod(path, mode)
525 char *path;
526 int mode;
527{
528 return _chmod(path, 1, mode);
529}
530
531int
532utime(path, times)
533 char *path;
534 time_t times[2];
535{
536 struct date dt;
537 struct time tm;
538 struct ftime dft;
539 int fh;
540 unixtodos(tv[0].tv_sec,&dt,&tm);
541 dft.ft_tsec = tm.ti_sec; dft.ft_min = tm.ti_min;
542 dft.ft_hour = tm.ti_hour; dft.ft_day = dt.da_day;
543 dft.ft_month = dt.da_mon;
544 dft.ft_year = (dt.da_year - 1980); /* this is for TC library */
545
546 if ((fh = open(getstringvalue(path),O_RDWR)) < 0)
547 return posix_error(); /* can't open file to set time */
548 if (setftime(fh,&dft) < 0)
549 {
550 close(fh);
551 return posix_error();
552 }
553 close(fh); /* close the temp handle */
554}
555
556#endif /* MSDOS */