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