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