diff options
Diffstat (limited to 'extension')
-rw-r--r-- | extension/ChangeLog | 5 | ||||
-rw-r--r-- | extension/Makefile.am | 3 | ||||
-rw-r--r-- | extension/Makefile.in | 22 | ||||
-rw-r--r-- | extension/readdir.c | 220 |
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; +} |