Annotation of libaitio/src/bufio.c, revision 1.10
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.10 ! misho 6: * $Id: bufio.c,v 1.9.8.3 2016/08/15 12:13:47 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.10 ! misho 15: Copyright 2004 - 2016
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.10 ! misho 73: #ifndef __linux__
1.4 misho 74: #ifdef __NetBSD__
75: static off_t
76: sf_lim(struct tagBufIO *buf, off_t pos, int w)
77: #else
1.2 misho 78: static fpos_t
79: sf_lim(struct tagBufIO *buf, fpos_t pos, int w)
1.4 misho 80: #endif
1.10 ! misho 81: #else
! 82: static off_t
! 83: sf_lim(struct tagBufIO *buf, off64_t *ppos, int w)
! 84: #endif
1.2 misho 85: {
1.10 ! misho 86: #ifdef __linux__
! 87: off_t pos = (off_t) *ppos;
! 88: #endif
! 89:
1.2 misho 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:
1.10 ! misho 151: #ifndef __linux__
1.4 misho 152: #ifdef __NetBSD__
153: static off_t
154: sf_inf(struct tagBufIO *buf, off_t pos, int w)
155: #else
1.2 misho 156: static fpos_t
157: sf_inf(struct tagBufIO *buf, fpos_t pos, int w)
1.4 misho 158: #endif
1.10 ! misho 159: #else
! 160: static off_t
! 161: sf_inf(struct tagBufIO *buf, off64_t *ppos, int w)
! 162: #endif
1.2 misho 163: {
164: void *b;
1.10 ! misho 165: #ifdef __linux__
! 166: off_t pos = (off_t) *ppos;
! 167: #endif
1.2 misho 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) {
1.7 misho 177: b = e_realloc(buf->buf_base, pos);
1.2 misho 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)) {
1.7 misho 193: b = e_realloc(buf->buf_base, buf->buf_offset + 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,
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)) {
1.7 misho 210: b = e_realloc(buf->buf_base, buf->buf_size + pos);
1.2 misho 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) {
1.7 misho 244: b = e_realloc(buf->buf_base, buf->buf_offset + siz);
1.2 misho 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: /*
1.5 misho 263: * io_fmemopen() - File buffered stream operations over memory block
1.2 misho 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;
1.10 ! misho 274: #ifdef __linux__
! 275: cookie_io_functions_t cookie;
! 276: #endif
1.2 misho 277:
278: if (!base) {
279: io_SetErr(EINVAL, "Invalid base argument ...");
280: return NULL;
281: }
282:
1.7 misho 283: buf = e_malloc(sizeof(struct tagBufIO));
1.2 misho 284: if (!buf) {
285: LOGERR;
286: return NULL;
287: } else
288: memset(buf, 0, sizeof(struct tagBufIO));
289:
290: if (!*base) {
1.7 misho 291: *base = e_malloc(basesize);
1.2 misho 292: if (!*base) {
293: LOGERR;
1.7 misho 294: e_free(buf);
1.2 misho 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:
1.10 ! misho 306: #ifndef __linux__
1.4 misho 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
1.2 misho 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_);
1.4 misho 329: #endif
1.10 ! misho 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
1.2 misho 345: if (!f) {
346: LOGERR;
347: if (buf->buf_mode == BUFIO_MODE_INFINIT) {
1.7 misho 348: e_free(*base);
1.2 misho 349: *base = NULL;
350: }
1.7 misho 351: e_free(buf);
1.2 misho 352: return NULL;
353: }
354:
355: return f;
356: }
357:
358: /*
1.5 misho 359: * io_fmapopen() - File buffered stream operations over MMAP block
1.2 misho 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;
1.10 ! misho 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
1.2 misho 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;
1.10 ! misho 409: base = mmap(NULL, basesize, prot, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1.2 misho 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:
1.7 misho 420: buf = e_malloc(sizeof(struct tagBufIO));
1.2 misho 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:
1.10 ! misho 433: #ifndef __linux__
1.4 misho 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
1.2 misho 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_);
1.10 ! misho 444: #endif
! 445: #else
! 446: f = fopencookie(buf, "r+", cookie);
1.4 misho 447: #endif
1.2 misho 448: if (!f) {
449: LOGERR;
1.7 misho 450: e_free(buf);
1.2 misho 451: munmap(base, basesize);
452: return NULL;
453: }
454:
455: return f;
456: }
457:
458: /*
1.5 misho 459: * io_dumbFile() - Create empry or dumb file with fixed size
1.2 misho 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: /*
1.5 misho 492: * io_fd2buf() - Convert open file handle to buffered file I/O
1.2 misho 493: *
494: * @fd = File handle
495: * @mode = Permissions for new buffered file I/O
496: * return: NULL error or open buffered file
497: */
1.8 misho 498: FILE *
1.2 misho 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>