More of:
[bpt/guile.git] / libguile / filesys.c
1 /* Copyright (C) 1996,1997,1998,1999,2000,2001, 2002, 2004 Free Software Foundation, Inc.
2 *
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.
7 *
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.
12 *
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 */
17
18
19 \f
20 #define _GNU_SOURCE /* ask glibc for everything */
21 #define _POSIX_C_SOURCE 199506L /* for readdir_r elsewhere */
22
23 #if HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <errno.h>
29
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"
37 #include "libguile/lang.h"
38
39 #include "libguile/validate.h"
40 #include "libguile/filesys.h"
41
42 \f
43 #ifdef HAVE_IO_H
44 #include <io.h>
45 #endif
46
47 #ifdef HAVE_DIRECT_H
48 #include <direct.h>
49 #endif
50
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
66 #ifdef LIBC_H_WITH_UNISTD_H
67 #include <libc.h>
68 #endif
69
70 #ifdef HAVE_SYS_SELECT_H
71 #include <sys/select.h>
72 #endif
73
74 #ifdef HAVE_STRING_H
75 #include <string.h>
76 #endif
77
78 #include <sys/types.h>
79 #include <sys/stat.h>
80 #include <fcntl.h>
81
82 #ifdef HAVE_PWD_H
83 #include <pwd.h>
84 #endif
85
86
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
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
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
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__
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)
162 # define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
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__ */
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__ */
176 \f
177
178
179 \f
180
181 /* {Permissions}
182 */
183
184 #ifdef HAVE_CHOWN
185 SCM_DEFINE (scm_chown, "chown", 3, 0, 0,
186 (SCM object, SCM owner, SCM group),
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"
192 "is unspecified.\n\n"
193 "If @var{object} is a symbolic link, either the\n"
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.")
198 #define FUNC_NAME s_scm_chown
199 {
200 int rv;
201
202 object = SCM_COERCE_OUTPORT (object);
203
204 SCM_VALIDATE_INUM (2, owner);
205 SCM_VALIDATE_INUM (3, group);
206 #ifdef HAVE_FCHOWN
207 if (SCM_INUMP (object) || (SCM_OPFPORTP (object)))
208 {
209 int fdes = SCM_INUMP (object) ? SCM_INUM (object)
210 : SCM_FPORT_FDES (object);
211
212 SCM_SYSCALL (rv = fchown (fdes, SCM_INUM (owner), SCM_INUM (group)));
213 }
214 else
215 #endif
216 {
217 SCM_VALIDATE_STRING (1, object);
218 SCM_SYSCALL (rv = chown (SCM_STRING_CHARS (object),
219 SCM_INUM (owner), SCM_INUM (group)));
220 }
221 if (rv == -1)
222 SCM_SYSERROR;
223 return SCM_UNSPECIFIED;
224 }
225 #undef FUNC_NAME
226 #endif /* HAVE_CHOWN */
227
228
229 SCM_DEFINE (scm_chmod, "chmod", 2, 0, 0,
230 (SCM object, SCM mode),
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.")
238 #define FUNC_NAME s_scm_chmod
239 {
240 int rv;
241 int fdes;
242
243 object = SCM_COERCE_OUTPORT (object);
244
245 SCM_VALIDATE_INUM (2, mode);
246 if (SCM_INUMP (object) || SCM_OPFPORTP (object))
247 {
248 if (SCM_INUMP (object))
249 fdes = SCM_INUM (object);
250 else
251 fdes = SCM_FPORT_FDES (object);
252 SCM_SYSCALL (rv = fchmod (fdes, SCM_INUM (mode)));
253 }
254 else
255 {
256 SCM_VALIDATE_STRING (1, object);
257 SCM_SYSCALL (rv = chmod (SCM_STRING_CHARS (object), SCM_INUM (mode)));
258 }
259 if (rv == -1)
260 SCM_SYSERROR;
261 return SCM_UNSPECIFIED;
262 }
263 #undef FUNC_NAME
264
265 SCM_DEFINE (scm_umask, "umask", 0, 1, 0,
266 (SCM mode),
267 "If @var{mode} is omitted, returns a decimal number representing the current\n"
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.")
271 #define FUNC_NAME s_scm_umask
272 {
273 mode_t mask;
274 if (SCM_UNBNDP (mode))
275 {
276 mask = umask (0);
277 umask (mask);
278 }
279 else
280 {
281 SCM_VALIDATE_INUM (1, mode);
282 mask = umask (SCM_INUM (mode));
283 }
284 return SCM_MAKINUM (mask);
285 }
286 #undef FUNC_NAME
287
288 \f
289
290 SCM_DEFINE (scm_open_fdes, "open-fdes", 2, 1, 0,
291 (SCM path, SCM flags, SCM mode),
292 "Similar to @code{open} but return a file descriptor instead of\n"
293 "a port.")
294 #define FUNC_NAME s_scm_open_fdes
295 {
296 int fd;
297 int iflags;
298 int imode;
299
300 SCM_VALIDATE_STRING (1, path);
301 iflags = SCM_NUM2INT (2, flags);
302 imode = SCM_NUM2INT_DEF (3, mode, 0666);
303 SCM_SYSCALL (fd = open (SCM_STRING_CHARS (path), iflags, imode));
304 if (fd == -1)
305 SCM_SYSERROR;
306 return SCM_MAKINUM (fd);
307 }
308 #undef FUNC_NAME
309
310 SCM_DEFINE (scm_open, "open", 2, 1, 0,
311 (SCM path, SCM flags, SCM mode),
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"
323 "Open the file write-only.\n"
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.")
336 #define FUNC_NAME s_scm_open
337 {
338 SCM newpt;
339 char *port_mode;
340 int fd;
341 int iflags;
342
343 fd = SCM_INUM (scm_open_fdes (path, flags, mode));
344 iflags = SCM_NUM2INT (2, flags);
345 if (iflags & O_RDWR)
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 }
354 else {
355 if (iflags & O_APPEND)
356 port_mode = "a";
357 else if (iflags & O_WRONLY)
358 port_mode = "w";
359 else
360 port_mode = "r";
361 }
362 newpt = scm_fdes_to_port (fd, port_mode, path);
363 return newpt;
364 }
365 #undef FUNC_NAME
366
367 SCM_DEFINE (scm_close, "close", 1, 0, 0,
368 (SCM fd_or_port),
369 "Similar to close-port (@pxref{Closing, close-port}),\n"
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.")
374 #define FUNC_NAME s_scm_close
375 {
376 int rv;
377 int fd;
378
379 fd_or_port = SCM_COERCE_OUTPORT (fd_or_port);
380
381 if (SCM_PORTP (fd_or_port))
382 return scm_close_port (fd_or_port);
383 SCM_VALIDATE_INUM (1, fd_or_port);
384 fd = SCM_INUM (fd_or_port);
385 scm_evict_ports (fd); /* see scsh manual. */
386 SCM_SYSCALL (rv = close (fd));
387 /* following scsh, closing an already closed file descriptor is
388 not an error. */
389 if (rv < 0 && errno != EBADF)
390 SCM_SYSERROR;
391 return SCM_BOOL (rv >= 0);
392 }
393 #undef FUNC_NAME
394
395 SCM_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
415 \f
416 /* {Files}
417 */
418
419 SCM_SYMBOL (scm_sym_regular, "regular");
420 SCM_SYMBOL (scm_sym_directory, "directory");
421 #ifdef HAVE_S_ISLNK
422 SCM_SYMBOL (scm_sym_symlink, "symlink");
423 #endif
424 SCM_SYMBOL (scm_sym_block_special, "block-special");
425 SCM_SYMBOL (scm_sym_char_special, "char-special");
426 SCM_SYMBOL (scm_sym_fifo, "fifo");
427 SCM_SYMBOL (scm_sym_sock, "socket");
428 SCM_SYMBOL (scm_sym_unknown, "unknown");
429
430 static SCM
431 scm_stat2scm (struct stat *stat_temp)
432 {
433 SCM ans = scm_c_make_vector (15, SCM_UNSPECIFIED);
434
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));
441 #ifdef HAVE_STRUCT_STAT_ST_RDEV
442 SCM_VECTOR_SET(ans, 6, scm_ulong2num ((unsigned long) stat_temp->st_rdev));
443 #else
444 SCM_VECTOR_SET(ans, 6, SCM_BOOL_F);
445 #endif
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));
450 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
451 SCM_VECTOR_SET(ans, 11, scm_ulong2num ((unsigned long) stat_temp->st_blksize));
452 #else
453 SCM_VECTOR_SET(ans, 11, scm_ulong2num (4096L));
454 #endif
455 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
456 SCM_VECTOR_SET(ans, 12, scm_ulong2num ((unsigned long) stat_temp->st_blocks));
457 #else
458 SCM_VECTOR_SET(ans, 12, SCM_BOOL_F);
459 #endif
460 {
461 int mode = stat_temp->st_mode;
462
463 if (S_ISREG (mode))
464 SCM_VECTOR_SET(ans, 13, scm_sym_regular);
465 else if (S_ISDIR (mode))
466 SCM_VECTOR_SET(ans, 13, scm_sym_directory);
467 #ifdef HAVE_S_ISLNK
468 else if (S_ISLNK (mode))
469 SCM_VECTOR_SET(ans, 13, scm_sym_symlink);
470 #endif
471 else if (S_ISBLK (mode))
472 SCM_VECTOR_SET(ans, 13, scm_sym_block_special);
473 else if (S_ISCHR (mode))
474 SCM_VECTOR_SET(ans, 13, scm_sym_char_special);
475 else if (S_ISFIFO (mode))
476 SCM_VECTOR_SET(ans, 13, scm_sym_fifo);
477 #ifdef S_ISSOCK
478 else if (S_ISSOCK (mode))
479 SCM_VECTOR_SET(ans, 13, scm_sym_sock);
480 #endif
481 else
482 SCM_VECTOR_SET(ans, 13, scm_sym_unknown);
483
484 SCM_VECTOR_SET(ans, 14, SCM_MAKINUM ((~S_IFMT) & mode));
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
513 SCM_VECTOR_SET(ans, 14, SCM_MAKINUM (tmp));
514
515 */
516 }
517
518 return ans;
519 }
520
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 */
527 static 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
546 SCM_DEFINE (scm_stat, "stat", 1, 0, 0,
547 (SCM object),
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"
558 "@table @code\n"
559 "@item stat:dev\n"
560 "The device containing the file.\n"
561 "@item stat:ino\n"
562 "The file serial number, which distinguishes this file from all\n"
563 "other files on the same device.\n"
564 "@item stat:mode\n"
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"
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"
586 "The optimal block size for reading or writing the file, in\n"
587 "bytes.\n"
588 "@item stat:blocks\n"
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"
593 "In addition, the following procedures return the information\n"
594 "from stat:mode in a more convenient form:\n"
595 "\n"
596 "@table @code\n"
597 "@item stat:type\n"
598 "A symbol representing the type of file. Possible values are\n"
599 "regular, directory, symlink, block-special, char-special, fifo,\n"
600 "socket and unknown\n"
601 "@item stat:perms\n"
602 "An integer representing the access permission bits.\n"
603 "@end table")
604 #define FUNC_NAME s_scm_stat
605 {
606 int rv;
607 int fdes;
608 struct stat stat_temp;
609
610 if (SCM_INUMP (object))
611 {
612 #ifdef __MINGW32__
613 SCM_SYSCALL (rv = fstat_Win32 (SCM_INUM (object), &stat_temp));
614 #else
615 SCM_SYSCALL (rv = fstat (SCM_INUM (object), &stat_temp));
616 #endif
617 }
618 else if (SCM_STRINGP (object))
619 {
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
628 SCM_SYSCALL (rv = stat (SCM_STRING_CHARS (object), &stat_temp));
629 #endif
630 }
631 else
632 {
633 object = SCM_COERCE_OUTPORT (object);
634 SCM_VALIDATE_OPFPORT (1, object);
635 fdes = SCM_FPORT_FDES (object);
636 #ifdef __MINGW32__
637 SCM_SYSCALL (rv = fstat_Win32 (fdes, &stat_temp));
638 #else
639 SCM_SYSCALL (rv = fstat (fdes, &stat_temp));
640 #endif
641 }
642
643 if (rv == -1)
644 {
645 int en = errno;
646
647 SCM_SYSERROR_MSG ("~A: ~S",
648 scm_list_2 (scm_makfrom0str (strerror (errno)),
649 object),
650 en);
651 }
652 return scm_stat2scm (&stat_temp);
653 }
654 #undef FUNC_NAME
655
656 \f
657 /* {Modifying Directories}
658 */
659
660 #ifdef HAVE_LINK
661 SCM_DEFINE (scm_link, "link", 2, 0, 0,
662 (SCM oldpath, SCM newpath),
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.")
667 #define FUNC_NAME s_scm_link
668 {
669 int val;
670
671 SCM_VALIDATE_STRING (1, oldpath);
672 SCM_VALIDATE_STRING (2, newpath);
673 SCM_SYSCALL (val = link (SCM_STRING_CHARS (oldpath),
674 SCM_STRING_CHARS (newpath)));
675 if (val != 0)
676 SCM_SYSERROR;
677 return SCM_UNSPECIFIED;
678 }
679 #undef FUNC_NAME
680 #endif /* HAVE_LINK */
681
682
683
684 SCM_DEFINE (scm_rename, "rename-file", 2, 0, 0,
685 (SCM oldname, SCM newname),
686 "Renames the file specified by @var{oldname} to @var{newname}.\n"
687 "The return value is unspecified.")
688 #define FUNC_NAME s_scm_rename
689 {
690 int rv;
691 SCM_VALIDATE_STRING (1, oldname);
692 SCM_VALIDATE_STRING (2, newname);
693 #ifdef HAVE_RENAME
694 SCM_SYSCALL (rv = rename (SCM_STRING_CHARS (oldname), SCM_STRING_CHARS (newname)));
695 #else
696 SCM_SYSCALL (rv = link (SCM_STRING_CHARS (oldname), SCM_STRING_CHARS (newname)));
697 if (rv == 0)
698 {
699 SCM_SYSCALL (rv = unlink (SCM_STRING_CHARS (oldname)));;
700 if (rv != 0)
701 /* unlink failed. remove new name */
702 SCM_SYSCALL (unlink (SCM_STRING_CHARS (newname)));
703 }
704 #endif
705 if (rv != 0)
706 SCM_SYSERROR;
707 return SCM_UNSPECIFIED;
708 }
709 #undef FUNC_NAME
710
711
712 SCM_DEFINE (scm_delete_file, "delete-file", 1, 0, 0,
713 (SCM str),
714 "Deletes (or \"unlinks\") the file specified by @var{path}.")
715 #define FUNC_NAME s_scm_delete_file
716 {
717 int ans;
718 SCM_VALIDATE_STRING (1, str);
719 SCM_SYSCALL (ans = unlink (SCM_STRING_CHARS (str)));
720 if (ans != 0)
721 SCM_SYSERROR;
722 return SCM_UNSPECIFIED;
723 }
724 #undef FUNC_NAME
725
726 #ifdef HAVE_MKDIR
727 SCM_DEFINE (scm_mkdir, "mkdir", 1, 1, 0,
728 (SCM path, SCM mode),
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.")
733 #define FUNC_NAME s_scm_mkdir
734 {
735 int rv;
736 mode_t mask;
737 SCM_VALIDATE_STRING (1, path);
738 if (SCM_UNBNDP (mode))
739 {
740 mask = umask (0);
741 umask (mask);
742 SCM_SYSCALL (rv = mkdir (SCM_STRING_CHARS (path), 0777 ^ mask));
743 }
744 else
745 {
746 SCM_VALIDATE_INUM (2, mode);
747 SCM_SYSCALL (rv = mkdir (SCM_STRING_CHARS (path), SCM_INUM (mode)));
748 }
749 if (rv != 0)
750 SCM_SYSERROR;
751 return SCM_UNSPECIFIED;
752 }
753 #undef FUNC_NAME
754 #endif /* HAVE_MKDIR */
755
756 #ifdef HAVE_RMDIR
757 SCM_DEFINE (scm_rmdir, "rmdir", 1, 0, 0,
758 (SCM path),
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.")
761 #define FUNC_NAME s_scm_rmdir
762 {
763 int val;
764
765 SCM_VALIDATE_STRING (1, path);
766 SCM_SYSCALL (val = rmdir (SCM_STRING_CHARS (path)));
767 if (val != 0)
768 SCM_SYSERROR;
769 return SCM_UNSPECIFIED;
770 }
771 #undef FUNC_NAME
772 #endif
773
774 \f
775
776 /* {Examining Directories}
777 */
778
779 scm_t_bits scm_tc16_dir;
780
781
782 SCM_DEFINE (scm_directory_stream_p, "directory-stream?", 1, 0, 0,
783 (SCM obj),
784 "Return a boolean indicating whether @var{object} is a directory\n"
785 "stream as returned by @code{opendir}.")
786 #define FUNC_NAME s_scm_directory_stream_p
787 {
788 return SCM_BOOL (SCM_DIRP (obj));
789 }
790 #undef FUNC_NAME
791
792
793 SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0,
794 (SCM dirname),
795 "Open the directory specified by @var{path} and return a directory\n"
796 "stream.")
797 #define FUNC_NAME s_scm_opendir
798 {
799 DIR *ds;
800 SCM_VALIDATE_STRING (1, dirname);
801 SCM_SYSCALL (ds = opendir (SCM_STRING_CHARS (dirname)));
802 if (ds == NULL)
803 SCM_SYSERROR;
804 SCM_RETURN_NEWSMOB (scm_tc16_dir | SCM_DIR_FLAG_OPEN, ds);
805 }
806 #undef FUNC_NAME
807
808
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
814 SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
815 (SCM port),
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.")
819 #define FUNC_NAME s_scm_readdir
820 {
821 struct dirent *rdent;
822
823 SCM_VALIDATE_DIR (1, port);
824 if (!SCM_DIR_OPEN_P (port))
825 SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
826
827 errno = 0;
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;
846
847 return (rdent ? scm_mem2string (rdent->d_name, NAMLEN (rdent))
848 : SCM_EOF_VAL);
849 }
850 }
851 #undef FUNC_NAME
852
853
854 SCM_DEFINE (scm_rewinddir, "rewinddir", 1, 0, 0,
855 (SCM port),
856 "Reset the directory port @var{stream} so that the next call to\n"
857 "@code{readdir} will return the first directory entry.")
858 #define FUNC_NAME s_scm_rewinddir
859 {
860 SCM_VALIDATE_DIR (1, port);
861 if (!SCM_DIR_OPEN_P (port))
862 SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
863
864 rewinddir ((DIR *) SCM_CELL_WORD_1 (port));
865
866 return SCM_UNSPECIFIED;
867 }
868 #undef FUNC_NAME
869
870
871 SCM_DEFINE (scm_closedir, "closedir", 1, 0, 0,
872 (SCM port),
873 "Close the directory stream @var{stream}.\n"
874 "The return value is unspecified.")
875 #define FUNC_NAME s_scm_closedir
876 {
877 SCM_VALIDATE_DIR (1, port);
878
879 if (SCM_DIR_OPEN_P (port))
880 {
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);
888 }
889
890 return SCM_UNSPECIFIED;
891 }
892 #undef FUNC_NAME
893
894
895 static int
896 scm_dir_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
897 {
898 scm_puts ("#<", port);
899 if (!SCM_DIR_OPEN_P (exp))
900 scm_puts ("closed: ", port);
901 scm_puts ("directory stream ", port);
902 scm_intprint (SCM_CELL_WORD_1 (exp), 16, port);
903 scm_putc ('>', port);
904 return 1;
905 }
906
907
908 static size_t
909 scm_dir_free (SCM p)
910 {
911 if (SCM_DIR_OPEN_P (p))
912 closedir ((DIR *) SCM_CELL_WORD_1 (p));
913 return 0;
914 }
915
916 \f
917 /* {Navigating Directories}
918 */
919
920
921 SCM_DEFINE (scm_chdir, "chdir", 1, 0, 0,
922 (SCM str),
923 "Change the current working directory to @var{path}.\n"
924 "The return value is unspecified.")
925 #define FUNC_NAME s_scm_chdir
926 {
927 int ans;
928
929 SCM_VALIDATE_STRING (1, str);
930 SCM_SYSCALL (ans = chdir (SCM_STRING_CHARS (str)));
931 if (ans != 0)
932 SCM_SYSERROR;
933 return SCM_UNSPECIFIED;
934 }
935 #undef FUNC_NAME
936
937 #ifdef HAVE_GETCWD
938 SCM_DEFINE (scm_getcwd, "getcwd", 0, 0, 0,
939 (),
940 "Return the name of the current working directory.")
941 #define FUNC_NAME s_scm_getcwd
942 {
943 char *rv;
944 size_t size = 100;
945 char *wd;
946 SCM result;
947
948 wd = scm_malloc (size);
949 while ((rv = getcwd (wd, size)) == 0 && errno == ERANGE)
950 {
951 free (wd);
952 size *= 2;
953 wd = scm_malloc (size);
954 }
955 if (rv == 0)
956 {
957 int save_errno = errno;
958 free (wd);
959 errno = save_errno;
960 SCM_SYSERROR;
961 }
962 result = scm_mem2string (wd, strlen (wd));
963 free (wd);
964 return result;
965 }
966 #undef FUNC_NAME
967 #endif /* HAVE_GETCWD */
968
969 \f
970
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. */
978 static int
979 set_element (SELECT_TYPE *set, SCM *ports_ready, SCM element, int pos)
980 {
981 int fd;
982
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. */
996 scm_t_port *pt = SCM_PTAB_ENTRY (element);
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. */
1004 scm_t_port *pt = SCM_PTAB_ENTRY (element);
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);
1016 return fd;
1017 }
1018
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. */
1024 static int
1025 fill_select_type (SELECT_TYPE *set, SCM *ports_ready, SCM list_or_vec, int pos)
1026 {
1027 int max_fd = 0;
1028
1029 if (SCM_VECTORP (list_or_vec))
1030 {
1031 int i = SCM_VECTOR_LENGTH (list_or_vec);
1032 SCM const *ve = SCM_VELTS (list_or_vec);
1033
1034 while (--i >= 0)
1035 {
1036 int fd = set_element (set, ports_ready, ve[i], pos);
1037
1038 if (fd > max_fd)
1039 max_fd = fd;
1040 }
1041 }
1042 else
1043 {
1044 while (!SCM_NULL_OR_NIL_P (list_or_vec))
1045 {
1046 int fd = set_element (set, ports_ready, SCM_CAR (list_or_vec), pos);
1047
1048 if (fd > max_fd)
1049 max_fd = fd;
1050 list_or_vec = SCM_CDR (list_or_vec);
1051 }
1052 }
1053
1054 return max_fd;
1055 }
1056
1057 /* if element (a file descriptor or port) appears in *set, cons it to
1058 list. return list. */
1059 static SCM
1060 get_element (SELECT_TYPE *set, SCM element, SCM list)
1061 {
1062 int fd;
1063
1064 if (SCM_INUMP (element))
1065 {
1066 fd = SCM_INUM (element);
1067 }
1068 else
1069 {
1070 fd = SCM_FPORT_FDES (SCM_COERCE_OUTPORT (element));
1071 }
1072 if (FD_ISSET (fd, set))
1073 list = scm_cons (element, list);
1074 return list;
1075 }
1076
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. */
1085 static SCM
1086 retrieve_select_type (SELECT_TYPE *set, SCM ports_ready, SCM list_or_vec)
1087 {
1088 SCM answer_list = ports_ready;
1089
1090 if (SCM_VECTORP (list_or_vec))
1091 {
1092 int i = SCM_VECTOR_LENGTH (list_or_vec);
1093 SCM const *ve = SCM_VELTS (list_or_vec);
1094
1095 while (--i >= 0)
1096 {
1097 answer_list = get_element (set, ve[i], answer_list);
1098 }
1099 return scm_vector (answer_list);
1100 }
1101 else
1102 {
1103 /* list_or_vec must be a list. */
1104 while (!SCM_NULL_OR_NIL_P (list_or_vec))
1105 {
1106 answer_list = get_element (set, SCM_CAR (list_or_vec), answer_list);
1107 list_or_vec = SCM_CDR (list_or_vec);
1108 }
1109 return answer_list;
1110 }
1111 }
1112
1113 /* Static helper functions above refer to s_scm_select directly as s_select */
1114 SCM_DEFINE (scm_select, "select", 3, 2, 0,
1115 (SCM reads, SCM writes, SCM excepts, SCM secs, SCM usecs),
1116 "This procedure has a variety of uses: waiting for the ability\n"
1117 "to provide input, accept output, or the existence of\n"
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"
1141 "An additional @code{select!} interface is provided.")
1142 #define FUNC_NAME s_scm_select
1143 {
1144 struct timeval timeout;
1145 struct timeval * time_ptr;
1146 SELECT_TYPE read_set;
1147 SELECT_TYPE write_set;
1148 SELECT_TYPE except_set;
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 {
1160 read_count = SCM_VECTOR_LENGTH (reads);
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 {
1169 write_count = SCM_VECTOR_LENGTH (writes);
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 {
1178 except_count = SCM_VECTOR_LENGTH (excepts);
1179 }
1180 else
1181 {
1182 except_count = scm_ilength (excepts);
1183 SCM_ASSERT (except_count >= 0, excepts, SCM_ARG3, FUNC_NAME);
1184 }
1185
1186 FD_ZERO (&read_set);
1187 FD_ZERO (&write_set);
1188 FD_ZERO (&except_set);
1189
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 }
1203
1204 /* if there's a port with a ready buffer, don't block, just
1205 check for ready file descriptors. */
1206 if (!SCM_NULLP (read_ports_ready) || !SCM_NULLP (write_ports_ready))
1207 {
1208 timeout.tv_sec = 0;
1209 timeout.tv_usec = 0;
1210 time_ptr = &timeout;
1211 }
1212 else if (SCM_UNBNDP (secs) || SCM_FALSEP (secs))
1213 time_ptr = 0;
1214 else
1215 {
1216 if (SCM_INUMP (secs))
1217 {
1218 timeout.tv_sec = SCM_INUM (secs);
1219 if (SCM_UNBNDP (usecs))
1220 timeout.tv_usec = 0;
1221 else
1222 {
1223 SCM_VALIDATE_INUM (5, usecs);
1224 timeout.tv_usec = SCM_INUM (usecs);
1225 }
1226 }
1227 else
1228 {
1229 double fl = scm_num2dbl (secs, FUNC_NAME);
1230
1231 if (!SCM_UNBNDP (usecs))
1232 SCM_WRONG_TYPE_ARG (4, secs);
1233 if (fl > LONG_MAX)
1234 SCM_OUT_OF_RANGE (4, secs);
1235 timeout.tv_sec = (long) fl;
1236 timeout.tv_usec = (long) ((fl - timeout.tv_sec) * 1000000);
1237 }
1238 time_ptr = &timeout;
1239 }
1240
1241 {
1242 int rv = scm_internal_select (max_fd + 1,
1243 &read_set, &write_set, &except_set,
1244 time_ptr);
1245 if (rv < 0)
1246 SCM_SYSERROR;
1247 }
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));
1251 }
1252 #undef FUNC_NAME
1253 #endif /* HAVE_SELECT */
1254
1255 \f
1256
1257 #ifdef HAVE_FCNTL
1258 SCM_DEFINE (scm_fcntl, "fcntl", 2, 1, 0,
1259 (SCM object, SCM cmd, SCM value),
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"
1280 "The value used to indicate the \"close on exec\" flag with @code{F_GETFL} or\n"
1281 "@code{F_SETFL}.\n"
1282 "@end table")
1283 #define FUNC_NAME s_scm_fcntl
1284 {
1285 int rv;
1286 int fdes;
1287 int ivalue;
1288
1289 object = SCM_COERCE_OUTPORT (object);
1290
1291 SCM_VALIDATE_INUM (2, cmd);
1292 if (SCM_OPFPORTP (object))
1293 fdes = SCM_FPORT_FDES (object);
1294 else
1295 {
1296 SCM_VALIDATE_INUM (1, object);
1297 fdes = SCM_INUM (object);
1298 }
1299
1300 if (SCM_UNBNDP (value)) {
1301 ivalue = 0;
1302 } else {
1303 SCM_VALIDATE_INUM_COPY (SCM_ARG3, value, ivalue);
1304 }
1305
1306 SCM_SYSCALL (rv = fcntl (fdes, SCM_INUM (cmd), ivalue));
1307 if (rv == -1)
1308 SCM_SYSERROR;
1309 return SCM_MAKINUM (rv);
1310 }
1311 #undef FUNC_NAME
1312 #endif /* HAVE_FCNTL */
1313
1314 SCM_DEFINE (scm_fsync, "fsync", 1, 0, 0,
1315 (SCM object),
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.")
1320 #define FUNC_NAME s_scm_fsync
1321 {
1322 int fdes;
1323
1324 object = SCM_COERCE_OUTPORT (object);
1325
1326 if (SCM_OPFPORTP (object))
1327 {
1328 scm_flush (object);
1329 fdes = SCM_FPORT_FDES (object);
1330 }
1331 else
1332 {
1333 SCM_VALIDATE_INUM (1, object);
1334 fdes = SCM_INUM (object);
1335 }
1336 if (fsync (fdes) == -1)
1337 SCM_SYSERROR;
1338 return SCM_UNSPECIFIED;
1339 }
1340 #undef FUNC_NAME
1341
1342 #ifdef HAVE_SYMLINK
1343 SCM_DEFINE (scm_symlink, "symlink", 2, 0, 0,
1344 (SCM oldpath, SCM newpath),
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.")
1347 #define FUNC_NAME s_scm_symlink
1348 {
1349 int val;
1350
1351 SCM_VALIDATE_STRING (1, oldpath);
1352 SCM_VALIDATE_STRING (2, newpath);
1353 SCM_SYSCALL (val = symlink (SCM_STRING_CHARS (oldpath), SCM_STRING_CHARS (newpath)));
1354 if (val != 0)
1355 SCM_SYSERROR;
1356 return SCM_UNSPECIFIED;
1357 }
1358 #undef FUNC_NAME
1359 #endif /* HAVE_SYMLINK */
1360
1361 #ifdef HAVE_READLINK
1362 SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0,
1363 (SCM path),
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.")
1366 #define FUNC_NAME s_scm_readlink
1367 {
1368 int rv;
1369 int size = 100;
1370 char *buf;
1371 SCM result;
1372 SCM_VALIDATE_STRING (1, path);
1373 buf = scm_malloc (size);
1374 while ((rv = readlink (SCM_STRING_CHARS (path), buf, size)) == size)
1375 {
1376 free (buf);
1377 size *= 2;
1378 buf = scm_malloc (size);
1379 }
1380 if (rv == -1)
1381 {
1382 int save_errno = errno;
1383 free (buf);
1384 errno = save_errno;
1385 SCM_SYSERROR;
1386 }
1387 result = scm_mem2string (buf, rv);
1388 free (buf);
1389 return result;
1390 }
1391 #undef FUNC_NAME
1392 #endif /* HAVE_READLINK */
1393
1394 #ifdef HAVE_LSTAT
1395 SCM_DEFINE (scm_lstat, "lstat", 1, 0, 0,
1396 (SCM str),
1397 "Similar to @code{stat}, but does not follow symbolic links, i.e.,\n"
1398 "it will return information about a symbolic link itself, not the\n"
1399 "file it points to. @var{path} must be a string.")
1400 #define FUNC_NAME s_scm_lstat
1401 {
1402 int rv;
1403 struct stat stat_temp;
1404
1405 SCM_VALIDATE_STRING (1, str);
1406 SCM_SYSCALL (rv = lstat (SCM_STRING_CHARS (str), &stat_temp));
1407 if (rv != 0)
1408 {
1409 int en = errno;
1410
1411 SCM_SYSERROR_MSG ("~A: ~S",
1412 scm_list_2 (scm_makfrom0str (strerror (errno)), str),
1413 en);
1414 }
1415 return scm_stat2scm(&stat_temp);
1416 }
1417 #undef FUNC_NAME
1418 #endif /* HAVE_LSTAT */
1419
1420 SCM_DEFINE (scm_copy_file, "copy-file", 2, 0, 0,
1421 (SCM oldfile, SCM newfile),
1422 "Copy the file specified by @var{path-from} to @var{path-to}.\n"
1423 "The return value is unspecified.")
1424 #define FUNC_NAME s_scm_copy_file
1425 {
1426 int oldfd, newfd;
1427 int n;
1428 char buf[BUFSIZ];
1429 struct stat oldstat;
1430
1431 SCM_VALIDATE_STRING (1, oldfile);
1432 SCM_VALIDATE_STRING (2, newfile);
1433 if (stat (SCM_STRING_CHARS (oldfile), &oldstat) == -1)
1434 SCM_SYSERROR;
1435 oldfd = open (SCM_STRING_CHARS (oldfile), O_RDONLY);
1436 if (oldfd == -1)
1437 SCM_SYSERROR;
1438
1439 /* use POSIX flags instead of 07777?. */
1440 newfd = open (SCM_STRING_CHARS (newfile), O_WRONLY | O_CREAT | O_TRUNC,
1441 oldstat.st_mode & 07777);
1442 if (newfd == -1)
1443 SCM_SYSERROR;
1444
1445 while ((n = read (oldfd, buf, sizeof buf)) > 0)
1446 if (write (newfd, buf, n) != n)
1447 {
1448 close (oldfd);
1449 close (newfd);
1450 SCM_SYSERROR;
1451 }
1452 close (oldfd);
1453 if (close (newfd) == -1)
1454 SCM_SYSERROR;
1455 return SCM_UNSPECIFIED;
1456 }
1457 #undef FUNC_NAME
1458
1459 \f
1460 /* Filename manipulation */
1461
1462 SCM scm_dot_string;
1463
1464 SCM_DEFINE (scm_dirname, "dirname", 1, 0, 0,
1465 (SCM filename),
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.")
1469 #define FUNC_NAME s_scm_dirname
1470 {
1471 char *s;
1472 long int i;
1473 unsigned long int len;
1474
1475 SCM_VALIDATE_STRING (1, filename);
1476
1477 s = SCM_STRING_CHARS (filename);
1478 len = SCM_STRING_LENGTH (filename);
1479
1480 i = len - 1;
1481 #ifdef __MINGW32__
1482 while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
1483 while (i >= 0 && (s[i] != '/' && s[i] != '\\')) --i;
1484 while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i;
1485 #else
1486 while (i >= 0 && s[i] == '/') --i;
1487 while (i >= 0 && s[i] != '/') --i;
1488 while (i >= 0 && s[i] == '/') --i;
1489 #endif /* ndef __MINGW32__ */
1490 if (i < 0)
1491 {
1492 #ifdef __MINGW32__
1493 if (len > 0 && (s[0] == '/' || s[0] == '\\'))
1494 #else
1495 if (len > 0 && s[0] == '/')
1496 #endif /* ndef __MINGW32__ */
1497 return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
1498 else
1499 return scm_dot_string;
1500 }
1501 else
1502 return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (i + 1));
1503 }
1504 #undef FUNC_NAME
1505
1506 SCM_DEFINE (scm_basename, "basename", 1, 1, 0,
1507 (SCM filename, SCM suffix),
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"
1510 "If @var{suffix} is provided, and is equal to the end of\n"
1511 "@var{basename}, it is removed also.")
1512 #define FUNC_NAME s_scm_basename
1513 {
1514 char *f, *s = 0;
1515 int i, j, len, end;
1516
1517 SCM_VALIDATE_STRING (1, filename);
1518 f = SCM_STRING_CHARS (filename);
1519 len = SCM_STRING_LENGTH (filename);
1520
1521 if (SCM_UNBNDP (suffix))
1522 j = -1;
1523 else
1524 {
1525 SCM_VALIDATE_STRING (2, suffix);
1526 s = SCM_STRING_CHARS (suffix);
1527 j = SCM_STRING_LENGTH (suffix) - 1;
1528 }
1529 i = len - 1;
1530 #ifdef __MINGW32__
1531 while (i >= 0 && (f[i] == '/' || f[i] == '\\')) --i;
1532 #else
1533 while (i >= 0 && f[i] == '/') --i;
1534 #endif /* ndef __MINGW32__ */
1535 end = i;
1536 while (i >= 0 && j >= 0 && f[i] == s[j]) --i, --j;
1537 if (j == -1)
1538 end = i;
1539 #ifdef __MINGW32__
1540 while (i >= 0 && f[i] != '/' && f[i] != '\\') --i;
1541 #else
1542 while (i >= 0 && f[i] != '/') --i;
1543 #endif /* ndef __MINGW32__ */
1544 if (i == end)
1545 {
1546 #ifdef __MINGW32__
1547 if (len > 0 && (f[0] == '/' || f[0] == '\\'))
1548 #else
1549 if (len > 0 && f[0] == '/')
1550 #endif /* ndef __MINGW32__ */
1551 return scm_substring (filename, SCM_INUM0, SCM_MAKINUM (1));
1552 else
1553 return scm_dot_string;
1554 }
1555 else
1556 return scm_substring (filename, SCM_MAKINUM (i + 1), SCM_MAKINUM (end + 1));
1557 }
1558 #undef FUNC_NAME
1559
1560
1561
1562 \f
1563
1564 void
1565 scm_init_filesys ()
1566 {
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);
1570
1571 scm_dot_string = scm_permanent_object (scm_makfrom0str ("."));
1572
1573 #ifdef O_RDONLY
1574 scm_c_define ("O_RDONLY", scm_long2num (O_RDONLY));
1575 #endif
1576 #ifdef O_WRONLY
1577 scm_c_define ("O_WRONLY", scm_long2num (O_WRONLY));
1578 #endif
1579 #ifdef O_RDWR
1580 scm_c_define ("O_RDWR", scm_long2num (O_RDWR));
1581 #endif
1582 #ifdef O_CREAT
1583 scm_c_define ("O_CREAT", scm_long2num (O_CREAT));
1584 #endif
1585 #ifdef O_EXCL
1586 scm_c_define ("O_EXCL", scm_long2num (O_EXCL));
1587 #endif
1588 #ifdef O_NOCTTY
1589 scm_c_define ("O_NOCTTY", scm_long2num (O_NOCTTY));
1590 #endif
1591 #ifdef O_TRUNC
1592 scm_c_define ("O_TRUNC", scm_long2num (O_TRUNC));
1593 #endif
1594 #ifdef O_APPEND
1595 scm_c_define ("O_APPEND", scm_long2num (O_APPEND));
1596 #endif
1597 #ifdef O_NONBLOCK
1598 scm_c_define ("O_NONBLOCK", scm_long2num (O_NONBLOCK));
1599 #endif
1600 #ifdef O_NDELAY
1601 scm_c_define ("O_NDELAY", scm_long2num (O_NDELAY));
1602 #endif
1603 #ifdef O_SYNC
1604 scm_c_define ("O_SYNC", scm_long2num (O_SYNC));
1605 #endif
1606
1607 #ifdef F_DUPFD
1608 scm_c_define ("F_DUPFD", scm_long2num (F_DUPFD));
1609 #endif
1610 #ifdef F_GETFD
1611 scm_c_define ("F_GETFD", scm_long2num (F_GETFD));
1612 #endif
1613 #ifdef F_SETFD
1614 scm_c_define ("F_SETFD", scm_long2num (F_SETFD));
1615 #endif
1616 #ifdef F_GETFL
1617 scm_c_define ("F_GETFL", scm_long2num (F_GETFL));
1618 #endif
1619 #ifdef F_SETFL
1620 scm_c_define ("F_SETFL", scm_long2num (F_SETFL));
1621 #endif
1622 #ifdef F_GETOWN
1623 scm_c_define ("F_GETOWN", scm_long2num (F_GETOWN));
1624 #endif
1625 #ifdef F_SETOWN
1626 scm_c_define ("F_SETOWN", scm_long2num (F_SETOWN));
1627 #endif
1628 #ifdef FD_CLOEXEC
1629 scm_c_define ("FD_CLOEXEC", scm_long2num (FD_CLOEXEC));
1630 #endif
1631
1632 #include "libguile/filesys.x"
1633 }
1634
1635 /*
1636 Local Variables:
1637 c-file-style: "gnu"
1638 End:
1639 */