summaryrefslogtreecommitdiff
path: root/package/heirloom-cpio/src/oblok.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/heirloom-cpio/src/oblok.c')
-rw-r--r--package/heirloom-cpio/src/oblok.c260
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;
+}