aboutsummaryrefslogtreecommitdiffstats
path: root/extension
diff options
context:
space:
mode:
Diffstat (limited to 'extension')
-rw-r--r--extension/ChangeLog5
-rw-r--r--extension/Makefile.am3
-rw-r--r--extension/Makefile.in22
-rw-r--r--extension/readdir.c220
4 files changed, 246 insertions, 4 deletions
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 80cb44d7..939a6aed 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-25 Arnold D. Robbins <arnold@skeeve.com>
+
+ * readdir.c: New file.
+ * Makefile.am (readdir): New extension.
+
2012-07-20 Arnold D. Robbins <arnold@skeeve.com>
* filefuncs.3am, fnmatch.3am, ordchr.3am, readfile.3am:
diff --git a/extension/Makefile.am b/extension/Makefile.am
index abe778e2..32969099 100644
--- a/extension/Makefile.am
+++ b/extension/Makefile.am
@@ -36,6 +36,7 @@ pkgextension_LTLIBRARIES = \
fnmatch.la \
fork.la \
ordchr.la \
+ readdir.la \
readfile.la \
rwarray.la \
testext.la \
@@ -51,6 +52,8 @@ fork_la_SOURCES = fork.c
fork_la_LDFLAGS = $(MY_MODULE_FLAGS)
ordchr_la_SOURCES = ordchr.c
ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS)
+readdir_la_SOURCES = readdir.c
+readdir_la_LDFLAGS = $(MY_MODULE_FLAGS)
readfile_la_SOURCES = readfile.c
readfile_la_LDFLAGS = $(MY_MODULE_FLAGS)
rwarray_la_SOURCES = rwarray.c
diff --git a/extension/Makefile.in b/extension/Makefile.in
index 71920fec..14c9e149 100644
--- a/extension/Makefile.in
+++ b/extension/Makefile.in
@@ -154,6 +154,12 @@ ordchr_la_OBJECTS = $(am_ordchr_la_OBJECTS)
ordchr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(ordchr_la_LDFLAGS) $(LDFLAGS) -o $@
+readdir_la_LIBADD =
+am_readdir_la_OBJECTS = readdir.lo
+readdir_la_OBJECTS = $(am_readdir_la_OBJECTS)
+readdir_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(readdir_la_LDFLAGS) $(LDFLAGS) -o $@
readfile_la_LIBADD =
am_readfile_la_OBJECTS = readfile.lo
readfile_la_OBJECTS = $(am_readfile_la_OBJECTS)
@@ -192,11 +198,13 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \
- $(fork_la_SOURCES) $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \
- $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES)
+ $(fork_la_SOURCES) $(ordchr_la_SOURCES) $(readdir_la_SOURCES) \
+ $(readfile_la_SOURCES) $(rwarray_la_SOURCES) \
+ $(testext_la_SOURCES) $(time_la_SOURCES)
DIST_SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \
- $(fork_la_SOURCES) $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \
- $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES)
+ $(fork_la_SOURCES) $(ordchr_la_SOURCES) $(readdir_la_SOURCES) \
+ $(readfile_la_SOURCES) $(rwarray_la_SOURCES) \
+ $(testext_la_SOURCES) $(time_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -349,6 +357,7 @@ pkgextension_LTLIBRARIES = \
fnmatch.la \
fork.la \
ordchr.la \
+ readdir.la \
readfile.la \
rwarray.la \
testext.la \
@@ -363,6 +372,8 @@ fork_la_SOURCES = fork.c
fork_la_LDFLAGS = $(MY_MODULE_FLAGS)
ordchr_la_SOURCES = ordchr.c
ordchr_la_LDFLAGS = $(MY_MODULE_FLAGS)
+readdir_la_SOURCES = readdir.c
+readdir_la_LDFLAGS = $(MY_MODULE_FLAGS)
readfile_la_SOURCES = readfile.c
readfile_la_LDFLAGS = $(MY_MODULE_FLAGS)
rwarray_la_SOURCES = rwarray.c
@@ -471,6 +482,8 @@ fork.la: $(fork_la_OBJECTS) $(fork_la_DEPENDENCIES) $(EXTRA_fork_la_DEPENDENCIES
$(fork_la_LINK) -rpath $(pkgextensiondir) $(fork_la_OBJECTS) $(fork_la_LIBADD) $(LIBS)
ordchr.la: $(ordchr_la_OBJECTS) $(ordchr_la_DEPENDENCIES) $(EXTRA_ordchr_la_DEPENDENCIES)
$(ordchr_la_LINK) -rpath $(pkgextensiondir) $(ordchr_la_OBJECTS) $(ordchr_la_LIBADD) $(LIBS)
+readdir.la: $(readdir_la_OBJECTS) $(readdir_la_DEPENDENCIES) $(EXTRA_readdir_la_DEPENDENCIES)
+ $(readdir_la_LINK) -rpath $(pkgextensiondir) $(readdir_la_OBJECTS) $(readdir_la_LIBADD) $(LIBS)
readfile.la: $(readfile_la_OBJECTS) $(readfile_la_DEPENDENCIES) $(EXTRA_readfile_la_DEPENDENCIES)
$(readfile_la_LINK) -rpath $(pkgextensiondir) $(readfile_la_OBJECTS) $(readfile_la_LIBADD) $(LIBS)
rwarray.la: $(rwarray_la_OBJECTS) $(rwarray_la_DEPENDENCIES) $(EXTRA_rwarray_la_DEPENDENCIES)
@@ -490,6 +503,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fork.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ordchr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdir.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readfile.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwarray.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testext.Plo@am__quote@
diff --git a/extension/readdir.c b/extension/readdir.c
new file mode 100644
index 00000000..a39e0c3a
--- /dev/null
+++ b/extension/readdir.c
@@ -0,0 +1,220 @@
+/*
+ * readdir.c --- Provide an open hook to read directories
+ *
+ * Arnold Robbins
+ * arnold@skeeve.com
+ * Written 7/2012
+ */
+
+/*
+ * Copyright (C) 2012 the Free Software Foundation, Inc.
+ *
+ * This file is part of GAWK, the GNU implementation of the
+ * AWK Programming Language.
+ *
+ * GAWK is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GAWK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _BSD_SOURCE
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "config.h"
+#include "gawkapi.h"
+
+static const gawk_api_t *api; /* for convenience macros to work */
+static awk_ext_id_t *ext_id;
+
+int plugin_is_GPL_compatible;
+
+/* ftype --- return type of file as a single character string */
+
+static const char *
+ftype(struct dirent *entry)
+{
+#ifdef DT_BLK
+ switch (entry->d_type) {
+ case DT_BLK: return "b";
+ case DT_CHR: return "c";
+ case DT_DIR: return "d";
+ case DT_FIFO: return "p";
+ case DT_LNK: return "l";
+ case DT_REG: return "f";
+ case DT_SOCK: return "s";
+ default:
+ case DT_UNKNOWN: return "u";
+ }
+#else
+ struct stat sbuf;
+
+ if (lstat(entry->d_name, & sbuf) < 0)
+ return "u";
+
+ switch (sbuf.st_mode & S_IFMT) {
+ case S_IFREG: return "f";
+ case S_IFBLK: return "b";
+ case S_IFCHR: return "c";
+ case S_IFDIR: return "d";
+#ifdef S_IFSOCK
+ case S_IFSOCK: return "s";
+#endif
+#ifdef S_IFIFO
+ case S_IFIFO: return "p";
+#endif
+#ifdef S_IFLNK
+ case S_IFLNK: return "l";
+#endif
+#ifdef S_IFDOOR /* Solaris weirdness */
+ case S_IFDOOR: return "D";
+#endif /* S_IFDOOR */
+ }
+ return "u";
+#endif
+}
+
+
+/* dir_get_record --- get one record at a time out of a directory */
+
+static int
+dir_get_record(char **out, struct iobuf_public *iobuf, int *errcode)
+{
+ DIR *dp;
+ struct dirent *dirent;
+ char buf[1000];
+ size_t len;
+
+ if (out == NULL || iobuf == NULL || iobuf->opaque == NULL)
+ return EOF;
+
+ if (errcode != NULL)
+ *errcode = 0;
+
+ /* FIXME: Need stuff for setting RT */
+ dp = (DIR *) iobuf->opaque;
+ 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);
+ return len;
+}
+
+/* dir_close --- close up when done */
+
+static void
+dir_close(struct iobuf_public *iobuf)
+{
+ DIR *dp;
+
+ if (iobuf == NULL || iobuf->opaque == NULL)
+ return;
+
+ dp = (DIR *) iobuf->opaque;
+ closedir(dp);
+ iobuf->fd = -1;
+}
+
+/* dir_can_take_file --- return true if we want the file */
+
+static int
+dir_can_take_file(IOBUF_PUBLIC *iobuf)
+{
+ struct stat sbuf;
+ int fd;
+
+ if (iobuf == NULL)
+ return 0;
+
+ fd = iobuf->fd;
+ return (fd >= 0 && fstat(fd, & sbuf) >= 0 && S_ISDIR(sbuf.st_mode));
+}
+
+/* dir_take_control_of --- set up input parser */
+
+static int
+dir_take_control_of(IOBUF_PUBLIC *iobuf)
+{
+ struct stat sbuf;
+ int fd;
+ DIR *dp = NULL;
+
+ if (iobuf == NULL)
+ return 0;
+
+ fd = iobuf->fd;
+ if (dir_can_take_file(iobuf)) {
+ dp = fdopendir(fd);
+ if (dp == NULL)
+ return 0;
+
+ iobuf->opaque = dp;
+ iobuf->get_record = dir_get_record;
+ iobuf->close_func = dir_close;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static awk_input_parser_t readdir_parser = {
+ "readdir",
+ dir_can_take_file,
+ dir_take_control_of,
+ NULL
+};
+
+#ifdef TEST_DUPLICATE
+static awk_input_parser_t readdir_parser2 = {
+ "readdir2",
+ dir_can_take_file,
+ dir_take_control_of,
+ NULL
+};
+#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);
+ }
+
+
+ register_input_parser(& readdir_parser);
+#ifdef TEST_DUPLICATE
+ register_input_parser(& readdir_parser2);
+#endif
+
+ return 1;
+}