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