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