diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2012-07-26 23:03:08 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2012-07-26 23:03:08 +0300 |
commit | dfff2221d2d36ef3fba2a3970440079e2415f8b2 (patch) | |
tree | 1bac0ef853458058e4de288c451e6418b64a20c1 /extension | |
parent | 11cdf30aa3c7b397ba0702a043f5a44f3607b218 (diff) | |
download | egawk-dfff2221d2d36ef3fba2a3970440079e2415f8b2.tar.gz egawk-dfff2221d2d36ef3fba2a3970440079e2415f8b2.tar.bz2 egawk-dfff2221d2d36ef3fba2a3970440079e2415f8b2.zip |
Robustify extension/readdir.c.
Diffstat (limited to 'extension')
-rw-r--r-- | extension/ChangeLog | 3 | ||||
-rw-r--r-- | extension/configh.in | 6 | ||||
-rwxr-xr-x | extension/configure | 4 | ||||
-rw-r--r-- | extension/configure.ac | 4 | ||||
-rw-r--r-- | extension/readdir.c | 139 |
5 files changed, 121 insertions, 35 deletions
diff --git a/extension/ChangeLog b/extension/ChangeLog index 05682e50..ae0df1a7 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -8,6 +8,9 @@ * testext.c (valrep2str): Add AWK_VALUE_COOKIE. + * readdir.c: Add readdir_do_ftype function for systems without + dirent->d_type. Clean up buffer handling. + 2012-07-26 Andrew J. Schorr <aschorr@telemetry-investments.com> * readdir.c (dir_get_record): No need to set *errcode to 0. diff --git a/extension/configh.in b/extension/configh.in index 179b5863..7307d382 100644 --- a/extension/configh.in +++ b/extension/configh.in @@ -1,8 +1,14 @@ /* configh.in. Generated from configure.ac by autoheader. */ +/* Define to 1 if you have the <dirent.h> header file. */ +#undef HAVE_DIRENT_H + /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the `fdopendir' function. */ +#undef HAVE_FDOPENDIR + /* Define to 1 if you have the `fnmatch' function. */ #undef HAVE_FNMATCH diff --git a/extension/configure b/extension/configure index 94be75b9..4fa61f37 100755 --- a/extension/configure +++ b/extension/configure @@ -11462,7 +11462,7 @@ then CFLAGS="$CFLAGS -Wall -Wextra" fi -for ac_header in fnmatch.h time.h sys/time.h sys/select.h +for ac_header in dirent.h fnmatch.h time.h sys/time.h sys/select.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -11476,7 +11476,7 @@ fi done -for ac_func in fnmatch gettimeofday nanosleep select GetSystemTimeAsFileTime +for ac_func in fdopendir fnmatch gettimeofday nanosleep select GetSystemTimeAsFileTime do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/extension/configure.ac b/extension/configure.ac index 4583962d..8f674777 100644 --- a/extension/configure.ac +++ b/extension/configure.ac @@ -45,9 +45,9 @@ then CFLAGS="$CFLAGS -Wall -Wextra" fi -AC_CHECK_HEADERS(fnmatch.h time.h sys/time.h sys/select.h) +AC_CHECK_HEADERS(dirent.h fnmatch.h time.h sys/time.h sys/select.h) -AC_CHECK_FUNCS(fnmatch gettimeofday nanosleep select GetSystemTimeAsFileTime) +AC_CHECK_FUNCS(fdopendir fnmatch gettimeofday nanosleep select GetSystemTimeAsFileTime) dnl checks for compiler characteristics AC_C_INLINE diff --git a/extension/readdir.c b/extension/readdir.c index a0a82a2d..f2a16029 100644 --- a/extension/readdir.c +++ b/extension/readdir.c @@ -1,5 +1,5 @@ /* - * readdir.c --- Provide an open hook to read directories + * readdir.c --- Provide an input parser to read directories * * Arnold Robbins * arnold@skeeve.com @@ -37,16 +37,35 @@ #include <sys/types.h> #include <sys/stat.h> -#include <dirent.h> #include "config.h" + +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#else +#error Cannot compile the dirent extension on this system! +#endif + #include "gawkapi.h" +#include "gettext.h" +#define _(msgid) gettext(msgid) +#define N_(msgid) msgid + static const gawk_api_t *api; /* for convenience macros to work */ static awk_ext_id_t *ext_id; +static awk_bool_t init_readdir(void); +static awk_bool_t (*init_func)(void) = init_readdir; + int plugin_is_GPL_compatible; +#ifdef DT_BLK +static const int do_ftype = 1; +#else +static int do_ftype; +#endif + /* ftype --- return type of file as a single character string */ static const char * @@ -93,6 +112,11 @@ ftype(struct dirent *entry) } +typedef struct open_directory { + DIR *dp; + char *buf; +} open_directory_t; + /* dir_get_record --- get one record at a time out of a directory */ static int @@ -100,28 +124,37 @@ dir_get_record(char **out, struct iobuf_public *iobuf, int *errcode) { DIR *dp; struct dirent *dirent; - char buf[1000]; size_t len; - static const awk_value_t null_val = { AWK_UNDEFINED }; - - if (out == NULL || iobuf == NULL || iobuf->opaque == NULL) - return EOF; + open_directory_t *the_dir; + static const awk_value_t null_val = { AWK_UNDEFINED, { { 0, 0 } } }; /* * The caller sets *errcode to 0, so we should set it only if an - * error occurs. + * error occurs. Except that the compiler complains that it + * is unused, so we set it anyways. */ + *errcode = 0; /* keep the compiler happy */ + + if (out == NULL || iobuf == NULL || iobuf->opaque == NULL) + return EOF; set_RT((awk_value_t *) & null_val); - dp = (DIR *) iobuf->opaque; + the_dir = (open_directory_t *) iobuf->opaque; + dp = the_dir->dp; dirent = readdir(dp); if (dirent == NULL) return EOF; - sprintf(buf, "%ld/%s/%s", dirent->d_ino, dirent->d_name, ftype(dirent)); - len = strlen(buf); - emalloc(*out, char *, len + 1, "dir_get_record"); - strcpy(*out, buf); + if (do_ftype) + sprintf(the_dir->buf, "%ld/%s/%s", + dirent->d_ino, dirent->d_name, ftype(dirent)); + else + sprintf(the_dir->buf, "%ld/%s", + dirent->d_ino, dirent->d_name); + + *out = the_dir->buf; + len = strlen(the_dir->buf); + return len; } @@ -130,13 +163,17 @@ dir_get_record(char **out, struct iobuf_public *iobuf, int *errcode) static void dir_close(struct iobuf_public *iobuf) { - DIR *dp; + open_directory_t *the_dir; if (iobuf == NULL || iobuf->opaque == NULL) return; - dp = (DIR *) iobuf->opaque; - closedir(dp); + the_dir = (open_directory_t *) iobuf->opaque; + + closedir(the_dir->dp); + free(the_dir->buf); + free(the_dir); + iobuf->fd = -1; } @@ -165,12 +202,25 @@ static int dir_take_control_of(IOBUF_PUBLIC *iobuf) { DIR *dp; + open_directory_t *the_dir; + size_t size; +#ifdef HAVE_FDOPENDIR dp = fdopendir(iobuf->fd); +#else + dp = opendir(iob->name); + if (dp != NULL) + iobuf->fd = dirfd(dp); +#endif if (dp == NULL) return 0; - iobuf->opaque = dp; + emalloc(the_dir, open_directory_t *, sizeof(open_directory_t), "dir_take_control_of"); + the_dir->dp = dp; + size = sizeof(struct dirent) + 20 /* max digits in inode */ + 2 /* slashes */; + emalloc(the_dir->buf, char *, size, "dir_take_control_of"); + + iobuf->opaque = the_dir; iobuf->get_record = dir_get_record; iobuf->close_func = dir_close; @@ -193,21 +243,11 @@ static awk_input_parser_t readdir_parser2 = { }; #endif -int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) -{ - api = api_p; - ext_id = id; - - if (api->major_version != GAWK_API_MAJOR_VERSION - || api->minor_version < GAWK_API_MINOR_VERSION) { - fprintf(stderr, "readdir: version mismatch with gawk!\n"); - fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n", - GAWK_API_MAJOR_VERSION, GAWK_API_MINOR_VERSION, - api->major_version, api->minor_version); - exit(1); - } - +/* init_readdir --- set things ups */ +static awk_bool_t +init_readdir() +{ register_input_parser(& readdir_parser); #ifdef TEST_DUPLICATE register_input_parser(& readdir_parser2); @@ -215,3 +255,40 @@ int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) return 1; } + +/* do_readdir_do_ftype --- enable / disable ftype where need to do stat */ + +static awk_value_t * +do_readdir_do_ftype(int nargs, awk_value_t *result) +{ + awk_value_t flag; + + make_number(1.0, result); + if (nargs < 1) { + warning(ext_id, _("readdir_do_ftype: called with no arguments")); + make_number(0.0, result); + goto out; + } else if (do_lint && nargs > 3) + lintwarn(ext_id, _("readdir_do_ftype: called with more than one argument")); + + if (! get_argument(0, AWK_NUMBER, & flag)) { + warning(ext_id, _("readdir_do_ftype: could not get argument")); + make_number(0.0, result); + goto out; + } + +#ifndef DT_BLK + do_ftype = (flag.num_value != 0.0); +#endif + +out: + return result; +} + +static awk_ext_func_t func_table[] = { + { "readdir_do_ftype", do_readdir_do_ftype, 1 }, +}; + +/* define the dl_load function using the boilerplate macro */ + +dl_load_func(func_table, readdir, "") |