File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / bufio.c
Revision 1.10: download - view: text, annotated - select for diffs - revision graph
Thu Aug 18 09:06:31 2016 UTC (7 years, 9 months ago) by misho
Branches: MAIN
CVS tags: io7_4, IO7_3, HEAD
version 7.3

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

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