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