aboutsummaryrefslogtreecommitdiffstats
path: root/extension/filefuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'extension/filefuncs.c')
-rw-r--r--extension/filefuncs.c187
1 files changed, 87 insertions, 100 deletions
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 <sys/types.h>
#include <sys/stat.h>
+
#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));