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