aboutsummaryrefslogtreecommitdiffstats
path: root/extension
diff options
context:
space:
mode:
Diffstat (limited to 'extension')
-rw-r--r--extension/ChangeLog6
-rw-r--r--extension/readdir.3am46
-rw-r--r--extension/readdir.c113
3 files changed, 25 insertions, 140 deletions
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 12cbfcba..f581eef3 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,9 @@
+2012-11-19 Arnold D. Robbins <arnold@skeeve.com>
+
+ * readdir.c: Simplify code to always print file type and not
+ use stat().
+ * readdir.3am: Document same.
+
2012-11-16 Arnold D. Robbins <arnold@skeeve.com>
* testext.c: In awk code, use printf(...) instead of the form
diff --git a/extension/readdir.3am b/extension/readdir.3am
index 9d60b054..297e24be 100644
--- a/extension/readdir.3am
+++ b/extension/readdir.3am
@@ -1,26 +1,22 @@
-.TH READDIR 3am "Sep 11 2012" "Free Software Foundation" "GNU Awk Extension Modules"
+.TH READDIR 3am "Nov 18 2012" "Free Software Foundation" "GNU Awk Extension Modules"
.SH NAME
readdir \- directory input parser for gawk
.SH SYNOPSIS
.ft CW
@load "readdir"
-.sp
-readdir_do_ftype("stat") # or "dirent" or "never"
.ft R
.SH DESCRIPTION
The
.I readdir
extension
-adds an input parser for directories, and
-adds a single function named
-.BR readdir_do_ftype() .
+adds an input parser for directories.
.PP
When this extension is in use, instead of skipping directories named
on the command line (or with
.BR getline ),
they are read, with each entry returned as a record.
.PP
-The record consists of at least two fields: the inode number and the
+The record consists of three fields. The first two are the inode number and the
filename, separated by a forward slash character.
On systems where the directory entry contains the file type, the record
has a third field which is a single letter indicating the type of the
@@ -42,28 +38,8 @@ for a socket, and
.B u
(unknown) for anything else.
.PP
-On systems without the file type information, calling
-.B readdir_do_ftype("stat")
-causes the extension to use
-.IR lstat (2)
-to retrieve the appropriate information. This is not the default, since
-.IR lstat (2)
-is a potentially expensive operation. By calling
-.B readdir_do_ftype("never")
-one can ensure that the file type
-information is never displayed, even when readily available in the
-directory entry.
-.PP
-The third option,
-.BR readdir_do_ftype("dirent") ,
-takes file type information from the directory entry, if it is available.
-This is the default on systems that supply this information.
-.PP
-The
-.B readdir_do_ftype()
-function will set
-.B ERRNO
-if called without arguments or with invalid arguments.
+On systems without the file type information, the third field is always
+.BR u .
.SH NOTES
On GNU/Linux systems, there are filesystems that don't support the
.B d_type
@@ -71,13 +47,11 @@ entry (see
.IR readdir (3)),
and so the file type is always
.BR u .
-Therefore, using
-.B readdir_do_ftype("stat")
-is advisable even on GNU/Linux systems. In this case, the
-.I readdir
-extension will fall back to using
-.IR lstat (2)
-when it encounters an unknown file type.
+You can use the
+.I filefuncs
+extension to call
+.I stat()
+in order to get correct type information.
... .SH BUGS
.SH EXAMPLE
.ft CW
diff --git a/extension/readdir.c b/extension/readdir.c
index de430194..05ac8b90 100644
--- a/extension/readdir.c
+++ b/extension/readdir.c
@@ -6,6 +6,7 @@
* Written 7/2012
*
* Andrew Schorr and Arnold Robbins: further fixes 8/2012.
+ * Simplified 11/2012.
*/
/*
@@ -64,34 +65,18 @@ static awk_bool_t (*init_func)(void) = init_readdir;
int plugin_is_GPL_compatible;
-enum {
- NEVER_DO_INFO,
- USE_DIRENT_INFO,
- USE_STAT_INFO
-} do_ftype =
-#ifdef DT_BLK
- USE_DIRENT_INFO
-#else
- NEVER_DO_INFO
-#endif
- ;
-
/* data type for the opaque pointer: */
typedef struct open_directory {
DIR *dp;
char *buf;
- const char *path; /* directory path */
- char *dbuf; /* buffer for <directory>/<name> needed for lstat */
} open_directory_t;
/* ftype --- return type of file as a single character string */
static const char *
-ftype(struct dirent *entry, open_directory_t *the_dir)
+ftype(struct dirent *entry)
{
- struct stat sbuf;
-
#ifdef DT_BLK
switch (entry->d_type) {
case DT_BLK: return "b";
@@ -102,48 +87,11 @@ ftype(struct dirent *entry, open_directory_t *the_dir)
case DT_REG: return "f";
case DT_SOCK: return "s";
default:
- case DT_UNKNOWN:
- /*
- * Could be that filesystem doesn't support d_type,
- * even if the OS does. (E.g., XFS on GNU/Linux).
- * So let lstat() do it.
- */
- break;
- }
-#endif
-
- if (do_ftype < USE_STAT_INFO)
- /*
- * Avoid "/u" since user did not insist on file type info,
- * and it does not seem to be supported by dirent on this
- * filesystem.
- */
- return NULL;
-
- /* Should we set ERRNO here? */
- sprintf(the_dir->dbuf, "%s/%s", the_dir->path, entry->d_name);
- if (lstat(the_dir->dbuf, & sbuf) < 0)
- return "u";
-
- switch (sbuf.st_mode & S_IFMT) {
- case S_IFREG: return "f";
- case S_IFBLK: return "b";
- case S_IFCHR: return "c";
- case S_IFDIR: return "d";
-#ifdef S_IFSOCK
- case S_IFSOCK: return "s";
-#endif
-#ifdef S_IFIFO
- case S_IFIFO: return "p";
-#endif
-#ifdef S_IFLNK
- case S_IFLNK: return "l";
-#endif
-#ifdef S_IFDOOR /* Solaris weirdness */
- case S_IFDOOR: return "D";
-#endif /* S_IFDOOR */
+ case DT_UNKNOWN: return "u";
}
+#else
return "u";
+#endif
}
/* dir_get_record --- get one record at a time out of a directory */
@@ -156,6 +104,7 @@ dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
struct dirent *dirent;
int len;
open_directory_t *the_dir;
+ const char *ftstr;
/*
* The caller sets *errcode to 0, so we should set it only if an
@@ -188,11 +137,8 @@ dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
dirent->d_name);
#endif
- if (do_ftype != NEVER_DO_INFO) {
- const char *ftstr = ftype(dirent, the_dir);
- if (ftstr)
- len += sprintf(the_dir->buf + len, "/%s", ftstr);
- }
+ ftstr = ftype(dirent);
+ len += sprintf(the_dir->buf + len, "/%s", ftstr);
*out = the_dir->buf;
@@ -214,7 +160,6 @@ dir_close(awk_input_buf_t *iobuf)
closedir(the_dir->dp);
free(the_dir->buf);
- free(the_dir->dbuf);
free(the_dir);
iobuf->fd = -1;
@@ -263,8 +208,6 @@ dir_take_control_of(awk_input_buf_t *iobuf)
the_dir->dp = dp;
size = sizeof(struct dirent) + 21 /* max digits in inode */ + 2 /* slashes */;
emalloc(the_dir->buf, char *, size, "dir_take_control_of");
- emalloc(the_dir->dbuf, char *, strlen(iobuf->name)+size+2, "dir_take_control_of");
- the_dir->path = iobuf->name;
iobuf->opaque = the_dir;
iobuf->get_record = dir_get_record;
@@ -302,46 +245,8 @@ init_readdir()
return 1;
}
-/* do_readdir_do_ftype --- enable / disable ftype where need to do stat */
-
-static awk_value_t *
-do_readdir_do_ftype(int nargs, awk_value_t *result)
-{
- awk_value_t flag;
-
- make_number(1.0, result);
- if (nargs < 1) {
- warning(ext_id, _("readdir_do_ftype: called with no arguments"));
- update_ERRNO_int(EINVAL);
- make_number(0.0, result);
- goto out;
- } else if (do_lint && nargs > 3)
- lintwarn(ext_id, _("readdir_do_ftype: called with more than one argument"));
-
- if (! get_argument(0, AWK_STRING, & flag)) {
- warning(ext_id, _("readdir_do_ftype: could not get argument"));
- update_ERRNO_int(EINVAL);
- make_number(0.0, result);
- goto out;
- }
-
- if (strcmp(flag.str_value.str, "never") == 0)
- do_ftype = NEVER_DO_INFO;
- else if (strcmp(flag.str_value.str, "dirent") == 0)
- do_ftype = USE_DIRENT_INFO;
- else if (strcmp(flag.str_value.str, "stat") == 0)
- do_ftype = USE_STAT_INFO;
- else {
- update_ERRNO_int(EINVAL);
- make_number(0.0, result);
- }
-
-out:
- return result;
-}
-
static awk_ext_func_t func_table[] = {
- { "readdir_do_ftype", do_readdir_do_ftype, 1 },
+ { NULL, NULL, 0 }
};
/* define the dl_load function using the boilerplate macro */