File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / bufio.c
Revision 1.9.8.1: download - view: text, annotated - select for diffs - revision graph
Thu Aug 11 12:25:51 2016 UTC (7 years, 10 months ago) by misho
Branches: io7_3
Diff to: branchpoint 1.9: preferred, unified
port another part of library bufio

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

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