diff options
Diffstat (limited to 'extension/filefuncs.c')
-rw-r--r-- | extension/filefuncs.c | 187 |
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)); |