On some systems <libc.h> conflicts with <unistd.h>, and should not
[bpt/guile.git] / libguile / filesys.c
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
15 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
19 *
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
25 *
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
28 *
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
36 *
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
39 * If you do not wish that, delete this exception notice.
40 */
41 \f
42 #include "_scm.h"
43 #include "genio.h"
44 #include "smob.h"
45 #include "feature.h"
46
47 #include "filesys.h"
48 \f
49 #ifdef TIME_WITH_SYS_TIME
50 # include <sys/time.h>
51 # include <time.h>
52 #else
53 # if HAVE_SYS_TIME_H
54 # include <sys/time.h>
55 # else
56 # include <time.h>
57 # endif
58 #endif
59
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63
64 #ifdef LIBC_H_WITH_UNISTD_H
65 #include <libc.h>
66 #endif
67
68 #ifdef HAVE_SYS_SELECT_H
69 #include <sys/select.h>
70 #endif
71
72 #ifdef HAVE_STRING_H
73 #include <string.h>
74 #endif
75
76 #include <sys/types.h>
77 #include <sys/stat.h>
78 #include <fcntl.h>
79
80 #include <pwd.h>
81
82
83 #ifdef FD_SET
84
85 #define SELECT_TYPE fd_set
86 #define SELECT_SET_SIZE FD_SETSIZE
87
88 #else /* no FD_SET */
89
90 /* Define the macros to access a single-int bitmap of descriptors. */
91 #define SELECT_SET_SIZE 32
92 #define SELECT_TYPE int
93 #define FD_SET(n, p) (*(p) |= (1 << (n)))
94 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
95 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
96 #define FD_ZERO(p) (*(p) = 0)
97
98 #endif /* no FD_SET */
99
100 #if HAVE_DIRENT_H
101 # include <dirent.h>
102 # define NAMLEN(dirent) strlen((dirent)->d_name)
103 #else
104 # define dirent direct
105 # define NAMLEN(dirent) (dirent)->d_namlen
106 # if HAVE_SYS_NDIR_H
107 # include <sys/ndir.h>
108 # endif
109 # if HAVE_SYS_DIR_H
110 # include <sys/dir.h>
111 # endif
112 # if HAVE_NDIR_H
113 # include <ndir.h>
114 # endif
115 #endif
116
117 \f
118
119 #ifdef O_CREAT
120 SCM_CONST_LONG (scm_O_CREAT, "O_CREAT", O_CREAT);
121 #endif
122
123 #ifdef O_EXCL
124 SCM_CONST_LONG (scm_O_EXCL, "O_EXCL", O_EXCL);
125 #endif
126
127 #ifdef O_NOCTTY
128 SCM_CONST_LONG (scm_O_NOCTTY, "O_NOCTTY", O_NOCTTY);
129 #endif
130
131 #ifdef O_TRUNC
132 SCM_CONST_LONG (scm_O_TRUNC, "O_TRUNC", O_TRUNC);
133 #endif
134
135 #ifdef O_APPEND
136 SCM_CONST_LONG (scm_O_APPEND, "O_APPEND", O_APPEND);
137 #endif
138
139 #ifdef O_NONBLOCK
140 SCM_CONST_LONG (scm_O_NONBLOCK, "O_NONBLOCK", O_NONBLOCK);
141 #endif
142
143 #ifdef O_NDELAY
144 SCM_CONST_LONG (scm_O_NDELAY, "O_NDELAY", O_NDELAY);
145 #endif
146
147 #ifdef O_SYNC
148 SCM_CONST_LONG (scm_O_SYNC, "O_SYNC", O_SYNC);
149 #endif
150
151
152
153 \f
154
155 /* {Permissions}
156 */
157
158 SCM_PROC (s_sys_chown, "chown", 3, 0, 0, scm_sys_chown);
159
160 SCM
161 scm_sys_chown (path, owner, group)
162 SCM path;
163 SCM owner;
164 SCM group;
165 {
166 int val;
167
168 SCM_ASSERT (SCM_NIMP (path) && SCM_ROSTRINGP (path), path, SCM_ARG1, s_sys_chown);
169 if (SCM_SUBSTRP (path))
170 path = scm_makfromstr (SCM_ROCHARS (path), SCM_ROLENGTH (path), 0);
171 SCM_ASSERT (SCM_INUMP (owner), owner, SCM_ARG2, s_sys_chown);
172 SCM_ASSERT (SCM_INUMP (group), group, SCM_ARG3, s_sys_chown);
173 SCM_SYSCALL (val = chown (SCM_ROCHARS (path),
174 SCM_INUM (owner), SCM_INUM (group)));
175 if (val != 0)
176 scm_syserror (s_sys_chown);
177 return SCM_UNSPECIFIED;
178 }
179
180
181 SCM_PROC (s_sys_chmod, "chmod", 2, 0, 0, scm_sys_chmod);
182
183 SCM
184 scm_sys_chmod (port_or_path, mode)
185 SCM port_or_path;
186 SCM mode;
187 {
188 int rv;
189 SCM_ASSERT (SCM_INUMP (mode), mode, SCM_ARG2, s_sys_chmod);
190 SCM_ASSERT (SCM_NIMP (port_or_path), port_or_path, SCM_ARG1, s_sys_chmod);
191 if (SCM_STRINGP (port_or_path))
192 SCM_SYSCALL (rv = chmod (SCM_CHARS (port_or_path), SCM_INUM (mode)));
193 else
194 {
195 SCM_ASSERT (SCM_OPFPORTP (port_or_path), port_or_path, SCM_ARG1, s_sys_chmod);
196 rv = fileno ((FILE *)SCM_STREAM (port_or_path));
197 if (rv != -1)
198 SCM_SYSCALL (rv = fchmod (rv, SCM_INUM (mode)));
199 }
200 if (rv != 0)
201 scm_syserror (s_sys_chmod);
202 return SCM_UNSPECIFIED;
203 }
204
205 SCM_PROC (s_umask, "umask", 0, 1, 0, scm_umask);
206
207 SCM
208 scm_umask (mode)
209 SCM mode;
210 {
211 mode_t mask;
212 if (SCM_UNBNDP (mode))
213 {
214 mask = umask (0);
215 umask (mask);
216 }
217 else
218 {
219 SCM_ASSERT (SCM_INUMP (mode), mode, SCM_ARG1, s_umask);
220 mask = umask (SCM_INUM (mode));
221 }
222 return SCM_MAKINUM (mask);
223 }
224
225 \f
226 /* {File Descriptors}
227 */
228 long scm_tc16_fd;
229
230
231 static int scm_fd_print SCM_P ((SCM sexp, SCM port, scm_print_state *pstate));
232
233 static int
234 scm_fd_print (sexp, port, pstate)
235 SCM sexp;
236 SCM port;
237 scm_print_state *pstate;
238 {
239 scm_gen_puts (scm_regular_string, "#<fd ", port);
240 scm_intprint (SCM_CDR (sexp), 10, port);
241 scm_gen_puts (scm_regular_string, ">", port);
242 return 1;
243 }
244
245
246 static scm_sizet scm_fd_free SCM_P ((SCM p));
247
248 static scm_sizet
249 scm_fd_free (p)
250 SCM p;
251 {
252 SCM flags;
253
254 flags = SCM_FD_FLAGS (p);
255 if ((scm_close_fd_on_gc & flags) && (scm_fd_is_open & flags))
256 {
257 SCM_SYSCALL( close (SCM_FD (p)) );
258 }
259 return 0;
260 }
261
262 static scm_smobfuns fd_smob = {scm_mark0, scm_fd_free, scm_fd_print, 0};
263
264
265 SCM
266 scm_intern_fd (fd, flags)
267 int fd;
268 int flags;
269 {
270 SCM it;
271 SCM_NEWCELL (it);
272 SCM_REDEFER_INTS;
273 SCM_SETCAR (it, (scm_tc16_fd | (flags << 16)));
274 SCM_SETCDR (it, (SCM)fd);
275 SCM_REALLOW_INTS;
276 return it;
277 }
278
279 \f
280
281 SCM_PROC (s_sys_open, "open", 3, 0, 0, scm_sys_open);
282
283 SCM
284 scm_sys_open (path, flags, mode)
285 SCM path;
286 SCM flags;
287 SCM mode;
288 {
289 int fd;
290 SCM sfd;
291
292 SCM_ASSERT (SCM_NIMP (path) && SCM_ROSTRINGP (path), path, SCM_ARG1, s_sys_open);
293 SCM_ASSERT (SCM_INUMP (flags), flags, SCM_ARG2, s_sys_open);
294 SCM_ASSERT (SCM_INUMP (mode), mode, SCM_ARG3, s_sys_open);
295
296 if (SCM_SUBSTRP (path))
297 path = scm_makfromstr (SCM_ROCHARS (path), SCM_ROLENGTH (path), 0);
298
299 SCM_DEFER_INTS;
300 SCM_SYSCALL ( fd = open (SCM_ROCHARS (path), SCM_INUM (flags), SCM_INUM (mode)) );
301 if (fd == -1)
302 scm_syserror (s_sys_open);
303 sfd = scm_intern_fd (fd, scm_fd_is_open | scm_close_fd_on_gc);
304 SCM_ALLOW_INTS;
305
306 return scm_return_first (sfd, path);
307 }
308
309
310 SCM_PROC (s_sys_create, "create", 2, 0, 0, scm_sys_create);
311
312 SCM
313 scm_sys_create (path, mode)
314 SCM path;
315 SCM mode;
316 {
317 int fd;
318 SCM sfd;
319
320 SCM_ASSERT (SCM_NIMP (path) && SCM_ROSTRINGP (path), path, SCM_ARG1, s_sys_create);
321 SCM_ASSERT (SCM_INUMP (mode), mode, SCM_ARG2, s_sys_create);
322
323 if (SCM_SUBSTRP (path))
324 path = scm_makfromstr (SCM_ROCHARS (path), SCM_ROLENGTH (path), 0);
325
326 SCM_DEFER_INTS;
327 SCM_SYSCALL ( fd = creat (SCM_ROCHARS (path), SCM_INUM (mode)) );
328 if (fd == -1)
329 scm_syserror (s_sys_create);
330 sfd = scm_intern_fd (fd, scm_fd_is_open | scm_close_fd_on_gc);
331 SCM_ALLOW_INTS;
332
333 return scm_return_first (sfd, path);
334 }
335
336
337 SCM_PROC (s_sys_close, "close", 1, 0, 0, scm_sys_close);
338
339 SCM
340 scm_sys_close (sfd)
341 SCM sfd;
342 {
343 int fd;
344 int got;
345 SCM_ASSERT (SCM_NIMP (sfd) && SCM_FD_P (sfd), sfd, SCM_ARG1, s_sys_close);
346 fd = SCM_FD (sfd);
347
348 SCM_DEFER_INTS;
349 got = close (fd);
350 SCM_SETCAR (sfd, scm_tc16_fd);
351 SCM_ALLOW_INTS;
352 if (got == -1)
353 scm_syserror (s_sys_close);
354 return SCM_UNSPECIFIED;
355 }
356
357
358 SCM_PROC (s_sys_write_fd, "write-fd", 2, 0, 0, scm_sys_write_fd);
359
360 SCM
361 scm_sys_write_fd (sfd, buf)
362 SCM sfd;
363 SCM buf;
364 {
365 SCM answer;
366 int fd;
367 size_t written;
368 SCM_ASSERT (SCM_NIMP (sfd) && SCM_FD_P (sfd), sfd, SCM_ARG1, s_sys_write_fd);
369 SCM_ASSERT (SCM_NIMP (buf) && SCM_ROSTRINGP (buf), buf, SCM_ARG2, s_sys_write_fd);
370 fd = SCM_FD (sfd);
371 SCM_DEFER_INTS;
372 written = write (fd, SCM_ROCHARS (buf), SCM_ROLENGTH (buf));
373 if (written == -1)
374 scm_syserror (s_sys_write_fd);
375 answer = scm_long2num (written);
376 SCM_ALLOW_INTS;
377 return scm_return_first (answer, buf);
378 }
379
380
381 SCM_PROC (s_sys_read_fd, "read-fd", 2, 2, 0, scm_sys_read_fd);
382
383 SCM
384 scm_sys_read_fd (sfd, buf, offset, length)
385 SCM sfd;
386 SCM buf;
387 SCM offset;
388 SCM length;
389 {
390 SCM answer;
391 int fd;
392 char * bytes;
393 int off;
394 int len;
395 size_t got;
396
397 SCM_ASSERT (SCM_NIMP (sfd) && SCM_FD_P (sfd), sfd, SCM_ARG1, s_sys_read_fd);
398 fd = SCM_FD (sfd);
399
400 SCM_ASSERT (SCM_NIMP (buf) && SCM_STRINGP (buf), buf, SCM_ARG2, s_sys_read_fd);
401 bytes = SCM_CHARS (buf);
402
403 if (SCM_UNBNDP (offset))
404 off = 0;
405 else
406 {
407 SCM_ASSERT (SCM_INUMP (offset), offset, SCM_ARG3, s_sys_read_fd);
408 off = SCM_INUM (offset);
409 }
410
411 if (SCM_UNBNDP (length))
412 len = SCM_LENGTH (buf);
413 else
414 {
415 SCM_ASSERT (SCM_INUMP (length), length, SCM_ARG3, s_sys_read_fd);
416 len = SCM_INUM (length);
417 }
418
419 SCM_DEFER_INTS;
420 got = read (fd, bytes + off, len);
421 if (got == -1)
422 scm_syserror (s_sys_read_fd);
423 answer = scm_long2num (got);
424 SCM_ALLOW_INTS;
425 return scm_return_first (answer, buf);
426 }
427
428 SCM_PROC (s_sys_lseek, "lseek", 2, 1, 0, scm_sys_lseek);
429
430 SCM
431 scm_sys_lseek (sfd, offset, whence)
432 SCM sfd;
433 SCM offset;
434 SCM whence;
435 {
436 SCM answer;
437 int fd;
438 long off;
439 int wh;
440 long got;
441
442 SCM_ASSERT (SCM_NIMP (sfd) && SCM_FD_P (sfd), sfd, SCM_ARG1, s_sys_lseek);
443 fd = SCM_FD (sfd);
444
445 off = scm_num2long (offset, (char *)SCM_ARG2, s_sys_lseek);
446 if (SCM_UNBNDP (whence))
447 wh = SEEK_SET;
448 else
449 {
450 SCM_ASSERT (SCM_INUMP (whence), whence, SCM_ARG3, s_sys_lseek);
451 wh = SCM_INUM (whence);
452 }
453
454 SCM_DEFER_INTS;
455 SCM_SYSCALL (got = lseek (fd, off, wh));
456 if (got == -1)
457 scm_syserror (s_sys_lseek);
458 answer = scm_long2num (got);
459 SCM_ALLOW_INTS;
460 return answer;
461 }
462
463
464 SCM_PROC (s_sys_dup, "dup", 1, 1, 0, scm_sys_dup);
465
466 SCM
467 scm_sys_dup (oldfd, newfd)
468 SCM oldfd;
469 SCM newfd;
470 {
471 SCM answer;
472 int fd;
473 int nfd;
474 int (*fn)();
475
476 SCM_ASSERT (SCM_NIMP (oldfd) && SCM_FD_P (oldfd), oldfd, SCM_ARG1, s_sys_dup);
477 SCM_ASSERT (SCM_UNBNDP (newfd) || SCM_INUMP (newfd), newfd, SCM_ARG2, s_sys_dup);
478 fd = SCM_FD (oldfd);
479 nfd = (SCM_INUMP (newfd) ? SCM_INUM (newfd) : -1);
480
481 SCM_DEFER_INTS;
482 fn = ((nfd == -1) ? (int (*)())dup : (int (*)())dup2);
483 nfd = fn (fd, nfd);
484 if (nfd == -1)
485 scm_syserror (s_sys_dup);
486 answer = SCM_MAKINUM (nfd);
487 SCM_ALLOW_INTS;
488 return answer;
489 }
490
491
492 \f
493 /* {Files}
494 */
495
496 SCM_SYMBOL (scm_sym_regular, "regular");
497 SCM_SYMBOL (scm_sym_directory, "directory");
498 SCM_SYMBOL (scm_sym_symlink, "symlink");
499 SCM_SYMBOL (scm_sym_block_special, "block-special");
500 SCM_SYMBOL (scm_sym_char_special, "char-special");
501 SCM_SYMBOL (scm_sym_fifo, "fifo");
502 SCM_SYMBOL (scm_sym_sock, "socket");
503 SCM_SYMBOL (scm_sym_unknown, "unknown");
504
505 static SCM scm_stat2scm SCM_P ((struct stat *stat_temp));
506
507 static SCM
508 scm_stat2scm (stat_temp)
509 struct stat *stat_temp;
510 {
511 SCM ans = scm_make_vector (SCM_MAKINUM (15), SCM_UNSPECIFIED, SCM_BOOL_F);
512 SCM *ve = SCM_VELTS (ans);
513
514 ve[0] = scm_ulong2num ((unsigned long) stat_temp->st_dev);
515 ve[1] = scm_ulong2num ((unsigned long) stat_temp->st_ino);
516 ve[2] = scm_ulong2num ((unsigned long) stat_temp->st_mode);
517 ve[3] = scm_ulong2num ((unsigned long) stat_temp->st_nlink);
518 ve[4] = scm_ulong2num ((unsigned long) stat_temp->st_uid);
519 ve[5] = scm_ulong2num ((unsigned long) stat_temp->st_gid);
520 #ifdef HAVE_ST_RDEV
521 ve[6] = scm_ulong2num ((unsigned long) stat_temp->st_rdev);
522 #else
523 ve[6] = SCM_BOOL_F;
524 #endif
525 ve[7] = scm_ulong2num ((unsigned long) stat_temp->st_size);
526 ve[8] = scm_ulong2num ((unsigned long) stat_temp->st_atime);
527 ve[9] = scm_ulong2num ((unsigned long) stat_temp->st_mtime);
528 ve[10] = scm_ulong2num ((unsigned long) stat_temp->st_ctime);
529 #ifdef HAVE_ST_BLKSIZE
530 ve[11] = scm_ulong2num ((unsigned long) stat_temp->st_blksize);
531 #else
532 ve[11] = scm_ulong2num (4096L);
533 #endif
534 #ifdef HAVE_ST_BLOCKS
535 ve[12] = scm_ulong2num ((unsigned long) stat_temp->st_blocks);
536 #else
537 ve[12] = SCM_BOOL_F;
538 #endif
539 {
540 int mode = stat_temp->st_mode;
541
542 if (S_ISREG (mode))
543 ve[13] = scm_sym_regular;
544 else if (S_ISDIR (mode))
545 ve[13] = scm_sym_directory;
546 else if (S_ISLNK (mode))
547 ve[13] = scm_sym_symlink;
548 else if (S_ISBLK (mode))
549 ve[13] = scm_sym_block_special;
550 else if (S_ISCHR (mode))
551 ve[13] = scm_sym_char_special;
552 else if (S_ISFIFO (mode))
553 ve[13] = scm_sym_fifo;
554 else if (S_ISSOCK (mode))
555 ve[13] = scm_sym_sock;
556 else
557 ve[13] = scm_sym_unknown;
558
559 ve[14] = SCM_MAKINUM ((~S_IFMT) & mode);
560
561 /* the layout of the bits in ve[14] is intended to be portable.
562 If there are systems that don't follow the usual convention,
563 the following could be used:
564
565 tmp = 0;
566 if (S_ISUID & mode) tmp += 1;
567 tmp <<= 1;
568 if (S_IRGRP & mode) tmp += 1;
569 tmp <<= 1;
570 if (S_ISVTX & mode) tmp += 1;
571 tmp <<= 1;
572 if (S_IRUSR & mode) tmp += 1;
573 tmp <<= 1;
574 if (S_IWUSR & mode) tmp += 1;
575 tmp <<= 1;
576 if (S_IXUSR & mode) tmp += 1;
577 tmp <<= 1;
578 if (S_IWGRP & mode) tmp += 1;
579 tmp <<= 1;
580 if (S_IXGRP & mode) tmp += 1;
581 tmp <<= 1;
582 if (S_IROTH & mode) tmp += 1;
583 tmp <<= 1;
584 if (S_IWOTH & mode) tmp += 1;
585 tmp <<= 1;
586 if (S_IXOTH & mode) tmp += 1;
587
588 ve[14] = SCM_MAKINUM (tmp);
589
590 */
591 }
592
593 return ans;
594 }
595
596 SCM_PROC (s_sys_stat, "stat", 1, 0, 0, scm_sys_stat);
597
598 SCM
599 scm_sys_stat (fd_or_path)
600 SCM fd_or_path;
601 {
602 int rv = 1;
603 struct stat stat_temp;
604
605 if (SCM_INUMP (fd_or_path))
606 {
607 rv = SCM_INUM (fd_or_path);
608 SCM_SYSCALL (rv = fstat (rv, &stat_temp));
609 }
610 else if (SCM_NIMP (fd_or_path) && SCM_FD_P (fd_or_path))
611 {
612 rv = SCM_FD (fd_or_path);
613 SCM_SYSCALL (rv = fstat (rv, &stat_temp));
614 }
615 else
616 {
617 SCM_ASSERT (SCM_NIMP (fd_or_path), fd_or_path, SCM_ARG1, s_sys_stat);
618 SCM_ASSERT (SCM_ROSTRINGP (fd_or_path), fd_or_path, SCM_ARG1, s_sys_stat);
619 if (SCM_ROSTRINGP (fd_or_path))
620 {
621 if (SCM_SUBSTRP (fd_or_path))
622 fd_or_path = scm_makfromstr (SCM_ROCHARS (fd_or_path), SCM_ROLENGTH (fd_or_path), 0);
623 SCM_SYSCALL (rv = stat (SCM_CHARS (fd_or_path), &stat_temp));
624 }
625
626 }
627 if (rv != 0)
628 scm_syserror_msg (s_sys_stat, "%s: %S",
629 scm_listify (scm_makfrom0str (strerror (errno)),
630 fd_or_path,
631 SCM_UNDEFINED));
632 return scm_stat2scm (&stat_temp);
633 }
634
635
636 \f
637 /* {Modifying Directories}
638 */
639
640 SCM_PROC (s_sys_link, "link", 2, 0, 0, scm_sys_link);
641
642 SCM
643 scm_sys_link (oldpath, newpath)
644 SCM oldpath;
645 SCM newpath;
646 {
647 int val;
648
649 SCM_ASSERT (SCM_NIMP (oldpath) && SCM_ROSTRINGP (oldpath), oldpath, SCM_ARG1, s_sys_link);
650 if (SCM_SUBSTRP (oldpath))
651 oldpath = scm_makfromstr (SCM_ROCHARS (oldpath), SCM_ROLENGTH (oldpath), 0);
652 SCM_ASSERT (SCM_NIMP (newpath) && SCM_ROSTRINGP (newpath), newpath, SCM_ARG2, s_sys_link);
653 if (SCM_SUBSTRP (newpath))
654 newpath = scm_makfromstr (SCM_ROCHARS (newpath), SCM_ROLENGTH (newpath), 0);
655 SCM_SYSCALL (val = link (SCM_ROCHARS (oldpath), SCM_ROCHARS (newpath)));
656 if (val != 0)
657 scm_syserror (s_sys_link);
658 return SCM_UNSPECIFIED;
659 }
660
661
662
663 SCM_PROC (s_sys_rename, "rename-file", 2, 0, 0, scm_sys_rename);
664
665 SCM
666 scm_sys_rename (oldname, newname)
667 SCM oldname;
668 SCM newname;
669 {
670 int rv;
671 SCM_ASSERT (SCM_NIMP (oldname) && SCM_STRINGP (oldname), oldname, SCM_ARG1, s_sys_rename);
672 SCM_ASSERT (SCM_NIMP (newname) && SCM_STRINGP (newname), newname, SCM_ARG2, s_sys_rename);
673 #ifdef HAVE_RENAME
674 SCM_SYSCALL (rv = rename (SCM_CHARS (oldname), SCM_CHARS (newname)));
675 if (rv != 0)
676 scm_syserror (s_sys_rename);
677 return SCM_UNSPECIFIED;
678 #else
679 SCM_DEFER_INTS;
680 SCM_SYSCALL (rv = link (SCM_CHARS (oldname), SCM_CHARS (newname)));
681 if (rv == 0)
682 {
683 SCM_SYSCALL (rv = unlink (SCM_CHARS (oldname)));;
684 if (rv != 0)
685 /* unlink failed. remove new name */
686 SCM_SYSCALL (unlink (SCM_CHARS (newname)));
687 }
688 SCM_ALLOW_INTS;
689 if (rv != 0)
690 scm_syserror (s_sys_rename);
691 return SCM_UNSPECIFIED;
692 #endif
693 }
694
695
696 SCM_PROC(s_sys_delete_file, "delete-file", 1, 0, 0, scm_sys_delete_file);
697
698 SCM
699 scm_sys_delete_file (str)
700 SCM str;
701 {
702 int ans;
703 SCM_ASSERT (SCM_NIMP (str) && SCM_STRINGP (str), str, SCM_ARG1, s_sys_delete_file);
704 SCM_SYSCALL (ans = unlink (SCM_CHARS (str)));
705 if (ans != 0)
706 scm_syserror (s_sys_delete_file);
707 return SCM_UNSPECIFIED;
708 }
709
710
711 SCM_PROC (s_sys_mkdir, "mkdir", 1, 1, 0, scm_sys_mkdir);
712
713 SCM
714 scm_sys_mkdir (path, mode)
715 SCM path;
716 SCM mode;
717 {
718 #ifdef HAVE_MKDIR
719 int rv;
720 mode_t mask;
721 SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path, SCM_ARG1, s_sys_mkdir);
722 if (SCM_UNBNDP (mode))
723 {
724 mask = umask (0);
725 umask (mask);
726 SCM_SYSCALL (rv = mkdir (SCM_CHARS (path), 0777 ^ mask));
727 }
728 else
729 {
730 SCM_ASSERT (SCM_INUMP (mode), mode, SCM_ARG2, s_sys_mkdir);
731 SCM_SYSCALL (rv = mkdir (SCM_CHARS (path), SCM_INUM (mode)));
732 }
733 if (rv != 0)
734 scm_syserror (s_sys_mkdir);
735 return SCM_UNSPECIFIED;
736 #else
737 scm_sysmissing (s_sys_mkdir);
738 /* not reached. */
739 return SCM_BOOL_F;
740 #endif
741 }
742
743
744 SCM_PROC (s_sys_rmdir, "rmdir", 1, 0, 0, scm_sys_rmdir);
745
746 SCM
747 scm_sys_rmdir (path)
748 SCM path;
749 {
750 #ifdef HAVE_RMDIR
751 int val;
752
753 SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path, SCM_ARG1, s_sys_rmdir);
754 SCM_SYSCALL (val = rmdir (SCM_CHARS (path)));
755 if (val != 0)
756 scm_syserror (s_sys_rmdir);
757 return SCM_UNSPECIFIED;
758 #else
759 scm_sysmissing (s_sys_rmdir);
760 /* not reached. */
761 return SCM_BOOL_F;
762 #endif
763 }
764
765 \f
766 /* {Examining Directories}
767 */
768
769 long scm_tc16_dir;
770
771 SCM_PROC (s_sys_opendir, "opendir", 1, 0, 0, scm_sys_opendir);
772
773 SCM
774 scm_sys_opendir (dirname)
775 SCM dirname;
776 {
777 DIR *ds;
778 SCM dir;
779 SCM_ASSERT (SCM_NIMP (dirname) && SCM_STRINGP (dirname), dirname, SCM_ARG1, s_sys_opendir);
780 SCM_NEWCELL (dir);
781 SCM_DEFER_INTS;
782 SCM_SYSCALL (ds = opendir (SCM_CHARS (dirname)));
783 if (ds == NULL)
784 scm_syserror (s_sys_opendir);
785 SCM_SETCAR (dir, scm_tc16_dir | SCM_OPN);
786 SCM_SETCDR (dir, ds);
787 SCM_ALLOW_INTS;
788 return dir;
789 }
790
791
792 SCM_PROC (s_sys_readdir, "readdir", 1, 0, 0, scm_sys_readdir);
793
794 SCM
795 scm_sys_readdir (port)
796 SCM port;
797 {
798 struct dirent *rdent;
799 SCM_DEFER_INTS;
800 SCM_ASSERT (SCM_NIMP (port) && SCM_OPDIRP (port), port, SCM_ARG1, s_sys_readdir);
801 errno = 0;
802 SCM_SYSCALL (rdent = readdir ((DIR *) SCM_CDR (port)));
803 SCM_ALLOW_INTS;
804 if (errno != 0)
805 scm_syserror (s_sys_readdir);
806 return (rdent ? scm_makfromstr (rdent->d_name, NAMLEN (rdent), 0)
807 : SCM_EOF_VAL);
808 }
809
810
811
812 SCM_PROC (s_rewinddir, "rewinddir", 1, 0, 0, scm_rewinddir);
813
814 SCM
815 scm_rewinddir (port)
816 SCM port;
817 {
818 SCM_ASSERT (SCM_NIMP (port) && SCM_OPDIRP (port), port, SCM_ARG1, s_rewinddir);
819 rewinddir ((DIR *) SCM_CDR (port));
820 return SCM_UNSPECIFIED;
821 }
822
823
824
825 SCM_PROC (s_sys_closedir, "closedir", 1, 0, 0, scm_sys_closedir);
826
827 SCM
828 scm_sys_closedir (port)
829 SCM port;
830 {
831 int sts;
832
833 SCM_ASSERT (SCM_NIMP (port) && SCM_DIRP (port), port, SCM_ARG1, s_sys_closedir);
834 SCM_DEFER_INTS;
835 if (SCM_CLOSEDP (port))
836 {
837 SCM_ALLOW_INTS;
838 return SCM_UNSPECIFIED;
839 }
840 SCM_SYSCALL (sts = closedir ((DIR *) SCM_CDR (port)));
841 if (sts != 0)
842 scm_syserror (s_sys_closedir);
843 SCM_SETCAR (port, scm_tc16_dir);
844 SCM_ALLOW_INTS;
845 return SCM_UNSPECIFIED;
846 }
847
848
849
850
851 static int scm_dir_print SCM_P ((SCM sexp, SCM port, scm_print_state *pstate));
852
853 static int
854 scm_dir_print (sexp, port, pstate)
855 SCM sexp;
856 SCM port;
857 scm_print_state *pstate;
858 {
859 scm_prinport (sexp, port, "directory");
860 return 1;
861 }
862
863
864 static scm_sizet scm_dir_free SCM_P ((SCM p));
865
866 static scm_sizet
867 scm_dir_free (p)
868 SCM p;
869 {
870 if (SCM_OPENP (p))
871 closedir ((DIR *) SCM_CDR (p));
872 return 0;
873 }
874
875 static scm_smobfuns dir_smob = {scm_mark0, scm_dir_free, scm_dir_print, 0};
876
877 \f
878 /* {Navigating Directories}
879 */
880
881
882 SCM_PROC (s_sys_chdir, "chdir", 1, 0, 0, scm_sys_chdir);
883
884 SCM
885 scm_sys_chdir (str)
886 SCM str;
887 {
888 int ans;
889
890 SCM_ASSERT (SCM_NIMP (str) && SCM_STRINGP (str), str, SCM_ARG1, s_sys_chdir);
891 SCM_SYSCALL (ans = chdir (SCM_CHARS (str)));
892 if (ans != 0)
893 scm_syserror (s_sys_chdir);
894 return SCM_UNSPECIFIED;
895 }
896
897
898
899 SCM_PROC (s_sys_getcwd, "getcwd", 0, 0, 0, scm_sys_getcwd);
900
901 SCM
902 scm_sys_getcwd ()
903 {
904 #ifdef HAVE_GETCWD
905 char *rv;
906
907 scm_sizet size = 100;
908 char *wd;
909 SCM result;
910
911 SCM_DEFER_INTS;
912 wd = scm_must_malloc (size, s_sys_getcwd);
913 while ((rv = getcwd (wd, size)) == 0 && errno == ERANGE)
914 {
915 scm_must_free (wd);
916 size *= 2;
917 wd = scm_must_malloc (size, s_sys_getcwd);
918 }
919 if (rv == 0)
920 scm_syserror (s_sys_getcwd);
921 result = scm_makfromstr (wd, strlen (wd), 0);
922 scm_must_free (wd);
923 SCM_ALLOW_INTS;
924 return result;
925 #else
926 scm_sysmissing (s_sys_getcwd);
927 /* not reached. */
928 return SCM_BOOL_F;
929 #endif
930 }
931
932 \f
933
934
935 static void fill_select_type SCM_P ((SELECT_TYPE * set, SCM list));
936
937 static void
938 fill_select_type (set, list)
939 SELECT_TYPE * set;
940 SCM list;
941 {
942 while (list != SCM_EOL)
943 {
944 if ( SCM_NIMP (SCM_CAR (list))
945 && (scm_tc16_fport == SCM_TYP16 (SCM_CAR (list)))
946 && SCM_OPPORTP (SCM_CAR (list)))
947 FD_SET (fileno ((FILE *)SCM_STREAM (SCM_CAR (list))), set);
948 else if (SCM_INUMP (SCM_CAR (list)))
949 FD_SET (SCM_INUM (SCM_CAR (list)), set);
950 else if (SCM_NIMP (SCM_CAR (list)) && SCM_FD_P (SCM_CAR (list)))
951 FD_SET (SCM_FD (SCM_CAR (list)), set);
952 list = SCM_CDR (list);
953 }
954 }
955
956
957 static SCM retrieve_select_type SCM_P ((SELECT_TYPE * set, SCM list));
958
959 static SCM
960 retrieve_select_type (set, list)
961 SELECT_TYPE * set;
962 SCM list;
963 {
964 SCM answer;
965 answer = SCM_EOL;
966 while (list != SCM_EOL)
967 {
968 if ( SCM_NIMP (SCM_CAR (list))
969 && (scm_tc16_fport == SCM_TYP16 (SCM_CAR (list)))
970 && SCM_OPPORTP (SCM_CAR (list)))
971 {
972 if (FD_ISSET (fileno ((FILE *)SCM_STREAM (SCM_CAR (list))), set))
973 answer = scm_cons (SCM_CAR (list), answer);
974 }
975 else if (SCM_INUMP (SCM_CAR (list)))
976 {
977 if (FD_ISSET (SCM_INUM (SCM_CAR (list)), set))
978 answer = scm_cons (SCM_CAR (list), answer);
979 }
980 else if (SCM_NIMP (SCM_CAR (list)) && SCM_FD_P (SCM_CAR (list)))
981 {
982 if (FD_ISSET (SCM_FD (SCM_CAR (list)), set))
983 answer = scm_cons (SCM_CAR (list), answer);
984 }
985 list = SCM_CDR (list);
986 }
987 return answer;
988 }
989
990
991 /* {Checking for events}
992 */
993
994 SCM_PROC (s_sys_select, "select", 3, 2, 0, scm_sys_select);
995
996 SCM
997 scm_sys_select (reads, writes, excepts, secs, msecs)
998 SCM reads;
999 SCM writes;
1000 SCM excepts;
1001 SCM secs;
1002 SCM msecs;
1003 {
1004 #ifdef HAVE_SELECT
1005 struct timeval timeout;
1006 struct timeval * time_p;
1007 SELECT_TYPE read_set;
1008 SELECT_TYPE write_set;
1009 SELECT_TYPE except_set;
1010 int sreturn;
1011
1012 SCM_ASSERT (-1 < scm_ilength (reads), reads, SCM_ARG1, s_sys_select);
1013 SCM_ASSERT (-1 < scm_ilength (writes), reads, SCM_ARG1, s_sys_select);
1014 SCM_ASSERT (-1 < scm_ilength (excepts), reads, SCM_ARG1, s_sys_select);
1015
1016 FD_ZERO (&read_set);
1017 FD_ZERO (&write_set);
1018 FD_ZERO (&except_set);
1019
1020 fill_select_type (&read_set, reads);
1021 fill_select_type (&write_set, writes);
1022 fill_select_type (&except_set, excepts);
1023
1024 if (SCM_UNBNDP (secs))
1025 time_p = 0;
1026 else
1027 {
1028 SCM_ASSERT (SCM_INUMP (secs), secs, SCM_ARG4, s_sys_select);
1029 if (SCM_UNBNDP (msecs))
1030 msecs = SCM_INUM0;
1031 else
1032 SCM_ASSERT (SCM_INUMP (msecs), msecs, SCM_ARG5, s_sys_select);
1033
1034 timeout.tv_sec = SCM_INUM (secs);
1035 timeout.tv_usec = 1000 * SCM_INUM (msecs);
1036 time_p = &timeout;
1037 }
1038
1039 SCM_DEFER_INTS;
1040 sreturn = select (SELECT_SET_SIZE,
1041 &read_set, &write_set, &except_set, time_p);
1042 if (sreturn < 0)
1043 scm_syserror (s_sys_select);
1044 SCM_ALLOW_INTS;
1045 return scm_listify (retrieve_select_type (&read_set, reads),
1046 retrieve_select_type (&write_set, writes),
1047 retrieve_select_type (&except_set, excepts),
1048 SCM_UNDEFINED);
1049 #else
1050 scm_sysmissing (s_sys_select);
1051 /* not reached. */
1052 return SCM_BOOL_F;
1053 #endif
1054 }
1055
1056 /* Check if FILE has characters waiting to be read. */
1057
1058 #ifdef __IBMC__
1059 # define MSDOS
1060 #endif
1061 #ifdef MSDOS
1062 # ifndef GO32
1063 # include <io.h>
1064 # include <conio.h>
1065
1066 int
1067 scm_input_waiting_p (f, caller)
1068 FILE *f;
1069 char *caller;
1070 {
1071 if (feof (f))
1072 return 1;
1073 if (fileno (f) == fileno (stdin) && (isatty (fileno (stdin))))
1074 return kbhit ();
1075 return -1;
1076 }
1077
1078 # endif
1079 #else
1080 # ifdef _DCC
1081 # include <ioctl.h>
1082 # else
1083 # ifndef AMIGA
1084 # ifndef vms
1085 # ifdef MWC
1086 # include <sys/io.h>
1087 # else
1088 # ifndef THINK_C
1089 # ifndef ARM_ULIB
1090 # include <sys/ioctl.h>
1091 # endif
1092 # endif
1093 # endif
1094 # endif
1095 # endif
1096 # endif
1097
1098 int
1099 scm_input_waiting_p (f, caller)
1100 FILE *f;
1101 char *caller;
1102 {
1103 /* Can we return an end-of-file character? */
1104 if (feof (f))
1105 return 1;
1106
1107 /* Do we have characters in the stdio buffer? */
1108 # ifdef FILE_CNT_FIELD
1109 if (f->FILE_CNT_FIELD > 0)
1110 return 1;
1111 # else
1112 # ifdef FILE_CNT_GPTR
1113 if (f->_gptr != f->_egptr)
1114 return 1;
1115 # else
1116 # ifdef FILE_CNT_READPTR
1117 if (f->_IO_read_end != f->_IO_read_ptr)
1118 return 1;
1119 # else
1120 Configure.in could not guess the name of the correct field in a FILE *.
1121 This function needs to be ported to your system.
1122 It should return zero iff no characters are waiting to be read.;
1123 # endif
1124 # endif
1125 # endif
1126
1127 /* Is the file prepared to deliver input? */
1128 # ifdef FIONREAD
1129 {
1130 long remir;
1131 ioctl(fileno(f), FIONREAD, &remir);
1132 return remir;
1133 }
1134 # else
1135 # ifdef HAVE_SELECT
1136 {
1137 struct timeval timeout;
1138 SELECT_TYPE read_set;
1139 SELECT_TYPE write_set;
1140 SELECT_TYPE except_set;
1141 int fno = fileno ((FILE *)f);
1142
1143 FD_ZERO (&read_set);
1144 FD_ZERO (&write_set);
1145 FD_ZERO (&except_set);
1146
1147 FD_SET (fno, &read_set);
1148
1149 timeout.tv_sec = 0;
1150 timeout.tv_usec = 0;
1151
1152 SCM_DEFER_INTS;
1153 if (select (SELECT_SET_SIZE,
1154 &read_set, &write_set, &except_set, &timeout)
1155 < 0)
1156 scm_syserror (caller);
1157 SCM_ALLOW_INTS;
1158 return FD_ISSET (fno, &read_set);
1159 }
1160 # else
1161 return -1;
1162 # endif
1163 # endif
1164 }
1165 #endif
1166
1167 \f
1168 /* {Symbolic Links}
1169 */
1170
1171 SCM_PROC (s_sys_symlink, "symlink", 2, 0, 0, scm_sys_symlink);
1172
1173 SCM
1174 scm_sys_symlink(oldpath, newpath)
1175 SCM oldpath;
1176 SCM newpath;
1177 {
1178 #ifdef HAVE_SYMLINK
1179 int val;
1180
1181 SCM_ASSERT(SCM_NIMP(oldpath) && SCM_STRINGP(oldpath), oldpath, SCM_ARG1, s_sys_symlink);
1182 SCM_ASSERT(SCM_NIMP(newpath) && SCM_STRINGP(newpath), newpath, SCM_ARG2, s_sys_symlink);
1183 SCM_SYSCALL (val = symlink(SCM_CHARS(oldpath), SCM_CHARS(newpath)));
1184 if (val != 0)
1185 scm_syserror (s_sys_symlink);
1186 return SCM_UNSPECIFIED;
1187 #else
1188 scm_sysmissing (s_sys_symlink);
1189 /* not reached. */
1190 return SCM_BOOL_F;
1191 #endif
1192 }
1193
1194
1195 SCM_PROC (s_sys_readlink, "readlink", 1, 0, 0, scm_sys_readlink);
1196
1197 SCM
1198 scm_sys_readlink(path)
1199 SCM path;
1200 {
1201 #ifdef HAVE_READLINK
1202 scm_sizet rv;
1203 scm_sizet size = 100;
1204 char *buf;
1205 SCM result;
1206 SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path, (char *) SCM_ARG1, s_sys_readlink);
1207 SCM_DEFER_INTS;
1208 buf = scm_must_malloc (size, s_sys_readlink);
1209 while ((rv = readlink (SCM_CHARS (path), buf, (scm_sizet) size)) == size)
1210 {
1211 scm_must_free (buf);
1212 size *= 2;
1213 buf = scm_must_malloc (size, s_sys_readlink);
1214 }
1215 if (rv == -1)
1216 scm_syserror (s_sys_readlink);
1217 result = scm_makfromstr (buf, rv, 0);
1218 scm_must_free (buf);
1219 SCM_ALLOW_INTS;
1220 return result;
1221 #else
1222 scm_sysmissing (s_sys_readlink);
1223 /* not reached. */
1224 return SCM_BOOL_F;
1225 #endif
1226 }
1227
1228
1229 SCM_PROC (s_sys_lstat, "lstat", 1, 0, 0, scm_sys_lstat);
1230
1231 SCM
1232 scm_sys_lstat(str)
1233 SCM str;
1234 {
1235 #ifdef HAVE_LSTAT
1236 int rv;
1237 struct stat stat_temp;
1238
1239 SCM_ASSERT(SCM_NIMP(str) && SCM_STRINGP(str), str, (char *)SCM_ARG1, s_sys_lstat);
1240 SCM_SYSCALL(rv = lstat(SCM_CHARS(str), &stat_temp));
1241 if (rv != 0)
1242 scm_syserror_msg (s_sys_lstat, "%s: %S",
1243 scm_listify (scm_makfrom0str (strerror (errno)),
1244 str,
1245 SCM_UNDEFINED));
1246 return scm_stat2scm(&stat_temp);
1247 #else
1248 scm_sysmissing (s_sys_lstat);
1249 /* not reached. */
1250 return SCM_BOOL_F;
1251 #endif
1252 }
1253
1254
1255 SCM_PROC (s_sys_copy_file, "copy-file", 2, 0, 0, scm_sys_copy_file);
1256
1257 SCM
1258 scm_sys_copy_file (oldfile, newfile)
1259 SCM oldfile;
1260 SCM newfile;
1261 {
1262 int oldfd, newfd;
1263 int n;
1264 char buf[BUFSIZ]; /* this space could be shared. */
1265 struct stat oldstat;
1266
1267 SCM_ASSERT (SCM_NIMP (oldfile) && SCM_ROSTRINGP (oldfile), oldfile, SCM_ARG1, s_sys_copy_file);
1268 if (SCM_SUBSTRP (oldfile))
1269 oldfile = scm_makfromstr (SCM_ROCHARS (oldfile), SCM_ROLENGTH (oldfile), 0);
1270 SCM_ASSERT (SCM_NIMP (newfile) && SCM_ROSTRINGP (newfile), newfile, SCM_ARG2, s_sys_copy_file);
1271 if (SCM_SUBSTRP (newfile))
1272 newfile = scm_makfromstr (SCM_ROCHARS (newfile), SCM_ROLENGTH (newfile), 0);
1273 if (stat (SCM_ROCHARS (oldfile), &oldstat) == -1)
1274 scm_syserror (s_sys_copy_file);
1275 SCM_DEFER_INTS;
1276 oldfd = open (SCM_ROCHARS (oldfile), O_RDONLY);
1277 if (oldfd == -1)
1278 scm_syserror (s_sys_copy_file);
1279
1280 /* use POSIX flags instead of 07777?. */
1281 newfd = open (SCM_ROCHARS (newfile), O_WRONLY | O_CREAT | O_TRUNC,
1282 oldstat.st_mode & 07777);
1283 if (newfd == -1)
1284 scm_syserror (s_sys_copy_file);
1285
1286 while ((n = read (oldfd, buf, sizeof buf)) > 0)
1287 if (write (newfd, buf, n) != n)
1288 {
1289 close (oldfd);
1290 close (newfd);
1291 scm_syserror (s_sys_copy_file);
1292 }
1293 close (oldfd);
1294 if (close (newfd) == -1)
1295 scm_syserror (s_sys_copy_file);
1296 SCM_ALLOW_INTS;
1297 return SCM_UNSPECIFIED;
1298 }
1299
1300 \f
1301
1302 void
1303 scm_init_filesys ()
1304 {
1305 scm_add_feature ("i/o-extensions");
1306
1307 scm_tc16_fd = scm_newsmob (&fd_smob);
1308 scm_tc16_dir = scm_newsmob (&dir_smob);
1309
1310 #include "filesys.x"
1311 }