aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extension/ChangeLog3
-rw-r--r--extension/configh.in6
-rwxr-xr-xextension/configure4
-rw-r--r--extension/configure.ac4
-rw-r--r--extension/readdir.c139
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, "")