File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / bufio.c
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Thu Mar 29 01:31:34 2012 UTC (12 years, 3 months ago) by misho
Branches: MAIN
CVS tags: io2_6, IO2_5, HEAD
version 2.5

    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.4 2012/03/29 01:31:34 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: #ifdef __NetBSD__
   74: static off_t
   75: sf_lim(struct tagBufIO *buf, off_t pos, int w)
   76: #else
   77: static fpos_t
   78: sf_lim(struct tagBufIO *buf, fpos_t pos, int w)
   79: #endif
   80: {
   81: 	if (!buf)
   82: 		goto err;
   83: 
   84: 	switch (w) {
   85: 		case SEEK_SET:
   86: 			if (buf->buf_size < pos || pos < 0)
   87: 				goto err;
   88: 			buf->buf_offset = pos;
   89: 			break;
   90: 		case SEEK_CUR:
   91: 			if (buf->buf_size < (buf->buf_offset + pos) || (buf->buf_offset + pos) < 0)
   92: 				goto err;
   93: 			buf->buf_offset += pos;
   94: 			break;
   95: 		case SEEK_END:
   96: 			if (buf->buf_size < (buf->buf_size + pos) || (buf->buf_size + pos) < 0)
   97: 				goto err;
   98: 			buf->buf_offset = buf->buf_size + pos;
   99: 			break;
  100: 		default:
  101: 			goto err;
  102: 	}
  103: 
  104: 	return buf->buf_offset;
  105: err:
  106: 	io_SetErr(EINVAL, "Invalid arguments ...");
  107: 	return -1;
  108: }
  109: 
  110: static int
  111: rf_lim(struct tagBufIO *buf, char *dat, int siz)
  112: {
  113: 	if (!buf || !dat) {
  114: 		io_SetErr(EINVAL, "Invalid arguments ...");
  115: 		return -1;
  116: 	}
  117: 
  118: 	if (buf->buf_offset + siz > buf->buf_size)
  119: 		siz = buf->buf_size - buf->buf_offset;
  120: 
  121: 	memcpy(dat, buf->buf_base + buf->buf_offset, siz);
  122: 	buf->buf_offset += siz;
  123: 	return siz;
  124: }
  125: 
  126: static int
  127: wf_lim(struct tagBufIO *buf, const char *dat, int siz)
  128: {
  129: 	if (!buf || !dat) {
  130: 		io_SetErr(EINVAL, "Invalid arguments ...");
  131: 		return -1;
  132: 	}
  133: 
  134: 	if (buf->buf_offset + siz > buf->buf_size)
  135: 		siz = buf->buf_size - buf->buf_offset;
  136: 
  137: 	memcpy(buf->buf_base + buf->buf_offset, dat, siz);
  138: 	buf->buf_offset += siz;
  139: 	return siz;
  140: }
  141: 
  142: #ifdef __NetBSD__
  143: static off_t
  144: sf_inf(struct tagBufIO *buf, off_t pos, int w)
  145: #else
  146: static fpos_t
  147: sf_inf(struct tagBufIO *buf, fpos_t pos, int w)
  148: #endif
  149: {
  150: 	void *b;
  151: 
  152: 	if (!buf)
  153: 		goto err;
  154: 
  155: 	switch (w) {
  156: 		case SEEK_SET:
  157: 			if (pos < 0)
  158: 				goto err;
  159: 			if (buf->buf_size < pos) {
  160: 				b = realloc(buf->buf_base, pos);
  161: 				if (!b) {
  162: 					LOGERR;
  163: 					return -1;
  164: 				} else {
  165: 					buf->buf_base = b;
  166: 					memset(buf->buf_base + buf->buf_size, 0, pos - buf->buf_size);
  167: 					buf->buf_size = pos;
  168: 				}
  169: 			}
  170: 			buf->buf_offset = pos;
  171: 			break;
  172: 		case SEEK_CUR:
  173: 			if ((buf->buf_offset + pos) < 0)
  174: 				goto err;
  175: 			if (buf->buf_size < (buf->buf_offset + pos)) {
  176: 				b = realloc(buf->buf_base, buf->buf_offset + pos);
  177: 				if (!b) {
  178: 					LOGERR;
  179: 					return -1;
  180: 				} else {
  181: 					buf->buf_base = b;
  182: 					memset(buf->buf_base + buf->buf_size, 0, 
  183: 							buf->buf_offset + pos - buf->buf_size);
  184: 					buf->buf_size = buf->buf_offset + pos;
  185: 				}
  186: 			}
  187: 			buf->buf_offset += pos;
  188: 			break;
  189: 		case SEEK_END:
  190: 			if ((buf->buf_size + pos) < 0)
  191: 				goto err;
  192: 			if (buf->buf_size < (buf->buf_size + pos)) {
  193: 				b = realloc(buf->buf_base, buf->buf_size + pos);
  194: 				if (!b) {
  195: 					LOGERR;
  196: 					return -1;
  197: 				} else {
  198: 					buf->buf_base = b;
  199: 					memset(buf->buf_base + buf->buf_size, 0, pos);
  200: 					buf->buf_size += pos;
  201: 					buf->buf_offset = buf->buf_size;
  202: 				}
  203: 			} else
  204: 				buf->buf_offset = buf->buf_size + pos;
  205: 			break;
  206: 		default:
  207: 			goto err;
  208: 	}
  209: 
  210: 	return buf->buf_offset;
  211: err:
  212: 	io_SetErr(EINVAL, "Invalid arguments ...");
  213: 	return -1;
  214: }
  215: 
  216: static int
  217: wf_inf(struct tagBufIO *buf, const char *dat, int siz)
  218: {
  219: 	void *b;
  220: 
  221: 	if (!buf || !dat) {
  222: 		io_SetErr(EINVAL, "Invalid arguments ...");
  223: 		return -1;
  224: 	}
  225: 
  226: 	if (buf->buf_offset + siz > buf->buf_size) {
  227: 		b = realloc(buf->buf_base, buf->buf_offset + siz);
  228: 		if (!b) {
  229: 			LOGERR;
  230: 			return -1;
  231: 		} else {
  232: 			buf->buf_base = b;
  233: 			memset(buf->buf_base + buf->buf_size, 0, 
  234: 					buf->buf_offset + siz - buf->buf_size);
  235: 			buf->buf_size = buf->buf_offset + siz;
  236: 		}
  237: 	}
  238: 
  239: 	memcpy(buf->buf_base + buf->buf_offset, dat, siz);
  240: 	buf->buf_offset += siz;
  241: 	return siz;
  242: }
  243: 
  244: 
  245: /*
  246:  * io_fmemopen() File buffered stream operations over memory block
  247:  *
  248:  * @base = Base address of memory block, if =NULL Infinit length(auto-grow)
  249:  * @basesize = Size of memory block
  250:  * return: NULL error or !=NULL Opened file resource
  251:  */
  252: FILE *
  253: io_fmemopen(void ** __restrict base, off_t basesize)
  254: {
  255: 	FILE *f = NULL;
  256: 	struct tagBufIO *buf;
  257: 
  258: 	if (!base) {
  259: 		io_SetErr(EINVAL, "Invalid base argument ...");
  260: 		return NULL;
  261: 	}
  262: 
  263: 	buf = malloc(sizeof(struct tagBufIO));
  264: 	if (!buf) {
  265: 		LOGERR;
  266: 		return NULL;
  267: 	} else
  268: 		memset(buf, 0, sizeof(struct tagBufIO));
  269: 
  270: 	if (!*base) {
  271: 		*base = malloc(basesize);
  272: 		if (!*base) {
  273: 			LOGERR;
  274: 			free(buf);
  275: 			return NULL;
  276: 		} else
  277: 			memset(*base, 0, basesize);
  278: 
  279: 		buf->buf_mode = BUFIO_MODE_INFINIT;
  280: 	} else
  281: 		buf->buf_mode = BUFIO_MODE_LIMIT;
  282: 
  283: 	buf->buf_base = *base;
  284: 	buf->buf_size = basesize;
  285: 
  286: #ifdef __NetBSD__
  287: 	if (buf->buf_mode == BUFIO_MODE_INFINIT)
  288: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  289: 				(int (*)(void *, char const *, int)) wf_inf, 
  290: 				(off_t (*)(void *, off_t, int)) sf_inf, 
  291: 				(int (*)(void *)) cf_);
  292: 	else
  293: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  294: 				(int (*)(void *, char const *, int)) wf_lim, 
  295: 				(off_t (*)(void *, off_t, int)) sf_lim, 
  296: 				(int (*)(void *)) cf_);
  297: #else
  298: 	if (buf->buf_mode == BUFIO_MODE_INFINIT)
  299: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  300: 				(int (*)(void *, char const *, int)) wf_inf, 
  301: 				(fpos_t (*)(void *, fpos_t, int)) sf_inf, 
  302: 				(int (*)(void *)) cf_);
  303: 	else
  304: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  305: 				(int (*)(void *, char const *, int)) wf_lim, 
  306: 				(fpos_t (*)(void *, fpos_t, int)) sf_lim, 
  307: 				(int (*)(void *)) cf_);
  308: #endif
  309: 	if (!f) {
  310: 		LOGERR;
  311: 		if (buf->buf_mode == BUFIO_MODE_INFINIT) {
  312: 			free(*base);
  313: 			*base = NULL;
  314: 		}
  315: 		free(buf);
  316: 		return NULL;
  317: 	}
  318: 
  319: 	return f;
  320: }
  321: 
  322: /*
  323:  * io_fmapopen() File buffered stream operations over MMAP block
  324:  *
  325:  * @csFile = Filename for MMAP, if =NULL private MMAP block
  326:  * @mode = File open mode
  327:  * @perm = If file not exists will be created with this access permissions
  328:  * @prot = MMAP protection
  329:  * @flags = MMAP mode flags
  330:  * @offset = Map from file offset, if csFile==NULL then this is size of MMAP private block
  331:  * return: NULL error or !=NULL Opened file resource
  332:  */
  333: FILE *
  334: io_fmapopen(const char *csFile, int mode, int perm, int prot, int flags, off_t offset)
  335: {
  336: 	FILE *f;
  337: 	struct tagBufIO *buf;
  338: 	void *base;
  339: 	off_t basesize;
  340: 	int fd = -1;
  341: 
  342: 	if (csFile) {
  343: 		fd = open(csFile, mode, perm);
  344: 		if (fd == -1) {
  345: 			LOGERR;
  346: 			return NULL;
  347: 		}
  348: 		basesize = lseek(fd, 0, SEEK_END);
  349: 		if (basesize == -1) {
  350: 			LOGERR;
  351: 			close(fd);
  352: 			return NULL;
  353: 		} else
  354: 			lseek(fd, 0, SEEK_SET);
  355: 
  356: 		base = mmap(NULL, basesize, prot, flags | MAP_FILE, fd, offset);
  357: 		if (base == MAP_FAILED) {
  358: 			LOGERR;
  359: 			close(fd);
  360: 			return NULL;
  361: 		} else
  362: 			close(fd);
  363: 	} else if (offset) {
  364: 		basesize = offset;
  365: 		base = mmap(NULL, basesize, prot, MAP_ANON, -1, 0);
  366: 		if (base == MAP_FAILED) {
  367: 			LOGERR;
  368: 			return NULL;
  369: 		}
  370: 	} else {
  371: 		io_SetErr(EINVAL, "Invalid base argument ...");
  372: 		return NULL;
  373: 	}
  374: 
  375: 
  376: 	buf = malloc(sizeof(struct tagBufIO));
  377: 	if (!buf) {
  378: 		LOGERR;
  379: 		munmap(base, basesize);
  380: 		return NULL;
  381: 	} else
  382: 		memset(buf, 0, sizeof(struct tagBufIO));
  383: 
  384: 	buf->buf_mode = BUFIO_MODE_LIMIT;
  385: 	buf->buf_base = base;
  386: 	buf->buf_size = basesize;
  387: 	buf->buf_unmap = unmap_cf;
  388: 
  389: #ifdef __NetBSD__
  390: 	f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  391: 			(int (*)(void *, char const *, int)) wf_lim, 
  392: 			(off_t (*)(void *, off_t, int)) sf_lim, 
  393: 			(int (*)(void *)) cf_);
  394: #else
  395: 	f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  396: 			(int (*)(void *, char const *, int)) wf_lim, 
  397: 			(fpos_t (*)(void *, fpos_t, int)) sf_lim, 
  398: 			(int (*)(void *)) cf_);
  399: #endif
  400: 	if (!f) {
  401: 		LOGERR;
  402: 		free(buf);
  403: 		munmap(base, basesize);
  404: 		return NULL;
  405: 	}
  406: 
  407: 	return f;
  408: }
  409: 
  410: /*
  411:  * io_dumbFile() Create empry or dumb file with fixed size
  412:  *
  413:  * @csFile = Filename for create
  414:  * @mode = File access permissions
  415:  * @size = File size
  416:  * return: -1 error or open file handle
  417:  */
  418: int
  419: io_dumbFile(const char *csFile, int mode, off_t size)
  420: {
  421: 	int fd;
  422: 
  423: 	fd = open(csFile, O_RDWR | O_CREAT, mode);
  424: 	if (fd == -1) {
  425: 		LOGERR;
  426: 		return -1;
  427: 	}
  428: 
  429: 	if (lseek(fd, size - 1, SEEK_SET) == -1)
  430: 		goto err;
  431: 	if (write(fd, "", 1) != 1)
  432: 		goto err;
  433: 	else
  434: 		lseek(fd, 0, SEEK_SET);
  435: 
  436: 	return fd;
  437: err:
  438: 	LOGERR;
  439: 	close(fd);
  440: 	return -1;
  441: }
  442: 
  443: /*
  444:  * io_fd2buf() Convert open file handle to buffered file I/O
  445:  *
  446:  * @fd = File handle
  447:  * @mode = Permissions for new buffered file I/O
  448:  * return: NULL error or open buffered file
  449:  */
  450: inline FILE *
  451: io_fd2buf(int fd, const char *mode)
  452: {
  453: 	FILE *f;
  454: 
  455: 	f = fdopen(fd, mode);
  456: 	if (!f)
  457: 		LOGERR;
  458: 
  459: 	return f;
  460: }

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