From b51edf37c4271bf5ec5dcad9d35169f55e38efa9 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Tue, 20 Mar 2012 10:46:03 -0400 Subject: - Add new environment variable AWKLIBPATH to use when searching for shared libraries. - Instead of hardcoding the default ".so" suffix for shared libraries, use autoconf to get the right value for this platform. - Build and install some of the bundled shared library extensions so that they will now be available using the default AWKLIBPATH. --- extension/filefuncs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 1a0a86ef..dd1b29a8 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -177,7 +177,7 @@ do_stat(int nargs) array = get_array_argument(1, FALSE); /* empty out the array */ - assoc_clear(array, NULL); + assoc_clear(array); /* lstat the file, if error, set ERRNO and return */ (void) force_string(file); -- cgit v1.2.3 From 3438b2129cd933e430349a6bd66a1933071c92c2 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 1 Apr 2012 17:07:45 -0400 Subject: Update ERRNO API. --- extension/filefuncs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index dd1b29a8..63010c35 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -48,7 +48,7 @@ do_chdir(int nargs) (void) force_string(newdir); ret = chdir(newdir->stptr); if (ret < 0) - update_ERRNO(); + update_ERRNO_int(errno); return make_number((AWKNUM) ret); } @@ -183,7 +183,7 @@ do_stat(int nargs) (void) force_string(file); ret = lstat(file->stptr, & sbuf); if (ret < 0) { - update_ERRNO(); + update_ERRNO_int(errno); return make_number((AWKNUM) ret); } -- cgit v1.2.3 From bc9ed3fd239984429613095e6cfc142092f036c4 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sat, 7 Apr 2012 16:30:50 -0400 Subject: Extension enhancements and tests. --- extension/filefuncs.c | 73 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 13 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 63010c35..6d46c5e5 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -29,8 +29,6 @@ #include "awk.h" -#include - int plugin_is_GPL_compatible; /* do_chdir --- provide dynamically loaded chdir() builtin for gawk */ @@ -157,6 +155,60 @@ format_mode(unsigned long fmode) return outbuf; } +/* read_symlink -- read a symbolic link into an allocated buffer. + This is based on xreadlink; the basic problem is that lstat cannot be relied + upon to return the proper size for a symbolic link. This happens, + for example, on linux in the /proc filesystem, where the symbolic link + sizes are often 0. */ + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +#endif + +#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX) + +static char * +read_symlink(const char *fname, size_t bufsize, ssize_t *linksize) +{ + if (bufsize) + bufsize += 2; + else + bufsize = BUFSIZ*2; + /* Make sure that bufsize >= 2 and within range */ + if ((bufsize > MAXSIZE) || (bufsize < 2)) + bufsize = MAXSIZE; + while (1) { + char *buf; + + emalloc(buf, char *, bufsize, "read_symlink"); + if ((*linksize = readlink(fname, buf, bufsize)) < 0) { + /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink + returns -1 with errno == ERANGE if the buffer is + too small. */ + if (errno != ERANGE) { + free(buf); + return NULL; + } + } + /* N.B. This test is safe because bufsize must be >= 2 */ + else if ((size_t)*linksize <= bufsize-2) { + buf[*linksize] = '\0'; + return buf; + } + free(buf); + if (bufsize <= MAXSIZE/2) + bufsize *= 2; + else if (bufsize < MAXSIZE) + bufsize = MAXSIZE; + else + return NULL; + } + return NULL; +} + /* do_stat --- provide a stat() function for gawk */ static NODE * @@ -265,22 +317,17 @@ do_stat(int nargs) /* for symbolic links, add a linkval field */ if (S_ISLNK(sbuf.st_mode)) { char *buf; - int linksize; - - emalloc(buf, char *, sbuf.st_size + 2, "do_stat"); - if (((linksize = readlink(file->stptr, buf, - sbuf.st_size + 2)) >= 0) && - (linksize <= sbuf.st_size)) { - /* - * set the linkval field only if we are able to - * retrieve the entire link value successfully. - */ - buf[linksize] = '\0'; + ssize_t linksize; + if ((buf = read_symlink(file->stptr, sbuf.st_size, + &linksize)) != NULL) { aptr = assoc_lookup(array, tmp = make_string("linkval", 7)); *aptr = make_str_node(buf, linksize, ALREADY_MALLOCED); unref(tmp); } + else + warning(_("unable to read symbolic link `%s'"), + file->stptr); } /* add a type field */ -- cgit v1.2.3 From b2a499ad0442dc0d8d4ac4b51c31d215fd810bf9 Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Wed, 11 Apr 2012 16:20:56 -0400 Subject: Set array elements properly in stat() extension. --- extension/filefuncs.c | 110 +++++++++++++++++--------------------------------- 1 file changed, 36 insertions(+), 74 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 6d46c5e5..8e5e8daa 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -209,15 +209,29 @@ read_symlink(const char *fname, size_t bufsize, ssize_t *linksize) return NULL; } +/* array_set --- set an array element */ + +static void +array_set(NODE *array, const char *sub, NODE *value) +{ + NODE *tmp; + NODE **aptr; + + tmp = make_string(sub, strlen(sub)); + aptr = assoc_lookup(array, tmp); + unref(tmp); + unref(*aptr); + *aptr = value; +} + /* do_stat --- provide a stat() function for gawk */ static NODE * do_stat(int nargs) { - NODE *file, *array, *tmp; + NODE *file, *array; struct stat sbuf; int ret; - NODE **aptr; char *pmode; /* printable mode */ char *type = "unknown"; @@ -240,79 +254,32 @@ do_stat(int nargs) } /* fill in the array */ - aptr = assoc_lookup(array, tmp = make_string("name", 4)); - *aptr = dupnode(file); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("dev", 3)); - *aptr = make_number((AWKNUM) sbuf.st_dev); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("ino", 3)); - *aptr = make_number((AWKNUM) sbuf.st_ino); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("mode", 4)); - *aptr = make_number((AWKNUM) sbuf.st_mode); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("nlink", 5)); - *aptr = make_number((AWKNUM) sbuf.st_nlink); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("uid", 3)); - *aptr = make_number((AWKNUM) sbuf.st_uid); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("gid", 3)); - *aptr = make_number((AWKNUM) sbuf.st_gid); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("size", 4)); - *aptr = make_number((AWKNUM) sbuf.st_size); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("blocks", 6)); - *aptr = make_number((AWKNUM) sbuf.st_blocks); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("atime", 5)); - *aptr = make_number((AWKNUM) sbuf.st_atime); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("mtime", 5)); - *aptr = make_number((AWKNUM) sbuf.st_mtime); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("ctime", 5)); - *aptr = make_number((AWKNUM) sbuf.st_ctime); - unref(tmp); + array_set(array, "name", dupnode(file)); + array_set(array, "dev", make_number((AWKNUM) sbuf.st_dev)); + array_set(array, "ino", make_number((AWKNUM) sbuf.st_ino)); + array_set(array, "mode", make_number((AWKNUM) sbuf.st_mode)); + array_set(array, "nlink", make_number((AWKNUM) sbuf.st_nlink)); + array_set(array, "uid", make_number((AWKNUM) sbuf.st_uid)); + array_set(array, "gid", make_number((AWKNUM) sbuf.st_gid)); + array_set(array, "size", make_number((AWKNUM) sbuf.st_size)); + array_set(array, "blocks", make_number((AWKNUM) sbuf.st_blocks)); + array_set(array, "atime", make_number((AWKNUM) sbuf.st_atime)); + array_set(array, "mtime", make_number((AWKNUM) sbuf.st_mtime)); + array_set(array, "ctime", make_number((AWKNUM) sbuf.st_ctime)); /* for block and character devices, add rdev, major and minor numbers */ if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode)) { - aptr = assoc_lookup(array, tmp = make_string("rdev", 4)); - *aptr = make_number((AWKNUM) sbuf.st_rdev); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("major", 5)); - *aptr = make_number((AWKNUM) major(sbuf.st_rdev)); - unref(tmp); - - aptr = assoc_lookup(array, tmp = make_string("minor", 5)); - *aptr = make_number((AWKNUM) minor(sbuf.st_rdev)); - unref(tmp); + array_set(array, "rdev", make_number((AWKNUM) sbuf.st_rdev)); + array_set(array, "major", make_number((AWKNUM) major(sbuf.st_rdev))); + array_set(array, "minor", make_number((AWKNUM) minor(sbuf.st_rdev))); } #ifdef HAVE_ST_BLKSIZE - aptr = assoc_lookup(array, tmp = make_string("blksize", 7)); - *aptr = make_number((AWKNUM) sbuf.st_blksize); - unref(tmp); + array_set(array, "blksize", make_number((AWKNUM) sbuf.st_blksize)); #endif /* HAVE_ST_BLKSIZE */ - aptr = assoc_lookup(array, tmp = make_string("pmode", 5)); pmode = format_mode(sbuf.st_mode); - *aptr = make_string(pmode, strlen(pmode)); - unref(tmp); + array_set(array, "pmode", make_string(pmode, strlen(pmode))); /* for symbolic links, add a linkval field */ if (S_ISLNK(sbuf.st_mode)) { @@ -320,11 +287,8 @@ do_stat(int nargs) ssize_t linksize; if ((buf = read_symlink(file->stptr, sbuf.st_size, - &linksize)) != NULL) { - aptr = assoc_lookup(array, tmp = make_string("linkval", 7)); - *aptr = make_str_node(buf, linksize, ALREADY_MALLOCED); - unref(tmp); - } + &linksize)) != NULL) + array_set(array, "linkval", make_str_node(buf, linksize, ALREADY_MALLOCED)); else warning(_("unable to read symbolic link `%s'"), file->stptr); @@ -366,9 +330,7 @@ do_stat(int nargs) #endif } - aptr = assoc_lookup(array, tmp = make_string("type", 4)); - *aptr = make_string(type, strlen(type)); - unref(tmp); + array_set(array, "type", make_string(type, strlen(type))); return make_number((AWKNUM) ret); } -- cgit v1.2.3