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