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