File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / bufio.c
Revision 1.9.8.2: download - view: text, annotated - select for diffs - revision graph
Thu Aug 11 12:51:52 2016 UTC (8 years, 1 month ago) by misho
Branches: io7_3
Diff to: branchpoint 1.9: preferred, unified
hmmm
finish bufio porting process under linux

    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.2 2016/08/11 12:51:52 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: #if defined(__NetBSD__) || defined(__linux__)
   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: #if defined(__NetBSD__) || defined(__linux__)
  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 = e_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 = e_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 = e_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 = e_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: #ifdef __linux__
  258: 	cookie_io_functions_t cookie;
  259: #endif
  260: 
  261: 	if (!base) {
  262: 		io_SetErr(EINVAL, "Invalid base argument ...");
  263: 		return NULL;
  264: 	}
  265: 
  266: 	buf = e_malloc(sizeof(struct tagBufIO));
  267: 	if (!buf) {
  268: 		LOGERR;
  269: 		return NULL;
  270: 	} else
  271: 		memset(buf, 0, sizeof(struct tagBufIO));
  272: 
  273: 	if (!*base) {
  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_mode = BUFIO_MODE_INFINIT;
  283: 	} else
  284: 		buf->buf_mode = BUFIO_MODE_LIMIT;
  285: 
  286: 	buf->buf_base = *base;
  287: 	buf->buf_size = basesize;
  288: 
  289: #ifndef __linux__
  290: #ifdef __NetBSD__
  291: 	if (buf->buf_mode == BUFIO_MODE_INFINIT)
  292: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  293: 				(int (*)(void *, char const *, int)) wf_inf, 
  294: 				(off_t (*)(void *, off_t, int)) sf_inf, 
  295: 				(int (*)(void *)) cf_);
  296: 	else
  297: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  298: 				(int (*)(void *, char const *, int)) wf_lim, 
  299: 				(off_t (*)(void *, off_t, int)) sf_lim, 
  300: 				(int (*)(void *)) cf_);
  301: #else
  302: 	if (buf->buf_mode == BUFIO_MODE_INFINIT)
  303: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  304: 				(int (*)(void *, char const *, int)) wf_inf, 
  305: 				(fpos_t (*)(void *, fpos_t, int)) sf_inf, 
  306: 				(int (*)(void *)) cf_);
  307: 	else
  308: 		f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  309: 				(int (*)(void *, char const *, int)) wf_lim, 
  310: 				(fpos_t (*)(void *, fpos_t, int)) sf_lim, 
  311: 				(int (*)(void *)) cf_);
  312: #endif
  313: #else
  314: 	if (buf->buf_mode == BUFIO_MODE_INFINIT) {
  315: 		cookie.read = (cookie_read_function_t*) rf_lim;
  316: 		cookie.write = (cookie_write_function_t*) wf_inf;
  317: 		cookie.seek = (cookie_seek_function_t*) sf_inf;
  318: 		cookie.close = (cookie_close_function_t*) cf_;
  319: 	} else {
  320: 		cookie.read = (cookie_read_function_t*) rf_lim;
  321: 		cookie.write = (cookie_write_function_t*) wf_lim;
  322: 		cookie.seek = (cookie_seek_function_t*) sf_lim;
  323: 		cookie.close = (cookie_close_function_t*) cf_;
  324: 	}
  325: 
  326: 	f = fopencookie(buf, "r+", cookie);
  327: #endif
  328: 	if (!f) {
  329: 		LOGERR;
  330: 		if (buf->buf_mode == BUFIO_MODE_INFINIT) {
  331: 			e_free(*base);
  332: 			*base = NULL;
  333: 		}
  334: 		e_free(buf);
  335: 		return NULL;
  336: 	}
  337: 
  338: 	return f;
  339: }
  340: 
  341: /*
  342:  * io_fmapopen() - File buffered stream operations over MMAP block
  343:  *
  344:  * @csFile = Filename for MMAP, if =NULL private MMAP block
  345:  * @mode = File open mode
  346:  * @perm = If file not exists will be created with this access permissions
  347:  * @prot = MMAP protection
  348:  * @flags = MMAP mode flags
  349:  * @offset = Map from file offset, if csFile==NULL then this is size of MMAP private block
  350:  * return: NULL error or !=NULL Opened file resource
  351:  */
  352: FILE *
  353: io_fmapopen(const char *csFile, int mode, int perm, int prot, int flags, off_t offset)
  354: {
  355: 	FILE *f;
  356: 	struct tagBufIO *buf;
  357: 	void *base;
  358: 	off_t basesize;
  359: 	int fd = -1;
  360: #ifdef __linux__
  361: 	cookie_io_functions_t cookie = {
  362: 		.read = (cookie_read_function_t*) rf_lim, 
  363: 		.write = (cookie_write_function_t*) wf_lim, 
  364: 		.seek = (cookie_seek_function_t*) sf_lim, 
  365: 		.close = (cookie_close_function_t*) cf_
  366: 	};
  367: #endif
  368: 
  369: 	if (csFile) {
  370: 		fd = open(csFile, mode, perm);
  371: 		if (fd == -1) {
  372: 			LOGERR;
  373: 			return NULL;
  374: 		}
  375: 		basesize = lseek(fd, 0, SEEK_END);
  376: 		if (basesize == -1) {
  377: 			LOGERR;
  378: 			close(fd);
  379: 			return NULL;
  380: 		} else
  381: 			lseek(fd, 0, SEEK_SET);
  382: 
  383: 		base = mmap(NULL, basesize, prot, flags | MAP_FILE, fd, offset);
  384: 		if (base == MAP_FAILED) {
  385: 			LOGERR;
  386: 			close(fd);
  387: 			return NULL;
  388: 		} else
  389: 			close(fd);
  390: 	} else if (offset) {
  391: 		basesize = offset;
  392: 		base = mmap(NULL, basesize, prot, MAP_ANON, -1, 0);
  393: 		if (base == MAP_FAILED) {
  394: 			LOGERR;
  395: 			return NULL;
  396: 		}
  397: 	} else {
  398: 		io_SetErr(EINVAL, "Invalid base argument ...");
  399: 		return NULL;
  400: 	}
  401: 
  402: 
  403: 	buf = e_malloc(sizeof(struct tagBufIO));
  404: 	if (!buf) {
  405: 		LOGERR;
  406: 		munmap(base, basesize);
  407: 		return NULL;
  408: 	} else
  409: 		memset(buf, 0, sizeof(struct tagBufIO));
  410: 
  411: 	buf->buf_mode = BUFIO_MODE_LIMIT;
  412: 	buf->buf_base = base;
  413: 	buf->buf_size = basesize;
  414: 	buf->buf_unmap = unmap_cf;
  415: 
  416: #ifndef __linux__
  417: #ifdef __NetBSD__
  418: 	f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  419: 			(int (*)(void *, char const *, int)) wf_lim, 
  420: 			(off_t (*)(void *, off_t, int)) sf_lim, 
  421: 			(int (*)(void *)) cf_);
  422: #else
  423: 	f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
  424: 			(int (*)(void *, char const *, int)) wf_lim, 
  425: 			(fpos_t (*)(void *, fpos_t, int)) sf_lim, 
  426: 			(int (*)(void *)) cf_);
  427: #endif
  428: #else
  429: 	f = fopencookie(buf, "r+", cookie);
  430: #endif
  431: 	if (!f) {
  432: 		LOGERR;
  433: 		e_free(buf);
  434: 		munmap(base, basesize);
  435: 		return NULL;
  436: 	}
  437: 
  438: 	return f;
  439: }
  440: 
  441: /*
  442:  * io_dumbFile() - Create empry or dumb file with fixed size
  443:  *
  444:  * @csFile = Filename for create
  445:  * @mode = File access permissions
  446:  * @size = File size
  447:  * return: -1 error or open file handle
  448:  */
  449: int
  450: io_dumbFile(const char *csFile, int mode, off_t size)
  451: {
  452: 	int fd;
  453: 
  454: 	fd = open(csFile, O_RDWR | O_CREAT, mode);
  455: 	if (fd == -1) {
  456: 		LOGERR;
  457: 		return -1;
  458: 	}
  459: 
  460: 	if (lseek(fd, size - 1, SEEK_SET) == -1)
  461: 		goto err;
  462: 	if (write(fd, "", 1) != 1)
  463: 		goto err;
  464: 	else
  465: 		lseek(fd, 0, SEEK_SET);
  466: 
  467: 	return fd;
  468: err:
  469: 	LOGERR;
  470: 	close(fd);
  471: 	return -1;
  472: }
  473: 
  474: /*
  475:  * io_fd2buf() - Convert open file handle to buffered file I/O
  476:  *
  477:  * @fd = File handle
  478:  * @mode = Permissions for new buffered file I/O
  479:  * return: NULL error or open buffered file
  480:  */
  481: FILE *
  482: io_fd2buf(int fd, const char *mode)
  483: {
  484: 	FILE *f;
  485: 
  486: 	f = fdopen(fd, mode);
  487: 	if (!f)
  488: 		LOGERR;
  489: 
  490: 	return f;
  491: }

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