(Hash Table Reference): In scm_hash_ref etc,
[bpt/guile.git] / libguile / filesys.c
CommitLineData
3d7f708f 1/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2002 Free Software Foundation, Inc.
0f2d19dd 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
0f2d19dd 7 *
73be1d9e
MV
8 * This library 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 GNU
11 * Lesser General Public License for more details.
0f2d19dd 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd 19\f
83079454
RB
20#if HAVE_CONFIG_H
21# include <config.h>
22#endif
23
3d8d56df 24#include <stdio.h>
e6e2e95a
MD
25#include <errno.h>
26
a0599745
MD
27#include "libguile/_scm.h"
28#include "libguile/smob.h"
29#include "libguile/feature.h"
30#include "libguile/fports.h"
31#include "libguile/iselect.h"
32#include "libguile/strings.h"
33#include "libguile/vectors.h"
c96d76b8 34#include "libguile/lang.h"
0f2d19dd 35
a0599745
MD
36#include "libguile/validate.h"
37#include "libguile/filesys.h"
def804a3 38
0f2d19dd 39\f
def804a3
JB
40#ifdef HAVE_IO_H
41#include <io.h>
42#endif
43
e0c73a1c
MV
44#ifdef HAVE_DIRECT_H
45#include <direct.h>
46#endif
47
0f2d19dd
JB
48#ifdef TIME_WITH_SYS_TIME
49# include <sys/time.h>
50# include <time.h>
51#else
52# if HAVE_SYS_TIME_H
53# include <sys/time.h>
54# else
55# include <time.h>
56# endif
57#endif
58
59#ifdef HAVE_UNISTD_H
60#include <unistd.h>
61#endif
62
3594582b 63#ifdef LIBC_H_WITH_UNISTD_H
1f9e2226
JB
64#include <libc.h>
65#endif
66
0f2d19dd
JB
67#ifdef HAVE_SYS_SELECT_H
68#include <sys/select.h>
69#endif
70
1f9e2226
JB
71#ifdef HAVE_STRING_H
72#include <string.h>
73#endif
74
8cc71382 75#include <sys/types.h>
0f2d19dd
JB
76#include <sys/stat.h>
77#include <fcntl.h>
78
82893676 79#ifdef HAVE_PWD_H
0f2d19dd 80#include <pwd.h>
82893676 81#endif
0f2d19dd
JB
82
83
e0c73a1c
MV
84#if defined (__MINGW32__) || defined (_MSC_VER) || defined (__BORLANDC__)
85# include "win32-dirent.h"
86# define NAMLEN(dirent) strlen((dirent)->d_name)
87#elif HAVE_DIRENT_H
0f2d19dd
JB
88# include <dirent.h>
89# define NAMLEN(dirent) strlen((dirent)->d_name)
90#else
91# define dirent direct
92# define NAMLEN(dirent) (dirent)->d_namlen
93# if HAVE_SYS_NDIR_H
94# include <sys/ndir.h>
95# endif
96# if HAVE_SYS_DIR_H
97# include <sys/dir.h>
98# endif
99# if HAVE_NDIR_H
100# include <ndir.h>
101# endif
102#endif
103
d7b8a21a
JB
104/* Ultrix has S_IFSOCK, but no S_ISSOCK. Ipe! */
105#if defined (S_IFSOCK) && ! defined (S_ISSOCK)
106#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
107#endif
82893676
MG
108
109/* The MinGW gcc does not define the S_ISSOCK macro. Any other native Windows
110 compiler like BorlandC or MSVC has none of these macros defined. */
111#ifdef __MINGW32__
8f99e3f3
SJ
112
113# ifdef _S_IFIFO
114# undef _S_IFIFO
115# endif
116# ifdef _S_IFCHR
117# undef _S_IFCHR
118# endif
119# ifdef _S_IFBLK
120# undef _S_IFBLK
121# endif
122# ifdef _S_IFDIR
123# undef _S_IFDIR
124# endif
125# ifdef _S_IFREG
126# undef _S_IFREG
127# endif
128# ifdef _S_IFSOCK
129# undef _S_IFSOCK
130# endif
131
132# define _S_IFIFO 0x1000 /* FIFO */
133# define _S_IFCHR 0x2000 /* Character */
134# define _S_IFBLK 0x3000 /* Block */
135# define _S_IFDIR 0x4000 /* Directory */
136# define _S_IFREG 0x8000 /* Regular */
137# define _S_IFSOCK 0xC000 /* Socket */
138
139# ifdef S_ISBLK
140# undef S_ISBLK
141# endif
142# ifdef S_ISFIFO
143# undef S_ISFIFO
144# endif
145# ifdef S_ISCHR
146# undef S_ISCHR
147# endif
148# ifdef S_ISDIR
149# undef S_ISDIR
150# endif
151# ifdef S_ISREG
152# undef S_ISREG
153# endif
154# ifdef S_ISSOCK
155# undef S_ISSOCK
156# endif
157
158# define S_ISBLK(mode) (((mode) & _S_IFMT) == _S_IFBLK)
82893676 159# define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
8f99e3f3
SJ
160# define S_ISCHR(mode) (((mode) & _S_IFMT) == _S_IFCHR)
161# define S_ISDIR(mode) (((mode) & _S_IFMT) == _S_IFDIR)
162# define S_ISREG(mode) (((mode) & _S_IFMT) == _S_IFREG)
163# define S_ISSOCK(mode) (((mode) & _S_IFMT) == _S_IFSOCK)
164
165#endif /* __MINGW32__ */
82893676
MG
166
167/* Some more definitions for the native Windows port. */
168#ifdef __MINGW32__
169# define mkdir(path, mode) mkdir (path)
170# define fsync(fd) _commit (fd)
171# define fchmod(fd, mode) (-1)
172#endif /* __MINGW32__ */
0f2d19dd
JB
173\f
174
0f2d19dd
JB
175
176\f
177
178/* {Permissions}
179 */
180
82893676 181#ifdef HAVE_CHOWN
a1ec6916 182SCM_DEFINE (scm_chown, "chown", 3, 0, 0,
1bbd0b84 183 (SCM object, SCM owner, SCM group),
d831b039
GH
184 "Change the ownership and group of the file referred to by @var{object} to\n"
185 "the integer values @var{owner} and @var{group}. @var{object} can be\n"
186 "a string containing a file name or, if the platform\n"
187 "supports fchown, a port or integer file descriptor\n"
188 "which is open on the file. The return value\n"
d3818c29 189 "is unspecified.\n\n"
d831b039 190 "If @var{object} is a symbolic link, either the\n"
d3818c29
MD
191 "ownership of the link or the ownership of the referenced file will be\n"
192 "changed depending on the operating system (lchown is\n"
193 "unsupported at present). If @var{owner} or @var{group} is specified\n"
194 "as @code{-1}, then that ID is not changed.")
1bbd0b84 195#define FUNC_NAME s_scm_chown
0f2d19dd 196{
6afcd3b2 197 int rv;
02b754d3 198
78446828
MV
199 object = SCM_COERCE_OUTPORT (object);
200
34d19ef6
HWN
201 SCM_VALIDATE_INUM (2, owner);
202 SCM_VALIDATE_INUM (3, group);
d831b039 203#ifdef HAVE_FCHOWN
0c95b57d 204 if (SCM_INUMP (object) || (SCM_OPFPORTP (object)))
6afcd3b2 205 {
d831b039
GH
206 int fdes = SCM_INUMP (object) ? SCM_INUM (object)
207 : SCM_FPORT_FDES (object);
208
6afcd3b2
GH
209 SCM_SYSCALL (rv = fchown (fdes, SCM_INUM (owner), SCM_INUM (group)));
210 }
211 else
d831b039 212#endif
6afcd3b2 213 {
a6d9e5ab 214 SCM_VALIDATE_STRING (1, object);
a6d9e5ab 215 SCM_SYSCALL (rv = chown (SCM_STRING_CHARS (object),
6afcd3b2
GH
216 SCM_INUM (owner), SCM_INUM (group)));
217 }
218 if (rv == -1)
1bbd0b84 219 SCM_SYSERROR;
02b754d3 220 return SCM_UNSPECIFIED;
0f2d19dd 221}
1bbd0b84 222#undef FUNC_NAME
82893676 223#endif /* HAVE_CHOWN */
0f2d19dd
JB
224
225
a1ec6916 226SCM_DEFINE (scm_chmod, "chmod", 2, 0, 0,
1bbd0b84 227 (SCM object, SCM mode),
d3818c29
MD
228 "Changes the permissions of the file referred to by @var{obj}.\n"
229 "@var{obj} can be a string containing a file name or a port or integer file\n"
230 "descriptor which is open on a file (in which case @code{fchmod} is used\n"
231 "as the underlying system call).\n"
232 "@var{mode} specifies\n"
233 "the new permissions as a decimal number, e.g., @code{(chmod \"foo\" #o755)}.\n"
234 "The return value is unspecified.")
1bbd0b84 235#define FUNC_NAME s_scm_chmod
0f2d19dd
JB
236{
237 int rv;
6afcd3b2
GH
238 int fdes;
239
78446828
MV
240 object = SCM_COERCE_OUTPORT (object);
241
34d19ef6 242 SCM_VALIDATE_INUM (2, mode);
0c95b57d 243 if (SCM_INUMP (object) || SCM_OPFPORTP (object))
89958ad0 244 {
6afcd3b2
GH
245 if (SCM_INUMP (object))
246 fdes = SCM_INUM (object);
247 else
77a76b64 248 fdes = SCM_FPORT_FDES (object);
6afcd3b2 249 SCM_SYSCALL (rv = fchmod (fdes, SCM_INUM (mode)));
89958ad0 250 }
0f2d19dd
JB
251 else
252 {
a6d9e5ab 253 SCM_VALIDATE_STRING (1, object);
a6d9e5ab 254 SCM_SYSCALL (rv = chmod (SCM_STRING_CHARS (object), SCM_INUM (mode)));
0f2d19dd 255 }
6afcd3b2 256 if (rv == -1)
1bbd0b84 257 SCM_SYSERROR;
02b754d3 258 return SCM_UNSPECIFIED;
0f2d19dd 259}
1bbd0b84 260#undef FUNC_NAME
0f2d19dd 261
a1ec6916 262SCM_DEFINE (scm_umask, "umask", 0, 1, 0,
1bbd0b84 263 (SCM mode),
bb2c02f2 264 "If @var{mode} is omitted, returns a decimal number representing the current\n"
d3818c29
MD
265 "file creation mask. Otherwise the file creation mask is set to\n"
266 "@var{mode} and the previous value is returned.\n\n"
267 "E.g., @code{(umask #o022)} sets the mask to octal 22, decimal 18.")
1bbd0b84 268#define FUNC_NAME s_scm_umask
0f2d19dd
JB
269{
270 mode_t mask;
271 if (SCM_UNBNDP (mode))
272 {
273 mask = umask (0);
274 umask (mask);
275 }
276 else
277 {
34d19ef6 278 SCM_VALIDATE_INUM (1, mode);
0f2d19dd
JB
279 mask = umask (SCM_INUM (mode));
280 }
281 return SCM_MAKINUM (mask);
282}
1bbd0b84 283#undef FUNC_NAME
0f2d19dd
JB
284
285\f
0f2d19dd 286
a1ec6916 287SCM_DEFINE (scm_open_fdes, "open-fdes", 2, 1, 0,
1bbd0b84 288 (SCM path, SCM flags, SCM mode),
1e6808ea
MG
289 "Similar to @code{open} but return a file descriptor instead of\n"
290 "a port.")
1bbd0b84 291#define FUNC_NAME s_scm_open_fdes
0f2d19dd
JB
292{
293 int fd;
3d8d56df 294 int iflags;
6afcd3b2 295 int imode;
0f2d19dd 296
a6d9e5ab 297 SCM_VALIDATE_STRING (1, path);
1be6b49c
ML
298 iflags = SCM_NUM2INT (2, flags);
299 imode = SCM_NUM2INT_DEF (3, mode, 0666);
a6d9e5ab 300 SCM_SYSCALL (fd = open (SCM_STRING_CHARS (path), iflags, imode));
3d8d56df 301 if (fd == -1)
1bbd0b84 302 SCM_SYSERROR;
6afcd3b2
GH
303 return SCM_MAKINUM (fd);
304}
1bbd0b84 305#undef FUNC_NAME
6afcd3b2 306
a1ec6916 307SCM_DEFINE (scm_open, "open", 2, 1, 0,
1bbd0b84 308 (SCM path, SCM flags, SCM mode),
d3818c29
MD
309 "Open the file named by @var{path} for reading and/or writing.\n"
310 "@var{flags} is an integer specifying how the file should be opened.\n"
311 "@var{mode} is an integer specifying the permission bits of the file, if\n"
312 "it needs to be created, before the umask is applied. The default is 666\n"
313 "(Unix itself has no default).\n\n"
314 "@var{flags} can be constructed by combining variables using @code{logior}.\n"
315 "Basic flags are:\n\n"
316 "@defvar O_RDONLY\n"
317 "Open the file read-only.\n"
318 "@end defvar\n"
319 "@defvar O_WRONLY\n"
9401323e 320 "Open the file write-only.\n"
d3818c29
MD
321 "@end defvar\n"
322 "@defvar O_RDWR\n"
323 "Open the file read/write.\n"
324 "@end defvar\n"
325 "@defvar O_APPEND\n"
326 "Append to the file instead of truncating.\n"
327 "@end defvar\n"
328 "@defvar O_CREAT\n"
329 "Create the file if it does not already exist.\n"
330 "@end defvar\n\n"
331 "See the Unix documentation of the @code{open} system call\n"
332 "for additional flags.")
1bbd0b84 333#define FUNC_NAME s_scm_open
6afcd3b2
GH
334{
335 SCM newpt;
336 char *port_mode;
337 int fd;
6afcd3b2
GH
338 int iflags;
339
340 fd = SCM_INUM (scm_open_fdes (path, flags, mode));
1be6b49c 341 iflags = SCM_NUM2INT (2, flags);
3d8d56df 342 if (iflags & O_RDWR)
77a76b64
JB
343 {
344 if (iflags & O_APPEND)
345 port_mode = "a+";
346 else if (iflags & O_CREAT)
347 port_mode = "w+";
348 else
349 port_mode = "r+";
350 }
3d8d56df 351 else {
77a76b64
JB
352 if (iflags & O_APPEND)
353 port_mode = "a";
354 else if (iflags & O_WRONLY)
3d8d56df
GH
355 port_mode = "w";
356 else
357 port_mode = "r";
358 }
77a76b64 359 newpt = scm_fdes_to_port (fd, port_mode, path);
3d8d56df 360 return newpt;
0f2d19dd 361}
1bbd0b84 362#undef FUNC_NAME
0f2d19dd 363
a1ec6916 364SCM_DEFINE (scm_close, "close", 1, 0, 0,
1bbd0b84 365 (SCM fd_or_port),
8f85c0c6 366 "Similar to close-port (@pxref{Closing, close-port}),\n"
d3818c29
MD
367 "but also works on file descriptors. A side\n"
368 "effect of closing a file descriptor is that any ports using that file\n"
369 "descriptor are moved to a different file descriptor and have\n"
370 "their revealed counts set to zero.")
1bbd0b84 371#define FUNC_NAME s_scm_close
eadd48de
GH
372{
373 int rv;
374 int fd;
375
78446828
MV
376 fd_or_port = SCM_COERCE_OUTPORT (fd_or_port);
377
0c95b57d 378 if (SCM_PORTP (fd_or_port))
eadd48de 379 return scm_close_port (fd_or_port);
34d19ef6 380 SCM_VALIDATE_INUM (1, fd_or_port);
eadd48de 381 fd = SCM_INUM (fd_or_port);
eadd48de 382 scm_evict_ports (fd); /* see scsh manual. */
a9488d12 383 SCM_SYSCALL (rv = close (fd));
eadd48de
GH
384 /* following scsh, closing an already closed file descriptor is
385 not an error. */
386 if (rv < 0 && errno != EBADF)
1bbd0b84 387 SCM_SYSERROR;
36284627 388 return SCM_BOOL (rv >= 0);
eadd48de 389}
1bbd0b84 390#undef FUNC_NAME
eadd48de 391
c2ca4493
GH
392SCM_DEFINE (scm_close_fdes, "close-fdes", 1, 0, 0,
393 (SCM fd),
394 "A simple wrapper for the @code{close} system call.\n"
395 "Close file descriptor @var{fd}, which must be an integer.\n"
396 "Unlike close (@pxref{Ports and File Descriptors, close}),\n"
397 "the file descriptor will be closed even if a port is using it.\n"
398 "The return value is unspecified.")
399#define FUNC_NAME s_scm_close_fdes
400{
401 int c_fd;
402 int rv;
403
404 SCM_VALIDATE_INUM_COPY (1, fd, c_fd);
405 SCM_SYSCALL (rv = close (c_fd));
406 if (rv < 0)
407 SCM_SYSERROR;
408 return SCM_UNSPECIFIED;
409}
410#undef FUNC_NAME
411
0f2d19dd
JB
412\f
413/* {Files}
414 */
1cc91f1b 415
ae5253c5
GH
416SCM_SYMBOL (scm_sym_regular, "regular");
417SCM_SYMBOL (scm_sym_directory, "directory");
f326ecf3 418#ifdef HAVE_S_ISLNK
ae5253c5 419SCM_SYMBOL (scm_sym_symlink, "symlink");
f326ecf3 420#endif
ae5253c5
GH
421SCM_SYMBOL (scm_sym_block_special, "block-special");
422SCM_SYMBOL (scm_sym_char_special, "char-special");
423SCM_SYMBOL (scm_sym_fifo, "fifo");
424SCM_SYMBOL (scm_sym_sock, "socket");
425SCM_SYMBOL (scm_sym_unknown, "unknown");
426
0f2d19dd 427static SCM
1bbd0b84 428scm_stat2scm (struct stat *stat_temp)
0f2d19dd 429{
00ffa0e7 430 SCM ans = scm_c_make_vector (15, SCM_UNSPECIFIED);
ae5253c5 431
34d19ef6
HWN
432 SCM_VECTOR_SET(ans, 0, scm_ulong2num ((unsigned long) stat_temp->st_dev));
433 SCM_VECTOR_SET(ans, 1, scm_ulong2num ((unsigned long) stat_temp->st_ino));
434 SCM_VECTOR_SET(ans, 2, scm_ulong2num ((unsigned long) stat_temp->st_mode));
435 SCM_VECTOR_SET(ans, 3, scm_ulong2num ((unsigned long) stat_temp->st_nlink));
436 SCM_VECTOR_SET(ans, 4, scm_ulong2num ((unsigned long) stat_temp->st_uid));
437 SCM_VECTOR_SET(ans, 5, scm_ulong2num ((unsigned long) stat_temp->st_gid));
1fd85bc5 438#ifdef HAVE_STRUCT_STAT_ST_RDEV
34d19ef6 439 SCM_VECTOR_SET(ans, 6, scm_ulong2num ((unsigned long) stat_temp->st_rdev));
0f2d19dd 440#else
34d19ef6 441 SCM_VECTOR_SET(ans, 6, SCM_BOOL_F);
0f2d19dd 442#endif
34d19ef6
HWN
443 SCM_VECTOR_SET(ans, 7, scm_ulong2num ((unsigned long) stat_temp->st_size));
444 SCM_VECTOR_SET(ans, 8, scm_ulong2num ((unsigned long) stat_temp->st_atime));
445 SCM_VECTOR_SET(ans, 9, scm_ulong2num ((unsigned long) stat_temp->st_mtime));
446 SCM_VECTOR_SET(ans, 10, scm_ulong2num ((unsigned long) stat_temp->st_ctime));
1fd85bc5 447#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
34d19ef6 448 SCM_VECTOR_SET(ans, 11, scm_ulong2num ((unsigned long) stat_temp->st_blksize));
0f2d19dd 449#else
34d19ef6 450 SCM_VECTOR_SET(ans, 11, scm_ulong2num (4096L));
0f2d19dd 451#endif
1fd85bc5 452#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
34d19ef6 453 SCM_VECTOR_SET(ans, 12, scm_ulong2num ((unsigned long) stat_temp->st_blocks));
0f2d19dd 454#else
34d19ef6 455 SCM_VECTOR_SET(ans, 12, SCM_BOOL_F);
0f2d19dd 456#endif
ae5253c5
GH
457 {
458 int mode = stat_temp->st_mode;
459
460 if (S_ISREG (mode))
34d19ef6 461 SCM_VECTOR_SET(ans, 13, scm_sym_regular);
ae5253c5 462 else if (S_ISDIR (mode))
34d19ef6 463 SCM_VECTOR_SET(ans, 13, scm_sym_directory);
f326ecf3 464#ifdef HAVE_S_ISLNK
ae5253c5 465 else if (S_ISLNK (mode))
34d19ef6 466 SCM_VECTOR_SET(ans, 13, scm_sym_symlink);
f326ecf3 467#endif
ae5253c5 468 else if (S_ISBLK (mode))
34d19ef6 469 SCM_VECTOR_SET(ans, 13, scm_sym_block_special);
ae5253c5 470 else if (S_ISCHR (mode))
34d19ef6 471 SCM_VECTOR_SET(ans, 13, scm_sym_char_special);
ae5253c5 472 else if (S_ISFIFO (mode))
34d19ef6 473 SCM_VECTOR_SET(ans, 13, scm_sym_fifo);
e655d034 474#ifdef S_ISSOCK
ae5253c5 475 else if (S_ISSOCK (mode))
34d19ef6 476 SCM_VECTOR_SET(ans, 13, scm_sym_sock);
e655d034 477#endif
ae5253c5 478 else
34d19ef6 479 SCM_VECTOR_SET(ans, 13, scm_sym_unknown);
ae5253c5 480
34d19ef6 481 SCM_VECTOR_SET(ans, 14, SCM_MAKINUM ((~S_IFMT) & mode));
ae5253c5
GH
482
483 /* the layout of the bits in ve[14] is intended to be portable.
484 If there are systems that don't follow the usual convention,
485 the following could be used:
486
487 tmp = 0;
488 if (S_ISUID & mode) tmp += 1;
489 tmp <<= 1;
490 if (S_IRGRP & mode) tmp += 1;
491 tmp <<= 1;
492 if (S_ISVTX & mode) tmp += 1;
493 tmp <<= 1;
494 if (S_IRUSR & mode) tmp += 1;
495 tmp <<= 1;
496 if (S_IWUSR & mode) tmp += 1;
497 tmp <<= 1;
498 if (S_IXUSR & mode) tmp += 1;
499 tmp <<= 1;
500 if (S_IWGRP & mode) tmp += 1;
501 tmp <<= 1;
502 if (S_IXGRP & mode) tmp += 1;
503 tmp <<= 1;
504 if (S_IROTH & mode) tmp += 1;
505 tmp <<= 1;
506 if (S_IWOTH & mode) tmp += 1;
507 tmp <<= 1;
508 if (S_IXOTH & mode) tmp += 1;
509
34d19ef6 510 SCM_VECTOR_SET(ans, 14, SCM_MAKINUM (tmp));
ae5253c5
GH
511
512 */
513 }
0f2d19dd
JB
514
515 return ans;
516}
517
e0c73a1c
MV
518#ifdef __MINGW32__
519/*
520 * Try getting the appropiate stat buffer for a given file descriptor
521 * under Windows. It differentiates between file, pipe and socket
522 * descriptors.
523 */
524static int fstat_Win32 (int fdes, struct stat *buf)
525{
526 int error, optlen = sizeof (int);
527
528 memset (buf, 0, sizeof (struct stat));
529
530 /* Is this a socket ? */
531 if (getsockopt (fdes, SOL_SOCKET, SO_ERROR, (void *) &error, &optlen) >= 0)
532 {
533 buf->st_mode = _S_IFSOCK | _S_IREAD | _S_IWRITE | _S_IEXEC;
534 buf->st_nlink = 1;
535 buf->st_atime = buf->st_ctime = buf->st_mtime = time (NULL);
536 return 0;
537 }
538 /* Maybe a regular file or pipe ? */
539 return fstat (fdes, buf);
540}
541#endif /* __MINGW32__ */
542
a1ec6916 543SCM_DEFINE (scm_stat, "stat", 1, 0, 0,
1bbd0b84 544 (SCM object),
1e6808ea
MG
545 "Return an object containing various information about the file\n"
546 "determined by @var{obj}. @var{obj} can be a string containing\n"
547 "a file name or a port or integer file descriptor which is open\n"
548 "on a file (in which case @code{fstat} is used as the underlying\n"
549 "system call).\n"
550 "\n"
551 "The object returned by @code{stat} can be passed as a single\n"
552 "parameter to the following procedures, all of which return\n"
553 "integers:\n"
554 "\n"
d3818c29
MD
555 "@table @code\n"
556 "@item stat:dev\n"
557 "The device containing the file.\n"
558 "@item stat:ino\n"
1e6808ea
MG
559 "The file serial number, which distinguishes this file from all\n"
560 "other files on the same device.\n"
d3818c29 561 "@item stat:mode\n"
1e6808ea
MG
562 "The mode of the file. This includes file type information and\n"
563 "the file permission bits. See @code{stat:type} and\n"
564 "@code{stat:perms} below.\n"
d3818c29
MD
565 "@item stat:nlink\n"
566 "The number of hard links to the file.\n"
567 "@item stat:uid\n"
568 "The user ID of the file's owner.\n"
569 "@item stat:gid\n"
570 "The group ID of the file.\n"
571 "@item stat:rdev\n"
572 "Device ID; this entry is defined only for character or block\n"
573 "special files.\n"
574 "@item stat:size\n"
575 "The size of a regular file in bytes.\n"
576 "@item stat:atime\n"
577 "The last access time for the file.\n"
578 "@item stat:mtime\n"
579 "The last modification time for the file.\n"
580 "@item stat:ctime\n"
581 "The last modification time for the attributes of the file.\n"
582 "@item stat:blksize\n"
1e6808ea
MG
583 "The optimal block size for reading or writing the file, in\n"
584 "bytes.\n"
d3818c29 585 "@item stat:blocks\n"
1e6808ea
MG
586 "The amount of disk space that the file occupies measured in\n"
587 "units of 512 byte blocks.\n"
588 "@end table\n"
589 "\n"
d3818c29 590 "In addition, the following procedures return the information\n"
1e6808ea
MG
591 "from stat:mode in a more convenient form:\n"
592 "\n"
d3818c29
MD
593 "@table @code\n"
594 "@item stat:type\n"
595 "A symbol representing the type of file. Possible values are\n"
1e6808ea
MG
596 "regular, directory, symlink, block-special, char-special, fifo,\n"
597 "socket and unknown\n"
d3818c29
MD
598 "@item stat:perms\n"
599 "An integer representing the access permission bits.\n"
600 "@end table")
1bbd0b84 601#define FUNC_NAME s_scm_stat
0f2d19dd 602{
6afcd3b2
GH
603 int rv;
604 int fdes;
0f2d19dd
JB
605 struct stat stat_temp;
606
1ea47048 607 if (SCM_INUMP (object))
36284627 608 {
e0c73a1c
MV
609#ifdef __MINGW32__
610 SCM_SYSCALL (rv = fstat_Win32 (SCM_INUM (object), &stat_temp));
611#else
36284627 612 SCM_SYSCALL (rv = fstat (SCM_INUM (object), &stat_temp));
e0c73a1c 613#endif
36284627
DH
614 }
615 else if (SCM_STRINGP (object))
616 {
e0c73a1c
MV
617#ifdef __MINGW32__
618 char *p, *file = strdup (SCM_STRING_CHARS (object));
619 p = file + strlen (file) - 1;
620 while (p > file && (*p == '/' || *p == '\\'))
621 *p-- = '\0';
622 SCM_SYSCALL (rv = stat (file, &stat_temp));
623 free (file);
624#else
36284627 625 SCM_SYSCALL (rv = stat (SCM_STRING_CHARS (object), &stat_temp));
e0c73a1c 626#endif
36284627 627 }
1ea47048 628 else
0f2d19dd 629 {
36284627
DH
630 object = SCM_COERCE_OUTPORT (object);
631 SCM_VALIDATE_OPFPORT (1, object);
632 fdes = SCM_FPORT_FDES (object);
e0c73a1c
MV
633#ifdef __MINGW32__
634 SCM_SYSCALL (rv = fstat_Win32 (fdes, &stat_temp));
635#else
36284627 636 SCM_SYSCALL (rv = fstat (fdes, &stat_temp));
e0c73a1c 637#endif
6afcd3b2 638 }
36284627 639
6afcd3b2 640 if (rv == -1)
3d8d56df
GH
641 {
642 int en = errno;
643
5d2d2ffc 644 SCM_SYSERROR_MSG ("~A: ~S",
1afff620
KN
645 scm_list_2 (scm_makfrom0str (strerror (errno)),
646 object),
e0c08f17 647 en);
3d8d56df 648 }
02b754d3 649 return scm_stat2scm (&stat_temp);
0f2d19dd 650}
1bbd0b84 651#undef FUNC_NAME
0f2d19dd 652
0f2d19dd
JB
653\f
654/* {Modifying Directories}
655 */
656
82893676 657#ifdef HAVE_LINK
a1ec6916 658SCM_DEFINE (scm_link, "link", 2, 0, 0,
1bbd0b84 659 (SCM oldpath, SCM newpath),
6d36532c
GH
660 "Creates a new name @var{newpath} in the file system for the\n"
661 "file named by @var{oldpath}. If @var{oldpath} is a symbolic\n"
662 "link, the link may or may not be followed depending on the\n"
663 "system.")
1bbd0b84 664#define FUNC_NAME s_scm_link
0f2d19dd
JB
665{
666 int val;
02b754d3 667
a6d9e5ab 668 SCM_VALIDATE_STRING (1, oldpath);
a6d9e5ab 669 SCM_VALIDATE_STRING (2, newpath);
6d36532c
GH
670 SCM_SYSCALL (val = link (SCM_STRING_CHARS (oldpath),
671 SCM_STRING_CHARS (newpath)));
02b754d3 672 if (val != 0)
1bbd0b84 673 SCM_SYSERROR;
02b754d3 674 return SCM_UNSPECIFIED;
0f2d19dd 675}
1bbd0b84 676#undef FUNC_NAME
82893676 677#endif /* HAVE_LINK */
0f2d19dd
JB
678
679
680
a1ec6916 681SCM_DEFINE (scm_rename, "rename-file", 2, 0, 0,
1bbd0b84 682 (SCM oldname, SCM newname),
6d36532c 683 "Renames the file specified by @var{oldname} to @var{newname}.\n"
d3818c29 684 "The return value is unspecified.")
1bbd0b84 685#define FUNC_NAME s_scm_rename
0f2d19dd
JB
686{
687 int rv;
a6d9e5ab
DH
688 SCM_VALIDATE_STRING (1, oldname);
689 SCM_VALIDATE_STRING (2, newname);
0f2d19dd 690#ifdef HAVE_RENAME
a6d9e5ab 691 SCM_SYSCALL (rv = rename (SCM_STRING_CHARS (oldname), SCM_STRING_CHARS (newname)));
0f2d19dd 692#else
a6d9e5ab 693 SCM_SYSCALL (rv = link (SCM_STRING_CHARS (oldname), SCM_STRING_CHARS (newname)));
02b754d3 694 if (rv == 0)
0f2d19dd 695 {
a6d9e5ab 696 SCM_SYSCALL (rv = unlink (SCM_STRING_CHARS (oldname)));;
02b754d3 697 if (rv != 0)
0f2d19dd 698 /* unlink failed. remove new name */
a6d9e5ab 699 SCM_SYSCALL (unlink (SCM_STRING_CHARS (newname)));
0f2d19dd 700 }
6afcd3b2 701#endif
02b754d3 702 if (rv != 0)
1bbd0b84 703 SCM_SYSERROR;
02b754d3 704 return SCM_UNSPECIFIED;
0f2d19dd 705}
1bbd0b84 706#undef FUNC_NAME
0f2d19dd
JB
707
708
3b3b36dd 709SCM_DEFINE (scm_delete_file, "delete-file", 1, 0, 0,
1bbd0b84 710 (SCM str),
d3818c29 711 "Deletes (or \"unlinks\") the file specified by @var{path}.")
1bbd0b84 712#define FUNC_NAME s_scm_delete_file
2f3ed1ba
JB
713{
714 int ans;
a6d9e5ab 715 SCM_VALIDATE_STRING (1, str);
a6d9e5ab 716 SCM_SYSCALL (ans = unlink (SCM_STRING_CHARS (str)));
2f3ed1ba 717 if (ans != 0)
1bbd0b84 718 SCM_SYSERROR;
2f3ed1ba
JB
719 return SCM_UNSPECIFIED;
720}
1bbd0b84 721#undef FUNC_NAME
2f3ed1ba 722
f25f761d 723#ifdef HAVE_MKDIR
a1ec6916 724SCM_DEFINE (scm_mkdir, "mkdir", 1, 1, 0,
1bbd0b84 725 (SCM path, SCM mode),
d3818c29
MD
726 "Create a new directory named by @var{path}. If @var{mode} is omitted\n"
727 "then the permissions of the directory file are set using the current\n"
728 "umask. Otherwise they are set to the decimal value specified with\n"
729 "@var{mode}. The return value is unspecified.")
1bbd0b84 730#define FUNC_NAME s_scm_mkdir
0f2d19dd 731{
0f2d19dd
JB
732 int rv;
733 mode_t mask;
a6d9e5ab 734 SCM_VALIDATE_STRING (1, path);
0f2d19dd
JB
735 if (SCM_UNBNDP (mode))
736 {
737 mask = umask (0);
738 umask (mask);
a6d9e5ab 739 SCM_SYSCALL (rv = mkdir (SCM_STRING_CHARS (path), 0777 ^ mask));
0f2d19dd
JB
740 }
741 else
742 {
34d19ef6 743 SCM_VALIDATE_INUM (2, mode);
a6d9e5ab 744 SCM_SYSCALL (rv = mkdir (SCM_STRING_CHARS (path), SCM_INUM (mode)));
0f2d19dd 745 }
02b754d3 746 if (rv != 0)
1bbd0b84 747 SCM_SYSERROR;
02b754d3 748 return SCM_UNSPECIFIED;
0f2d19dd 749}
1bbd0b84 750#undef FUNC_NAME
f25f761d 751#endif /* HAVE_MKDIR */
0f2d19dd 752
f25f761d 753#ifdef HAVE_RMDIR
a1ec6916 754SCM_DEFINE (scm_rmdir, "rmdir", 1, 0, 0,
1bbd0b84 755 (SCM path),
d3818c29
MD
756 "Remove the existing directory named by @var{path}. The directory must\n"
757 "be empty for this to succeed. The return value is unspecified.")
1bbd0b84 758#define FUNC_NAME s_scm_rmdir
0f2d19dd 759{
0f2d19dd 760 int val;
02b754d3 761
a6d9e5ab 762 SCM_VALIDATE_STRING (1, path);
a6d9e5ab 763 SCM_SYSCALL (val = rmdir (SCM_STRING_CHARS (path)));
02b754d3 764 if (val != 0)
1bbd0b84 765 SCM_SYSERROR;
02b754d3 766 return SCM_UNSPECIFIED;
0f2d19dd 767}
1bbd0b84 768#undef FUNC_NAME
f25f761d 769#endif
0f2d19dd
JB
770
771\f
30ea841d 772
0f2d19dd
JB
773/* {Examining Directories}
774 */
775
92c2555f 776scm_t_bits scm_tc16_dir;
0f2d19dd 777
30ea841d 778
a1ec6916 779SCM_DEFINE (scm_directory_stream_p, "directory-stream?", 1, 0, 0,
1bbd0b84 780 (SCM obj),
1e6808ea
MG
781 "Return a boolean indicating whether @var{object} is a directory\n"
782 "stream as returned by @code{opendir}.")
1bbd0b84 783#define FUNC_NAME s_scm_directory_stream_p
77242ff9 784{
30ea841d 785 return SCM_BOOL (SCM_DIRP (obj));
77242ff9 786}
1bbd0b84 787#undef FUNC_NAME
77242ff9 788
30ea841d 789
a1ec6916 790SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0,
1bbd0b84 791 (SCM dirname),
d3818c29
MD
792 "Open the directory specified by @var{path} and return a directory\n"
793 "stream.")
1bbd0b84 794#define FUNC_NAME s_scm_opendir
0f2d19dd
JB
795{
796 DIR *ds;
a6d9e5ab 797 SCM_VALIDATE_STRING (1, dirname);
a6d9e5ab 798 SCM_SYSCALL (ds = opendir (SCM_STRING_CHARS (dirname)));
02b754d3 799 if (ds == NULL)
1bbd0b84 800 SCM_SYSERROR;
30ea841d 801 SCM_RETURN_NEWSMOB (scm_tc16_dir | SCM_DIR_FLAG_OPEN, ds);
0f2d19dd 802}
1bbd0b84 803#undef FUNC_NAME
0f2d19dd
JB
804
805
a1ec6916 806SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
1bbd0b84 807 (SCM port),
d3818c29
MD
808 "Return (as a string) the next directory entry from the directory stream\n"
809 "@var{stream}. If there is no remaining entry to be read then the\n"
810 "end of file object is returned.")
1bbd0b84 811#define FUNC_NAME s_scm_readdir
0f2d19dd
JB
812{
813 struct dirent *rdent;
30ea841d
DH
814
815 SCM_VALIDATE_DIR (1, port);
816 if (!SCM_DIR_OPEN_P (port))
1afff620 817 SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
30ea841d 818
0f2d19dd 819 errno = 0;
4260a7fc 820 SCM_SYSCALL (rdent = readdir ((DIR *) SCM_CELL_WORD_1 (port)));
02b754d3 821 if (errno != 0)
1bbd0b84 822 SCM_SYSERROR;
30ea841d 823
36284627 824 return (rdent ? scm_mem2string (rdent->d_name, NAMLEN (rdent))
02b754d3 825 : SCM_EOF_VAL);
0f2d19dd 826}
1bbd0b84 827#undef FUNC_NAME
0f2d19dd
JB
828
829
a1ec6916 830SCM_DEFINE (scm_rewinddir, "rewinddir", 1, 0, 0,
1bbd0b84 831 (SCM port),
d3818c29
MD
832 "Reset the directory port @var{stream} so that the next call to\n"
833 "@code{readdir} will return the first directory entry.")
1bbd0b84 834#define FUNC_NAME s_scm_rewinddir
0f2d19dd 835{
30ea841d
DH
836 SCM_VALIDATE_DIR (1, port);
837 if (!SCM_DIR_OPEN_P (port))
1afff620 838 SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
30ea841d 839
4260a7fc 840 rewinddir ((DIR *) SCM_CELL_WORD_1 (port));
30ea841d 841
0f2d19dd
JB
842 return SCM_UNSPECIFIED;
843}
1bbd0b84 844#undef FUNC_NAME
0f2d19dd
JB
845
846
a1ec6916 847SCM_DEFINE (scm_closedir, "closedir", 1, 0, 0,
1bbd0b84 848 (SCM port),
d3818c29
MD
849 "Close the directory stream @var{stream}.\n"
850 "The return value is unspecified.")
1bbd0b84 851#define FUNC_NAME s_scm_closedir
0f2d19dd 852{
30ea841d 853 SCM_VALIDATE_DIR (1, port);
02b754d3 854
30ea841d 855 if (SCM_DIR_OPEN_P (port))
0f2d19dd 856 {
30ea841d
DH
857 int sts;
858
859 SCM_SYSCALL (sts = closedir ((DIR *) SCM_CELL_WORD_1 (port)));
860 if (sts != 0)
861 SCM_SYSERROR;
862
863 SCM_SET_CELL_WORD_0 (port, scm_tc16_dir);
0f2d19dd 864 }
30ea841d 865
02b754d3 866 return SCM_UNSPECIFIED;
0f2d19dd 867}
1bbd0b84 868#undef FUNC_NAME
0f2d19dd
JB
869
870
0f2d19dd 871static int
e81d98ec 872scm_dir_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
0f2d19dd 873{
f8b16091 874 scm_puts ("#<", port);
30ea841d 875 if (!SCM_DIR_OPEN_P (exp))
f8b16091 876 scm_puts ("closed: ", port);
0d03da62 877 scm_puts ("directory stream ", port);
4260a7fc 878 scm_intprint (SCM_CELL_WORD_1 (exp), 16, port);
f8b16091 879 scm_putc ('>', port);
0f2d19dd
JB
880 return 1;
881}
882
1cc91f1b 883
1be6b49c 884static size_t
1bbd0b84 885scm_dir_free (SCM p)
0f2d19dd 886{
30ea841d 887 if (SCM_DIR_OPEN_P (p))
4260a7fc 888 closedir ((DIR *) SCM_CELL_WORD_1 (p));
0f2d19dd
JB
889 return 0;
890}
891
0f2d19dd
JB
892\f
893/* {Navigating Directories}
894 */
895
896
a1ec6916 897SCM_DEFINE (scm_chdir, "chdir", 1, 0, 0,
1bbd0b84 898 (SCM str),
d3818c29
MD
899 "Change the current working directory to @var{path}.\n"
900 "The return value is unspecified.")
1bbd0b84 901#define FUNC_NAME s_scm_chdir
0f2d19dd
JB
902{
903 int ans;
02b754d3 904
a6d9e5ab 905 SCM_VALIDATE_STRING (1, str);
a6d9e5ab 906 SCM_SYSCALL (ans = chdir (SCM_STRING_CHARS (str)));
02b754d3 907 if (ans != 0)
1bbd0b84 908 SCM_SYSERROR;
02b754d3 909 return SCM_UNSPECIFIED;
0f2d19dd 910}
1bbd0b84 911#undef FUNC_NAME
0f2d19dd 912
f25f761d 913#ifdef HAVE_GETCWD
a1ec6916 914SCM_DEFINE (scm_getcwd, "getcwd", 0, 0, 0,
1bbd0b84 915 (),
1e6808ea 916 "Return the name of the current working directory.")
1bbd0b84 917#define FUNC_NAME s_scm_getcwd
0f2d19dd 918{
0f2d19dd 919 char *rv;
1be6b49c 920 size_t size = 100;
0f2d19dd
JB
921 char *wd;
922 SCM result;
923
4c9419ac 924 wd = scm_malloc (size);
0f2d19dd
JB
925 while ((rv = getcwd (wd, size)) == 0 && errno == ERANGE)
926 {
4c9419ac 927 free (wd);
0f2d19dd 928 size *= 2;
4c9419ac 929 wd = scm_malloc (size);
0f2d19dd 930 }
02b754d3 931 if (rv == 0)
1bbd0b84 932 SCM_SYSERROR;
36284627 933 result = scm_mem2string (wd, strlen (wd));
4c9419ac 934 free (wd);
0f2d19dd 935 return result;
0f2d19dd 936}
1bbd0b84 937#undef FUNC_NAME
f25f761d 938#endif /* HAVE_GETCWD */
0f2d19dd
JB
939
940\f
941
28d77376
GH
942#ifdef HAVE_SELECT
943
944/* check that element is a port or file descriptor. if it's a port
945 and its buffer is ready for use, add it to the ports_ready list.
946 otherwise add its file descriptor to *set. the type of list can be
947 determined from pos: SCM_ARG1 for reads, SCM_ARG2 for writes,
948 SCM_ARG3 for excepts. */
cafc12ff 949static int
28d77376 950set_element (SELECT_TYPE *set, SCM *ports_ready, SCM element, int pos)
a48a89bc 951{
cafc12ff 952 int fd;
d831b039 953
28d77376
GH
954 if (SCM_INUMP (element))
955 {
956 fd = SCM_INUM (element);
957 }
958 else
959 {
960 int use_buf = 0;
961
962 element = SCM_COERCE_OUTPORT (element);
963 SCM_ASSERT (SCM_OPFPORTP (element), element, pos, "select");
964 if (pos == SCM_ARG1)
965 {
966 /* check whether port has buffered input. */
92c2555f 967 scm_t_port *pt = SCM_PTAB_ENTRY (element);
28d77376
GH
968
969 if (pt->read_pos < pt->read_end)
970 use_buf = 1;
971 }
972 else if (pos == SCM_ARG2)
973 {
974 /* check whether port's output buffer has room. */
92c2555f 975 scm_t_port *pt = SCM_PTAB_ENTRY (element);
28d77376
GH
976
977 /* > 1 since writing the last byte in the buffer causes flush. */
978 if (pt->write_end - pt->write_pos > 1)
979 use_buf = 1;
980 }
981 fd = use_buf ? -1 : SCM_FPORT_FDES (element);
982 }
983 if (fd == -1)
984 *ports_ready = scm_cons (element, *ports_ready);
985 else
986 FD_SET (fd, set);
cafc12ff 987 return fd;
a48a89bc 988}
1cc91f1b 989
28d77376
GH
990/* check list_or_vec, a list or vector of ports or file descriptors,
991 adding each member to either the ports_ready list (if it's a port
992 with a usable buffer) or to *set. the kind of list_or_vec can be
993 determined from pos: SCM_ARG1 for reads, SCM_ARG2 for writes,
994 SCM_ARG3 for excepts. */
cafc12ff 995static int
28d77376 996fill_select_type (SELECT_TYPE *set, SCM *ports_ready, SCM list_or_vec, int pos)
0f2d19dd 997{
28d77376
GH
998 int max_fd = 0;
999
1000 if (SCM_VECTORP (list_or_vec))
0f2d19dd 1001 {
9fd38a3d 1002 int i = SCM_VECTOR_LENGTH (list_or_vec);
34d19ef6 1003 SCM const *ve = SCM_VELTS (list_or_vec);
a48a89bc 1004
28d77376 1005 while (--i >= 0)
a48a89bc 1006 {
28d77376
GH
1007 int fd = set_element (set, ports_ready, ve[i], pos);
1008
cafc12ff
MD
1009 if (fd > max_fd)
1010 max_fd = fd;
a48a89bc
GH
1011 }
1012 }
1013 else
1014 {
c96d76b8 1015 while (!SCM_NULL_OR_NIL_P (list_or_vec))
a48a89bc 1016 {
28d77376
GH
1017 int fd = set_element (set, ports_ready, SCM_CAR (list_or_vec), pos);
1018
cafc12ff
MD
1019 if (fd > max_fd)
1020 max_fd = fd;
28d77376 1021 list_or_vec = SCM_CDR (list_or_vec);
a48a89bc 1022 }
0f2d19dd 1023 }
cafc12ff
MD
1024
1025 return max_fd;
0f2d19dd
JB
1026}
1027
28d77376
GH
1028/* if element (a file descriptor or port) appears in *set, cons it to
1029 list. return list. */
a48a89bc
GH
1030static SCM
1031get_element (SELECT_TYPE *set, SCM element, SCM list)
1032{
28d77376
GH
1033 int fd;
1034
1035 if (SCM_INUMP (element))
a48a89bc 1036 {
28d77376 1037 fd = SCM_INUM (element);
a48a89bc 1038 }
28d77376 1039 else
a48a89bc 1040 {
28d77376 1041 fd = SCM_FPORT_FDES (SCM_COERCE_OUTPORT (element));
a48a89bc 1042 }
28d77376
GH
1043 if (FD_ISSET (fd, set))
1044 list = scm_cons (element, list);
a48a89bc
GH
1045 return list;
1046}
1cc91f1b 1047
28d77376
GH
1048/* construct component of scm_select return value.
1049 set: pointer to set of file descriptors found by select to be ready
1050 ports_ready: ports ready due to buffering
1051 list_or_vec: original list/vector handed to scm_select.
1052 the return value is a list/vector of ready ports/file descriptors.
1053 works by finding the objects in list which correspond to members of
1054 *set and appending them to ports_ready. result is converted to a
1055 vector if list_or_vec is a vector. */
0f2d19dd 1056static SCM
28d77376 1057retrieve_select_type (SELECT_TYPE *set, SCM ports_ready, SCM list_or_vec)
0f2d19dd 1058{
28d77376 1059 SCM answer_list = ports_ready;
a48a89bc 1060
28d77376 1061 if (SCM_VECTORP (list_or_vec))
0f2d19dd 1062 {
9fd38a3d 1063 int i = SCM_VECTOR_LENGTH (list_or_vec);
34d19ef6 1064 SCM const *ve = SCM_VELTS (list_or_vec);
a48a89bc 1065
28d77376 1066 while (--i >= 0)
0f2d19dd 1067 {
28d77376 1068 answer_list = get_element (set, ve[i], answer_list);
0f2d19dd 1069 }
a48a89bc
GH
1070 return scm_vector (answer_list);
1071 }
1072 else
1073 {
28d77376 1074 /* list_or_vec must be a list. */
c96d76b8 1075 while (!SCM_NULL_OR_NIL_P (list_or_vec))
0f2d19dd 1076 {
28d77376
GH
1077 answer_list = get_element (set, SCM_CAR (list_or_vec), answer_list);
1078 list_or_vec = SCM_CDR (list_or_vec);
0f2d19dd 1079 }
a48a89bc 1080 return answer_list;
0f2d19dd 1081 }
0f2d19dd
JB
1082}
1083
1bbd0b84 1084/* Static helper functions above refer to s_scm_select directly as s_select */
a1ec6916 1085SCM_DEFINE (scm_select, "select", 3, 2, 0,
1bbd0b84 1086 (SCM reads, SCM writes, SCM excepts, SCM secs, SCM usecs),
28d77376 1087 "This procedure has a variety of uses: waiting for the ability\n"
bb2c02f2 1088 "to provide input, accept output, or the existence of\n"
28d77376
GH
1089 "exceptional conditions on a collection of ports or file\n"
1090 "descriptors, or waiting for a timeout to occur.\n"
1091 "It also returns if interrupted by a signal.\n\n"
1092 "@var{reads}, @var{writes} and @var{excepts} can be lists or\n"
1093 "vectors, with each member a port or a file descriptor.\n"
1094 "The value returned is a list of three corresponding\n"
1095 "lists or vectors containing only the members which meet the\n"
1096 "specified requirement. The ability of port buffers to\n"
1097 "provide input or accept output is taken into account.\n"
1098 "Ordering of the input lists or vectors is not preserved.\n\n"
1099 "The optional arguments @var{secs} and @var{usecs} specify the\n"
1100 "timeout. Either @var{secs} can be specified alone, as\n"
1101 "either an integer or a real number, or both @var{secs} and\n"
1102 "@var{usecs} can be specified as integers, in which case\n"
1103 "@var{usecs} is an additional timeout expressed in\n"
1104 "microseconds. If @var{secs} is omitted or is @code{#f} then\n"
1105 "select will wait for as long as it takes for one of the other\n"
1106 "conditions to be satisfied.\n\n"
1107 "The scsh version of @code{select} differs as follows:\n"
1108 "Only vectors are accepted for the first three arguments.\n"
1109 "The @var{usecs} argument is not supported.\n"
1110 "Multiple values are returned instead of a list.\n"
1111 "Duplicates in the input vectors appear only once in output.\n"
9401323e 1112 "An additional @code{select!} interface is provided.")
1bbd0b84 1113#define FUNC_NAME s_scm_select
0f2d19dd 1114{
0f2d19dd 1115 struct timeval timeout;
28d77376 1116 struct timeval * time_ptr;
0f2d19dd
JB
1117 SELECT_TYPE read_set;
1118 SELECT_TYPE write_set;
1119 SELECT_TYPE except_set;
28d77376
GH
1120 int read_count;
1121 int write_count;
1122 int except_count;
1123 /* these lists accumulate ports which are ready due to buffering.
1124 their file descriptors don't need to be added to the select sets. */
1125 SCM read_ports_ready = SCM_EOL;
1126 SCM write_ports_ready = SCM_EOL;
1127 int max_fd;
1128
1129 if (SCM_VECTORP (reads))
1130 {
9fd38a3d 1131 read_count = SCM_VECTOR_LENGTH (reads);
28d77376
GH
1132 }
1133 else
1134 {
1135 read_count = scm_ilength (reads);
1136 SCM_ASSERT (read_count >= 0, reads, SCM_ARG1, FUNC_NAME);
1137 }
1138 if (SCM_VECTORP (writes))
1139 {
9fd38a3d 1140 write_count = SCM_VECTOR_LENGTH (writes);
28d77376
GH
1141 }
1142 else
1143 {
1144 write_count = scm_ilength (writes);
1145 SCM_ASSERT (write_count >= 0, writes, SCM_ARG2, FUNC_NAME);
1146 }
1147 if (SCM_VECTORP (excepts))
1148 {
9fd38a3d 1149 except_count = SCM_VECTOR_LENGTH (excepts);
28d77376
GH
1150 }
1151 else
1152 {
1153 except_count = scm_ilength (excepts);
1154 SCM_ASSERT (except_count >= 0, excepts, SCM_ARG3, FUNC_NAME);
1155 }
0f2d19dd
JB
1156
1157 FD_ZERO (&read_set);
1158 FD_ZERO (&write_set);
1159 FD_ZERO (&except_set);
1160
28d77376
GH
1161 max_fd = fill_select_type (&read_set, &read_ports_ready, reads, SCM_ARG1);
1162
1163 {
1164 int write_max = fill_select_type (&write_set, &write_ports_ready,
1165 writes, SCM_ARG2);
1166 int except_max = fill_select_type (&except_set, NULL,
1167 excepts, SCM_ARG3);
1168
1169 if (write_max > max_fd)
1170 max_fd = write_max;
1171 if (except_max > max_fd)
1172 max_fd = except_max;
1173 }
0f2d19dd 1174
ae1b098b
GH
1175 /* if there's a port with a ready buffer, don't block, just
1176 check for ready file descriptors. */
4260a7fc 1177 if (!SCM_NULLP (read_ports_ready) || !SCM_NULLP (write_ports_ready))
ae1b098b
GH
1178 {
1179 timeout.tv_sec = 0;
1180 timeout.tv_usec = 0;
1181 time_ptr = &timeout;
1182 }
1183 else if (SCM_UNBNDP (secs) || SCM_FALSEP (secs))
28d77376 1184 time_ptr = 0;
0f2d19dd
JB
1185 else
1186 {
ae1b098b 1187 if (SCM_INUMP (secs))
a48a89bc
GH
1188 {
1189 timeout.tv_sec = SCM_INUM (secs);
1190 if (SCM_UNBNDP (usecs))
1191 timeout.tv_usec = 0;
1192 else
1193 {
34d19ef6 1194 SCM_VALIDATE_INUM (5, usecs);
a48a89bc
GH
1195 timeout.tv_usec = SCM_INUM (usecs);
1196 }
1197 }
0f2d19dd 1198 else
a48a89bc 1199 {
1bbd0b84 1200 double fl = scm_num2dbl (secs, FUNC_NAME);
a48a89bc
GH
1201
1202 if (!SCM_UNBNDP (usecs))
c1bfcf60 1203 SCM_WRONG_TYPE_ARG (4, secs);
a48a89bc 1204 if (fl > LONG_MAX)
c1bfcf60 1205 SCM_OUT_OF_RANGE (4, secs);
a48a89bc
GH
1206 timeout.tv_sec = (long) fl;
1207 timeout.tv_usec = (long) ((fl - timeout.tv_sec) * 1000000);
1208 }
28d77376 1209 time_ptr = &timeout;
0f2d19dd
JB
1210 }
1211
28d77376 1212 {
28d77376
GH
1213 int rv = scm_internal_select (max_fd + 1,
1214 &read_set, &write_set, &except_set,
1215 time_ptr);
28d77376
GH
1216 if (rv < 0)
1217 SCM_SYSERROR;
1218 }
1afff620
KN
1219 return scm_list_3 (retrieve_select_type (&read_set, read_ports_ready, reads),
1220 retrieve_select_type (&write_set, write_ports_ready, writes),
1221 retrieve_select_type (&except_set, SCM_EOL, excepts));
0f2d19dd 1222}
1bbd0b84 1223#undef FUNC_NAME
f25f761d 1224#endif /* HAVE_SELECT */
0f2d19dd
JB
1225
1226\f
4c1feaa5 1227
82893676 1228#ifdef HAVE_FCNTL
af45e3b0 1229SCM_DEFINE (scm_fcntl, "fcntl", 2, 1, 0,
1bbd0b84 1230 (SCM object, SCM cmd, SCM value),
d3818c29
MD
1231 "Apply @var{command} to the specified file descriptor or the underlying\n"
1232 "file descriptor of the specified port. @var{value} is an optional\n"
1233 "integer argument.\n\n"
1234 "Values for @var{command} are:\n\n"
1235 "@table @code\n"
1236 "@item F_DUPFD\n"
1237 "Duplicate a file descriptor\n"
1238 "@item F_GETFD\n"
1239 "Get flags associated with the file descriptor.\n"
1240 "@item F_SETFD\n"
1241 "Set flags associated with the file descriptor to @var{value}.\n"
1242 "@item F_GETFL\n"
1243 "Get flags associated with the open file.\n"
1244 "@item F_SETFL\n"
1245 "Set flags associated with the open file to @var{value}\n"
1246 "@item F_GETOWN\n"
1247 "Get the process ID of a socket's owner, for @code{SIGIO} signals.\n"
1248 "@item F_SETOWN\n"
1249 "Set the process that owns a socket to @var{value}, for @code{SIGIO} signals.\n"
1250 "@item FD_CLOEXEC\n"
55892d87
NJ
1251 "The value used to indicate the \"close on exec\" flag with @code{F_GETFL} or\n"
1252 "@code{F_SETFL}.\n"
a3c8b9fc 1253 "@end table")
1bbd0b84 1254#define FUNC_NAME s_scm_fcntl
4c1feaa5
JB
1255{
1256 int rv;
6afcd3b2
GH
1257 int fdes;
1258 int ivalue;
4c1feaa5 1259
78446828
MV
1260 object = SCM_COERCE_OUTPORT (object);
1261
34d19ef6 1262 SCM_VALIDATE_INUM (2, cmd);
0c95b57d 1263 if (SCM_OPFPORTP (object))
77a76b64 1264 fdes = SCM_FPORT_FDES (object);
6afcd3b2
GH
1265 else
1266 {
34d19ef6 1267 SCM_VALIDATE_INUM (1, object);
6afcd3b2
GH
1268 fdes = SCM_INUM (object);
1269 }
af45e3b0
DH
1270
1271 if (SCM_UNBNDP (value)) {
6afcd3b2 1272 ivalue = 0;
af45e3b0
DH
1273 } else {
1274 SCM_VALIDATE_INUM_COPY (SCM_ARG3, value, ivalue);
1275 }
1276
77a76b64
JB
1277 SCM_SYSCALL (rv = fcntl (fdes, SCM_INUM (cmd), ivalue));
1278 if (rv == -1)
1bbd0b84 1279 SCM_SYSERROR;
4c1feaa5
JB
1280 return SCM_MAKINUM (rv);
1281}
1bbd0b84 1282#undef FUNC_NAME
82893676 1283#endif /* HAVE_FCNTL */
6afcd3b2 1284
a1ec6916 1285SCM_DEFINE (scm_fsync, "fsync", 1, 0, 0,
1bbd0b84 1286 (SCM object),
d3818c29
MD
1287 "Copies any unwritten data for the specified output file descriptor to disk.\n"
1288 "If @var{port/fd} is a port, its buffer is flushed before the underlying\n"
1289 "file descriptor is fsync'd.\n"
1290 "The return value is unspecified.")
1bbd0b84 1291#define FUNC_NAME s_scm_fsync
6afcd3b2
GH
1292{
1293 int fdes;
1294
78446828
MV
1295 object = SCM_COERCE_OUTPORT (object);
1296
0c95b57d 1297 if (SCM_OPFPORTP (object))
6afcd3b2 1298 {
affc96b5 1299 scm_flush (object);
77a76b64 1300 fdes = SCM_FPORT_FDES (object);
6afcd3b2
GH
1301 }
1302 else
1303 {
34d19ef6 1304 SCM_VALIDATE_INUM (1, object);
6afcd3b2
GH
1305 fdes = SCM_INUM (object);
1306 }
1307 if (fsync (fdes) == -1)
1bbd0b84 1308 SCM_SYSERROR;
6afcd3b2
GH
1309 return SCM_UNSPECIFIED;
1310}
1bbd0b84 1311#undef FUNC_NAME
0f2d19dd 1312
f25f761d 1313#ifdef HAVE_SYMLINK
a1ec6916 1314SCM_DEFINE (scm_symlink, "symlink", 2, 0, 0,
1bbd0b84 1315 (SCM oldpath, SCM newpath),
d3818c29
MD
1316 "Create a symbolic link named @var{path-to} with the value (i.e., pointing to)\n"
1317 "@var{path-from}. The return value is unspecified.")
1bbd0b84 1318#define FUNC_NAME s_scm_symlink
0f2d19dd 1319{
0f2d19dd 1320 int val;
02b754d3 1321
a6d9e5ab
DH
1322 SCM_VALIDATE_STRING (1, oldpath);
1323 SCM_VALIDATE_STRING (2, newpath);
a6d9e5ab 1324 SCM_SYSCALL (val = symlink (SCM_STRING_CHARS (oldpath), SCM_STRING_CHARS (newpath)));
02b754d3 1325 if (val != 0)
1bbd0b84 1326 SCM_SYSERROR;
02b754d3 1327 return SCM_UNSPECIFIED;
0f2d19dd 1328}
1bbd0b84 1329#undef FUNC_NAME
f25f761d 1330#endif /* HAVE_SYMLINK */
0f2d19dd 1331
f25f761d 1332#ifdef HAVE_READLINK
a1ec6916 1333SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0,
1bbd0b84 1334 (SCM path),
1e6808ea
MG
1335 "Return the value of the symbolic link named by @var{path} (a\n"
1336 "string), i.e., the file that the link points to.")
1bbd0b84 1337#define FUNC_NAME s_scm_readlink
0f2d19dd 1338{
6a738a25
JB
1339 int rv;
1340 int size = 100;
0f2d19dd
JB
1341 char *buf;
1342 SCM result;
a6d9e5ab 1343 SCM_VALIDATE_STRING (1, path);
4c9419ac 1344 buf = scm_malloc (size);
a6d9e5ab 1345 while ((rv = readlink (SCM_STRING_CHARS (path), buf, size)) == size)
0f2d19dd 1346 {
4c9419ac 1347 free (buf);
0f2d19dd 1348 size *= 2;
4c9419ac 1349 buf = scm_malloc (size);
0f2d19dd 1350 }
02b754d3 1351 if (rv == -1)
1bbd0b84 1352 SCM_SYSERROR;
36284627 1353 result = scm_mem2string (buf, rv);
4c9419ac 1354 free (buf);
0f2d19dd 1355 return result;
0f2d19dd 1356}
1bbd0b84 1357#undef FUNC_NAME
f25f761d 1358#endif /* HAVE_READLINK */
0f2d19dd 1359
f25f761d 1360#ifdef HAVE_LSTAT
a1ec6916 1361SCM_DEFINE (scm_lstat, "lstat", 1, 0, 0,
1bbd0b84 1362 (SCM str),
d3818c29 1363 "Similar to @code{stat}, but does not follow symbolic links, i.e.,\n"
9401323e 1364 "it will return information about a symbolic link itself, not the\n"
d3818c29 1365 "file it points to. @var{path} must be a string.")
1bbd0b84 1366#define FUNC_NAME s_scm_lstat
0f2d19dd 1367{
02b754d3 1368 int rv;
0f2d19dd 1369 struct stat stat_temp;
02b754d3 1370
a6d9e5ab 1371 SCM_VALIDATE_STRING (1, str);
a6d9e5ab 1372 SCM_SYSCALL (rv = lstat (SCM_STRING_CHARS (str), &stat_temp));
02b754d3 1373 if (rv != 0)
3d8d56df
GH
1374 {
1375 int en = errno;
1376
5d2d2ffc 1377 SCM_SYSERROR_MSG ("~A: ~S",
1afff620 1378 scm_list_2 (scm_makfrom0str (strerror (errno)), str),
e0c08f17 1379 en);
3d8d56df 1380 }
02b754d3 1381 return scm_stat2scm(&stat_temp);
0f2d19dd 1382}
1bbd0b84 1383#undef FUNC_NAME
f25f761d 1384#endif /* HAVE_LSTAT */
0f2d19dd 1385
a1ec6916 1386SCM_DEFINE (scm_copy_file, "copy-file", 2, 0, 0,
1bbd0b84 1387 (SCM oldfile, SCM newfile),
d3818c29
MD
1388 "Copy the file specified by @var{path-from} to @var{path-to}.\n"
1389 "The return value is unspecified.")
1bbd0b84 1390#define FUNC_NAME s_scm_copy_file
0f2d19dd
JB
1391{
1392 int oldfd, newfd;
1393 int n;
77a76b64 1394 char buf[BUFSIZ];
0f2d19dd
JB
1395 struct stat oldstat;
1396
a6d9e5ab 1397 SCM_VALIDATE_STRING (1, oldfile);
a6d9e5ab 1398 SCM_VALIDATE_STRING (2, newfile);
a6d9e5ab 1399 if (stat (SCM_STRING_CHARS (oldfile), &oldstat) == -1)
1bbd0b84 1400 SCM_SYSERROR;
a6d9e5ab 1401 oldfd = open (SCM_STRING_CHARS (oldfile), O_RDONLY);
0f2d19dd 1402 if (oldfd == -1)
1bbd0b84 1403 SCM_SYSERROR;
02b754d3
GH
1404
1405 /* use POSIX flags instead of 07777?. */
a6d9e5ab 1406 newfd = open (SCM_STRING_CHARS (newfile), O_WRONLY | O_CREAT | O_TRUNC,
0f2d19dd
JB
1407 oldstat.st_mode & 07777);
1408 if (newfd == -1)
1bbd0b84 1409 SCM_SYSERROR;
02b754d3 1410
0f2d19dd
JB
1411 while ((n = read (oldfd, buf, sizeof buf)) > 0)
1412 if (write (newfd, buf, n) != n)
1413 {
1414 close (oldfd);
1415 close (newfd);
1bbd0b84 1416 SCM_SYSERROR;
0f2d19dd
JB
1417 }
1418 close (oldfd);
1419 if (close (newfd) == -1)
1bbd0b84 1420 SCM_SYSERROR;
02b754d3 1421 return SCM_UNSPECIFIED;
0f2d19dd 1422}
1bbd0b84 1423#undef FUNC_NAME
0f2d19dd
JB
1424
1425\f
6a738a25
JB
1426/* Filename manipulation */
1427
1428SCM scm_dot_string;
1429
a1ec6916 1430SCM_DEFINE (scm_dirname, "dirname", 1, 0, 0,
1bbd0b84 1431 (SCM filename),
fa6a543f
MG
1432 "Return the directory name component of the file name\n"
1433 "@var{filename}. If @var{filename} does not contain a directory\n"
1434 "component, @code{.} is returned.")
1bbd0b84 1435#define FUNC_NAME s_scm_dirname
6a738a25
JB
1436{
1437 char *s;
9fd38a3d
DH
1438 long int i;
1439 unsigned long int len;
1440
34d19ef6 1441 SCM_VALIDATE_STRING (1, filename);
9fd38a3d 1442
34f0f2b8 1443 s = SCM_STRING_CHARS (filename);
9fd38a3d
DH
1444 len = SCM_STRING_LENGTH (filename);
1445
6a738a25 1446 i = len - 1;
82893676
MG
1447#ifdef __MINGW32__
1448 while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
e0c73a1c 1449 while (i >= 0 && (s[i] != '/' && s[i] != '\\')) --i;
82893676
MG
1450 while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
1451#else
6a738a25
JB
1452 while (i >= 0 && s[i] == '/') --i;
1453 while (i >= 0 && s[i] != '/') --i;
1454 while (i >= 0 && s[i] == '/') --i;
82893676 1455#endif /* ndef __MINGW32__ */
6a738a25
JB
1456 if (i < 0)
1457 {
82893676
MG
1458#ifdef __MINGW32__
1459 if (len > 0 && (s[0] == '/' || s[0] == '\\'))
1460#else
6a738a25 1461 if (len > 0 && s[0] == '/')
82893676 1462#endif /* ndef __MINGW32__ */
d1ca2c64 1463 return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
6a738a25
JB
1464 else
1465 return scm_dot_string;
1466 }
1467 else
d1ca2c64 1468 return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (i + 1));
6a738a25 1469}
1bbd0b84 1470#undef FUNC_NAME
6a738a25 1471
a1ec6916 1472SCM_DEFINE (scm_basename, "basename", 1, 1, 0,
1bbd0b84 1473 (SCM filename, SCM suffix),
fa6a543f
MG
1474 "Return the base name of the file name @var{filename}. The\n"
1475 "base name is the file name without any directory components.\n"
bb2c02f2 1476 "If @var{suffix} is provided, and is equal to the end of\n"
fa6a543f 1477 "@var{basename}, it is removed also.")
1bbd0b84 1478#define FUNC_NAME s_scm_basename
6a738a25
JB
1479{
1480 char *f, *s = 0;
1481 int i, j, len, end;
9fd38a3d 1482
34d19ef6 1483 SCM_VALIDATE_STRING (1, filename);
34f0f2b8 1484 f = SCM_STRING_CHARS (filename);
9fd38a3d
DH
1485 len = SCM_STRING_LENGTH (filename);
1486
6a738a25
JB
1487 if (SCM_UNBNDP (suffix))
1488 j = -1;
1489 else
1490 {
9fd38a3d 1491 SCM_VALIDATE_STRING (2, suffix);
34f0f2b8 1492 s = SCM_STRING_CHARS (suffix);
9fd38a3d 1493 j = SCM_STRING_LENGTH (suffix) - 1;
6a738a25 1494 }
6a738a25 1495 i = len - 1;
82893676
MG
1496#ifdef __MINGW32__
1497 while (i >= 0 && (f[i] == '/' || f[i] == '\\')) --i;
1498#else
6a738a25 1499 while (i >= 0 && f[i] == '/') --i;
82893676 1500#endif /* ndef __MINGW32__ */
6a738a25
JB
1501 end = i;
1502 while (i >= 0 && j >= 0 && f[i] == s[j]) --i, --j;
1503 if (j == -1)
1504 end = i;
82893676 1505#ifdef __MINGW32__
2e945bcc 1506 while (i >= 0 && f[i] != '/' && f[i] != '\\') --i;
82893676 1507#else
6a738a25 1508 while (i >= 0 && f[i] != '/') --i;
82893676 1509#endif /* ndef __MINGW32__ */
6a738a25
JB
1510 if (i == end)
1511 {
82893676 1512#ifdef __MINGW32__
2e945bcc 1513 if (len > 0 && (f[0] == '/' || f[0] == '\\'))
82893676 1514#else
6a738a25 1515 if (len > 0 && f[0] == '/')
82893676 1516#endif /* ndef __MINGW32__ */
d1ca2c64 1517 return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
6a738a25
JB
1518 else
1519 return scm_dot_string;
1520 }
1521 else
d1ca2c64 1522 return scm_substring (filename, SCM_MAKINUM (i + 1), SCM_MAKINUM (end + 1));
6a738a25 1523}
1bbd0b84 1524#undef FUNC_NAME
6a738a25
JB
1525
1526
1527
1528\f
1cc91f1b 1529
0f2d19dd
JB
1530void
1531scm_init_filesys ()
0f2d19dd 1532{
e841c3e0
KN
1533 scm_tc16_dir = scm_make_smob_type ("directory", 0);
1534 scm_set_smob_free (scm_tc16_dir, scm_dir_free);
1535 scm_set_smob_print (scm_tc16_dir, scm_dir_print);
0f2d19dd 1536
a163dda9
MD
1537 scm_dot_string = scm_permanent_object (scm_makfrom0str ("."));
1538
3d8d56df 1539#ifdef O_RDONLY
86d31dfe 1540 scm_c_define ("O_RDONLY", scm_long2num (O_RDONLY));
3d8d56df
GH
1541#endif
1542#ifdef O_WRONLY
86d31dfe 1543 scm_c_define ("O_WRONLY", scm_long2num (O_WRONLY));
3d8d56df
GH
1544#endif
1545#ifdef O_RDWR
86d31dfe 1546 scm_c_define ("O_RDWR", scm_long2num (O_RDWR));
3d8d56df
GH
1547#endif
1548#ifdef O_CREAT
86d31dfe 1549 scm_c_define ("O_CREAT", scm_long2num (O_CREAT));
3d8d56df
GH
1550#endif
1551#ifdef O_EXCL
86d31dfe 1552 scm_c_define ("O_EXCL", scm_long2num (O_EXCL));
3d8d56df
GH
1553#endif
1554#ifdef O_NOCTTY
86d31dfe 1555 scm_c_define ("O_NOCTTY", scm_long2num (O_NOCTTY));
3d8d56df
GH
1556#endif
1557#ifdef O_TRUNC
86d31dfe 1558 scm_c_define ("O_TRUNC", scm_long2num (O_TRUNC));
3d8d56df
GH
1559#endif
1560#ifdef O_APPEND
86d31dfe 1561 scm_c_define ("O_APPEND", scm_long2num (O_APPEND));
3d8d56df 1562#endif
6afcd3b2 1563#ifdef O_NONBLOCK
86d31dfe 1564 scm_c_define ("O_NONBLOCK", scm_long2num (O_NONBLOCK));
3d8d56df
GH
1565#endif
1566#ifdef O_NDELAY
86d31dfe 1567 scm_c_define ("O_NDELAY", scm_long2num (O_NDELAY));
3d8d56df
GH
1568#endif
1569#ifdef O_SYNC
86d31dfe 1570 scm_c_define ("O_SYNC", scm_long2num (O_SYNC));
3d8d56df
GH
1571#endif
1572
4c1feaa5 1573#ifdef F_DUPFD
86d31dfe 1574 scm_c_define ("F_DUPFD", scm_long2num (F_DUPFD));
4c1feaa5
JB
1575#endif
1576#ifdef F_GETFD
86d31dfe 1577 scm_c_define ("F_GETFD", scm_long2num (F_GETFD));
4c1feaa5
JB
1578#endif
1579#ifdef F_SETFD
86d31dfe 1580 scm_c_define ("F_SETFD", scm_long2num (F_SETFD));
4c1feaa5
JB
1581#endif
1582#ifdef F_GETFL
86d31dfe 1583 scm_c_define ("F_GETFL", scm_long2num (F_GETFL));
4c1feaa5
JB
1584#endif
1585#ifdef F_SETFL
86d31dfe 1586 scm_c_define ("F_SETFL", scm_long2num (F_SETFL));
4c1feaa5
JB
1587#endif
1588#ifdef F_GETOWN
86d31dfe 1589 scm_c_define ("F_GETOWN", scm_long2num (F_GETOWN));
4c1feaa5
JB
1590#endif
1591#ifdef F_SETOWN
86d31dfe 1592 scm_c_define ("F_SETOWN", scm_long2num (F_SETOWN));
4c1feaa5
JB
1593#endif
1594#ifdef FD_CLOEXEC
86d31dfe 1595 scm_c_define ("FD_CLOEXEC", scm_long2num (FD_CLOEXEC));
bd9e24b3 1596#endif
3d8d56df 1597
a0599745 1598#include "libguile/filesys.x"
0f2d19dd 1599}
89e00824
ML
1600
1601/*
1602 Local Variables:
1603 c-file-style: "gnu"
1604 End:
1605*/