diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2014-04-02 07:37:27 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2014-04-02 07:37:27 +0200 |
commit | 7236e468162b3af51c0acecad10fbef1838c06ad (patch) | |
tree | 9c8027cf769aaa7ef7f0a6330b34d7666238b920 /package/heirloom-cpio/src/oblok.c | |
parent | a691abc857458de0023f5e532feee866af0218ed (diff) | |
parent | 309f13ab6858e1c1639814e210a6c86380ca717b (diff) |
Merge branch 'master' of git+ssh://openadk.org/git/openadk
Diffstat (limited to 'package/heirloom-cpio/src/oblok.c')
-rw-r--r-- | package/heirloom-cpio/src/oblok.c | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/package/heirloom-cpio/src/oblok.c b/package/heirloom-cpio/src/oblok.c new file mode 100644 index 000000000..38859ba6d --- /dev/null +++ b/package/heirloom-cpio/src/oblok.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2003 Gunnar Ritter + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + */ +/* Sccsid @(#)oblok.c 1.7 (gritter) 7/16/04 */ + +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <malloc.h> + +#include "memalign.h" +#include "oblok.h" + +struct list { + struct list *l_nxt; + struct oblok *l_op; +}; + +static struct list *bloks; +static int exitset; + +int +ob_clear(void) +{ + struct list *lp; + int val = 0; + + for (lp = bloks; lp; lp = lp->l_nxt) { + if (ob_flush(lp->l_op) < 0) + val = -1; + else if (val >= 0) + val++; + } + return val; +} + +static void +add(struct oblok *op) +{ + struct list *lp, *lq; + + if ((lp = calloc(1, sizeof *lp)) != NULL) { + lp->l_nxt = NULL; + lp->l_op = op; + if (bloks) { + for (lq = bloks; lq->l_nxt; lq = lq->l_nxt); + lq->l_nxt = lp; + } else + bloks = lp; + if (exitset == 0) { + exitset = 1; + atexit((void (*)(void))ob_clear); + } + } +} + +static void +del(struct oblok *op) +{ + struct list *lp, *lq = NULL; + + if (bloks) { + for (lp = bloks; lp && lp->l_op != op; lp = lp->l_nxt) + lq = lp; + if (lp) { + if (lq) + lq->l_nxt = lp->l_nxt; + if (lp == bloks) + bloks = bloks->l_nxt; + free(lp); + } + } +} + +struct oblok * +ob_alloc(int fd, enum ob_mode bf) +{ + static long pagesize; + struct oblok *op; + + if (pagesize == 0) + if ((pagesize = sysconf(_SC_PAGESIZE)) < 0) + pagesize = 4096; + if ((op = memalign(pagesize, sizeof *op)) == NULL) + return NULL; + memset(op, 0, sizeof *op); + op->ob_fd = fd; + switch (bf) { + case OB_EBF: + op->ob_bf = isatty(fd) ? OB_LBF : OB_FBF; + break; + default: + op->ob_bf = bf; + } + add(op); + return op; +} + +ssize_t +ob_free(struct oblok *op) +{ + ssize_t wrt; + + wrt = ob_flush(op); + del(op); + free(op); + return wrt; +} + +static ssize_t +swrite(int fd, const char *data, size_t sz) +{ + ssize_t wo, wt = 0; + + do { + if ((wo = write(fd, data + wt, sz - wt)) < 0) { + if (errno == EINTR) + continue; + else + return wt; + } + wt += wo; + } while (wt < sz); + return sz; +} + +ssize_t +ob_write(struct oblok *op, const char *data, size_t sz) +{ + ssize_t wrt; + size_t di, isz; + + switch (op->ob_bf) { + case OB_NBF: + wrt = swrite(op->ob_fd, data, sz); + op->ob_wrt += wrt; + if (wrt != sz) { + op->ob_bf = OB_EBF; + writerr(op, sz, wrt>0?wrt:0); + return -1; + } + return wrt; + case OB_LBF: + case OB_FBF: + isz = sz; + while (op->ob_pos + sz > (OBLOK)) { + di = (OBLOK) - op->ob_pos; + sz -= di; + if (op->ob_pos > 0) { + memcpy(&op->ob_blk[op->ob_pos], data, di); + wrt = swrite(op->ob_fd, op->ob_blk, (OBLOK)); + } else + wrt = swrite(op->ob_fd, data, (OBLOK)); + op->ob_wrt += wrt; + if (wrt != (OBLOK)) { + op->ob_bf = OB_EBF; + writerr(op, (OBLOK), wrt>0?wrt:0); + return -1; + } + data += di; + op->ob_pos = 0; + } + if (op->ob_bf == OB_LBF) { + const char *cp; + + cp = data; + while (cp < &data[sz]) { + if (*cp == '\n') { + di = cp - data + 1; + sz -= di; + if (op->ob_pos > 0) { + memcpy(&op->ob_blk[op->ob_pos], + data, di); + wrt = swrite(op->ob_fd, + op->ob_blk, + op->ob_pos + di); + } else + wrt = swrite(op->ob_fd, + data, di); + op->ob_wrt += wrt; + if (wrt != op->ob_pos + di) { + op->ob_bf = OB_EBF; + writerr(op, di, wrt>0?wrt:0); + return -1; + } + op->ob_pos = 0; + data += di; + cp = data; + } + cp++; + } + } + if (sz == (OBLOK)) { + wrt = swrite(op->ob_fd, data, sz); + op->ob_wrt += wrt; + if (wrt != sz) { + op->ob_bf = OB_EBF; + writerr(op, sz, wrt>0?wrt:0); + return -1; + } + } else if (sz) { + memcpy(&op->ob_blk[op->ob_pos], data, sz); + op->ob_pos += sz; + } + return isz; + case OB_EBF: + ; + } + return -1; +} + +ssize_t +ob_flush(struct oblok *op) +{ + ssize_t wrt = 0; + + if (op->ob_pos) { + wrt = swrite(op->ob_fd, op->ob_blk, op->ob_pos); + op->ob_wrt += wrt; + if (wrt != op->ob_pos) { + op->ob_bf = OB_EBF; + writerr(op, op->ob_pos, wrt>0?wrt:0); + wrt = -1; + } + op->ob_pos = 0; + } + return wrt; +} + +int +ob_chr(int c, struct oblok *op) +{ + char b; + ssize_t wrt; + + b = (char)c; + wrt = ob_write(op, &b, 1); + return wrt < 0 ? EOF : c; +} |