summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorkevans <kevans@FreeBSD.org>2018-01-18 21:59:13 +0000
committerkevans <kevans@FreeBSD.org>2018-01-18 21:59:13 +0000
commit95b8f69ef3baf8a9b45e0963cecac957b54eb93c (patch)
tree88c2cd02cfdee1164d4b8bc5dfdf591c470dad77 /usr.bin
parentcf061e9c775ef6885d6864aeb2c3fcb067c51002 (diff)
downloadFreeBSD-src-95b8f69ef3baf8a9b45e0963cecac957b54eb93c.zip
FreeBSD-src-95b8f69ef3baf8a9b45e0963cecac957b54eb93c.tar.gz
MFC r327567: hexdump(1): Speed up -s flag on devices
Using the -s flag on devices is extraordinarily slow due to using fseek(3) a little too conservatively. Address this by using fseek on character/block devices as well, falling back to getchar(3) only if we fail to seek or we're operating on tape drives, where fseek may succeed while not actually being supported. PR: 86485
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/hexdump/display.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/usr.bin/hexdump/display.c b/usr.bin/hexdump/display.c
index 36230aa..3b33f4d 100644
--- a/usr.bin/hexdump/display.c
+++ b/usr.bin/hexdump/display.c
@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)display.c 8.1 (Berkeley) 6/6/93";
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
#include <sys/stat.h>
#include <ctype.h>
@@ -52,6 +54,7 @@ static off_t address; /* address/offset in stream */
static off_t eaddress; /* end address */
static void print(PR *, u_char *);
+static void noseek(void);
void
display(void)
@@ -368,7 +371,7 @@ next(char **argv)
void
doskip(const char *fname, int statok)
{
- int cnt;
+ int type;
struct stat sb;
if (statok) {
@@ -380,16 +383,37 @@ doskip(const char *fname, int statok)
return;
}
}
- if (statok && S_ISREG(sb.st_mode)) {
- if (fseeko(stdin, skip, SEEK_SET))
+ if (!statok || S_ISFIFO(sb.st_mode) || S_ISSOCK(sb.st_mode)) {
+ noseek();
+ return;
+ }
+ if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ if (ioctl(fileno(stdin), FIODTYPE, &type))
err(1, "%s", fname);
- address += skip;
- skip = 0;
- } else {
- for (cnt = 0; cnt < skip; ++cnt)
- if (getchar() == EOF)
- break;
- address += cnt;
- skip -= cnt;
+ /*
+ * Most tape drives don't support seeking,
+ * yet fseek() would succeed.
+ */
+ if (type & D_TAPE) {
+ noseek();
+ return;
+ }
+ }
+ if (fseeko(stdin, skip, SEEK_SET)) {
+ noseek();
+ return;
}
+ address += skip;
+ skip = 0;
+}
+
+static void
+noseek(void)
+{
+ int count;
+ for (count = 0; count < skip; ++count)
+ if (getchar() == EOF)
+ break;
+ address += count;
+ skip -= count;
}
OpenPOWER on IntegriCloud