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