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