* filesys.c: #include <io.h>, if we have it.
[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");
298SCM_SYMBOL (scm_sym_symlink, "symlink");
299SCM_SYMBOL (scm_sym_block_special, "block-special");
300SCM_SYMBOL (scm_sym_char_special, "char-special");
301SCM_SYMBOL (scm_sym_fifo, "fifo");
302SCM_SYMBOL (scm_sym_sock, "socket");
303SCM_SYMBOL (scm_sym_unknown, "unknown");
304
1cc91f1b
JB
305static SCM scm_stat2scm SCM_P ((struct stat *stat_temp));
306
0f2d19dd
JB
307static SCM
308scm_stat2scm (stat_temp)
309 struct stat *stat_temp;
0f2d19dd 310{
a8741caa 311 SCM ans = scm_make_vector (SCM_MAKINUM (15), SCM_UNSPECIFIED);
0f2d19dd 312 SCM *ve = SCM_VELTS (ans);
ae5253c5 313
0f2d19dd
JB
314 ve[0] = scm_ulong2num ((unsigned long) stat_temp->st_dev);
315 ve[1] = scm_ulong2num ((unsigned long) stat_temp->st_ino);
316 ve[2] = scm_ulong2num ((unsigned long) stat_temp->st_mode);
317 ve[3] = scm_ulong2num ((unsigned long) stat_temp->st_nlink);
318 ve[4] = scm_ulong2num ((unsigned long) stat_temp->st_uid);
319 ve[5] = scm_ulong2num ((unsigned long) stat_temp->st_gid);
320#ifdef HAVE_ST_RDEV
321 ve[6] = scm_ulong2num ((unsigned long) stat_temp->st_rdev);
322#else
323 ve[6] = SCM_BOOL_F;
324#endif
325 ve[7] = scm_ulong2num ((unsigned long) stat_temp->st_size);
326 ve[8] = scm_ulong2num ((unsigned long) stat_temp->st_atime);
327 ve[9] = scm_ulong2num ((unsigned long) stat_temp->st_mtime);
328 ve[10] = scm_ulong2num ((unsigned long) stat_temp->st_ctime);
329#ifdef HAVE_ST_BLKSIZE
330 ve[11] = scm_ulong2num ((unsigned long) stat_temp->st_blksize);
331#else
332 ve[11] = scm_ulong2num (4096L);
333#endif
334#ifdef HAVE_ST_BLOCKS
335 ve[12] = scm_ulong2num ((unsigned long) stat_temp->st_blocks);
336#else
337 ve[12] = SCM_BOOL_F;
338#endif
ae5253c5
GH
339 {
340 int mode = stat_temp->st_mode;
341
342 if (S_ISREG (mode))
343 ve[13] = scm_sym_regular;
344 else if (S_ISDIR (mode))
345 ve[13] = scm_sym_directory;
346 else if (S_ISLNK (mode))
347 ve[13] = scm_sym_symlink;
348 else if (S_ISBLK (mode))
349 ve[13] = scm_sym_block_special;
350 else if (S_ISCHR (mode))
351 ve[13] = scm_sym_char_special;
352 else if (S_ISFIFO (mode))
353 ve[13] = scm_sym_fifo;
354 else if (S_ISSOCK (mode))
355 ve[13] = scm_sym_sock;
356 else
357 ve[13] = scm_sym_unknown;
358
359 ve[14] = SCM_MAKINUM ((~S_IFMT) & mode);
360
361 /* the layout of the bits in ve[14] is intended to be portable.
362 If there are systems that don't follow the usual convention,
363 the following could be used:
364
365 tmp = 0;
366 if (S_ISUID & mode) tmp += 1;
367 tmp <<= 1;
368 if (S_IRGRP & mode) tmp += 1;
369 tmp <<= 1;
370 if (S_ISVTX & mode) tmp += 1;
371 tmp <<= 1;
372 if (S_IRUSR & mode) tmp += 1;
373 tmp <<= 1;
374 if (S_IWUSR & mode) tmp += 1;
375 tmp <<= 1;
376 if (S_IXUSR & mode) tmp += 1;
377 tmp <<= 1;
378 if (S_IWGRP & mode) tmp += 1;
379 tmp <<= 1;
380 if (S_IXGRP & mode) tmp += 1;
381 tmp <<= 1;
382 if (S_IROTH & mode) tmp += 1;
383 tmp <<= 1;
384 if (S_IWOTH & mode) tmp += 1;
385 tmp <<= 1;
386 if (S_IXOTH & mode) tmp += 1;
387
388 ve[14] = SCM_MAKINUM (tmp);
389
390 */
391 }
0f2d19dd
JB
392
393 return ans;
394}
395
3d8d56df 396SCM_PROC (s_stat, "stat", 1, 0, 0, scm_stat);
1cc91f1b 397
0f2d19dd 398SCM
6afcd3b2
GH
399scm_stat (object)
400 SCM object;
0f2d19dd 401{
6afcd3b2
GH
402 int rv;
403 int fdes;
0f2d19dd
JB
404 struct stat stat_temp;
405
1ea47048
MD
406 if (SCM_INUMP (object))
407 SCM_SYSCALL (rv = fstat (SCM_INUM (object), &stat_temp));
408 else
0f2d19dd 409 {
1ea47048
MD
410 SCM_ASSERT (SCM_NIMP (object), object, SCM_ARG1, s_stat);
411 if (SCM_ROSTRINGP (object))
412 {
413 SCM_COERCE_SUBSTR (object);
414 SCM_SYSCALL (rv = stat (SCM_ROCHARS (object), &stat_temp));
415 }
c0ebd8c5 416 else
0f2d19dd 417 {
1ea47048
MD
418 object = SCM_COERCE_OUTPORT (object);
419 SCM_ASSERT (SCM_OPFPORTP (object), object, SCM_ARG1, s_stat);
77a76b64 420 fdes = SCM_FPORT_FDES (object);
1ea47048 421 SCM_SYSCALL (rv = fstat (fdes, &stat_temp));
0f2d19dd 422 }
6afcd3b2
GH
423 }
424 if (rv == -1)
3d8d56df
GH
425 {
426 int en = errno;
427
428 scm_syserror_msg (s_stat, "%s: %S",
429 scm_listify (scm_makfrom0str (strerror (errno)),
6afcd3b2 430 object,
3d8d56df
GH
431 SCM_UNDEFINED),
432 en);
433 }
02b754d3 434 return scm_stat2scm (&stat_temp);
0f2d19dd
JB
435}
436
0f2d19dd
JB
437\f
438/* {Modifying Directories}
439 */
440
3d8d56df 441SCM_PROC (s_link, "link", 2, 0, 0, scm_link);
1cc91f1b 442
0f2d19dd 443SCM
3d8d56df 444scm_link (oldpath, newpath)
0f2d19dd
JB
445 SCM oldpath;
446 SCM newpath;
0f2d19dd
JB
447{
448 int val;
02b754d3 449
6afcd3b2
GH
450 SCM_ASSERT (SCM_NIMP (oldpath) && SCM_ROSTRINGP (oldpath), oldpath,
451 SCM_ARG1, s_link);
0f2d19dd 452 if (SCM_SUBSTRP (oldpath))
6afcd3b2
GH
453 oldpath = scm_makfromstr (SCM_ROCHARS (oldpath),
454 SCM_ROLENGTH (oldpath), 0);
455 SCM_ASSERT (SCM_NIMP (newpath) && SCM_ROSTRINGP (newpath), newpath,
456 SCM_ARG2, s_link);
0f2d19dd 457 if (SCM_SUBSTRP (newpath))
6afcd3b2
GH
458 newpath = scm_makfromstr (SCM_ROCHARS (newpath),
459 SCM_ROLENGTH (newpath), 0);
0f2d19dd 460 SCM_SYSCALL (val = link (SCM_ROCHARS (oldpath), SCM_ROCHARS (newpath)));
02b754d3 461 if (val != 0)
3d8d56df 462 scm_syserror (s_link);
02b754d3 463 return SCM_UNSPECIFIED;
0f2d19dd
JB
464}
465
466
467
3d8d56df 468SCM_PROC (s_rename, "rename-file", 2, 0, 0, scm_rename);
1cc91f1b 469
0f2d19dd 470SCM
3d8d56df 471scm_rename (oldname, newname)
0f2d19dd
JB
472 SCM oldname;
473 SCM newname;
0f2d19dd
JB
474{
475 int rv;
89958ad0
JB
476 SCM_ASSERT (SCM_NIMP (oldname) && SCM_ROSTRINGP (oldname), oldname, SCM_ARG1,
477 s_rename);
478 SCM_ASSERT (SCM_NIMP (newname) && SCM_ROSTRINGP (newname), newname, SCM_ARG2,
479 s_rename);
480 SCM_COERCE_SUBSTR (oldname);
481 SCM_COERCE_SUBSTR (newname);
0f2d19dd 482#ifdef HAVE_RENAME
89958ad0 483 SCM_SYSCALL (rv = rename (SCM_ROCHARS (oldname), SCM_ROCHARS (newname)));
0f2d19dd 484#else
89958ad0 485 SCM_SYSCALL (rv = link (SCM_ROCHARS (oldname), SCM_ROCHARS (newname)));
02b754d3 486 if (rv == 0)
0f2d19dd 487 {
89958ad0 488 SCM_SYSCALL (rv = unlink (SCM_ROCHARS (oldname)));;
02b754d3 489 if (rv != 0)
0f2d19dd 490 /* unlink failed. remove new name */
89958ad0 491 SCM_SYSCALL (unlink (SCM_ROCHARS (newname)));
0f2d19dd 492 }
6afcd3b2 493#endif
02b754d3 494 if (rv != 0)
3d8d56df 495 scm_syserror (s_rename);
02b754d3 496 return SCM_UNSPECIFIED;
0f2d19dd
JB
497}
498
499
3d8d56df 500SCM_PROC(s_delete_file, "delete-file", 1, 0, 0, scm_delete_file);
1cc91f1b 501
2f3ed1ba 502SCM
3d8d56df 503scm_delete_file (str)
2f3ed1ba 504 SCM str;
2f3ed1ba
JB
505{
506 int ans;
6afcd3b2
GH
507 SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, SCM_ARG1,
508 s_delete_file);
89958ad0
JB
509 SCM_COERCE_SUBSTR (str);
510 SCM_SYSCALL (ans = unlink (SCM_ROCHARS (str)));
2f3ed1ba 511 if (ans != 0)
3d8d56df 512 scm_syserror (s_delete_file);
2f3ed1ba
JB
513 return SCM_UNSPECIFIED;
514}
515
6afcd3b2
GH
516SCM_PROC (s_truncate_file, "truncate-file", 2, 0, 0, scm_truncate_file);
517SCM
518scm_truncate_file (SCM object, SCM size)
519{
520 int rv;
521 scm_sizet csize;
522 int fdes;
523
78446828
MV
524 object = SCM_COERCE_OUTPORT (object);
525
6afcd3b2 526 csize = (scm_sizet) scm_num2long (size, (char *) SCM_ARG2, s_truncate_file);
6afcd3b2
GH
527 if (SCM_INUMP (object) || (SCM_NIMP (object) && SCM_OPFPORTP (object)))
528 {
529 if (SCM_INUMP (object))
530 fdes = SCM_INUM (object);
531 else
77a76b64 532 fdes = SCM_FPORT_FDES (object);
6afcd3b2
GH
533 SCM_SYSCALL (rv = ftruncate (fdes, csize));
534 }
535 else
536 {
537 SCM_ASSERT (SCM_NIMP (object) && SCM_ROSTRINGP (object),
538 object, SCM_ARG1, s_chown);
539 SCM_COERCE_SUBSTR (object);
540 SCM_SYSCALL (rv = truncate (SCM_ROCHARS (object), csize));
541 }
542 if (rv == -1)
543 scm_syserror (s_truncate_file);
6afcd3b2
GH
544 return SCM_UNSPECIFIED;
545}
0f2d19dd 546
3d8d56df 547SCM_PROC (s_mkdir, "mkdir", 1, 1, 0, scm_mkdir);
1cc91f1b 548
0f2d19dd 549SCM
3d8d56df 550scm_mkdir (path, mode)
0f2d19dd
JB
551 SCM path;
552 SCM mode;
0f2d19dd
JB
553{
554#ifdef HAVE_MKDIR
555 int rv;
556 mode_t mask;
89958ad0
JB
557 SCM_ASSERT (SCM_NIMP (path) && SCM_ROSTRINGP (path), path, SCM_ARG1,
558 s_mkdir);
559 SCM_COERCE_SUBSTR (path);
0f2d19dd
JB
560 if (SCM_UNBNDP (mode))
561 {
562 mask = umask (0);
563 umask (mask);
89958ad0 564 SCM_SYSCALL (rv = mkdir (SCM_ROCHARS (path), 0777 ^ mask));
0f2d19dd
JB
565 }
566 else
567 {
3d8d56df 568 SCM_ASSERT (SCM_INUMP (mode), mode, SCM_ARG2, s_mkdir);
89958ad0 569 SCM_SYSCALL (rv = mkdir (SCM_ROCHARS (path), SCM_INUM (mode)));
0f2d19dd 570 }
02b754d3 571 if (rv != 0)
3d8d56df 572 scm_syserror (s_mkdir);
02b754d3 573 return SCM_UNSPECIFIED;
0f2d19dd 574#else
3d8d56df 575 scm_sysmissing (s_mkdir);
02b754d3
GH
576 /* not reached. */
577 return SCM_BOOL_F;
0f2d19dd
JB
578#endif
579}
580
581
3d8d56df 582SCM_PROC (s_rmdir, "rmdir", 1, 0, 0, scm_rmdir);
1cc91f1b 583
0f2d19dd 584SCM
3d8d56df 585scm_rmdir (path)
0f2d19dd 586 SCM path;
0f2d19dd
JB
587{
588#ifdef HAVE_RMDIR
589 int val;
02b754d3 590
89958ad0
JB
591 SCM_ASSERT (SCM_NIMP (path) && SCM_ROSTRINGP (path), path, SCM_ARG1,
592 s_rmdir);
593 SCM_COERCE_SUBSTR (path);
594 SCM_SYSCALL (val = rmdir (SCM_ROCHARS (path)));
02b754d3 595 if (val != 0)
3d8d56df 596 scm_syserror (s_rmdir);
02b754d3 597 return SCM_UNSPECIFIED;
0f2d19dd 598#else
3d8d56df 599 scm_sysmissing (s_rmdir);
02b754d3
GH
600 /* not reached. */
601 return SCM_BOOL_F;
0f2d19dd
JB
602#endif
603}
604
605\f
606/* {Examining Directories}
607 */
608
609long scm_tc16_dir;
610
3d8d56df 611SCM_PROC (s_opendir, "opendir", 1, 0, 0, scm_opendir);
1cc91f1b 612
0f2d19dd 613SCM
3d8d56df 614scm_opendir (dirname)
0f2d19dd 615 SCM dirname;
0f2d19dd
JB
616{
617 DIR *ds;
89958ad0
JB
618 SCM_ASSERT (SCM_NIMP (dirname) && SCM_ROSTRINGP (dirname), dirname, SCM_ARG1,
619 s_opendir);
620 SCM_COERCE_SUBSTR (dirname);
89958ad0 621 SCM_SYSCALL (ds = opendir (SCM_ROCHARS (dirname)));
02b754d3 622 if (ds == NULL)
3d8d56df 623 scm_syserror (s_opendir);
23a62151 624 SCM_RETURN_NEWSMOB (scm_tc16_dir | SCM_OPN, ds);
0f2d19dd
JB
625}
626
627
3d8d56df 628SCM_PROC (s_readdir, "readdir", 1, 0, 0, scm_readdir);
1cc91f1b 629
0f2d19dd 630SCM
3d8d56df 631scm_readdir (port)
0f2d19dd 632 SCM port;
0f2d19dd
JB
633{
634 struct dirent *rdent;
3d8d56df 635 SCM_ASSERT (SCM_NIMP (port) && SCM_OPDIRP (port), port, SCM_ARG1, s_readdir);
0f2d19dd
JB
636 errno = 0;
637 SCM_SYSCALL (rdent = readdir ((DIR *) SCM_CDR (port)));
02b754d3 638 if (errno != 0)
3d8d56df 639 scm_syserror (s_readdir);
02b754d3
GH
640 return (rdent ? scm_makfromstr (rdent->d_name, NAMLEN (rdent), 0)
641 : SCM_EOF_VAL);
0f2d19dd
JB
642}
643
644
645
646SCM_PROC (s_rewinddir, "rewinddir", 1, 0, 0, scm_rewinddir);
1cc91f1b 647
0f2d19dd
JB
648SCM
649scm_rewinddir (port)
650 SCM port;
0f2d19dd
JB
651{
652 SCM_ASSERT (SCM_NIMP (port) && SCM_OPDIRP (port), port, SCM_ARG1, s_rewinddir);
653 rewinddir ((DIR *) SCM_CDR (port));
654 return SCM_UNSPECIFIED;
655}
656
657
658
3d8d56df 659SCM_PROC (s_closedir, "closedir", 1, 0, 0, scm_closedir);
1cc91f1b 660
0f2d19dd 661SCM
3d8d56df 662scm_closedir (port)
0f2d19dd 663 SCM port;
0f2d19dd
JB
664{
665 int sts;
02b754d3 666
3d8d56df 667 SCM_ASSERT (SCM_NIMP (port) && SCM_DIRP (port), port, SCM_ARG1, s_closedir);
0f2d19dd
JB
668 if (SCM_CLOSEDP (port))
669 {
02b754d3 670 return SCM_UNSPECIFIED;
0f2d19dd
JB
671 }
672 SCM_SYSCALL (sts = closedir ((DIR *) SCM_CDR (port)));
02b754d3 673 if (sts != 0)
3d8d56df 674 scm_syserror (s_closedir);
a6c64c3c 675 SCM_SETCAR (port, scm_tc16_dir);
02b754d3 676 return SCM_UNSPECIFIED;
0f2d19dd
JB
677}
678
679
680
1cc91f1b
JB
681
682static int scm_dir_print SCM_P ((SCM sexp, SCM port, scm_print_state *pstate));
683
0f2d19dd 684static int
9882ea19 685scm_dir_print (sexp, port, pstate)
0f2d19dd
JB
686 SCM sexp;
687 SCM port;
9882ea19 688 scm_print_state *pstate;
0f2d19dd
JB
689{
690 scm_prinport (sexp, port, "directory");
691 return 1;
692}
693
1cc91f1b
JB
694
695static scm_sizet scm_dir_free SCM_P ((SCM p));
696
0f2d19dd
JB
697static scm_sizet
698scm_dir_free (p)
699 SCM p;
0f2d19dd
JB
700{
701 if (SCM_OPENP (p))
702 closedir ((DIR *) SCM_CDR (p));
703 return 0;
704}
705
0f2d19dd
JB
706\f
707/* {Navigating Directories}
708 */
709
710
3d8d56df 711SCM_PROC (s_chdir, "chdir", 1, 0, 0, scm_chdir);
1cc91f1b 712
0f2d19dd 713SCM
3d8d56df 714scm_chdir (str)
0f2d19dd 715 SCM str;
0f2d19dd
JB
716{
717 int ans;
02b754d3 718
89958ad0
JB
719 SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, SCM_ARG1, s_chdir);
720 SCM_COERCE_SUBSTR (str);
721 SCM_SYSCALL (ans = chdir (SCM_ROCHARS (str)));
02b754d3 722 if (ans != 0)
3d8d56df 723 scm_syserror (s_chdir);
02b754d3 724 return SCM_UNSPECIFIED;
0f2d19dd
JB
725}
726
727
728
3d8d56df 729SCM_PROC (s_getcwd, "getcwd", 0, 0, 0, scm_getcwd);
1cc91f1b 730
0f2d19dd 731SCM
3d8d56df 732scm_getcwd ()
0f2d19dd
JB
733{
734#ifdef HAVE_GETCWD
735 char *rv;
736
737 scm_sizet size = 100;
738 char *wd;
739 SCM result;
740
3d8d56df 741 wd = scm_must_malloc (size, s_getcwd);
0f2d19dd
JB
742 while ((rv = getcwd (wd, size)) == 0 && errno == ERANGE)
743 {
744 scm_must_free (wd);
745 size *= 2;
3d8d56df 746 wd = scm_must_malloc (size, s_getcwd);
0f2d19dd 747 }
02b754d3 748 if (rv == 0)
3d8d56df 749 scm_syserror (s_getcwd);
02b754d3 750 result = scm_makfromstr (wd, strlen (wd), 0);
0f2d19dd 751 scm_must_free (wd);
0f2d19dd
JB
752 return result;
753#else
3d8d56df 754 scm_sysmissing (s_getcwd);
02b754d3
GH
755 /* not reached. */
756 return SCM_BOOL_F;
0f2d19dd
JB
757#endif
758}
759
760\f
761
cafc12ff
MD
762SCM_PROC (s_select, "select", 3, 2, 0, scm_select);
763
1cc91f1b 764
cafc12ff
MD
765static int
766set_element (SELECT_TYPE *set, SCM element, int arg)
a48a89bc 767{
cafc12ff 768 int fd;
78446828 769 element = SCM_COERCE_OUTPORT (element);
77a76b64
JB
770 if (SCM_NIMP (element) && SCM_OPFPORTP (element))
771 fd = SCM_FPORT_FDES (element);
cafc12ff
MD
772 else {
773 SCM_ASSERT (SCM_INUMP (element), element, arg, s_select);
774 fd = SCM_INUM (element);
775 }
776 FD_SET (fd, set);
777 return fd;
a48a89bc 778}
1cc91f1b 779
cafc12ff
MD
780static int
781fill_select_type (SELECT_TYPE *set, SCM list, int arg)
0f2d19dd 782{
cafc12ff 783 int max_fd = 0, fd;
a48a89bc 784 if (SCM_NIMP (list) && SCM_VECTORP (list))
0f2d19dd 785 {
a48a89bc
GH
786 int len = SCM_LENGTH (list);
787 SCM *ve = SCM_VELTS (list);
788
789 while (len > 0)
790 {
cafc12ff
MD
791 fd = set_element (set, ve[len - 1], arg);
792 if (fd > max_fd)
793 max_fd = fd;
a48a89bc
GH
794 len--;
795 }
796 }
797 else
798 {
799 while (list != SCM_EOL)
800 {
cafc12ff
MD
801 fd = set_element (set, SCM_CAR (list), arg);
802 if (fd > max_fd)
803 max_fd = fd;
a48a89bc
GH
804 list = SCM_CDR (list);
805 }
0f2d19dd 806 }
cafc12ff
MD
807
808 return max_fd;
0f2d19dd
JB
809}
810
a48a89bc
GH
811static SCM
812get_element (SELECT_TYPE *set, SCM element, SCM list)
813{
78446828 814 element = SCM_COERCE_OUTPORT (element);
77a76b64 815 if (SCM_NIMP (element) && SCM_OPFPORTP (element))
a48a89bc 816 {
77a76b64 817 if (FD_ISSET (SCM_FPORT_FDES (element), set))
a48a89bc
GH
818 list = scm_cons (element, list);
819 }
820 else if (SCM_INUMP (element))
821 {
822 if (FD_ISSET (SCM_INUM (element), set))
823 list = scm_cons (element, list);
824 }
825 return list;
826}
1cc91f1b 827
0f2d19dd 828static SCM
a48a89bc 829retrieve_select_type (SELECT_TYPE *set, SCM list)
0f2d19dd 830{
a48a89bc
GH
831 SCM answer_list = SCM_EOL;
832
833 if (SCM_NIMP (list) && SCM_VECTORP (list))
0f2d19dd 834 {
a48a89bc
GH
835 int len = SCM_LENGTH (list);
836 SCM *ve = SCM_VELTS (list);
837
838 while (len > 0)
0f2d19dd 839 {
a48a89bc
GH
840 answer_list = get_element (set, ve[len - 1], answer_list);
841 len--;
0f2d19dd 842 }
a48a89bc
GH
843 return scm_vector (answer_list);
844 }
845 else
846 {
847 /* list is a list. */
848 while (list != SCM_EOL)
0f2d19dd 849 {
a48a89bc
GH
850 answer_list = get_element (set, SCM_CAR (list), answer_list);
851 list = SCM_CDR (list);
0f2d19dd 852 }
a48a89bc 853 return answer_list;
0f2d19dd 854 }
0f2d19dd
JB
855}
856
857
0f2d19dd 858SCM
a48a89bc 859scm_select (reads, writes, excepts, secs, usecs)
0f2d19dd
JB
860 SCM reads;
861 SCM writes;
862 SCM excepts;
863 SCM secs;
a48a89bc 864 SCM usecs;
0f2d19dd
JB
865{
866#ifdef HAVE_SELECT
867 struct timeval timeout;
868 struct timeval * time_p;
869 SELECT_TYPE read_set;
870 SELECT_TYPE write_set;
871 SELECT_TYPE except_set;
cafc12ff 872 int max_fd, fd;
0f2d19dd
JB
873 int sreturn;
874
a48a89bc
GH
875#define assert_set(x, arg) \
876 SCM_ASSERT (scm_ilength (x) > -1 || (SCM_NIMP (x) && SCM_VECTORP (x)), \
877 x, arg, s_select)
878 assert_set (reads, SCM_ARG1);
879 assert_set (writes, SCM_ARG2);
880 assert_set (excepts, SCM_ARG3);
881#undef assert_set
0f2d19dd
JB
882
883 FD_ZERO (&read_set);
884 FD_ZERO (&write_set);
885 FD_ZERO (&except_set);
886
cafc12ff
MD
887 max_fd = fill_select_type (&read_set, reads, SCM_ARG1);
888 fd = fill_select_type (&write_set, writes, SCM_ARG2);
889 if (fd > max_fd)
890 max_fd = fd;
891 fd = fill_select_type (&except_set, excepts, SCM_ARG3);
892 if (fd > max_fd)
893 max_fd = fd;
0f2d19dd 894
a48a89bc 895 if (SCM_UNBNDP (secs) || SCM_FALSEP (secs))
0f2d19dd
JB
896 time_p = 0;
897 else
898 {
a48a89bc
GH
899 if (SCM_INUMP (secs))
900 {
901 timeout.tv_sec = SCM_INUM (secs);
902 if (SCM_UNBNDP (usecs))
903 timeout.tv_usec = 0;
904 else
905 {
906 SCM_ASSERT (SCM_INUMP (usecs), usecs, SCM_ARG5, s_select);
907
908 timeout.tv_usec = SCM_INUM (usecs);
909 }
910 }
0f2d19dd 911 else
a48a89bc
GH
912 {
913 double fl = scm_num2dbl (secs, s_select);
914
915 if (!SCM_UNBNDP (usecs))
916 scm_wrong_type_arg (s_select, 4, secs);
917 if (fl > LONG_MAX)
918 scm_out_of_range (s_select, secs);
919 timeout.tv_sec = (long) fl;
920 timeout.tv_usec = (long) ((fl - timeout.tv_sec) * 1000000);
921 }
0f2d19dd
JB
922 time_p = &timeout;
923 }
924
44e8413c 925#ifdef GUILE_ISELECT
cafc12ff 926 sreturn = scm_internal_select (max_fd + 1,
44e8413c
MD
927 &read_set, &write_set, &except_set, time_p);
928#else
cafc12ff 929 sreturn = select (max_fd + 1,
0f2d19dd 930 &read_set, &write_set, &except_set, time_p);
44e8413c 931#endif
0f2d19dd 932 if (sreturn < 0)
3d8d56df 933 scm_syserror (s_select);
02b754d3
GH
934 return scm_listify (retrieve_select_type (&read_set, reads),
935 retrieve_select_type (&write_set, writes),
936 retrieve_select_type (&except_set, excepts),
937 SCM_UNDEFINED);
0f2d19dd 938#else
3d8d56df 939 scm_sysmissing (s_select);
02b754d3
GH
940 /* not reached. */
941 return SCM_BOOL_F;
0f2d19dd
JB
942#endif
943}
944
945\f
4c1feaa5 946
6afcd3b2 947SCM_PROC (s_fcntl, "fcntl", 2, 0, 1, scm_fcntl);
4c1feaa5 948SCM
6afcd3b2 949scm_fcntl (SCM object, SCM cmd, SCM value)
4c1feaa5
JB
950{
951 int rv;
6afcd3b2
GH
952 int fdes;
953 int ivalue;
4c1feaa5 954
78446828
MV
955 object = SCM_COERCE_OUTPORT (object);
956
4c1feaa5 957 SCM_ASSERT (SCM_INUMP (cmd), cmd, SCM_ARG2, s_fcntl);
6afcd3b2 958 if (SCM_NIMP (object) && SCM_OPFPORTP (object))
77a76b64 959 fdes = SCM_FPORT_FDES (object);
6afcd3b2
GH
960 else
961 {
962 SCM_ASSERT (SCM_INUMP (object), object, SCM_ARG1, s_fcntl);
963 fdes = SCM_INUM (object);
964 }
965 if (SCM_NULLP (value))
966 ivalue = 0;
967 else
968 {
969 SCM_ASSERT (SCM_INUMP (SCM_CAR (value)), value, SCM_ARG3, s_fcntl);
970 ivalue = SCM_INUM (SCM_CAR (value));
971 }
77a76b64
JB
972 SCM_SYSCALL (rv = fcntl (fdes, SCM_INUM (cmd), ivalue));
973 if (rv == -1)
4c1feaa5
JB
974 scm_syserror (s_fcntl);
975 return SCM_MAKINUM (rv);
976}
6afcd3b2
GH
977
978SCM_PROC (s_fsync, "fsync", 1, 0, 0, scm_fsync);
979SCM
980scm_fsync (SCM object)
981{
982 int fdes;
983
78446828
MV
984 object = SCM_COERCE_OUTPORT (object);
985
6afcd3b2
GH
986 if (SCM_NIMP (object) && SCM_OPFPORTP (object))
987 {
77a76b64
JB
988 scm_fflush (object);
989 fdes = SCM_FPORT_FDES (object);
6afcd3b2
GH
990 }
991 else
992 {
993 SCM_ASSERT (SCM_INUMP (object), object, SCM_ARG1, s_fsync);
994 fdes = SCM_INUM (object);
995 }
996 if (fsync (fdes) == -1)
997 scm_syserror (s_fsync);
6afcd3b2
GH
998 return SCM_UNSPECIFIED;
999}
0f2d19dd 1000
3d8d56df 1001SCM_PROC (s_symlink, "symlink", 2, 0, 0, scm_symlink);
1cc91f1b 1002
0f2d19dd 1003SCM
3d8d56df 1004scm_symlink(oldpath, newpath)
0f2d19dd
JB
1005 SCM oldpath;
1006 SCM newpath;
0f2d19dd
JB
1007{
1008#ifdef HAVE_SYMLINK
1009 int val;
02b754d3 1010
89958ad0
JB
1011 SCM_ASSERT (SCM_NIMP (oldpath) && SCM_ROSTRINGP (oldpath), oldpath, SCM_ARG1,
1012 s_symlink);
1013 SCM_ASSERT (SCM_NIMP (newpath) && SCM_ROSTRINGP (newpath), newpath, SCM_ARG2,
1014 s_symlink);
1015 SCM_COERCE_SUBSTR (oldpath);
1016 SCM_COERCE_SUBSTR (newpath);
1017 SCM_SYSCALL (val = symlink(SCM_ROCHARS(oldpath), SCM_ROCHARS(newpath)));
02b754d3 1018 if (val != 0)
3d8d56df 1019 scm_syserror (s_symlink);
02b754d3 1020 return SCM_UNSPECIFIED;
0f2d19dd 1021#else
3d8d56df 1022 scm_sysmissing (s_symlink);
02b754d3
GH
1023 /* not reached. */
1024 return SCM_BOOL_F;
0f2d19dd
JB
1025#endif
1026}
1027
1028
3d8d56df 1029SCM_PROC (s_readlink, "readlink", 1, 0, 0, scm_readlink);
1cc91f1b 1030
0f2d19dd 1031SCM
3d8d56df 1032scm_readlink(path)
0f2d19dd 1033 SCM path;
0f2d19dd
JB
1034{
1035#ifdef HAVE_READLINK
6a738a25
JB
1036 int rv;
1037 int size = 100;
0f2d19dd
JB
1038 char *buf;
1039 SCM result;
89958ad0
JB
1040 SCM_ASSERT (SCM_NIMP (path) && SCM_ROSTRINGP (path), path, (char *) SCM_ARG1,
1041 s_readlink);
1042 SCM_COERCE_SUBSTR (path);
3d8d56df 1043 buf = scm_must_malloc (size, s_readlink);
6a738a25 1044 while ((rv = readlink (SCM_ROCHARS (path), buf, size)) == size)
0f2d19dd
JB
1045 {
1046 scm_must_free (buf);
1047 size *= 2;
3d8d56df 1048 buf = scm_must_malloc (size, s_readlink);
0f2d19dd 1049 }
02b754d3 1050 if (rv == -1)
3d8d56df 1051 scm_syserror (s_readlink);
02b754d3 1052 result = scm_makfromstr (buf, rv, 0);
0f2d19dd 1053 scm_must_free (buf);
0f2d19dd
JB
1054 return result;
1055#else
3d8d56df 1056 scm_sysmissing (s_readlink);
02b754d3
GH
1057 /* not reached. */
1058 return SCM_BOOL_F;
0f2d19dd
JB
1059#endif
1060}
1061
1062
3d8d56df 1063SCM_PROC (s_lstat, "lstat", 1, 0, 0, scm_lstat);
1cc91f1b 1064
0f2d19dd 1065SCM
3d8d56df 1066scm_lstat(str)
0f2d19dd 1067 SCM str;
0f2d19dd 1068{
02b754d3
GH
1069#ifdef HAVE_LSTAT
1070 int rv;
0f2d19dd 1071 struct stat stat_temp;
02b754d3 1072
89958ad0
JB
1073 SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, (char *) SCM_ARG1,
1074 s_lstat);
1075 SCM_COERCE_SUBSTR (str);
1076 SCM_SYSCALL(rv = lstat(SCM_ROCHARS(str), &stat_temp));
02b754d3 1077 if (rv != 0)
3d8d56df
GH
1078 {
1079 int en = errno;
1080
1081 scm_syserror_msg (s_lstat, "%s: %S",
1082 scm_listify (scm_makfrom0str (strerror (errno)),
1083 str,
1084 SCM_UNDEFINED),
1085 en);
1086 }
02b754d3 1087 return scm_stat2scm(&stat_temp);
0f2d19dd 1088#else
3d8d56df 1089 scm_sysmissing (s_lstat);
02b754d3
GH
1090 /* not reached. */
1091 return SCM_BOOL_F;
0f2d19dd
JB
1092#endif
1093}
1094
1095
3d8d56df 1096SCM_PROC (s_copy_file, "copy-file", 2, 0, 0, scm_copy_file);
1cc91f1b 1097
0f2d19dd 1098SCM
3d8d56df 1099scm_copy_file (oldfile, newfile)
0f2d19dd
JB
1100 SCM oldfile;
1101 SCM newfile;
0f2d19dd
JB
1102{
1103 int oldfd, newfd;
1104 int n;
77a76b64 1105 char buf[BUFSIZ];
0f2d19dd
JB
1106 struct stat oldstat;
1107
3d8d56df 1108 SCM_ASSERT (SCM_NIMP (oldfile) && SCM_ROSTRINGP (oldfile), oldfile, SCM_ARG1, s_copy_file);
0f2d19dd
JB
1109 if (SCM_SUBSTRP (oldfile))
1110 oldfile = scm_makfromstr (SCM_ROCHARS (oldfile), SCM_ROLENGTH (oldfile), 0);
3d8d56df 1111 SCM_ASSERT (SCM_NIMP (newfile) && SCM_ROSTRINGP (newfile), newfile, SCM_ARG2, s_copy_file);
0f2d19dd
JB
1112 if (SCM_SUBSTRP (newfile))
1113 newfile = scm_makfromstr (SCM_ROCHARS (newfile), SCM_ROLENGTH (newfile), 0);
1114 if (stat (SCM_ROCHARS (oldfile), &oldstat) == -1)
3d8d56df 1115 scm_syserror (s_copy_file);
0f2d19dd
JB
1116 oldfd = open (SCM_ROCHARS (oldfile), O_RDONLY);
1117 if (oldfd == -1)
3d8d56df 1118 scm_syserror (s_copy_file);
02b754d3
GH
1119
1120 /* use POSIX flags instead of 07777?. */
0f2d19dd
JB
1121 newfd = open (SCM_ROCHARS (newfile), O_WRONLY | O_CREAT | O_TRUNC,
1122 oldstat.st_mode & 07777);
1123 if (newfd == -1)
3d8d56df 1124 scm_syserror (s_copy_file);
02b754d3 1125
0f2d19dd
JB
1126 while ((n = read (oldfd, buf, sizeof buf)) > 0)
1127 if (write (newfd, buf, n) != n)
1128 {
1129 close (oldfd);
1130 close (newfd);
3d8d56df 1131 scm_syserror (s_copy_file);
0f2d19dd
JB
1132 }
1133 close (oldfd);
1134 if (close (newfd) == -1)
3d8d56df 1135 scm_syserror (s_copy_file);
02b754d3 1136 return SCM_UNSPECIFIED;
0f2d19dd
JB
1137}
1138
1139\f
6a738a25
JB
1140/* Filename manipulation */
1141
1142SCM scm_dot_string;
1143
1144SCM_PROC (s_dirname, "dirname", 1, 0, 0, scm_dirname);
1145
1146SCM
1147scm_dirname (SCM filename)
1148{
1149 char *s;
1150 int i, len;
1151 SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename),
1152 filename,
1153 SCM_ARG1,
1154 s_dirname);
1155 s = SCM_ROCHARS (filename);
1156 len = SCM_LENGTH (filename);
1157 i = len - 1;
1158 while (i >= 0 && s[i] == '/') --i;
1159 while (i >= 0 && s[i] != '/') --i;
1160 while (i >= 0 && s[i] == '/') --i;
1161 if (i < 0)
1162 {
1163 if (len > 0 && s[0] == '/')
1164 return scm_make_shared_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
1165 else
1166 return scm_dot_string;
1167 }
1168 else
1169 return scm_make_shared_substring (filename, SCM_INUM0, SCM_MAKINUM (i + 1));
1170}
1171
1172SCM_PROC (s_basename, "basename", 1, 1, 0, scm_basename);
1173
1174SCM
1175scm_basename (SCM filename, SCM suffix)
1176{
1177 char *f, *s = 0;
1178 int i, j, len, end;
1179 SCM_ASSERT (SCM_NIMP (filename) && SCM_ROSTRINGP (filename),
1180 filename,
1181 SCM_ARG1,
1182 s_basename);
1183 SCM_ASSERT (SCM_UNBNDP (suffix)
1184 || (SCM_NIMP (suffix) && SCM_ROSTRINGP (suffix)),
1185 suffix,
1186 SCM_ARG2,
1187 s_basename);
1188 f = SCM_ROCHARS (filename);
1189 if (SCM_UNBNDP (suffix))
1190 j = -1;
1191 else
1192 {
1193 s = SCM_ROCHARS (suffix);
1194 j = SCM_LENGTH (suffix) - 1;
1195 }
1196 len = SCM_LENGTH (filename);
1197 i = len - 1;
1198 while (i >= 0 && f[i] == '/') --i;
1199 end = i;
1200 while (i >= 0 && j >= 0 && f[i] == s[j]) --i, --j;
1201 if (j == -1)
1202 end = i;
1203 while (i >= 0 && f[i] != '/') --i;
1204 if (i == end)
1205 {
1206 if (len > 0 && f[0] == '/')
1207 return scm_make_shared_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
1208 else
1209 return scm_dot_string;
1210 }
1211 else
1212 return scm_make_shared_substring (filename,
1213 SCM_MAKINUM (i + 1),
1214 SCM_MAKINUM (end + 1));
1215}
1216
1217
1218
1219\f
1cc91f1b 1220
0f2d19dd
JB
1221void
1222scm_init_filesys ()
0f2d19dd 1223{
52f4f4d6 1224 scm_add_feature ("i/o-extensions");
0f2d19dd 1225
23a62151
MD
1226 scm_tc16_dir = scm_make_smob_type_mfpe ("directory", 0,
1227 NULL, scm_dir_free,scm_dir_print, NULL);
0f2d19dd 1228
a163dda9
MD
1229 scm_dot_string = scm_permanent_object (scm_makfrom0str ("."));
1230
3d8d56df
GH
1231#ifdef O_RDONLY
1232scm_sysintern ("O_RDONLY", scm_long2num (O_RDONLY));
1233#endif
1234#ifdef O_WRONLY
1235scm_sysintern ("O_WRONLY", scm_long2num (O_WRONLY));
1236#endif
1237#ifdef O_RDWR
1238scm_sysintern ("O_RDWR", scm_long2num (O_RDWR));
1239#endif
1240#ifdef O_CREAT
1241scm_sysintern ("O_CREAT", scm_long2num (O_CREAT));
1242#endif
1243#ifdef O_EXCL
1244scm_sysintern ("O_EXCL", scm_long2num (O_EXCL));
1245#endif
1246#ifdef O_NOCTTY
1247scm_sysintern ("O_NOCTTY", scm_long2num (O_NOCTTY));
1248#endif
1249#ifdef O_TRUNC
1250scm_sysintern ("O_TRUNC", scm_long2num (O_TRUNC));
1251#endif
1252#ifdef O_APPEND
1253scm_sysintern ("O_APPEND", scm_long2num (O_APPEND));
1254#endif
6afcd3b2 1255#ifdef O_NONBLOCK
3d8d56df
GH
1256scm_sysintern ("O_NONBLOCK", scm_long2num (O_NONBLOCK));
1257#endif
1258#ifdef O_NDELAY
1259scm_sysintern ("O_NDELAY", scm_long2num (O_NDELAY));
1260#endif
1261#ifdef O_SYNC
1262scm_sysintern ("O_SYNC", scm_long2num (O_SYNC));
1263#endif
1264
4c1feaa5
JB
1265#ifdef F_DUPFD
1266scm_sysintern ("F_DUPFD", scm_long2num (F_DUPFD));
1267#endif
1268#ifdef F_GETFD
1269scm_sysintern ("F_GETFD", scm_long2num (F_GETFD));
1270#endif
1271#ifdef F_SETFD
1272scm_sysintern ("F_SETFD", scm_long2num (F_SETFD));
1273#endif
1274#ifdef F_GETFL
1275scm_sysintern ("F_GETFL", scm_long2num (F_GETFL));
1276#endif
1277#ifdef F_SETFL
1278scm_sysintern ("F_SETFL", scm_long2num (F_SETFL));
1279#endif
1280#ifdef F_GETOWN
1281scm_sysintern ("F_GETOWN", scm_long2num (F_GETOWN));
1282#endif
1283#ifdef F_SETOWN
1284scm_sysintern ("F_SETOWN", scm_long2num (F_SETOWN));
1285#endif
1286#ifdef FD_CLOEXEC
1287scm_sysintern ("FD_CLOEXEC", scm_long2num (FD_CLOEXEC));
1288#endif
3d8d56df 1289
0f2d19dd
JB
1290#include "filesys.x"
1291}