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 From e5353c0f447a8628985722296f57fc02dd2e0063 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 11 May 2012 15:05:35 +0300 Subject: Move to use of bool type, true, false, everywhere. --- extension/filefuncs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 8e5e8daa..9758ba8e 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -42,7 +42,7 @@ do_chdir(int nargs) if (do_lint && nargs != 1) lintwarn("chdir: called with incorrect number of arguments"); - newdir = get_scalar_argument(0, FALSE); + newdir = get_scalar_argument(0, false); (void) force_string(newdir); ret = chdir(newdir->stptr); if (ret < 0) @@ -239,8 +239,8 @@ do_stat(int nargs) lintwarn("stat: called with too many arguments"); /* file is first arg, array to hold results is second */ - file = get_scalar_argument(0, FALSE); - array = get_array_argument(1, FALSE); + file = get_scalar_argument(0, false); + array = get_array_argument(1, false); /* empty out the array */ assoc_clear(array); -- cgit v1.2.3 From 06323619397520aba2fc2f8f983d67d06c6610fa Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Sun, 13 May 2012 16:39:35 -0400 Subject: Add comment to extension/filefuncs.c discussing unref on value from assoc_lookup. --- extension/filefuncs.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 9758ba8e..01f3fce2 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -220,6 +220,13 @@ array_set(NODE *array, const char *sub, NODE *value) tmp = make_string(sub, strlen(sub)); aptr = assoc_lookup(array, tmp); unref(tmp); + /* + * Note: since we initialized with assoc_clear, we know that aptr + * has been initialized with Nnull_string. Thus, the call to + * unref(*aptr) is not strictly necessary. However, I think it is + * generally more correct to call unref to maintain the proper + * reference count. + */ unref(*aptr); *aptr = value; } -- cgit v1.2.3 From 577c3fc31a2718461fba2e599d162de96fe838fa Mon Sep 17 00:00:00 2001 From: "Andrew J. Schorr" Date: Thu, 24 May 2012 15:34:17 -0400 Subject: First working version of new API mechanism (probably has memory leaks). --- extension/filefuncs.c | 221 +++++++++++++++++++++++++++----------------------- 1 file changed, 118 insertions(+), 103 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 01f3fce2..74a086a9 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -7,7 +7,8 @@ */ /* - * Copyright (C) 2001, 2004, 2005, 2010, 2011 the Free Software Foundation, Inc. + * Copyright (C) 2001, 2004, 2005, 2010, 2011, 2012 + * the Free Software Foundation, Inc. * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. @@ -27,28 +28,40 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "awk.h" +#include +#include +#include +#include +#include + +#include +#include +#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; /* do_chdir --- provide dynamically loaded chdir() builtin for gawk */ -static NODE * -do_chdir(int nargs) +static awk_value_t * +do_chdir(int nargs, awk_value_t *result) { - NODE *newdir; + awk_value_t newdir; int ret = -1; if (do_lint && nargs != 1) - lintwarn("chdir: called with incorrect number of arguments"); + lintwarn(ext_id, "chdir: called with incorrect number of arguments"); - newdir = get_scalar_argument(0, false); - (void) force_string(newdir); - ret = chdir(newdir->stptr); - if (ret < 0) - update_ERRNO_int(errno); + if (get_curfunc_param(0, AWK_STRING, &newdir) != NULL) { + ret = chdir(newdir.str_value.str); + if (ret < 0) + update_ERRNO_int(errno); + } - return make_number((AWKNUM) ret); + return make_number(ret, result); } /* format_mode --- turn a stat mode field into something readable */ @@ -57,7 +70,15 @@ static char * format_mode(unsigned long fmode) { static char outbuf[12]; - int i; + static struct mode_map { + int mask; + int rep; + } map[] = { + { S_IRUSR, 'r' }, { S_IWUSR, 'w' }, { S_IXUSR, 'x' }, + { S_IRGRP, 'r' }, { S_IWGRP, 'w' }, { S_IXGRP, 'x' }, + { S_IROTH, 'r' }, { S_IWOTH, 'w' }, { S_IXOTH, 'x' }, + }; + int i, j, k; strcpy(outbuf, "----------"); /* first, get the file type */ @@ -97,39 +118,16 @@ format_mode(unsigned long fmode) #endif } - i++; - if ((fmode & S_IRUSR) != 0) - outbuf[i] = 'r'; - i++; - if ((fmode & S_IWUSR) != 0) - outbuf[i] = 'w'; - i++; - if ((fmode & S_IXUSR) != 0) - outbuf[i] = 'x'; - i++; - - if ((fmode & S_IRGRP) != 0) - outbuf[i] = 'r'; - i++; - if ((fmode & S_IWGRP) != 0) - outbuf[i] = 'w'; - i++; - if ((fmode & S_IXGRP) != 0) - outbuf[i] = 'x'; - i++; + for (j = 0, k = sizeof(map)/sizeof(map[0]); j < k; j++) { + i++; + if ((fmode & map[j].mask) != 0) + outbuf[i] = map[j].rep; + } - if ((fmode & S_IROTH) != 0) - outbuf[i] = 'r'; - i++; - if ((fmode & S_IWOTH) != 0) - outbuf[i] = 'w'; i++; - if ((fmode & S_IXOTH) != 0) - outbuf[i] = 'x'; - i++; - outbuf[i] = '\0'; + /* setuid bit */ if ((fmode & S_ISUID) != 0) { if (outbuf[3] == 'x') outbuf[3] = 's'; @@ -145,6 +143,7 @@ format_mode(unsigned long fmode) outbuf[6] = 'l'; } + /* the so-called "sticky" bit */ if ((fmode & S_ISVTX) != 0) { if (outbuf[9] == 'x') outbuf[9] = 't'; @@ -158,7 +157,7 @@ format_mode(unsigned long fmode) /* 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 + for example, on GNU/Linux in the /proc filesystem, where the symbolic link sizes are often 0. */ #ifndef SIZE_MAX @@ -176,10 +175,12 @@ read_symlink(const char *fname, size_t bufsize, ssize_t *linksize) if (bufsize) bufsize += 2; else - bufsize = BUFSIZ*2; + bufsize = BUFSIZ * 2; + /* Make sure that bufsize >= 2 and within range */ - if ((bufsize > MAXSIZE) || (bufsize < 2)) + if (bufsize > MAXSIZE || bufsize < 2) bufsize = MAXSIZE; + while (1) { char *buf; @@ -212,93 +213,106 @@ read_symlink(const char *fname, size_t bufsize, ssize_t *linksize) /* array_set --- set an array element */ static void -array_set(NODE *array, const char *sub, NODE *value) +array_set(awk_array_t array, const char *sub, awk_value_t *value) +{ + awk_element_t element; + awk_value_t tmp; + + memset(& element, 0, sizeof(element)); + + element.index = dup_string(sub, strlen(sub), & tmp)->str_value; + element.value = *value; + + set_array_element(array, & element); +} + +static void +array_set_numeric(awk_array_t array, const char *sub, double num) { - NODE *tmp; - NODE **aptr; - - tmp = make_string(sub, strlen(sub)); - aptr = assoc_lookup(array, tmp); - unref(tmp); - /* - * Note: since we initialized with assoc_clear, we know that aptr - * has been initialized with Nnull_string. Thus, the call to - * unref(*aptr) is not strictly necessary. However, I think it is - * generally more correct to call unref to maintain the proper - * reference count. - */ - unref(*aptr); - *aptr = value; + awk_value_t tmp; + return array_set(array, sub, make_number(num, & tmp)); } /* do_stat --- provide a stat() function for gawk */ -static NODE * -do_stat(int nargs) +static awk_value_t * +do_stat(int nargs, awk_value_t *result) { - NODE *file, *array; + awk_value_t file_param, array_param; + char *name; + awk_array_t array; struct stat sbuf; int ret; char *pmode; /* printable mode */ char *type = "unknown"; + awk_value_t tmp; - if (do_lint && nargs > 2) - lintwarn("stat: called with too many arguments"); + if (do_lint && nargs != 2) { + lintwarn(ext_id, "stat: called with wrong number of arguments"); + /* XXX previous version returned 0; why? */ + return make_number(-1, result); + } /* file is first arg, array to hold results is second */ - file = get_scalar_argument(0, false); - array = get_array_argument(1, false); + if (get_curfunc_param(0, AWK_STRING, &file_param) == NULL || + get_curfunc_param(1, AWK_ARRAY, &array_param) == NULL) { + warning(ext_id, "stat: bad parameters"); + /* XXX previous version returned 0; why? */ + return make_number(-1, result); + } + + name = file_param.str_value.str; + array = array_param.array_cookie; /* empty out the array */ - assoc_clear(array); + clear_array(array); /* lstat the file, if error, set ERRNO and return */ - (void) force_string(file); - ret = lstat(file->stptr, & sbuf); + ret = lstat(name, & sbuf); if (ret < 0) { update_ERRNO_int(errno); - return make_number((AWKNUM) ret); + /* XXX previous version returned 0; why? */ + return make_number(-1, result); } /* fill in the array */ - 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)); + array_set(array, "name", make_string(name, file_param.str_value.len, &tmp)); + array_set_numeric(array, "dev", sbuf.st_dev); + array_set_numeric(array, "ino", sbuf.st_ino); + array_set_numeric(array, "mode", sbuf.st_mode); + array_set_numeric(array, "nlink", sbuf.st_nlink); + array_set_numeric(array, "uid", sbuf.st_uid); + array_set_numeric(array, "gid", sbuf.st_gid); + array_set_numeric(array, "size", sbuf.st_size); + array_set_numeric(array, "blocks", sbuf.st_blocks); + array_set_numeric(array, "atime", sbuf.st_atime); + array_set_numeric(array, "mtime", sbuf.st_mtime); + array_set_numeric(array, "ctime", 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)) { - 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))); + array_set_numeric(array, "rdev", sbuf.st_rdev); + array_set_numeric(array, "major", major(sbuf.st_rdev)); + array_set_numeric(array, "minor", minor(sbuf.st_rdev)); } #ifdef HAVE_ST_BLKSIZE - array_set(array, "blksize", make_number((AWKNUM) sbuf.st_blksize)); + array_set_numeric(array, "blksize", sbuf.st_blksize); #endif /* HAVE_ST_BLKSIZE */ pmode = format_mode(sbuf.st_mode); - array_set(array, "pmode", make_string(pmode, strlen(pmode))); + array_set(array, "pmode", make_string(pmode, strlen(pmode), &tmp)); /* for symbolic links, add a linkval field */ if (S_ISLNK(sbuf.st_mode)) { char *buf; ssize_t linksize; - if ((buf = read_symlink(file->stptr, sbuf.st_size, + if ((buf = read_symlink(name, sbuf.st_size, &linksize)) != NULL) - array_set(array, "linkval", make_str_node(buf, linksize, ALREADY_MALLOCED)); + array_set(array, "linkval", make_string(buf, linksize, &tmp)); else - warning(_("unable to read symbolic link `%s'"), - file->stptr); + warning(ext_id, "unable to read symbolic link `%s'", name); } /* add a type field */ @@ -337,18 +351,19 @@ do_stat(int nargs) #endif } - array_set(array, "type", make_string(type, strlen(type))); + array_set(array, "type", make_string(type, strlen(type), &tmp)); - return make_number((AWKNUM) ret); + ret = 1; /* success */ + + return make_number(ret, result); } -/* dlload --- load new builtins in this library */ +static awk_ext_func_t func_table[] = { + { "chdir", do_chdir, 1 }, + { "stat", do_stat, 2 }, +}; -NODE * -dlload(NODE *tree, void *dl) -{ - make_builtin("chdir", do_chdir, 1); - make_builtin("stat", do_stat, 2); - return make_number((AWKNUM) 0); -} +/* define the dl_load function using the boilerplate macro */ + +dl_load_func(func_table, filefuncs, "") -- cgit v1.2.3 From eec7101174a3b2807fb282272f75cc13d4b953c3 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 25 May 2012 15:18:43 +0300 Subject: Additional changes / some cleanups. --- 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 74a086a9..fb19f2b3 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -230,7 +230,7 @@ static void array_set_numeric(awk_array_t array, const char *sub, double num) { awk_value_t tmp; - return array_set(array, sub, make_number(num, & tmp)); + array_set(array, sub, make_number(num, & tmp)); } /* do_stat --- provide a stat() function for gawk */ -- cgit v1.2.3 From 04dc190623f0d99d80387b33ca747b8cbad37724 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 29 May 2012 23:33:27 +0300 Subject: Further API work. --- extension/filefuncs.c | 187 +++++++++++++++++++++++--------------------------- 1 file changed, 87 insertions(+), 100 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index fb19f2b3..46b1596e 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -4,6 +4,7 @@ * * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998 * Arnold Robbins and John Haque, update for 3.1.4, applied Mon Jun 14 13:55:30 IDT 2004 + * Arnold Robbins and Andrew Schorr, revised for new extension API, May 2012. */ /* @@ -36,6 +37,7 @@ #include #include + #include "config.h" #include "gawkapi.h" @@ -53,9 +55,9 @@ do_chdir(int nargs, awk_value_t *result) int ret = -1; if (do_lint && nargs != 1) - lintwarn(ext_id, "chdir: called with incorrect number of arguments"); + lintwarn(ext_id, "chdir: called with incorrect number of arguments, expecting 1"); - if (get_curfunc_param(0, AWK_STRING, &newdir) != NULL) { + if (get_curfunc_param(0, AWK_STRING, & newdir) != NULL) { ret = chdir(newdir.str_value.str); if (ret < 0) update_ERRNO_int(errno); @@ -70,6 +72,27 @@ static char * format_mode(unsigned long fmode) { static char outbuf[12]; + static struct ftype_map { + int mask; + int charval; + } ftype_map[] = { + { S_IFREG, '-' }, /* redundant */ + { S_IFBLK, 'b' }, + { S_IFCHR, 'c' }, + { S_IFDIR, 'd' }, +#ifdef S_IFSOCK + { S_IFSOCK, 's' }, +#endif +#ifdef S_IFIFO + { S_IFIFO, 'p' }, +#endif +#ifdef S_IFLNK + { S_IFLNK, 'l' }, +#endif +#ifdef S_IFDOOR /* Solaris weirdness */ + { S_IFDOOR, 'D' }, +#endif /* S_IFDOOR */ + }; static struct mode_map { int mask; int rep; @@ -78,46 +101,30 @@ format_mode(unsigned long fmode) { S_IRGRP, 'r' }, { S_IWGRP, 'w' }, { S_IXGRP, 'x' }, { S_IROTH, 'r' }, { S_IWOTH, 'w' }, { S_IXOTH, 'x' }, }; + static struct setuid_map { + int mask; + int index; + int small_rep; + int big_rep; + } setuid_map[] = { + { S_ISUID, 3, 's', 'S' }, /* setuid bit */ + { S_ISGID, 6, 's', 'l' }, /* setgid without execute == locking */ + { S_ISVTX, 9, 't', 'T' }, /* the so-called "sticky" bit */ + }; int i, j, k; strcpy(outbuf, "----------"); + /* first, get the file type */ i = 0; - switch (fmode & S_IFMT) { -#ifdef S_IFSOCK - case S_IFSOCK: - outbuf[i] = 's'; - break; -#endif -#ifdef S_IFLNK - case S_IFLNK: - outbuf[i] = 'l'; - break; -#endif - case S_IFREG: - outbuf[i] = '-'; /* redundant */ - break; - case S_IFBLK: - outbuf[i] = 'b'; - break; - case S_IFDIR: - outbuf[i] = 'd'; - break; -#ifdef S_IFDOOR /* Solaris weirdness */ - case S_IFDOOR: - outbuf[i] = 'D'; - break; -#endif /* S_IFDOOR */ - case S_IFCHR: - outbuf[i] = 'c'; - break; -#ifdef S_IFIFO - case S_IFIFO: - outbuf[i] = 'p'; - break; -#endif + for (j = 0, k = sizeof(ftype_map)/sizeof(ftype_map[0]); j < k; j++) { + if ((fmode & S_IFMT) == ftype_map[j].mask) { + outbuf[i] = ftype_map[j].charval; + break; + } } + /* now the permissions */ for (j = 0, k = sizeof(map)/sizeof(map[0]); j < k; j++) { i++; if ((fmode & map[j].mask) != 0) @@ -127,28 +134,14 @@ format_mode(unsigned long fmode) i++; outbuf[i] = '\0'; - /* setuid bit */ - if ((fmode & S_ISUID) != 0) { - if (outbuf[3] == 'x') - outbuf[3] = 's'; - else - outbuf[3] = 'S'; - } - - /* setgid without execute == locking */ - if ((fmode & S_ISGID) != 0) { - if (outbuf[6] == 'x') - outbuf[6] = 's'; - else - outbuf[6] = 'l'; - } - - /* the so-called "sticky" bit */ - if ((fmode & S_ISVTX) != 0) { - if (outbuf[9] == 'x') - outbuf[9] = 't'; - else - outbuf[9] = 'T'; + /* tweaks for the setuid / setgid / sticky bits */ + for (j = 0, k = sizeof(setuid_map)/sizeof(setuid_map[0]); j < k; j++) { + if (fmode & setuid_map[j].mask) { + if (outbuf[setuid_map[j].index] == 'x') + outbuf[setuid_map[j].index] = setuid_map[j].small_rep; + else + outbuf[setuid_map[j].index] = setuid_map[j].big_rep; + } } return outbuf; @@ -226,10 +219,13 @@ array_set(awk_array_t array, const char *sub, awk_value_t *value) set_array_element(array, & element); } +/* array_set_numeric --- set an array element with a number */ + static void array_set_numeric(awk_array_t array, const char *sub, double num) { awk_value_t tmp; + array_set(array, sub, make_number(num, & tmp)); } @@ -242,22 +238,41 @@ do_stat(int nargs, awk_value_t *result) char *name; awk_array_t array; struct stat sbuf; - int ret; + int ret, j, k; char *pmode; /* printable mode */ char *type = "unknown"; awk_value_t tmp; + static struct ftype_map { + int mask; + const char *type; + } ftype_map[] = { + { S_IFREG, "file" }, + { S_IFBLK, "blockdev" }, + { S_IFCHR, "chardev" }, + { S_IFDIR, "directory" }, +#ifdef S_IFSOCK + { S_IFSOCK, "socket" }, +#endif +#ifdef S_IFIFO + { S_IFIFO, "fifo" }, +#endif +#ifdef S_IFLNK + { S_IFLNK, "symlink" }, +#endif +#ifdef S_IFDOOR /* Solaris weirdness */ + { S_IFDOOR, "door" }, +#endif /* S_IFDOOR */ + }; if (do_lint && nargs != 2) { lintwarn(ext_id, "stat: called with wrong number of arguments"); - /* XXX previous version returned 0; why? */ return make_number(-1, result); } /* file is first arg, array to hold results is second */ - if (get_curfunc_param(0, AWK_STRING, &file_param) == NULL || - get_curfunc_param(1, AWK_ARRAY, &array_param) == NULL) { + if ( get_curfunc_param(0, AWK_STRING, & file_param) == NULL + || get_curfunc_param(1, AWK_ARRAY, & array_param) == NULL) { warning(ext_id, "stat: bad parameters"); - /* XXX previous version returned 0; why? */ return make_number(-1, result); } @@ -271,7 +286,6 @@ do_stat(int nargs, awk_value_t *result) ret = lstat(name, & sbuf); if (ret < 0) { update_ERRNO_int(errno); - /* XXX previous version returned 0; why? */ return make_number(-1, result); } @@ -301,7 +315,7 @@ do_stat(int nargs, awk_value_t *result) #endif /* HAVE_ST_BLKSIZE */ pmode = format_mode(sbuf.st_mode); - array_set(array, "pmode", make_string(pmode, strlen(pmode), &tmp)); + array_set(array, "pmode", make_string(pmode, strlen(pmode), & tmp)); /* for symbolic links, add a linkval field */ if (S_ISLNK(sbuf.st_mode)) { @@ -309,46 +323,19 @@ do_stat(int nargs, awk_value_t *result) ssize_t linksize; if ((buf = read_symlink(name, sbuf.st_size, - &linksize)) != NULL) - array_set(array, "linkval", make_string(buf, linksize, &tmp)); + & linksize)) != NULL) + array_set(array, "linkval", make_string(buf, linksize, & tmp)); else - warning(ext_id, "unable to read symbolic link `%s'", name); + warning(ext_id, "stat: unable to read symbolic link `%s'", name); } /* add a type field */ - switch (sbuf.st_mode & S_IFMT) { -#ifdef S_IFSOCK - case S_IFSOCK: - type = "socket"; - break; -#endif -#ifdef S_IFLNK - case S_IFLNK: - type = "symlink"; - break; -#endif - case S_IFREG: - type = "file"; - break; - case S_IFBLK: - type = "blockdev"; - break; - case S_IFDIR: - type = "directory"; - break; -#ifdef S_IFDOOR - case S_IFDOOR: - type = "door"; - break; -#endif - case S_IFCHR: - type = "chardev"; - break; -#ifdef S_IFIFO - case S_IFIFO: - type = "fifo"; - break; -#endif + type = "unknown"; /* shouldn't happen */ + for (j = 0, k = sizeof(ftype_map)/sizeof(ftype_map[0]); j < k; j++) { + if ((sbuf.st_mode & S_IFMT) == ftype_map[j].mask) { + type = ftype_map[j].type; + break; + } } array_set(array, "type", make_string(type, strlen(type), &tmp)); -- cgit v1.2.3 From fcc37ab5b658388a6fa14bcd9c0254454418c96a Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 6 Jun 2012 20:03:29 +0300 Subject: Minor fixes for printf compile warnings. --- 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 46b1596e..4d382005 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -240,7 +240,7 @@ do_stat(int nargs, awk_value_t *result) struct stat sbuf; int ret, j, k; char *pmode; /* printable mode */ - char *type = "unknown"; + const char *type = "unknown"; awk_value_t tmp; static struct ftype_map { int mask; -- cgit v1.2.3 From 820b6a2ccb7859e15ade36af6ac1d0d08c1da4b1 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Tue, 12 Jun 2012 22:10:31 +0300 Subject: Further cleanups and improvements in API. --- extension/filefuncs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 4d382005..12f3acb6 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -57,7 +57,7 @@ do_chdir(int nargs, awk_value_t *result) if (do_lint && nargs != 1) lintwarn(ext_id, "chdir: called with incorrect number of arguments, expecting 1"); - if (get_curfunc_param(0, AWK_STRING, & newdir) != NULL) { + if (get_argument(0, AWK_STRING, & newdir)) { ret = chdir(newdir.str_value.str); if (ret < 0) update_ERRNO_int(errno); @@ -73,7 +73,7 @@ format_mode(unsigned long fmode) { static char outbuf[12]; static struct ftype_map { - int mask; + unsigned int mask; int charval; } ftype_map[] = { { S_IFREG, '-' }, /* redundant */ @@ -94,7 +94,7 @@ format_mode(unsigned long fmode) #endif /* S_IFDOOR */ }; static struct mode_map { - int mask; + unsigned int mask; int rep; } map[] = { { S_IRUSR, 'r' }, { S_IWUSR, 'w' }, { S_IXUSR, 'x' }, @@ -102,7 +102,7 @@ format_mode(unsigned long fmode) { S_IROTH, 'r' }, { S_IWOTH, 'w' }, { S_IXOTH, 'x' }, }; static struct setuid_map { - int mask; + unsigned int mask; int index; int small_rep; int big_rep; @@ -243,7 +243,7 @@ do_stat(int nargs, awk_value_t *result) const char *type = "unknown"; awk_value_t tmp; static struct ftype_map { - int mask; + unsigned int mask; const char *type; } ftype_map[] = { { S_IFREG, "file" }, @@ -270,8 +270,8 @@ do_stat(int nargs, awk_value_t *result) } /* file is first arg, array to hold results is second */ - if ( get_curfunc_param(0, AWK_STRING, & file_param) == NULL - || get_curfunc_param(1, AWK_ARRAY, & array_param) == NULL) { + if ( ! get_argument(0, AWK_STRING, & file_param) + || ! get_argument(1, AWK_ARRAY, & array_param)) { warning(ext_id, "stat: bad parameters"); return make_number(-1, result); } -- cgit v1.2.3 From 5e79fa8735ec2984fee9054cccd51d86fa939621 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 17 Jun 2012 20:47:50 +0300 Subject: Still more API and testext.c work. --- extension/filefuncs.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 12f3acb6..433a0ea9 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -30,6 +30,7 @@ */ #include +#include #include #include #include @@ -54,6 +55,8 @@ do_chdir(int nargs, awk_value_t *result) awk_value_t newdir; int ret = -1; + assert(result != NULL); + if (do_lint && nargs != 1) lintwarn(ext_id, "chdir: called with incorrect number of arguments, expecting 1"); @@ -264,6 +267,8 @@ do_stat(int nargs, awk_value_t *result) #endif /* S_IFDOOR */ }; + assert(result != NULL); + if (do_lint && nargs != 2) { lintwarn(ext_id, "stat: called with wrong number of arguments"); return make_number(-1, result); -- cgit v1.2.3 From 1e3ac8a49caeeb991d8163042a576a66db51c74b Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 18 Jun 2012 23:00:58 +0300 Subject: Get most of array flattening done. --- 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 433a0ea9..d4e1b57c 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -216,7 +216,7 @@ array_set(awk_array_t array, const char *sub, awk_value_t *value) memset(& element, 0, sizeof(element)); - element.index = dup_string(sub, strlen(sub), & tmp)->str_value; + element.index = *make_string(sub, strlen(sub), & tmp); element.value = *value; set_array_element(array, & element); -- cgit v1.2.3 From 7d37bcd5a8066718b15de8c03725708819389931 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Mon, 9 Jul 2012 21:17:10 +0300 Subject: API: Update set_array_element(). Adjust extensions. --- extension/filefuncs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index d4e1b57c..32a3cee6 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -211,15 +211,12 @@ read_symlink(const char *fname, size_t bufsize, ssize_t *linksize) static void array_set(awk_array_t array, const char *sub, awk_value_t *value) { - awk_element_t element; - awk_value_t tmp; - - memset(& element, 0, sizeof(element)); + awk_value_t index; - element.index = *make_string(sub, strlen(sub), & tmp); - element.value = *value; + set_array_element(array, + make_string(sub, strlen(sub), & index), + value); - set_array_element(array, & element); } /* array_set_numeric --- set an array element with a number */ -- cgit v1.2.3 From 6d1724214a95330b63a6a557f89fb9b40b4a521f Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 11 Jul 2012 21:26:37 +0300 Subject: API clean up and require strings to be malloced. --- extension/filefuncs.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 32a3cee6..74af8b1b 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -214,7 +214,7 @@ array_set(awk_array_t array, const char *sub, awk_value_t *value) awk_value_t index; set_array_element(array, - make_string(sub, strlen(sub), & index), + make_const_string(sub, strlen(sub), & index), value); } @@ -292,7 +292,7 @@ do_stat(int nargs, awk_value_t *result) } /* fill in the array */ - array_set(array, "name", make_string(name, file_param.str_value.len, &tmp)); + array_set(array, "name", make_const_string(name, file_param.str_value.len, &tmp)); array_set_numeric(array, "dev", sbuf.st_dev); array_set_numeric(array, "ino", sbuf.st_ino); array_set_numeric(array, "mode", sbuf.st_mode); @@ -317,7 +317,7 @@ do_stat(int nargs, awk_value_t *result) #endif /* HAVE_ST_BLKSIZE */ pmode = format_mode(sbuf.st_mode); - array_set(array, "pmode", make_string(pmode, strlen(pmode), & tmp)); + array_set(array, "pmode", make_const_string(pmode, strlen(pmode), & tmp)); /* for symbolic links, add a linkval field */ if (S_ISLNK(sbuf.st_mode)) { @@ -326,7 +326,7 @@ do_stat(int nargs, awk_value_t *result) if ((buf = read_symlink(name, sbuf.st_size, & linksize)) != NULL) - array_set(array, "linkval", make_string(buf, linksize, & tmp)); + array_set(array, "linkval", make_malloced_string(buf, linksize, & tmp)); else warning(ext_id, "stat: unable to read symbolic link `%s'", name); } @@ -340,7 +340,7 @@ do_stat(int nargs, awk_value_t *result) } } - array_set(array, "type", make_string(type, strlen(type), &tmp)); + array_set(array, "type", make_const_string(type, strlen(type), &tmp)); ret = 1; /* success */ -- cgit v1.2.3 From 73533707616e119778993fe18540098239ecbb2e Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 11 Jul 2012 21:41:54 +0300 Subject: Add ability to call an initialization routine. --- extension/filefuncs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 74af8b1b..71387cb3 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -44,6 +44,7 @@ static const gawk_api_t *api; /* for convenience macros to work */ static awk_ext_id_t *ext_id; +static awk_bool_t (*init_func)(void) = NULL; int plugin_is_GPL_compatible; -- cgit v1.2.3 From 77036f5ae0d0c4e2e1551838c193dd2ca877a54e Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 13 Jul 2012 14:02:02 +0300 Subject: Refactoring filefuncs.c before fts changes. --- extension/filefuncs.c | 66 +++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 28 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 71387cb3..41783c85 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -230,18 +230,14 @@ array_set_numeric(awk_array_t array, const char *sub, double num) array_set(array, sub, make_number(num, & tmp)); } -/* do_stat --- provide a stat() function for gawk */ +/* fill_stat_array --- do the work to fill an array with stat info */ -static awk_value_t * -do_stat(int nargs, awk_value_t *result) +static int +fill_stat_array(const char *name, awk_array_t array) { - awk_value_t file_param, array_param; - char *name; - awk_array_t array; - struct stat sbuf; - int ret, j, k; char *pmode; /* printable mode */ const char *type = "unknown"; + struct stat sbuf; awk_value_t tmp; static struct ftype_map { unsigned int mask; @@ -264,23 +260,7 @@ do_stat(int nargs, awk_value_t *result) { S_IFDOOR, "door" }, #endif /* S_IFDOOR */ }; - - assert(result != NULL); - - if (do_lint && nargs != 2) { - lintwarn(ext_id, "stat: called with wrong number of arguments"); - return make_number(-1, result); - } - - /* file is first arg, array to hold results is second */ - if ( ! get_argument(0, AWK_STRING, & file_param) - || ! get_argument(1, AWK_ARRAY, & array_param)) { - warning(ext_id, "stat: bad parameters"); - return make_number(-1, result); - } - - name = file_param.str_value.str; - array = array_param.array_cookie; + int ret, j, k; /* empty out the array */ clear_array(array); @@ -289,11 +269,11 @@ do_stat(int nargs, awk_value_t *result) ret = lstat(name, & sbuf); if (ret < 0) { update_ERRNO_int(errno); - return make_number(-1, result); + return -1; } /* fill in the array */ - array_set(array, "name", make_const_string(name, file_param.str_value.len, &tmp)); + array_set(array, "name", make_const_string(name, strlen(name), & tmp)); array_set_numeric(array, "dev", sbuf.st_dev); array_set_numeric(array, "ino", sbuf.st_ino); array_set_numeric(array, "mode", sbuf.st_mode); @@ -343,7 +323,37 @@ do_stat(int nargs, awk_value_t *result) array_set(array, "type", make_const_string(type, strlen(type), &tmp)); - ret = 1; /* success */ + return 0; +} + +/* do_stat --- provide a stat() function for gawk */ + +static awk_value_t * +do_stat(int nargs, awk_value_t *result) +{ + awk_value_t file_param, array_param; + char *name; + awk_array_t array; + int ret; + + assert(result != NULL); + + if (do_lint && nargs != 2) { + lintwarn(ext_id, "stat: called with wrong number of arguments"); + return make_number(-1, result); + } + + /* file is first arg, array to hold results is second */ + if ( ! get_argument(0, AWK_STRING, & file_param) + || ! get_argument(1, AWK_ARRAY, & array_param)) { + warning(ext_id, "stat: bad parameters"); + return make_number(-1, result); + } + + name = file_param.str_value.str; + array = array_param.array_cookie; + + ret = fill_stat_array(name, array); return make_number(ret, result); } -- cgit v1.2.3 From 7e5b2a94ce3c089c50c5862168d1d917e5febcf4 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 25 Jul 2012 23:10:35 +0300 Subject: Add translation to the extensions. --- extension/filefuncs.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 41783c85..e8c16e8f 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -42,6 +42,10 @@ #include "config.h" #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_func)(void) = NULL; @@ -59,7 +63,7 @@ do_chdir(int nargs, awk_value_t *result) assert(result != NULL); if (do_lint && nargs != 1) - lintwarn(ext_id, "chdir: called with incorrect number of arguments, expecting 1"); + lintwarn(ext_id, _("chdir: called with incorrect number of arguments, expecting 1")); if (get_argument(0, AWK_STRING, & newdir)) { ret = chdir(newdir.str_value.str); @@ -339,14 +343,14 @@ do_stat(int nargs, awk_value_t *result) assert(result != NULL); if (do_lint && nargs != 2) { - lintwarn(ext_id, "stat: called with wrong number of arguments"); + lintwarn(ext_id, _("stat: called with wrong number of arguments")); return make_number(-1, result); } /* file is first arg, array to hold results is second */ if ( ! get_argument(0, AWK_STRING, & file_param) || ! get_argument(1, AWK_ARRAY, & array_param)) { - warning(ext_id, "stat: bad parameters"); + warning(ext_id, _("stat: bad parameters")); return make_number(-1, result); } -- cgit v1.2.3 From 88e81c931345aa485e55c6d6c7f3ad61dc200fed Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 8 Aug 2012 22:37:55 +0300 Subject: Add fts() extension, support, doc, and test. --- extension/filefuncs.c | 429 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 395 insertions(+), 34 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index e8c16e8f..e27e51bf 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -5,6 +5,7 @@ * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998 * Arnold Robbins and John Haque, update for 3.1.4, applied Mon Jun 14 13:55:30 IDT 2004 * Arnold Robbins and Andrew Schorr, revised for new extension API, May 2012. + * Arnold Robbins, add fts(), August 2012 */ /* @@ -46,9 +47,20 @@ #define _(msgid) gettext(msgid) #define N_(msgid) msgid +#if defined(HAVE_FTS_H) && defined(HAVE_FTS_OPEN) && defined(HAVE_FTS_READ) +#define HAVE_FTS_ROUTINES +#endif + + +#ifdef HAVE_FTS_ROUTINES +#include +#include "stack.h" +#endif + static const gawk_api_t *api; /* for convenience macros to work */ static awk_ext_id_t *ext_id; -static awk_bool_t (*init_func)(void) = NULL; +static awk_bool_t init_filefuncs(void); +static awk_bool_t (*init_func)(void) = init_filefuncs; int plugin_is_GPL_compatible; @@ -237,11 +249,10 @@ array_set_numeric(awk_array_t array, const char *sub, double num) /* fill_stat_array --- do the work to fill an array with stat info */ static int -fill_stat_array(const char *name, awk_array_t array) +fill_stat_array(const char *name, awk_array_t array, struct stat *sbuf) { char *pmode; /* printable mode */ const char *type = "unknown"; - struct stat sbuf; awk_value_t tmp; static struct ftype_map { unsigned int mask; @@ -264,52 +275,45 @@ fill_stat_array(const char *name, awk_array_t array) { S_IFDOOR, "door" }, #endif /* S_IFDOOR */ }; - int ret, j, k; + int j, k; /* empty out the array */ clear_array(array); - /* lstat the file, if error, set ERRNO and return */ - ret = lstat(name, & sbuf); - if (ret < 0) { - update_ERRNO_int(errno); - return -1; - } - /* fill in the array */ array_set(array, "name", make_const_string(name, strlen(name), & tmp)); - array_set_numeric(array, "dev", sbuf.st_dev); - array_set_numeric(array, "ino", sbuf.st_ino); - array_set_numeric(array, "mode", sbuf.st_mode); - array_set_numeric(array, "nlink", sbuf.st_nlink); - array_set_numeric(array, "uid", sbuf.st_uid); - array_set_numeric(array, "gid", sbuf.st_gid); - array_set_numeric(array, "size", sbuf.st_size); - array_set_numeric(array, "blocks", sbuf.st_blocks); - array_set_numeric(array, "atime", sbuf.st_atime); - array_set_numeric(array, "mtime", sbuf.st_mtime); - array_set_numeric(array, "ctime", sbuf.st_ctime); + array_set_numeric(array, "dev", sbuf->st_dev); + array_set_numeric(array, "ino", sbuf->st_ino); + array_set_numeric(array, "mode", sbuf->st_mode); + array_set_numeric(array, "nlink", sbuf->st_nlink); + array_set_numeric(array, "uid", sbuf->st_uid); + array_set_numeric(array, "gid", sbuf->st_gid); + array_set_numeric(array, "size", sbuf->st_size); + array_set_numeric(array, "blocks", sbuf->st_blocks); + array_set_numeric(array, "atime", sbuf->st_atime); + array_set_numeric(array, "mtime", sbuf->st_mtime); + array_set_numeric(array, "ctime", 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)) { - array_set_numeric(array, "rdev", sbuf.st_rdev); - array_set_numeric(array, "major", major(sbuf.st_rdev)); - array_set_numeric(array, "minor", minor(sbuf.st_rdev)); + if (S_ISBLK(sbuf->st_mode) || S_ISCHR(sbuf->st_mode)) { + array_set_numeric(array, "rdev", sbuf->st_rdev); + array_set_numeric(array, "major", major(sbuf->st_rdev)); + array_set_numeric(array, "minor", minor(sbuf->st_rdev)); } #ifdef HAVE_ST_BLKSIZE - array_set_numeric(array, "blksize", sbuf.st_blksize); + array_set_numeric(array, "blksize", sbuf->st_blksize); #endif /* HAVE_ST_BLKSIZE */ - pmode = format_mode(sbuf.st_mode); + pmode = format_mode(sbuf->st_mode); array_set(array, "pmode", make_const_string(pmode, strlen(pmode), & tmp)); /* for symbolic links, add a linkval field */ - if (S_ISLNK(sbuf.st_mode)) { + if (S_ISLNK(sbuf->st_mode)) { char *buf; ssize_t linksize; - if ((buf = read_symlink(name, sbuf.st_size, + if ((buf = read_symlink(name, sbuf->st_size, & linksize)) != NULL) array_set(array, "linkval", make_malloced_string(buf, linksize, & tmp)); else @@ -319,7 +323,7 @@ fill_stat_array(const char *name, awk_array_t array) /* add a type field */ type = "unknown"; /* shouldn't happen */ for (j = 0, k = sizeof(ftype_map)/sizeof(ftype_map[0]); j < k; j++) { - if ((sbuf.st_mode & S_IFMT) == ftype_map[j].mask) { + if ((sbuf->st_mode & S_IFMT) == ftype_map[j].mask) { type = ftype_map[j].type; break; } @@ -339,6 +343,7 @@ do_stat(int nargs, awk_value_t *result) char *name; awk_array_t array; int ret; + struct stat sbuf; assert(result != NULL); @@ -357,14 +362,370 @@ do_stat(int nargs, awk_value_t *result) name = file_param.str_value.str; array = array_param.array_cookie; - ret = fill_stat_array(name, array); + /* lstat the file, if error, set ERRNO and return */ + ret = lstat(name, & sbuf); + if (ret < 0) { + update_ERRNO_int(errno); + return make_number(ret, result); + } + + ret = fill_stat_array(name, array, & sbuf); return make_number(ret, result); } +/* init_filefuncs --- initialization routine */ + +static awk_bool_t +init_filefuncs(void) +{ + int errors = 0; + + /* at least right now, only FTS needs initializing */ +#ifdef HAVE_FTS_ROUTINES + int i; + awk_value_t value; + + static struct flagtab { + const char *name; + int value; + } opentab[] = { +#define ENTRY(x) { #x, x } + ENTRY(FTS_COMFOLLOW), + ENTRY(FTS_LOGICAL), + ENTRY(FTS_NOCHDIR), + ENTRY(FTS_PHYSICAL), + ENTRY(FTS_SEEDOT), + ENTRY(FTS_XDEV), + { NULL, 0 } + }; + + for (i = 0; opentab[i].name != NULL; i++) { + (void) make_number(opentab[i].value, & value); + if (! sym_constant(opentab[i].name, & value)) { + warning(ext_id, "fts init: could not create constant %s", + opentab[i].name); + errors++; + } + } +#endif + return errors == 0; +} + +#ifdef HAVE_FTS_ROUTINES +static int fts_errors = 0; + +/* fill_stat_element --- fill in stat element of array */ + +static void +fill_stat_element(awk_array_t element_array, const char *name, struct stat *sbuf) +{ + awk_value_t index, value; + awk_array_t stat_array; + + stat_array = create_array(); + if (stat_array == NULL) { + warning(ext_id, _("fill_stat_element: could not create array")); + fts_errors++; + return; + } + fill_stat_array(name, stat_array, sbuf); + (void) make_const_string("stat", 4, & index); + value.val_type = AWK_ARRAY; + value.array_cookie = stat_array; + if (! set_array_element(element_array, & index, & value)) { + warning(ext_id, _("fill_stat_element: could not set element")); + fts_errors++; + } +} + +/* fill_path_element --- fill in path element of array */ + +static void +fill_path_element(awk_array_t element_array, const char *path) +{ + awk_value_t index, value; + + (void) make_const_string("path", 4, & index); + (void) make_const_string(path, strlen(path), & value); + if (! set_array_element(element_array, & index, & value)) { + warning(ext_id, _("fill_path_element: could not set element")); + fts_errors++; + } +} + +/* fill_error_element --- fill in error element of array */ + +static void +fill_error_element(awk_array_t element_array, const int errcode) +{ + awk_value_t index, value; + const char *err = strerror(errcode); + + (void) make_const_string("error", 5, & index); + (void) make_const_string(err, strlen(err), & value); + if (! set_array_element(element_array, & index, & value)) { + warning(ext_id, _("fill_error_element: could not set element")); + fts_errors++; + } +} + +/* fill_default_elements --- fill in stat and path elements */ + +static void +fill_default_elements(awk_array_t element_array, const FTSENT *const fentry, int bad_ret) +{ + /* full path */ + fill_path_element(element_array, fentry->fts_path); + + /* stat info */ + if (! bad_ret) { + fill_stat_element(element_array, + fentry->fts_name, + fentry->fts_statp); + } + + /* error info */ + if (bad_ret || fentry->fts_errno != 0) { + fill_error_element(element_array, fentry->fts_errno); + } +} + +/* process --- process the heirarchy */ + +static void +process(FTS *heirarchy, awk_array_t destarray, int seedot) +{ + FTSENT *fentry; + awk_value_t index, value; + awk_array_t element_array, newdir_array, dot_array; + int bad_ret = 0; + + /* path is full path, pathlen is length thereof */ + /* name is name in directory, namelen is length thereof */ + while ((fentry = fts_read(heirarchy)) != NULL) { + bad_ret = 0; + + switch (fentry->fts_info) { + case FTS_D: + /* directory */ + /* create array to hold entries */ + newdir_array = create_array(); + if (newdir_array == NULL) { + warning(ext_id, _("fts-process: could not create array")); + fts_errors++; + break; + } + + /* store new directory in its parent directory */ + (void) make_const_string(fentry->fts_name, fentry->fts_namelen, & index); + value.val_type = AWK_ARRAY; + value.array_cookie = newdir_array; + if (! set_array_element(destarray, & index, & value)) { + warning(ext_id, _("fts-process: could not set element")); + fts_errors++; + break; + } + newdir_array = value.array_cookie; + + /* push current directory */ + stack_push(destarray); + + /* new directory becomes current */ + destarray = newdir_array; + break; + + case FTS_DNR: + case FTS_DC: + case FTS_ERR: + case FTS_NS: + /* error */ + bad_ret = 1; + /* fall through */ + + case FTS_NSOK: + case FTS_SL: + case FTS_SLNONE: + case FTS_F: + case FTS_DOT: + /* if see dot, skip "." */ + if (seedot && strcmp(fentry->fts_name, ".") == 0) + break; + + /* + * File case. + * destarray is the directory we're reading. + * step 1: create new empty array + */ + element_array = create_array(); + if (element_array == NULL) { + warning(ext_id, _("fts-process: could not create array")); + fts_errors++; + break; + } + + /* step 2: add element array to parent array */ + (void) make_const_string(fentry->fts_name, fentry->fts_namelen, & index); + value.val_type = AWK_ARRAY; + value.array_cookie = element_array; + if (! set_array_element(destarray, & index, & value)) { + warning(ext_id, _("fts-process: could not set element")); + fts_errors++; + break; + } + + /* step 3: fill in path, stat, error elements */ + fill_default_elements(element_array, fentry, bad_ret); + break; + + case FTS_DP: + /* create "." subarray */ + dot_array = create_array(); + + /* add it to parent */ + (void) make_const_string(".", 1, & index); + value.val_type = AWK_ARRAY; + value.array_cookie = dot_array; + if (! set_array_element(destarray, & index, & value)) { + warning(ext_id, _("fts-process: could not set element")); + fts_errors++; + break; + } + + /* fill it in with path, stat, error elements */ + fill_default_elements(dot_array, fentry, bad_ret); + + /* now pop the parent directory off the stack */ + if (! stack_empty()) { + /* pop stack */ + destarray = stack_pop(); + } + + break; + + case FTS_DEFAULT: + /* nothing to do */ + break; + } + } +} +#endif + +/* do_fts --- walk a heirarchy and fill in an array */ + +/* + * Usage from awk: + * flags = or(FTS_PHYSICAL, ...) + * result = fts(pathlist, flags, filedata) + */ + +static awk_value_t * +do_fts(int nargs, awk_value_t *result) +{ +#ifdef HAVE_FTS_ROUTINES + awk_value_t pathlist, flagval, dest; + awk_flat_array_t *path_array = NULL; + char **pathvector = NULL; + FTS *heirarchy; + int flags; + size_t i, count; + int ret = -1; + static const int mask = ( + FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR | FTS_PHYSICAL + | FTS_SEEDOT | FTS_XDEV); + + assert(result != NULL); + fts_errors = 0; /* ensure a fresh start */ + + if (do_lint && nargs != 3) + lintwarn(ext_id, _("fts: called with incorrect number of arguments, expecting 3")); + + if (! get_argument(0, AWK_ARRAY, & pathlist)) { + warning(ext_id, _("fts: bad first parameter")); + update_ERRNO_int(EINVAL); + goto out; + } + + if (! get_argument(1, AWK_NUMBER, & flagval)) { + warning(ext_id, _("fts: bad second parameter")); + update_ERRNO_int(EINVAL); + goto out; + } + + if (! get_argument(2, AWK_ARRAY, & dest)) { + warning(ext_id, _("fts: bad third parameter")); + update_ERRNO_int(EINVAL); + goto out; + } + + /* flatten pathlist */ + if (! flatten_array(pathlist.array_cookie, & path_array)) { + warning(ext_id, _("fts: could not flatten array\n")); + goto out; + } + + /* check the flags first, before the array flattening */ + + /* get flags */ + flags = flagval.num_value; + + /* enforce physical or logical but not both, and not no_stat */ + if ((flags & (FTS_PHYSICAL|FTS_LOGICAL)) == 0 + || (flags & (FTS_PHYSICAL|FTS_LOGICAL)) == (FTS_PHYSICAL|FTS_LOGICAL)) { + update_ERRNO_int(EINVAL); + goto out; + } + if ((flags & FTS_NOSTAT) != 0) { + flags &= ~FTS_NOSTAT; + if (do_lint) + lintwarn(ext_id, _("fts: ignoring sneaky FTS_NOSTAT flag. nyah, nyah, nyah.")); + } + flags &= mask; /* turn off anything else */ + + /* make pathvector */ + count = path_array->count + 1; + emalloc(pathvector, char **, count * sizeof(char *), "do_fts"); + memset(pathvector, 0, count * sizeof(char *)); + + /* fill it in */ + count--; /* ignore final NULL at end of vector */ + for (i = 0; i < count; i++) + pathvector[i] = path_array->elements[i].value.str_value.str; + + + /* clear dest array */ + if (! clear_array(dest.array_cookie)) { + warning(ext_id, _("fts: clear_array failed\n")); + goto out; + } + + /* let's do it! */ + if ((heirarchy = fts_open(pathvector, flags, NULL)) != NULL) { + process(heirarchy, dest.array_cookie, (flags & FTS_SEEDOT) != 0); + fts_close(heirarchy); + + if (fts_errors == 0) + ret = 0; + } else + update_ERRNO_int(errno); + +out: + if (pathvector != NULL) + free(pathvector); + if (path_array != NULL) + (void) release_flattened_array(pathlist.array_cookie, path_array); + + return make_number(ret, result); +#else + update_ERRNO_int(EINVAL); + return make_number(-1, result); +#endif +} + static awk_ext_func_t func_table[] = { - { "chdir", do_chdir, 1 }, - { "stat", do_stat, 2 }, + { "chdir", do_chdir, 1 }, + { "stat", do_stat, 2 }, + { "fts", do_fts, 3 }, }; -- cgit v1.2.3 From 759f2234c9bfa689151277fd2215bc0927cfc9c3 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 24 Aug 2012 13:40:22 +0300 Subject: Add facility to get vesion info from extensions. --- extension/filefuncs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index e27e51bf..9f498706 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -61,6 +61,7 @@ static const gawk_api_t *api; /* for convenience macros to work */ static awk_ext_id_t *ext_id; static awk_bool_t init_filefuncs(void); static awk_bool_t (*init_func)(void) = init_filefuncs; +static const char *ext_version = "filefuncs extension: version 1.0"; int plugin_is_GPL_compatible; -- cgit v1.2.3 From 0b4ff99fec136012af7a54f179bdf601e55e6274 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 26 Aug 2012 21:52:12 +0300 Subject: Use config.h properly. Add AC_SYS_LARGEFILE. --- extension/filefuncs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 9f498706..89eaffc7 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -30,6 +30,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -40,7 +44,6 @@ #include #include -#include "config.h" #include "gawkapi.h" #include "gettext.h" -- cgit v1.2.3 From 17edae8fbae125b54e85c2be94f198f228465f81 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 29 Aug 2012 22:38:15 +0300 Subject: More wonderful portability stuff in the extensions. --- extension/filefuncs.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 89eaffc7..bc2f2afc 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -50,15 +50,8 @@ #define _(msgid) gettext(msgid) #define N_(msgid) msgid -#if defined(HAVE_FTS_H) && defined(HAVE_FTS_OPEN) && defined(HAVE_FTS_READ) -#define HAVE_FTS_ROUTINES -#endif - - -#ifdef HAVE_FTS_ROUTINES -#include +#include "gawkfts.h" #include "stack.h" -#endif static const gawk_api_t *api; /* for convenience macros to work */ static awk_ext_id_t *ext_id; @@ -384,12 +377,10 @@ static awk_bool_t init_filefuncs(void) { int errors = 0; - - /* at least right now, only FTS needs initializing */ -#ifdef HAVE_FTS_ROUTINES int i; awk_value_t value; + /* at least right now, only FTS needs initializing */ static struct flagtab { const char *name; int value; @@ -412,11 +403,9 @@ init_filefuncs(void) errors++; } } -#endif return errors == 0; } -#ifdef HAVE_FTS_ROUTINES static int fts_errors = 0; /* fill_stat_element --- fill in stat element of array */ @@ -613,7 +602,6 @@ process(FTS *heirarchy, awk_array_t destarray, int seedot) } } } -#endif /* do_fts --- walk a heirarchy and fill in an array */ @@ -626,7 +614,6 @@ process(FTS *heirarchy, awk_array_t destarray, int seedot) static awk_value_t * do_fts(int nargs, awk_value_t *result) { -#ifdef HAVE_FTS_ROUTINES awk_value_t pathlist, flagval, dest; awk_flat_array_t *path_array = NULL; char **pathvector = NULL; @@ -720,10 +707,6 @@ out: (void) release_flattened_array(pathlist.array_cookie, path_array); return make_number(ret, result); -#else - update_ERRNO_int(EINVAL); - return make_number(-1, result); -#endif } static awk_ext_func_t func_table[] = { -- cgit v1.2.3 From d61172dcf8117f4d3092a186122e3c66c17c58ba Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 21 Oct 2012 21:42:19 +0200 Subject: Bug fix in do_stat(). --- extension/filefuncs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index bc2f2afc..f2479c50 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -359,6 +359,9 @@ do_stat(int nargs, awk_value_t *result) name = file_param.str_value.str; array = array_param.array_cookie; + /* always empty out the array */ + clear_array(array); + /* lstat the file, if error, set ERRNO and return */ ret = lstat(name, & sbuf); if (ret < 0) { -- cgit v1.2.3 From 4a267501525be3157b0d41e9030e9d4a9c7f5897 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Fri, 26 Oct 2012 12:47:21 +0200 Subject: API doc additions and related other edits. --- extension/filefuncs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index f2479c50..391ed11a 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -164,7 +164,7 @@ format_mode(unsigned long fmode) return outbuf; } -/* read_symlink -- read a symbolic link into an allocated buffer. +/* 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 GNU/Linux in the /proc filesystem, where the symbolic link @@ -314,7 +314,7 @@ fill_stat_array(const char *name, awk_array_t array, struct stat *sbuf) & linksize)) != NULL) array_set(array, "linkval", make_malloced_string(buf, linksize, & tmp)); else - warning(ext_id, "stat: unable to read symbolic link `%s'", name); + warning(ext_id, _("stat: unable to read symbolic link `%s'"), name); } /* add a type field */ @@ -401,7 +401,7 @@ init_filefuncs(void) for (i = 0; opentab[i].name != NULL; i++) { (void) make_number(opentab[i].value, & value); if (! sym_constant(opentab[i].name, & value)) { - warning(ext_id, "fts init: could not create constant %s", + warning(ext_id, _("fts init: could not create constant %s"), opentab[i].name); errors++; } @@ -689,7 +689,7 @@ do_fts(int nargs, awk_value_t *result) /* clear dest array */ if (! clear_array(dest.array_cookie)) { - warning(ext_id, _("fts: clear_array failed\n")); + warning(ext_id, _("fts: clear_array() failed\n")); goto out; } -- cgit v1.2.3 From 391c19511eda50484a80827694f4555127cca1c8 Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Wed, 21 Nov 2012 20:57:49 +0200 Subject: Add 3rd argument to stat() extension. --- extension/filefuncs.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'extension/filefuncs.c') diff --git a/extension/filefuncs.c b/extension/filefuncs.c index 391ed11a..c8ef0534 100644 --- a/extension/filefuncs.c +++ b/extension/filefuncs.c @@ -341,11 +341,13 @@ do_stat(int nargs, awk_value_t *result) awk_array_t array; int ret; struct stat sbuf; + int (*statfunc)(const char *path, struct stat *sbuf) = lstat; /* default */ assert(result != NULL); - if (do_lint && nargs != 2) { - lintwarn(ext_id, _("stat: called with wrong number of arguments")); + if (nargs != 2 && nargs != 3) { + if (do_lint) + lintwarn(ext_id, _("stat: called with wrong number of arguments")); return make_number(-1, result); } @@ -355,6 +357,10 @@ do_stat(int nargs, awk_value_t *result) warning(ext_id, _("stat: bad parameters")); return make_number(-1, result); } + + if (nargs == 3) { + statfunc = stat; + } name = file_param.str_value.str; array = array_param.array_cookie; @@ -362,8 +368,8 @@ do_stat(int nargs, awk_value_t *result) /* always empty out the array */ clear_array(array); - /* lstat the file, if error, set ERRNO and return */ - ret = lstat(name, & sbuf); + /* stat the file, if error, set ERRNO and return */ + ret = statfunc(name, & sbuf); if (ret < 0) { update_ERRNO_int(errno); return make_number(ret, result); -- cgit v1.2.3