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