Annotation of libaitio/src/bufio.c, revision 1.7.4.1
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 $
1.7.4.1 ! misho 6: * $Id: bufio.c,v 1.7 2013/03/13 14:54:39 misho Exp $
1.3 misho 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:
1.7 misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
1.3 misho 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)
1.7 misho 65: e_free(buf->buf_base);
1.2 misho 66: else if (buf->buf_unmap)
67: buf->buf_unmap(buf);
68:
1.7 misho 69: e_free(buf);
1.2 misho 70: return 0;
71: }
72:
1.4 misho 73: #ifdef __NetBSD__
74: static off_t
75: sf_lim(struct tagBufIO *buf, off_t pos, int w)
76: #else
1.2 misho 77: static fpos_t
78: sf_lim(struct tagBufIO *buf, fpos_t pos, int w)
1.4 misho 79: #endif
1.2 misho 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:
1.4 misho 142: #ifdef __NetBSD__
143: static off_t
144: sf_inf(struct tagBufIO *buf, off_t pos, int w)
145: #else
1.2 misho 146: static fpos_t
147: sf_inf(struct tagBufIO *buf, fpos_t pos, int w)
1.4 misho 148: #endif
1.2 misho 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) {
1.7 misho 160: b = e_realloc(buf->buf_base, pos);
1.2 misho 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)) {
1.7 misho 176: b = e_realloc(buf->buf_base, buf->buf_offset + pos);
1.2 misho 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)) {
1.7 misho 193: b = e_realloc(buf->buf_base, buf->buf_size + pos);
1.2 misho 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) {
1.7 misho 227: b = e_realloc(buf->buf_base, buf->buf_offset + siz);
1.2 misho 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: /*
1.5 misho 246: * io_fmemopen() - File buffered stream operations over memory block
1.2 misho 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:
1.7 misho 263: buf = e_malloc(sizeof(struct tagBufIO));
1.2 misho 264: if (!buf) {
265: LOGERR;
266: return NULL;
267: } else
268: memset(buf, 0, sizeof(struct tagBufIO));
269:
270: if (!*base) {
1.7 misho 271: *base = e_malloc(basesize);
1.2 misho 272: if (!*base) {
273: LOGERR;
1.7 misho 274: e_free(buf);
1.2 misho 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:
1.4 misho 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
1.2 misho 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_);
1.4 misho 308: #endif
1.2 misho 309: if (!f) {
310: LOGERR;
311: if (buf->buf_mode == BUFIO_MODE_INFINIT) {
1.7 misho 312: e_free(*base);
1.2 misho 313: *base = NULL;
314: }
1.7 misho 315: e_free(buf);
1.2 misho 316: return NULL;
317: }
318:
319: return f;
320: }
321:
322: /*
1.5 misho 323: * io_fmapopen() - File buffered stream operations over MMAP block
1.2 misho 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:
1.7 misho 376: buf = e_malloc(sizeof(struct tagBufIO));
1.2 misho 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:
1.4 misho 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
1.2 misho 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_);
1.4 misho 399: #endif
1.2 misho 400: if (!f) {
401: LOGERR;
1.7 misho 402: e_free(buf);
1.2 misho 403: munmap(base, basesize);
404: return NULL;
405: }
406:
407: return f;
408: }
409:
410: /*
1.5 misho 411: * io_dumbFile() - Create empry or dumb file with fixed size
1.2 misho 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: /*
1.5 misho 444: * io_fd2buf() - Convert open file handle to buffered file I/O
1.2 misho 445: *
446: * @fd = File handle
447: * @mode = Permissions for new buffered file I/O
448: * return: NULL error or open buffered file
449: */
1.7.4.1 ! misho 450: FILE *
1.2 misho 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>