hbase

heirloom base
git clone git://git.2f30.org/hbase
Log | Files | Refs | README

oblok.c (4937B)


      1 /*
      2  * Copyright (c) 2003 Gunnar Ritter
      3  *
      4  * This software is provided 'as-is', without any express or implied
      5  * warranty. In no event will the authors be held liable for any damages
      6  * arising from the use of this software.
      7  *
      8  * Permission is granted to anyone to use this software for any purpose,
      9  * including commercial applications, and to alter it and redistribute
     10  * it freely, subject to the following restrictions:
     11  *
     12  * 1. The origin of this software must not be misrepresented; you must not
     13  *    claim that you wrote the original software. If you use this software
     14  *    in a product, an acknowledgment in the product documentation would be
     15  *    appreciated but is not required.
     16  *
     17  * 2. Altered source versions must be plainly marked as such, and must not be
     18  *    misrepresented as being the original software.
     19  *
     20  * 3. This notice may not be removed or altered from any source distribution.
     21  */
     22 /*	Sccsid @(#)oblok.c	1.7 (gritter) 7/16/04	*/
     23 
     24 #include	<sys/types.h>
     25 #include	<unistd.h>
     26 #include	<string.h>
     27 #include	<errno.h>
     28 #include	<stdio.h>
     29 #include	<stdlib.h>
     30 #include	<malloc.h>
     31 
     32 #include	"memalign.h"
     33 #include	"oblok.h"
     34 
     35 struct	list {
     36 	struct list	*l_nxt;
     37 	struct oblok	*l_op;
     38 };
     39 
     40 static struct list	*bloks;
     41 static int	exitset;
     42 
     43 int
     44 ob_clear(void)
     45 {
     46 	struct list	*lp;
     47 	int	val = 0;
     48 
     49 	for (lp = bloks; lp; lp = lp->l_nxt) {
     50 		if (ob_flush(lp->l_op) < 0)
     51 			val = -1;
     52 		else if (val >= 0)
     53 			val++;
     54 	}
     55 	return val;
     56 }
     57 
     58 static void
     59 add(struct oblok *op)
     60 {
     61 	struct list	*lp, *lq;
     62 
     63 	if ((lp = calloc(1, sizeof *lp)) != NULL) {
     64 		lp->l_nxt = NULL;
     65 		lp->l_op = op;
     66 		if (bloks) {
     67 			for (lq = bloks; lq->l_nxt; lq = lq->l_nxt);
     68 			lq->l_nxt = lp;
     69 		} else
     70 			bloks = lp;
     71 		if (exitset == 0) {
     72 			exitset = 1;
     73 			atexit((void (*)(void))ob_clear);
     74 		}
     75 	}
     76 }
     77 
     78 static void
     79 del(struct oblok *op)
     80 {
     81 	struct list	*lp, *lq = NULL;
     82 
     83 	if (bloks) {
     84 		for (lp = bloks; lp && lp->l_op != op; lp = lp->l_nxt)
     85 			lq = lp;
     86 		if (lp) {
     87 			if (lq)
     88 				lq->l_nxt = lp->l_nxt;
     89 			if (lp == bloks)
     90 				bloks = bloks->l_nxt;
     91 			free(lp);
     92 		}
     93 	}
     94 }
     95 
     96 struct oblok *
     97 ob_alloc(int fd, enum ob_mode bf)
     98 {
     99 	static long	pagesize;
    100 	struct oblok	*op;
    101 
    102 	if (pagesize == 0)
    103 		if ((pagesize = sysconf(_SC_PAGESIZE)) < 0)
    104 			pagesize = 4096;
    105 	if ((op = memalign(pagesize, sizeof *op)) == NULL)
    106 		return NULL;
    107 	memset(op, 0, sizeof *op);
    108 	op->ob_fd = fd;
    109 	switch (bf) {
    110 	case OB_EBF:
    111 		op->ob_bf = isatty(fd) ? OB_LBF : OB_FBF;
    112 		break;
    113 	default:
    114 		op->ob_bf = bf;
    115 	}
    116 	add(op);
    117 	return op;
    118 }
    119 
    120 ssize_t
    121 ob_free(struct oblok *op)
    122 {
    123 	ssize_t	wrt;
    124 
    125 	wrt = ob_flush(op);
    126 	del(op);
    127 	free(op);
    128 	return wrt;
    129 }
    130 
    131 static ssize_t
    132 swrite(int fd, const char *data, size_t sz)
    133 {
    134 	ssize_t	wo, wt = 0;
    135 
    136 	do {
    137 		if ((wo = write(fd, data + wt, sz - wt)) < 0) {
    138 			if (errno == EINTR)
    139 				continue;
    140 			else
    141 				return wt;
    142 		}
    143 		wt += wo;
    144 	} while (wt < sz);
    145 	return sz;
    146 }
    147 
    148 ssize_t
    149 ob_write(struct oblok *op, const char *data, size_t sz)
    150 {
    151 	ssize_t	wrt;
    152 	size_t	di, isz;
    153 
    154 	switch (op->ob_bf) {
    155 	case OB_NBF:
    156 		wrt = swrite(op->ob_fd, data, sz);
    157 		op->ob_wrt += wrt;
    158 		if (wrt != sz) {
    159 			op->ob_bf = OB_EBF;
    160 			writerr(op, sz, wrt>0?wrt:0);
    161 			return -1;
    162 		}
    163 		return wrt;
    164 	case OB_LBF:
    165 	case OB_FBF:
    166 		isz = sz;
    167 		while (op->ob_pos + sz > (OBLOK)) {
    168 			di = (OBLOK) - op->ob_pos;
    169 			sz -= di;
    170 			if (op->ob_pos > 0) {
    171 				memcpy(&op->ob_blk[op->ob_pos], data, di);
    172 				wrt = swrite(op->ob_fd, op->ob_blk, (OBLOK));
    173 			} else
    174 				wrt = swrite(op->ob_fd, data, (OBLOK));
    175 			op->ob_wrt += wrt;
    176 			if (wrt != (OBLOK)) {
    177 				op->ob_bf = OB_EBF;
    178 				writerr(op, (OBLOK), wrt>0?wrt:0);
    179 				return -1;
    180 			}
    181 			data += di;
    182 			op->ob_pos = 0;
    183 		}
    184 		if (op->ob_bf == OB_LBF) {
    185 			const char	*cp;
    186 
    187 			cp = data;
    188 			while (cp < &data[sz]) {
    189 				if (*cp == '\n') {
    190 					di = cp - data + 1;
    191 					sz -= di;
    192 					if (op->ob_pos > 0) {
    193 						memcpy(&op->ob_blk[op->ob_pos],
    194 								data, di);
    195 						wrt = swrite(op->ob_fd,
    196 							op->ob_blk,
    197 							op->ob_pos + di);
    198 					} else
    199 						wrt = swrite(op->ob_fd,
    200 							data, di);
    201 					op->ob_wrt += wrt;
    202 					if (wrt != op->ob_pos + di) {
    203 						op->ob_bf = OB_EBF;
    204 						writerr(op, di, wrt>0?wrt:0);
    205 						return -1;
    206 					}
    207 					op->ob_pos = 0;
    208 					data += di;
    209 					cp = data;
    210 				}
    211 				cp++;
    212 			}
    213 		}
    214 		if (sz == (OBLOK)) {
    215 			wrt = swrite(op->ob_fd, data, sz);
    216 			op->ob_wrt += wrt;
    217 			if (wrt != sz) {
    218 				op->ob_bf = OB_EBF;
    219 				writerr(op, sz, wrt>0?wrt:0);
    220 				return -1;
    221 			}
    222 		} else if (sz) {
    223 			memcpy(&op->ob_blk[op->ob_pos], data, sz);
    224 			op->ob_pos += sz;
    225 		}
    226 		return isz;
    227 	case OB_EBF:
    228 		;
    229 	}
    230 	return -1;
    231 }
    232 
    233 ssize_t
    234 ob_flush(struct oblok *op)
    235 {
    236 	ssize_t	wrt = 0;
    237 
    238 	if (op->ob_pos) {
    239 		wrt = swrite(op->ob_fd, op->ob_blk, op->ob_pos);
    240 		op->ob_wrt += wrt;
    241 		if (wrt != op->ob_pos) {
    242 			op->ob_bf = OB_EBF;
    243 			writerr(op, op->ob_pos, wrt>0?wrt:0);
    244 			wrt = -1;
    245 		}
    246 		op->ob_pos = 0;
    247 	}
    248 	return wrt;
    249 }
    250 
    251 int
    252 ob_chr(int c, struct oblok *op)
    253 {
    254 	char	b;
    255 	ssize_t	wrt;
    256 
    257 	b = (char)c;
    258 	wrt = ob_write(op, &b, 1);
    259 	return wrt < 0 ? EOF : c;
    260 }