From 5845dd65e0039ae771a82338edb41579e55e8f69 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 7 Nov 2004 23:44:38 +0000 Subject: [PATCH] The last commit created a memory leak because 'buf' is static. Fix that, but also make the chosen block size more consistent by basing on the larger of STDOUT vs rfd rather then just basing it on STDOUT, and change the constant 1024 to BUFSIZ. It is unclear whether we should impose a minimum buffer size or a mod (e.g. x % st_blksize == 0) requirement as well. There are currently no cases where this matters as anyone in their right mind will use 'dd' instead of 'cat' on special block devices. But at least in regards to /proc/*/map imposing a minimum based on fstat(rfd, ...) makes sense, though to really be correct we should also 'fix' procfs to report a block size sufficient to hold the map data in that case. Reported-by: Jason Smethers --- bin/cat/cat.c | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/bin/cat/cat.c b/bin/cat/cat.c index bcf69c35e2..ec22577b48 100644 --- a/bin/cat/cat.c +++ b/bin/cat/cat.c @@ -36,7 +36,7 @@ * @(#) Copyright (c) 1989, 1993 The Regents of the University of California. All rights reserved. * @(#)cat.c 8.2 (Berkeley) 4/27/95 * $FreeBSD: src/bin/cat/cat.c,v 1.14.2.8 2002/06/29 05:09:26 tjr Exp $ - * $DragonFly: src/bin/cat/cat.c,v 1.12 2004/11/04 21:31:37 liamfoy Exp $ + * $DragonFly: src/bin/cat/cat.c,v 1.13 2004/11/07 23:44:38 dillon Exp $ */ #include @@ -239,21 +239,43 @@ static void raw_cat(int rfd) { int off; - ssize_t nr, nw; + size_t nbsize; + ssize_t nr; + ssize_t nw; + struct stat rst; + static struct stat ost; static size_t bsize; - static char *buf = NULL; - struct stat sbuf; + static char *buf; - if (fstat(STDOUT_FILENO, &sbuf)) + /* + * Figure out the block size to use. Use the larger of stdout vs + * the passed descriptor. The minimum blocksize we use is BUFSIZ. + */ + if (ost.st_blksize == 0) { + if (fstat(STDOUT_FILENO, &ost)) + err(1, ""); + if (ost.st_blksize < BUFSIZ) + ost.st_blksize = BUFSIZ; + } + /* + * note: rst.st_blksize can be 0, but it is handled ok. + */ + if (fstat(rfd, &rst)) err(1, "%s", filename); - bsize = MAX(sbuf.st_blksize, 1024); - if ((buf = malloc(bsize)) == NULL) - err(1, "malloc failed"); - while ((nr = read(rfd, buf, bsize)) > 0) - for (off = 0; nr; nr -= nw, off += nw) - if ((nw = write(STDOUT_FILENO, buf + off, (size_t)nr)) < 0) + nbsize = MAX(ost.st_blksize, rst.st_blksize); + if (bsize != nbsize) { + bsize = nbsize; + if ((buf = realloc(buf, bsize)) == NULL) + err(1, "malloc failed"); + } + while ((nr = read(rfd, buf, bsize)) > 0) { + for (off = 0; nr; nr -= nw, off += nw) { + nw = write(STDOUT_FILENO, buf + off, nr); + if (nw < 0) err(1, "stdout"); + } + } if (nr < 0) { warn("%s", filename); rval = 1; -- 2.41.0