blob: efe1ab4b0dc8ce619f6ae00de1eff6afd6f42234 [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 Rossum85a5fbb1990-10-14 12:07:46 +000032#include <signal.h>
33#include <string.h>
34#include <setjmp.h>
35#include <sys/types.h>
36#include <sys/stat.h>
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000037#ifdef SYSV
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000038#define UTIME_STRUCT
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000039#include <dirent.h>
40#define direct dirent
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000041#ifdef i386
42#define mode_t int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000043#endif
Guido van Rossum1ff6cb41991-04-08 20:59:13 +000044#else /* !SYSV */
45#include <sys/dir.h>
46#endif /* !SYSV */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000047
Guido van Rossum3f5da241990-12-20 15:06:42 +000048#include "allobjects.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000049#include "modsupport.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000050
Guido van Rossum7f77e2d1990-10-30 13:34:38 +000051extern char *strerror PROTO((int));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000052
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000053
54/* Return a dictionary corresponding to the POSIX environment table */
55
56extern char **environ;
57
58static object *
59convertenviron()
60{
61 object *d;
62 char **e;
63 d = newdictobject();
64 if (d == NULL)
65 return NULL;
66 if (environ == NULL)
67 return d;
68 /* XXX This part ignores errors */
69 for (e = environ; *e != NULL; e++) {
70 object *v;
71 char *p = strchr(*e, '=');
72 if (p == NULL)
73 continue;
74 v = newstringobject(p+1);
75 if (v == NULL)
76 continue;
77 *p = '\0';
78 (void) dictinsert(d, *e, v);
79 *p = '=';
80 DECREF(v);
81 }
82 return d;
83}
84
85
86static object *PosixError; /* Exception posix.error */
87
88/* Set a POSIX-specific error from errno, and return NULL */
89
Guido van Rossum9a1581c1990-10-21 13:12:47 +000090static object *
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000091posix_error()
92{
Guido van Rossume8f305a1990-10-14 20:04:28 +000093 return err_errno(PosixError);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000094}
95
96
97/* POSIX generic methods */
98
99static object *
100posix_1str(args, func)
101 object *args;
102 int (*func) FPROTO((const char *));
103{
104 object *path1;
105 if (!getstrarg(args, &path1))
106 return NULL;
107 if ((*func)(getstringvalue(path1)) < 0)
108 return posix_error();
109 INCREF(None);
110 return None;
111}
112
113static object *
114posix_2str(args, func)
115 object *args;
116 int (*func) FPROTO((const char *, const char *));
117{
118 object *path1, *path2;
119 if (!getstrstrarg(args, &path1, &path2))
120 return NULL;
121 if ((*func)(getstringvalue(path1), getstringvalue(path2)) < 0)
122 return posix_error();
123 INCREF(None);
124 return None;
125}
126
127static object *
128posix_strint(args, func)
129 object *args;
130 int (*func) FPROTO((const char *, int));
131{
132 object *path1;
133 int i;
134 if (!getstrintarg(args, &path1, &i))
135 return NULL;
136 if ((*func)(getstringvalue(path1), i) < 0)
137 return posix_error();
138 INCREF(None);
139 return None;
140}
141
142static object *
143posix_do_stat(self, args, statfunc)
144 object *self;
145 object *args;
146 int (*statfunc) FPROTO((const char *, struct stat *));
147{
148 struct stat st;
149 object *path;
150 object *v;
151 if (!getstrarg(args, &path))
152 return NULL;
153 if ((*statfunc)(getstringvalue(path), &st) != 0)
154 return posix_error();
155 v = newtupleobject(10);
156 if (v == NULL)
157 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000158#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
159 SET(0, st_mode);
160 SET(1, st_ino);
161 SET(2, st_dev);
162 SET(3, st_nlink);
163 SET(4, st_uid);
164 SET(5, st_gid);
165 SET(6, st_size);
166 SET(7, st_atime);
167 SET(8, st_mtime);
168 SET(9, st_ctime);
169#undef SET
Guido van Rossum3f5da241990-12-20 15:06:42 +0000170 if (err_occurred()) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000171 DECREF(v);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000172 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173 }
174 return v;
175}
176
177
178/* POSIX methods */
179
180static object *
181posix_chdir(self, args)
182 object *self;
183 object *args;
184{
185 extern int chdir PROTO((const char *));
186 return posix_1str(args, chdir);
187}
188
189static object *
190posix_chmod(self, args)
191 object *self;
192 object *args;
193{
194 extern int chmod PROTO((const char *, mode_t));
195 return posix_strint(args, chmod);
196}
197
198static object *
199posix_getcwd(self, args)
200 object *self;
201 object *args;
202{
203 char buf[1026];
204 extern char *getcwd PROTO((char *, int));
205 if (!getnoarg(args))
206 return NULL;
207 if (getcwd(buf, sizeof buf) == NULL)
208 return posix_error();
209 return newstringobject(buf);
210}
211
212static object *
213posix_link(self, args)
214 object *self;
215 object *args;
216{
217 extern int link PROTO((const char *, const char *));
218 return posix_2str(args, link);
219}
220
221static object *
222posix_listdir(self, args)
223 object *self;
224 object *args;
225{
226 object *name, *d, *v;
227 DIR *dirp;
228 struct direct *ep;
229 if (!getstrarg(args, &name))
230 return NULL;
231 if ((dirp = opendir(getstringvalue(name))) == NULL)
232 return posix_error();
233 if ((d = newlistobject(0)) == NULL) {
234 closedir(dirp);
235 return NULL;
236 }
237 while ((ep = readdir(dirp)) != NULL) {
238 v = newstringobject(ep->d_name);
239 if (v == NULL) {
240 DECREF(d);
241 d = NULL;
242 break;
243 }
244 if (addlistitem(d, v) != 0) {
245 DECREF(v);
246 DECREF(d);
247 d = NULL;
248 break;
249 }
250 DECREF(v);
251 }
252 closedir(dirp);
253 return d;
254}
255
256static object *
257posix_mkdir(self, args)
258 object *self;
259 object *args;
260{
261 extern int mkdir PROTO((const char *, mode_t));
262 return posix_strint(args, mkdir);
263}
264
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000265#ifdef i386
266int
267rename(from, to)
268 char *from;
269 char *to;
270{
271 int status;
272 /* XXX Shouldn't this unlink the destination first? */
273 status = link(from, to);
274 if (status != 0)
275 return status;
276 return unlink(from);
277}
278#endif
279
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000280static object *
281posix_rename(self, args)
282 object *self;
283 object *args;
284{
285 extern int rename PROTO((const char *, const char *));
286 return posix_2str(args, rename);
287}
288
289static object *
290posix_rmdir(self, args)
291 object *self;
292 object *args;
293{
294 extern int rmdir PROTO((const char *));
295 return posix_1str(args, rmdir);
296}
297
298static object *
299posix_stat(self, args)
300 object *self;
301 object *args;
302{
303 extern int stat PROTO((const char *, struct stat *));
304 return posix_do_stat(self, args, stat);
305}
306
307static object *
308posix_system(self, args)
309 object *self;
310 object *args;
311{
312 object *command;
313 int sts;
314 if (!getstrarg(args, &command))
315 return NULL;
316 sts = system(getstringvalue(command));
317 return newintobject((long)sts);
318}
319
320static object *
321posix_umask(self, args)
322 object *self;
323 object *args;
324{
325 int i;
326 if (!getintarg(args, &i))
327 return NULL;
328 i = umask(i);
329 if (i < 0)
330 return posix_error();
331 return newintobject((long)i);
332}
333
334static object *
335posix_unlink(self, args)
336 object *self;
337 object *args;
338{
339 extern int unlink PROTO((const char *));
340 return posix_1str(args, unlink);
341}
342
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000343#ifdef UTIME_STRUCT
344#include <utime.h>
345#endif
346
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000347static object *
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000348posix_utime(self, args)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000349 object *self;
350 object *args;
351{
352 object *path;
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000353
354#ifdef UTIME_STRUCT
355 struct utimbuf buf;
356#define ATIME buf.actime
357#define MTIME buf.modtime
358#define UTIME_ARG &buf
359
360#else
361 time_t buf[2];
362#define ATIME buf[0]
363#define MTIME buf[1]
364#define UTIME_ARG buf
365#endif
366
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000367 if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
368 err_badarg();
369 return NULL;
370 }
371 if (!getstrarg(gettupleitem(args, 0), &path) ||
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000372 !getlonglongargs(gettupleitem(args, 1), &ATIME, &MTIME))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000373 return NULL;
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000374 if (utime(getstringvalue(path), UTIME_ARG) < 0)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000375 return posix_error();
376 INCREF(None);
377 return None;
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000378#undef UTIME_ARG
379#undef ATIME
380#undef MTIME
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000381}
382
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000383
384#ifndef NO_LSTAT
385
386static object *
387posix_lstat(self, args)
388 object *self;
389 object *args;
390{
391 extern int lstat PROTO((const char *, struct stat *));
392 return posix_do_stat(self, args, lstat);
393}
394
395static object *
396posix_readlink(self, args)
397 object *self;
398 object *args;
399{
400 char buf[1024]; /* XXX Should use MAXPATHLEN */
401 object *path;
402 int n;
403 if (!getstrarg(args, &path))
404 return NULL;
405 n = readlink(getstringvalue(path), buf, sizeof buf);
406 if (n < 0)
407 return posix_error();
408 return newsizedstringobject(buf, n);
409}
410
411static object *
412posix_symlink(self, args)
413 object *self;
414 object *args;
415{
416 extern int symlink PROTO((const char *, const char *));
417 return posix_2str(args, symlink);
418}
419
420#endif /* NO_LSTAT */
421
422
423static struct methodlist posix_methods[] = {
424 {"chdir", posix_chdir},
425 {"chmod", posix_chmod},
426 {"getcwd", posix_getcwd},
427 {"link", posix_link},
428 {"listdir", posix_listdir},
429 {"mkdir", posix_mkdir},
430 {"rename", posix_rename},
431 {"rmdir", posix_rmdir},
432 {"stat", posix_stat},
433 {"system", posix_system},
434 {"umask", posix_umask},
435 {"unlink", posix_unlink},
Guido van Rossum1ff6cb41991-04-08 20:59:13 +0000436 {"utime", posix_utime},
437 {"utimes", posix_utime}, /* XXX for compatibility only */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000438#ifndef NO_LSTAT
439 {"lstat", posix_lstat},
440 {"readlink", posix_readlink},
441 {"symlink", posix_symlink},
442#endif
443 {NULL, NULL} /* Sentinel */
444};
445
446
447void
448initposix()
449{
450 object *m, *d, *v;
451
452 m = initmodule("posix", posix_methods);
453 d = getmoduledict(m);
454
455 /* Initialize posix.environ dictionary */
456 v = convertenviron();
457 if (v == NULL || dictinsert(d, "environ", v) != 0)
458 fatal("can't define posix.environ");
459 DECREF(v);
460
461 /* Initialize posix.error exception */
462 PosixError = newstringobject("posix.error");
463 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
464 fatal("can't define posix.error");
465}