diff options
author | Ludovic Courtès <ludo@gnu.org> | 2011-04-25 22:52:00 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2011-04-25 22:52:00 +0200 |
commit | d0476fa2b061638879fed89cd8d79add6f586448 (patch) | |
tree | 81a4252a8e60c444e007f1ce8949e65dde7fdc81 | |
parent | d20912e67d810ce5eb9dc1b8f8afd8c22aa2451b (diff) | |
download | guile-d0476fa2b061638879fed89cd8d79add6f586448.tar.gz |
Compile more file system related procedures when `--disable-posix'.
* libguile/filesys.c (scm_tc16_dir, scm_directory_stream_p, scm_opendir,
scm_readdir, scm_rewinddir, scm_closedir, scm_dir_print,
scm_dir_free, scm_lstat): Compile unconditionally.
-rw-r--r-- | libguile/filesys.c | 402 |
1 files changed, 200 insertions, 202 deletions
diff --git a/libguile/filesys.c b/libguile/filesys.c index fab8ab41d..b43536f0a 100644 --- a/libguile/filesys.c +++ b/libguile/filesys.c @@ -602,6 +602,31 @@ SCM_DEFINE (scm_stat, "stat", 1, 1, 0, } #undef FUNC_NAME +#ifdef HAVE_LSTAT +SCM_DEFINE (scm_lstat, "lstat", 1, 0, 0, + (SCM str), + "Similar to @code{stat}, but does not follow symbolic links, i.e.,\n" + "it will return information about a symbolic link itself, not the\n" + "file it points to. @var{path} must be a string.") +#define FUNC_NAME s_scm_lstat +{ + int rv; + struct stat_or_stat64 stat_temp; + + STRING_SYSCALL (str, c_str, rv = lstat_or_lstat64 (c_str, &stat_temp)); + if (rv != 0) + { + int en = errno; + + SCM_SYSERROR_MSG ("~A: ~S", + scm_list_2 (scm_strerror (scm_from_int (en)), str), + en); + } + return scm_stat2scm (&stat_temp); +} +#undef FUNC_NAME +#endif /* HAVE_LSTAT */ + #ifdef HAVE_POSIX @@ -630,183 +655,6 @@ SCM_DEFINE (scm_link, "link", 2, 0, 0, #endif /* HAVE_LINK */ - -/* {Examining Directories} - */ - -scm_t_bits scm_tc16_dir; - - -SCM_DEFINE (scm_directory_stream_p, "directory-stream?", 1, 0, 0, - (SCM obj), - "Return a boolean indicating whether @var{object} is a directory\n" - "stream as returned by @code{opendir}.") -#define FUNC_NAME s_scm_directory_stream_p -{ - return scm_from_bool (SCM_DIRP (obj)); -} -#undef FUNC_NAME - - -SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0, - (SCM dirname), - "Open the directory specified by @var{path} and return a directory\n" - "stream.") -#define FUNC_NAME s_scm_opendir -{ - DIR *ds; - STRING_SYSCALL (dirname, c_dirname, ds = opendir (c_dirname)); - if (ds == NULL) - SCM_SYSERROR; - SCM_RETURN_NEWSMOB (scm_tc16_dir | (SCM_DIR_FLAG_OPEN<<16), ds); -} -#undef FUNC_NAME - - -/* FIXME: The glibc manual has a portability note that readdir_r may not - null-terminate its return string. The circumstances outlined for this - are not clear, nor is it clear what should be done about it. Lets use - NAMLEN and worry about what else should be done if/when someone can - figure it out. */ - -SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0, - (SCM port), - "Return (as a string) the next directory entry from the directory stream\n" - "@var{stream}. If there is no remaining entry to be read then the\n" - "end of file object is returned.") -#define FUNC_NAME s_scm_readdir -{ - struct dirent_or_dirent64 *rdent; - - SCM_VALIDATE_DIR (1, port); - if (!SCM_DIR_OPEN_P (port)) - SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port)); - -#if HAVE_READDIR_R - /* As noted in the glibc manual, on various systems (such as Solaris) the - d_name[] field is only 1 char and you're expected to size the dirent - buffer for readdir_r based on NAME_MAX. The SCM_MAX expressions below - effectively give either sizeof(d_name) or NAME_MAX+1, whichever is - bigger. - - On solaris 10 there's no NAME_MAX constant, it's necessary to use - pathconf(). We prefer NAME_MAX though, since it should be a constant - and will therefore save a system call. We also prefer it since dirfd() - is not available everywhere. - - An alternative to dirfd() would be to open() the directory and then use - fdopendir(), if the latter is available. That'd let us hold the fd - somewhere in the smob, or just the dirent size calculated once. */ - { - struct dirent_or_dirent64 de; /* just for sizeof */ - DIR *ds = (DIR *) SCM_SMOB_DATA_1 (port); -#ifdef NAME_MAX - char buf [SCM_MAX (sizeof (de), - sizeof (de) - sizeof (de.d_name) + NAME_MAX + 1)]; -#else - char *buf; - long name_max = fpathconf (dirfd (ds), _PC_NAME_MAX); - if (name_max == -1) - SCM_SYSERROR; - buf = alloca (SCM_MAX (sizeof (de), - sizeof (de) - sizeof (de.d_name) + name_max + 1)); -#endif - - errno = 0; - SCM_SYSCALL (readdir_r_or_readdir64_r (ds, (struct dirent_or_dirent64 *) buf, &rdent)); - if (errno != 0) - SCM_SYSERROR; - if (! rdent) - return SCM_EOF_VAL; - - return (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent)) - : SCM_EOF_VAL); - } -#else - { - SCM ret; - scm_dynwind_begin (0); - scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex); - - errno = 0; - SCM_SYSCALL (rdent = readdir_or_readdir64 ((DIR *) SCM_SMOB_DATA_1 (port))); - if (errno != 0) - SCM_SYSERROR; - - ret = (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent)) - : SCM_EOF_VAL); - - scm_dynwind_end (); - return ret; - } -#endif -} -#undef FUNC_NAME - - -SCM_DEFINE (scm_rewinddir, "rewinddir", 1, 0, 0, - (SCM port), - "Reset the directory port @var{stream} so that the next call to\n" - "@code{readdir} will return the first directory entry.") -#define FUNC_NAME s_scm_rewinddir -{ - SCM_VALIDATE_DIR (1, port); - if (!SCM_DIR_OPEN_P (port)) - SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port)); - - rewinddir ((DIR *) SCM_SMOB_DATA_1 (port)); - - return SCM_UNSPECIFIED; -} -#undef FUNC_NAME - - -SCM_DEFINE (scm_closedir, "closedir", 1, 0, 0, - (SCM port), - "Close the directory stream @var{stream}.\n" - "The return value is unspecified.") -#define FUNC_NAME s_scm_closedir -{ - SCM_VALIDATE_DIR (1, port); - - if (SCM_DIR_OPEN_P (port)) - { - int sts; - - SCM_SYSCALL (sts = closedir ((DIR *) SCM_SMOB_DATA_1 (port))); - if (sts != 0) - SCM_SYSERROR; - - SCM_SET_SMOB_DATA_0 (port, scm_tc16_dir); - } - - return SCM_UNSPECIFIED; -} -#undef FUNC_NAME - - -static int -scm_dir_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED) -{ - scm_puts ("#<", port); - if (!SCM_DIR_OPEN_P (exp)) - scm_puts ("closed: ", port); - scm_puts ("directory stream ", port); - scm_uintprint (SCM_SMOB_DATA_1 (exp), 16, port); - scm_putc ('>', port); - return 1; -} - - -static size_t -scm_dir_free (SCM p) -{ - if (SCM_DIR_OPEN_P (p)) - closedir ((DIR *) SCM_SMOB_DATA_1 (p)); - return 0; -} - - /* {Navigating Directories} */ @@ -1250,31 +1098,6 @@ SCM_DEFINE (scm_readlink, "readlink", 1, 0, 0, #undef FUNC_NAME #endif /* HAVE_READLINK */ -#ifdef HAVE_LSTAT -SCM_DEFINE (scm_lstat, "lstat", 1, 0, 0, - (SCM str), - "Similar to @code{stat}, but does not follow symbolic links, i.e.,\n" - "it will return information about a symbolic link itself, not the\n" - "file it points to. @var{path} must be a string.") -#define FUNC_NAME s_scm_lstat -{ - int rv; - struct stat_or_stat64 stat_temp; - - STRING_SYSCALL (str, c_str, rv = lstat_or_lstat64 (c_str, &stat_temp)); - if (rv != 0) - { - int en = errno; - - SCM_SYSERROR_MSG ("~A: ~S", - scm_list_2 (scm_strerror (scm_from_int (en)), str), - en); - } - return scm_stat2scm (&stat_temp); -} -#undef FUNC_NAME -#endif /* HAVE_LSTAT */ - SCM_DEFINE (scm_copy_file, "copy-file", 2, 0, 0, (SCM oldfile, SCM newfile), "Copy the file specified by @var{path-from} to @var{path-to}.\n" @@ -1814,6 +1637,181 @@ scm_i_relativize_path (SCM path, SCM in_path) return SCM_BOOL_F; } + +/* Examining directories. These procedures are used by `check-guile' + and thus compiled unconditionally. */ + +scm_t_bits scm_tc16_dir; + + +SCM_DEFINE (scm_directory_stream_p, "directory-stream?", 1, 0, 0, + (SCM obj), + "Return a boolean indicating whether @var{object} is a directory\n" + "stream as returned by @code{opendir}.") +#define FUNC_NAME s_scm_directory_stream_p +{ + return scm_from_bool (SCM_DIRP (obj)); +} +#undef FUNC_NAME + + +SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0, + (SCM dirname), + "Open the directory specified by @var{path} and return a directory\n" + "stream.") +#define FUNC_NAME s_scm_opendir +{ + DIR *ds; + STRING_SYSCALL (dirname, c_dirname, ds = opendir (c_dirname)); + if (ds == NULL) + SCM_SYSERROR; + SCM_RETURN_NEWSMOB (scm_tc16_dir | (SCM_DIR_FLAG_OPEN<<16), ds); +} +#undef FUNC_NAME + + +/* FIXME: The glibc manual has a portability note that readdir_r may not + null-terminate its return string. The circumstances outlined for this + are not clear, nor is it clear what should be done about it. Lets use + NAMLEN and worry about what else should be done if/when someone can + figure it out. */ + +SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0, + (SCM port), + "Return (as a string) the next directory entry from the directory stream\n" + "@var{stream}. If there is no remaining entry to be read then the\n" + "end of file object is returned.") +#define FUNC_NAME s_scm_readdir +{ + struct dirent_or_dirent64 *rdent; + + SCM_VALIDATE_DIR (1, port); + if (!SCM_DIR_OPEN_P (port)) + SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port)); + +#if HAVE_READDIR_R + /* As noted in the glibc manual, on various systems (such as Solaris) the + d_name[] field is only 1 char and you're expected to size the dirent + buffer for readdir_r based on NAME_MAX. The SCM_MAX expressions below + effectively give either sizeof(d_name) or NAME_MAX+1, whichever is + bigger. + + On solaris 10 there's no NAME_MAX constant, it's necessary to use + pathconf(). We prefer NAME_MAX though, since it should be a constant + and will therefore save a system call. We also prefer it since dirfd() + is not available everywhere. + + An alternative to dirfd() would be to open() the directory and then use + fdopendir(), if the latter is available. That'd let us hold the fd + somewhere in the smob, or just the dirent size calculated once. */ + { + struct dirent_or_dirent64 de; /* just for sizeof */ + DIR *ds = (DIR *) SCM_SMOB_DATA_1 (port); +#ifdef NAME_MAX + char buf [SCM_MAX (sizeof (de), + sizeof (de) - sizeof (de.d_name) + NAME_MAX + 1)]; +#else + char *buf; + long name_max = fpathconf (dirfd (ds), _PC_NAME_MAX); + if (name_max == -1) + SCM_SYSERROR; + buf = alloca (SCM_MAX (sizeof (de), + sizeof (de) - sizeof (de.d_name) + name_max + 1)); +#endif + + errno = 0; + SCM_SYSCALL (readdir_r_or_readdir64_r (ds, (struct dirent_or_dirent64 *) buf, &rdent)); + if (errno != 0) + SCM_SYSERROR; + if (! rdent) + return SCM_EOF_VAL; + + return (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent)) + : SCM_EOF_VAL); + } +#else + { + SCM ret; + scm_dynwind_begin (0); + scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex); + + errno = 0; + SCM_SYSCALL (rdent = readdir_or_readdir64 ((DIR *) SCM_SMOB_DATA_1 (port))); + if (errno != 0) + SCM_SYSERROR; + + ret = (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent)) + : SCM_EOF_VAL); + + scm_dynwind_end (); + return ret; + } +#endif +} +#undef FUNC_NAME + + +SCM_DEFINE (scm_rewinddir, "rewinddir", 1, 0, 0, + (SCM port), + "Reset the directory port @var{stream} so that the next call to\n" + "@code{readdir} will return the first directory entry.") +#define FUNC_NAME s_scm_rewinddir +{ + SCM_VALIDATE_DIR (1, port); + if (!SCM_DIR_OPEN_P (port)) + SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port)); + + rewinddir ((DIR *) SCM_SMOB_DATA_1 (port)); + + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + + +SCM_DEFINE (scm_closedir, "closedir", 1, 0, 0, + (SCM port), + "Close the directory stream @var{stream}.\n" + "The return value is unspecified.") +#define FUNC_NAME s_scm_closedir +{ + SCM_VALIDATE_DIR (1, port); + + if (SCM_DIR_OPEN_P (port)) + { + int sts; + + SCM_SYSCALL (sts = closedir ((DIR *) SCM_SMOB_DATA_1 (port))); + if (sts != 0) + SCM_SYSERROR; + + SCM_SET_SMOB_DATA_0 (port, scm_tc16_dir); + } + + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + + +static int +scm_dir_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED) +{ + scm_puts ("#<", port); + if (!SCM_DIR_OPEN_P (exp)) + scm_puts ("closed: ", port); + scm_puts ("directory stream ", port); + scm_uintprint (SCM_SMOB_DATA_1 (exp), 16, port); + scm_putc ('>', port); + return 1; +} + + +static size_t +scm_dir_free (SCM p) +{ + if (SCM_DIR_OPEN_P (p)) + closedir ((DIR *) SCM_SMOB_DATA_1 (p)); + return 0; +} |