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