Annotation of libaitio/src/bufio.c, revision 1.3
1.3 ! misho 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.2.2.1 2012/03/08 23:14:59 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: */
1.2 misho 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>