aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2012-07-29 16:33:00 +0300
committerArnold D. Robbins <arnold@skeeve.com>2012-07-29 16:33:00 +0300
commit82816b279615b27f7c4f87349a8c830a96939d8c (patch)
treecf30bf71692e090ca6ca4934e65184aa990a3055
parent207fc1458c7f168822e454a89f23428c64163427 (diff)
downloadegawk-82816b279615b27f7c4f87349a8c830a96939d8c.tar.gz
egawk-82816b279615b27f7c4f87349a8c830a96939d8c.tar.bz2
egawk-82816b279615b27f7c4f87349a8c830a96939d8c.zip
Finish work on iop management. New readdir test.
-rw-r--r--ChangeLog17
-rw-r--r--awk.h3
-rw-r--r--io.c104
-rw-r--r--pc/ChangeLog5
-rw-r--r--pc/gawkmisc.pc7
-rw-r--r--posix/ChangeLog5
-rw-r--r--posix/gawkmisc.c7
-rw-r--r--test/ChangeLog5
-rw-r--r--test/Makefile.am11
-rw-r--r--test/Makefile.in11
-rw-r--r--test/readdir.awk7
-rw-r--r--test/readdir0.awk9
-rw-r--r--vms/ChangeLog5
-rw-r--r--vms/gawkmisc.vms7
14 files changed, 160 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index d91717e1..bbf63a42 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2012-07-29 Arnold D. Robbins <arnold@skeeve.com>
+
+ * awk.h (os_isreadable): Adjust declaration.
+ (struct iobuf): Add new member `valid'.
+ * io.c (iop_alloc): Remove do_input_parsers parameter, it's
+ always true. Adjust logic to set things to invalid if could not
+ find an input parser.
+ (after_beginfile): Use valid member to check if iobuf is valid.
+ Don't clear iop->errcode.
+ (nextfile): Adjust logic to clear errcode if valid is true and
+ also to update ERRNO.
+ (redirect): Check iop->valid and cleanup as necessary, including
+ setting ERRNO.
+ (two_way_open): Ditto.
+ (gawk_popen): Ditto.
+ (devopen): Remove check for directory.
+
2012-07-27 Arnold D. Robbins <arnold@skeeve.com>
* awk.h (set_RT): Change to take a NODE * parameter.
diff --git a/awk.h b/awk.h
index afc18e2e..a1fe66b2 100644
--- a/awk.h
+++ b/awk.h
@@ -906,6 +906,7 @@ typedef struct iobuf {
*/
ssize_t (*read_func)();
+ bool valid;
int errcode;
int flag;
@@ -1532,7 +1533,7 @@ extern int os_devopen(const char *name, int flag);
extern void os_close_on_exec(int fd, const char *name, const char *what, const char *dir);
extern int os_isatty(int fd);
extern int os_isdir(int fd);
-extern int os_isreadable(int fd);
+extern int os_isreadable(int fd, bool *isdir);
extern int os_is_setuid(void);
extern int os_setbinmode(int fd, int mode);
extern void os_restore_mode(int fd);
diff --git a/io.c b/io.c
index 2f3c5f85..fdcf6b7b 100644
--- a/io.c
+++ b/io.c
@@ -203,7 +203,7 @@ static int close_redir(struct redirect *rp, bool exitwarn, two_way_close_type ho
static int wait_any(int interesting);
#endif
static IOBUF *gawk_popen(const char *cmd, struct redirect *rp);
-static IOBUF *iop_alloc(int fd, const char *name, bool do_input_parsers);
+static IOBUF *iop_alloc(int fd, const char *name);
static int gawk_pclose(struct redirect *rp);
static int str2mode(const char *mode);
static int two_way_open(const char *str, struct redirect *rp);
@@ -315,15 +315,16 @@ after_beginfile(IOBUF **curfile)
if (iop->public.fd == INVALID_HANDLE) {
const char *fname;
int errcode;
+ bool valid;
fname = iop->public.name;
errcode = iop->errcode;
- iop->errcode = 0;
+ valid = iop->valid;
errno = 0;
update_ERRNO_int(errno);
iop_close(iop);
*curfile = NULL;
- if (errcode == EISDIR && ! do_traditional) {
+ if (! valid && errcode == EISDIR && ! do_traditional) {
warning(_("command line argument `%s' is a directory: skipped"), fname);
return; /* read next file */
}
@@ -409,11 +410,15 @@ nextfile(IOBUF **curfile, bool skipping)
mpz_set_ui(MFNR, 0);
#endif
FNR = 0;
- iop = *curfile = iop_alloc(fd, fname, false);
+ iop = *curfile = iop_alloc(fd, fname);
if (fd == INVALID_HANDLE)
iop->errcode = errcode;
- else
+ else if (iop->valid)
iop->errcode = 0;
+
+ if (! do_traditional && iop->errcode != 0)
+ update_ERRNO_int(iop->errcode);
+
return ++i; /* run beginfile block */
}
}
@@ -429,7 +434,7 @@ nextfile(IOBUF **curfile, bool skipping)
FILENAME_node->var_value = make_string("-", 1);
FILENAME_node->var_value->flags |= MAYBE_NUM; /* be pedantic */
fname = "-";
- iop = *curfile = iop_alloc(fileno(stdin), fname, false);
+ iop = *curfile = iop_alloc(fileno(stdin), fname);
if (iop->public.fd == INVALID_HANDLE) {
errcode = errno;
@@ -802,7 +807,13 @@ redirect(NODE *redir_exp, int redirtype, int *errflg)
/* do not free rp, saving it for reuse (save_rp = rp) */
return NULL;
}
- rp->iop = iop_alloc(fd, str, true);
+ rp->iop = iop_alloc(fd, str);
+ if (! rp->iop->valid) {
+ if (! do_traditional && rp->iop->errcode != 0)
+ update_ERRNO_int(rp->iop->errcode);
+ iop_close(rp->iop);
+ rp->iop = NULL;
+ }
break;
case redirect_twoway:
direction = "to/from";
@@ -1605,13 +1616,6 @@ strictopen:
}
#endif
if (openfd != INVALID_HANDLE) {
- if (os_isdir(openfd)) {
- (void) close(openfd); /* don't leak fds */
- /* Set useful error number. */
- errno = EISDIR;
- return INVALID_HANDLE;
- }
-
if (openfd > fileno(stderr))
os_close_on_exec(openfd, name, "file", "");
}
@@ -1646,9 +1650,12 @@ two_way_open(const char *str, struct redirect *rp)
}
os_close_on_exec(fd, str, "socket", "to/from");
os_close_on_exec(newfd, str, "socket", "to/from");
- rp->iop = iop_alloc(newfd, str, true);
- if (rp->iop == NULL) {
- close(newfd);
+ rp->iop = iop_alloc(newfd, str);
+ if (! rp->iop->valid) {
+ if (! do_traditional && rp->iop->errcode != 0)
+ update_ERRNO_int(rp->iop->errcode);
+ iop_close(rp->iop);
+ rp->iop = NULL;
fclose(rp->fp);
return false;
}
@@ -1842,9 +1849,12 @@ two_way_open(const char *str, struct redirect *rp)
}
rp->pid = pid;
- rp->iop = iop_alloc(master, str, true);
- if (rp->iop == NULL) {
- (void) close(master);
+ rp->iop = iop_alloc(master, str);
+ if (! rp->iop->valid) {
+ if (! do_traditional && rp->iop->errcode != 0)
+ update_ERRNO_int(rp->iop->errcode);
+ iop_close(rp->iop);
+ rp->iop = NULL;
(void) kill(pid, SIGKILL);
return false;
}
@@ -1995,9 +2005,12 @@ use_pipes:
/* parent */
rp->pid = pid;
- rp->iop = iop_alloc(ctop[0], str, true);
- if (rp->iop == NULL) {
- (void) close(ctop[0]);
+ rp->iop = iop_alloc(ctop[0], str);
+ if (! rp->iop->valid) {
+ if (! do_traditional && rp->iop->errcode != 0)
+ update_ERRNO_int(rp->iop->errcode);
+ iop_close(rp->iop);
+ rp->iop = NULL;
(void) close(ctop[1]);
(void) close(ptoc[0]);
(void) close(ptoc[1]);
@@ -2159,9 +2172,13 @@ gawk_popen(const char *cmd, struct redirect *rp)
}
#endif
os_close_on_exec(p[0], cmd, "pipe", "from");
- rp->iop = iop_alloc(p[0], cmd, true);
- if (rp->iop == NULL)
- (void) close(p[0]);
+ rp->iop = iop_alloc(p[0], cmd);
+ if (! rp->iop->valid) {
+ if (! do_traditional && rp->iop->errcode != 0)
+ update_ERRNO_int(rp->iop->errcode);
+ iop_close(rp->iop);
+ rp->iop = NULL;
+ }
return rp->iop;
}
@@ -2204,9 +2221,14 @@ gawk_popen(const char *cmd, struct redirect *rp)
if (current == NULL)
return NULL;
os_close_on_exec(fileno(current), cmd, "pipe", "from");
- rp->iop = iop_alloc(fileno(current), cmd, true);
- if (rp->iop == NULL) {
+ rp->iop = iop_alloc(fileno(current), cmd);
+ if (! rp->iop->valid) {
+ if (! do_traditional && rp->iop->errcode != 0)
+ update_ERRNO_int(rp->iop->errcode);
(void) pclose(current);
+ rp->iop->public.fd = INVALID_HANDLE;
+ iop_close(rp->iop);
+ rp->iop = NULL;
current = NULL;
}
rp->ifp = current;
@@ -2629,10 +2651,11 @@ find_input_parser(IOBUF *iop)
/* iop_alloc --- allocate an IOBUF structure for an open fd */
static IOBUF *
-iop_alloc(int fd, const char *name, bool do_input_parsers)
+iop_alloc(int fd, const char *name)
{
struct stat sbuf;
IOBUF *iop;
+ bool isdir;
emalloc(iop, IOBUF *, sizeof(IOBUF), "iop_alloc");
@@ -2640,16 +2663,22 @@ iop_alloc(int fd, const char *name, bool do_input_parsers)
iop->public.fd = fd;
iop->public.name = name;
iop->read_func = ( ssize_t(*)() ) read;
+ iop->valid = false;
- if (do_input_parsers) {
- find_input_parser(iop);
- /* tried to find open parser and could not */
- if (iop->public.fd == INVALID_HANDLE) {
- efree(iop);
- return NULL;
- }
- } else if (iop->public.fd == INVALID_HANDLE)
+ find_input_parser(iop);
+
+ /* tried to find open parser and could not */
+ if ( iop->public.get_record == NULL
+ && ! os_isreadable(iop->public.fd, & isdir)) {
+ if (isdir)
+ iop->errcode = EISDIR;
+ close(iop->public.fd);
+ iop->public.fd = INVALID_HANDLE;
+ }
+
+ if (iop->public.fd == INVALID_HANDLE) {
return iop;
+ }
if (os_isatty(iop->public.fd))
iop->flag |= IOP_IS_TTY;
@@ -2664,6 +2693,7 @@ iop_alloc(int fd, const char *name, bool do_input_parsers)
iop->dataend = NULL;
iop->end = iop->buf + iop->size;
iop->flag |= IOP_AT_START;
+ iop->valid = true;
return iop;
}
diff --git a/pc/ChangeLog b/pc/ChangeLog
index 43221928..28dfb72b 100644
--- a/pc/ChangeLog
+++ b/pc/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-29 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawkmisc.c (os_isreadable): Add isdir pointer parameter to be
+ set to true if fd is for a directory.
+
2012-07-26 Arnold D. Robbins <arnold@skeeve.com>
* gawkmisc.pc (os_isreadable): New function.
diff --git a/pc/gawkmisc.pc b/pc/gawkmisc.pc
index 999167ca..d79a3207 100644
--- a/pc/gawkmisc.pc
+++ b/pc/gawkmisc.pc
@@ -235,10 +235,12 @@ int fd;
/* os_isreadable --- fd can be read from */
int
-os_isreadable(int fd)
+os_isreadable(int fd, bool *isdir)
{
struct stat sbuf;
+ *isdir = false;
+
if (fstat(fd, &sbuf) != 0)
return false;
@@ -252,6 +254,9 @@ os_isreadable(int fd)
case S_IFIFO:
#endif
return true;
+ case S_IFDIR:
+ *isdir = true;
+ /* fall through */
default:
return false;
}
diff --git a/posix/ChangeLog b/posix/ChangeLog
index a3ee87db..d49ff49e 100644
--- a/posix/ChangeLog
+++ b/posix/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-29 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawkmisc.c (os_isreadable): Add isdir pointer parameter to be
+ set to true if fd is for a directory.
+
2012-07-26 Arnold D. Robbins <arnold@skeeve.com>
* gawkmisc.c (os_isreadable): New function.
diff --git a/posix/gawkmisc.c b/posix/gawkmisc.c
index 87a6747c..a5c3a619 100644
--- a/posix/gawkmisc.c
+++ b/posix/gawkmisc.c
@@ -207,10 +207,12 @@ os_isdir(int fd)
/* os_isreadable --- fd can be read from */
int
-os_isreadable(int fd)
+os_isreadable(int fd, bool *isdir)
{
struct stat sbuf;
+ *isdir = false;
+
if (fstat(fd, &sbuf) != 0)
return false;
@@ -224,6 +226,9 @@ os_isreadable(int fd)
case S_IFIFO:
#endif
return true;
+ case S_IFDIR:
+ *isdir = true;
+ /* fall through */
default:
return false;
}
diff --git a/test/ChangeLog b/test/ChangeLog
index b38cf279..a3fb627a 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-29 Arnold D. Robbins <arnold@skeeve.com>
+
+ * Makefile.am (readdir): New test.
+ * readdir0.awk, readdir.awk: New files.
+
2012-07-16 Arnold D. Robbins <arnold@skeeve.com>
* fnmatch.awk, fnmatch.ok: Portability updates.
diff --git a/test/Makefile.am b/test/Makefile.am
index 78fd3117..5aa31b41 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -623,6 +623,8 @@ EXTRA_DIST = \
range1.awk \
range1.in \
range1.ok \
+ readdir0.awk \
+ readdir.awk \
rebt8b1.awk \
rebt8b1.ok \
rebt8b2.awk \
@@ -894,7 +896,7 @@ LOCALE_CHARSET_TESTS = \
SHLIB_TESTS = \
assignconst fnmatch filefuncs fork fork2 ordchr ordchr2 \
- readfile rwarray testext time
+ readdir readfile rwarray testext time
# List of the tests which should be run with --lint option:
NEED_LINT = \
@@ -1603,6 +1605,13 @@ assignconst:
done 2>&1 | grep -v at_exit > _$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+readdir:
+ @echo $@
+ @touch $@.out1 $@.out2 # create directory entries first
+ @ls -fli | sed 1d | $(AWK) -f $(srcdir)/readdir0.awk > $@.out1
+ @$(AWK) -f $(srcdir)/readdir.awk . > $@.out2
+ @-$(CMP) $@.out1 $@.out2 && rm -f $@.out[12]
+
# Targets generated for other tests:
include Maketests
diff --git a/test/Makefile.in b/test/Makefile.in
index 4868bdc6..5375aaee 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -836,6 +836,8 @@ EXTRA_DIST = \
range1.awk \
range1.in \
range1.ok \
+ readdir0.awk \
+ readdir.awk \
rebt8b1.awk \
rebt8b1.ok \
rebt8b2.awk \
@@ -1103,7 +1105,7 @@ LOCALE_CHARSET_TESTS = \
SHLIB_TESTS = \
assignconst fnmatch filefuncs fork fork2 ordchr ordchr2 \
- readfile rwarray testext time
+ readdir readfile rwarray testext time
# List of the tests which should be run with --lint option:
@@ -1985,6 +1987,13 @@ assignconst:
do $(AWK) -f $(srcdir)/$@.awk $$i ; \
done 2>&1 | grep -v at_exit > _$@
@-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@
+
+readdir:
+ @echo $@
+ @touch $@.out1 $@.out2 # create directory entries first
+ @ls -fli | sed 1d | $(AWK) -f $(srcdir)/readdir0.awk > $@.out1
+ @$(AWK) -f $(srcdir)/readdir.awk . > $@.out2
+ @-$(CMP) $@.out1 $@.out2 && rm -f $@.out[12]
Gt-dummy:
# file Maketests, generated from Makefile.am by the Gentests program
addcomma:
diff --git a/test/readdir.awk b/test/readdir.awk
new file mode 100644
index 00000000..4d35be6a
--- /dev/null
+++ b/test/readdir.awk
@@ -0,0 +1,7 @@
+@load "readdir"
+
+BEGIN {
+ readdir_do_ftype(1)
+}
+
+{ print }
diff --git a/test/readdir0.awk b/test/readdir0.awk
new file mode 100644
index 00000000..54306f10
--- /dev/null
+++ b/test/readdir0.awk
@@ -0,0 +1,9 @@
+{
+ ino = $1
+ name = $NF
+ type = substr($2, 1, 1)
+ if (type == "-")
+ type = "f"
+
+ printf "%s/%s/%s\n", ino, name, type
+}
diff --git a/vms/ChangeLog b/vms/ChangeLog
index c4cb6ed9..f65274f9 100644
--- a/vms/ChangeLog
+++ b/vms/ChangeLog
@@ -1,3 +1,8 @@
+2012-07-29 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawkmisc.c (os_isreadable): Add isdir pointer parameter to be
+ set to true if fd is for a directory.
+
2012-07-26 Arnold D. Robbins <arnold@skeeve.com>
* gawkmisc.vms (os_isreadable): New function.
diff --git a/vms/gawkmisc.vms b/vms/gawkmisc.vms
index f373b5f2..773b3556 100644
--- a/vms/gawkmisc.vms
+++ b/vms/gawkmisc.vms
@@ -147,10 +147,12 @@ int fd;
/* os_isreadable --- fd can be read from */
int
-os_isreadable(int fd)
+os_isreadable(int fd, bool *isdir)
{
struct stat sbuf;
+ *isdir = false;
+
if (fstat(fd, &sbuf) != 0)
return false;
@@ -164,6 +166,9 @@ os_isreadable(int fd)
case S_IFIFO:
#endif
return true;
+ case S_IFDIR:
+ *isdir = true;
+ /* fall through */
default:
return false;
}