File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / bufio.c
Revision 1.3: download - view: text, annotated - select for diffs - revision graph
Thu Mar 15 01:52:23 2012 UTC (12 years, 3 months ago) by misho
Branches: MAIN
CVS tags: io2_5, IO2_4, HEAD
release version 2.4

    1: /*************************************************************************
    2: * (C) 2011 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
    3: *  by Michael Pounov <misho@elwix.org>
    4: *
    5: * $Author: misho $
    6: * $Id: bufio.c,v 1.3 2012/03/15 01:52:23 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: 
   48: 
   49: static void
   50: unmap_cf(struct tagBufIO *buf)
   51: {
   52: 	if (buf)
   53: 		munmap(buf->buf_base, buf->buf_size);
   54: }
   55: 
   56: static int
   57: cf_(struct tagBufIO *buf)
   58: {
   59: 	if (!buf) {
   60: 		io_SetErr(EINVAL, "Invalid arguments ...");
   61: 		return -1;
   62: 	}
   63: 
   64: 	if (buf->buf_mode == BUFIO_MODE_INFINIT)
   65: 		free(buf->buf_base);
   66: 	else if (buf->buf_unmap)
   67: 		buf->buf_unmap(buf);
   68: 
   69: 	free(buf);
   70: 	return 0;
   71: }
   72: 
   73: static fpos_t
   74: sf_lim(struct tagBufIO *buf, fpos_t pos, int w)
   75: {
   76: 	if (!buf)
   77: 		goto err;
   78: 
   79: 	switch (w) {
   80: 		case SEEK_SET:
   81: 			if (buf->buf_size < pos || pos < 0)
   82: 				goto err;
   83: 			buf->buf_offset = pos;
   84: 			break;
   85: 		case SEEK_CUR:
   86: 			if (buf->buf_size < (buf->buf_offset + pos) || (buf->buf_offset + pos) < 0)
   87: 				goto err;
   88: 			buf->buf_offset += pos;
   89: 			break;
   90: 		case SEEK_END:
   91: 			if (buf->buf_size < (buf->buf_size + pos) || (buf->buf_size + pos) < 0)
   92: 				goto err;
   93: 			buf->buf_offset = buf->buf_size + pos;
   94: 			break;
   95: 		default:
   96: 			goto err;
   97: 	}
   98: 
   99: 	return buf->buf_offset;
  100: err:
  101: 	io_SetErr(EINVAL, "Invalid arguments ...");
  102: 	return -1;
  103: }
  104: 
  105: static int
  106: rf_lim(struct tagBufIO *buf, char *dat, int siz)
  107: {
  108: 	if (!buf || !dat) {
  109: 		io_SetErr(EINVAL, "Invalid arguments ...");
  110: 		return -1;
  111: 	}
  112: 
  113: 	if (buf->buf_offset + siz > buf->buf_size)
  114: 		siz = buf->buf_size - buf->buf_offset;
  115: 
  116: 	memcpy(dat, buf->buf_base + buf->buf_offset, siz);
  117: 	buf->buf_offset += siz;
  118: 	return siz;
  119: }
  120: 
  121: static int
  122: wf_lim(struct tagBufIO *buf, const char *dat, int siz)
  123: {
  124: 	if (!buf || !dat) {
  125: 		io_SetErr(EINVAL, "Invalid arguments ...");
  126: 		return -1;
  127: 	}
  128: 
  129: 	if (buf->buf_offset + siz > buf->buf_size)
  130: 		siz = buf->buf_size - buf->buf_offset;
  131: 
  132: 	memcpy(buf->buf_base + buf->buf_offset, dat, siz);
  133: 	buf->buf_offset += siz;
  134: 	return siz;
  135: }
  136: 
  137: static fpos_t
  138: sf_inf(struct tagBufIO *buf, fpos_t pos, int w)
  139: {
  140: 	void *b;
  141: 
  142: 	if (!buf)
  143: 		goto err;
  144: 
  145: 	switch (w) {
  146: 		case SEEK_SET:
  147: 			if (pos < 0)
  148: 				goto err;
  149: 			if (buf->buf_size < pos) {
  150: 				b = realloc(buf->buf_base, pos);
  151: 				if (!b) {
  152: 					LOGERR;
  153: 					return -1;
  154: 				} else {
  155: 					buf->buf_base = b;
  156: 					memset(buf->buf_base + buf->buf_size, 0, pos - buf->buf_size);
  157: 					buf->buf_size = pos;
  158: 				}
  159: 			}
  160: 			buf->buf_offset = pos;
  161: 			break;
  162: 		case SEEK_CUR:
  163: 			if ((buf->buf_offset + pos) < 0)
  164: 				goto err;
  165: 			if (buf->buf_size < (buf->buf_offset + pos)) {
  166: 				b = realloc(buf->buf_base, buf->buf_offset + pos);
  167: 				if (!b) {
  168: 					LOGERR;
  169: 					return -1;
  170: 				} else {
  171: 					buf->buf_base = b;
  172: 					memset(buf->buf_base + buf->buf_size, 0, 
  173: 							buf->buf_offset + pos - buf->buf_size);
  174: 					buf->buf_size = buf->buf_offset + pos;
  175: 				}
  176: 			}
  177: 			buf->buf_offset += pos;
  178: 			break;
  179: 		case SEEK_END:
  180: 			if ((buf->buf_size + pos) < 0)
  181: 				goto err;
  182: 			if (buf->buf_size < (buf->buf_size + pos)) {
  183: 				b = realloc(buf->buf_base, buf->buf_size + pos);
  184: 				if (!b) {
  185: 					LOGERR;
  186: 					return -1;
  187: 				} else {
  188: 					buf->buf_base = b;
  189: 					memset(buf->buf_base + buf->buf_size, 0, pos);
  190: 					buf->buf_size += pos;
  191: 					buf->buf_offset = buf->buf_size;
  192: 				}
  193: 			} else
  194: 				buf->buf_offset = buf->buf_size + pos;
  195: 			break;
  196: 		default:
  197: 			goto err;
  198: 	}
  199: 
  200: 	return buf->buf_offset;
  201: err:
  202: 	io_SetErr(EINVAL, "Invalid arguments ...");
  203: 	return -1;
  204: }
  205: 
  206: static int
  207: wf_inf(struct tagBufIO *buf, const char *dat, int siz)
  208: {
  209: 	void *b;
  210: 
  211: 	if (!buf || !dat) {
  212: 		io_SetErr(EINVAL, "Invalid arguments ...");
  213: 		return -1;
  214: 	}
  215: 
  216: 	if (buf->buf_offset + siz > buf->buf_size) {
  217: 		b = realloc(buf->buf_base, buf->buf_offset + siz);
  218: 		if (!b) {
  219: 			LOGERR;
  220: 			return -1;
  221: 		} else {
  222: 			buf->buf_base = b;
  223: 			memset(buf->buf_base + buf->buf_size, 0, 
  224: 					buf->buf_offset + siz - buf->buf_size);
  225: 			buf->buf_size = buf->buf_offset + siz;
  226: 		}
  227: 	}
  228: 
  229: 	memcpy(buf->buf_base + buf->buf_offset, dat, siz);
  230: 	buf->buf_offset += siz;
  231: 	return siz;
  232: }
  233: 
  234: 
  235: /*
  236:  * io_fmemopen() File buffered stream operations over memory block
  237:  *
  238:  * @base = Base address of memory block, if =NULL Infinit length(auto-grow)
  239:  * @basesize = Size of memory block
  240:  * return: NULL error or !=NULL Opened file resource
  241:  */
  242: FILE *
  243: io_fmemopen(void ** __restrict base, off_t basesize)
  244: {
  245: 	FILE *f = NULL;
  246: 	struct tagBufIO *buf;
  247: 
  248: 	if (!base) {
  249: 		io_SetErr(EINVAL, "Invalid base argument ...");
  250: 		return NULL;
  251: 	}
  252: 
  253: 	buf = malloc(sizeof(struct tagBufIO));
  254: 	if (!buf) {
  255: 		LOGERR;
  256: 		return NULL;
  257: 	} else
  258: 		memset(buf, 0, sizeof(struct tagBufIO));
  259: 
  260: 	if (!*base) {
  261: 		*base = malloc(basesize);
  262: 		if (!*base) {
  263: 			LOGERR;
  264: 			free(buf);
  265: 			return NULL;
  266: 		} else
  267: 			memset(*base, 0, basesize);
  268: 
  269: 		buf->buf_mode = BUFIO_MODE_INFINIT;
  270: 	} else
  271: 		buf->buf_mode = BUFIO_MODE_LIMIT;
  272: 
  273: 	buf->buf_base = *base;
  274: 	buf->buf_size = basesize;
  275: 
  276: 	if (buf->buf_mode == BUFIO_MODE_INFINIT)
  277: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  278: 				(int (*)(void *, char const *, int)) wf_inf, 
  279: 				(fpos_t (*)(void *, fpos_t, int)) sf_inf, 
  280: 				(int (*)(void *)) cf_);
  281: 	else
  282: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  283: 				(int (*)(void *, char const *, int)) wf_lim, 
  284: 				(fpos_t (*)(void *, fpos_t, int)) sf_lim, 
  285: 				(int (*)(void *)) cf_);
  286: 	if (!f) {
  287: 		LOGERR;
  288: 		if (buf->buf_mode == BUFIO_MODE_INFINIT) {
  289: 			free(*base);
  290: 			*base = NULL;
  291: 		}
  292: 		free(buf);
  293: 		return NULL;
  294: 	}
  295: 
  296: 	return f;
  297: }
  298: 
  299: /*
  300:  * io_fmapopen() File buffered stream operations over MMAP block
  301:  *
  302:  * @csFile = Filename for MMAP, if =NULL private MMAP block
  303:  * @mode = File open mode
  304:  * @perm = If file not exists will be created with this access permissions
  305:  * @prot = MMAP protection
  306:  * @flags = MMAP mode flags
  307:  * @offset = Map from file offset, if csFile==NULL then this is size of MMAP private block
  308:  * return: NULL error or !=NULL Opened file resource
  309:  */
  310: FILE *
  311: io_fmapopen(const char *csFile, int mode, int perm, int prot, int flags, off_t offset)
  312: {
  313: 	FILE *f;
  314: 	struct tagBufIO *buf;
  315: 	void *base;
  316: 	off_t basesize;
  317: 	int fd = -1;
  318: 
  319: 	if (csFile) {
  320: 		fd = open(csFile, mode, perm);
  321: 		if (fd == -1) {
  322: 			LOGERR;
  323: 			return NULL;
  324: 		}
  325: 		basesize = lseek(fd, 0, SEEK_END);
  326: 		if (basesize == -1) {
  327: 			LOGERR;
  328: 			close(fd);
  329: 			return NULL;
  330: 		} else
  331: 			lseek(fd, 0, SEEK_SET);
  332: 
  333: 		base = mmap(NULL, basesize, prot, flags | MAP_FILE, fd, offset);
  334: 		if (base == MAP_FAILED) {
  335: 			LOGERR;
  336: 			close(fd);
  337: 			return NULL;
  338: 		} else
  339: 			close(fd);
  340: 	} else if (offset) {
  341: 		basesize = offset;
  342: 		base = mmap(NULL, basesize, prot, MAP_ANON, -1, 0);
  343: 		if (base == MAP_FAILED) {
  344: 			LOGERR;
  345: 			return NULL;
  346: 		}
  347: 	} else {
  348: 		io_SetErr(EINVAL, "Invalid base argument ...");
  349: 		return NULL;
  350: 	}
  351: 
  352: 
  353: 	buf = malloc(sizeof(struct tagBufIO));
  354: 	if (!buf) {
  355: 		LOGERR;
  356: 		munmap(base, basesize);
  357: 		return NULL;
  358: 	} else
  359: 		memset(buf, 0, sizeof(struct tagBufIO));
  360: 
  361: 	buf->buf_mode = BUFIO_MODE_LIMIT;
  362: 	buf->buf_base = base;
  363: 	buf->buf_size = basesize;
  364: 	buf->buf_unmap = unmap_cf;
  365: 
  366: 	f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  367: 			(int (*)(void *, char const *, int)) wf_lim, 
  368: 			(fpos_t (*)(void *, fpos_t, int)) sf_lim, 
  369: 			(int (*)(void *)) cf_);
  370: 	if (!f) {
  371: 		LOGERR;
  372: 		free(buf);
  373: 		munmap(base, basesize);
  374: 		return NULL;
  375: 	}
  376: 
  377: 	return f;
  378: }
  379: 
  380: /*
  381:  * io_dumbFile() Create empry or dumb file with fixed size
  382:  *
  383:  * @csFile = Filename for create
  384:  * @mode = File access permissions
  385:  * @size = File size
  386:  * return: -1 error or open file handle
  387:  */
  388: int
  389: io_dumbFile(const char *csFile, int mode, off_t size)
  390: {
  391: 	int fd;
  392: 
  393: 	fd = open(csFile, O_RDWR | O_CREAT, mode);
  394: 	if (fd == -1) {
  395: 		LOGERR;
  396: 		return -1;
  397: 	}
  398: 
  399: 	if (lseek(fd, size - 1, SEEK_SET) == -1)
  400: 		goto err;
  401: 	if (write(fd, "", 1) != 1)
  402: 		goto err;
  403: 	else
  404: 		lseek(fd, 0, SEEK_SET);
  405: 
  406: 	return fd;
  407: err:
  408: 	LOGERR;
  409: 	close(fd);
  410: 	return -1;
  411: }
  412: 
  413: /*
  414:  * io_fd2buf() Convert open file handle to buffered file I/O
  415:  *
  416:  * @fd = File handle
  417:  * @mode = Permissions for new buffered file I/O
  418:  * return: NULL error or open buffered file
  419:  */
  420: inline FILE *
  421: io_fd2buf(int fd, const char *mode)
  422: {
  423: 	FILE *f;
  424: 
  425: 	f = fdopen(fd, mode);
  426: 	if (!f)
  427: 		LOGERR;
  428: 
  429: 	return f;
  430: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>