Annotation of libaitio/src/bufio.c, revision 1.9.8.2
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.9.8.2 ! misho 6: * $Id: bufio.c,v 1.9.8.1 2016/08/11 12:25:51 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.9.8.1 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.9.8.2 ! misho 73: #if defined(__NetBSD__) || defined(__linux__)
1.4 misho 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.9.8.2 ! misho 142: #if defined(__NetBSD__) || defined(__linux__)
1.4 misho 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;
1.9.8.2 ! misho 257: #ifdef __linux__
! 258: cookie_io_functions_t cookie;
! 259: #endif
1.2 misho 260:
261: if (!base) {
262: io_SetErr(EINVAL, "Invalid base argument ...");
263: return NULL;
264: }
265:
1.7 misho 266: buf = e_malloc(sizeof(struct tagBufIO));
1.2 misho 267: if (!buf) {
268: LOGERR;
269: return NULL;
270: } else
271: memset(buf, 0, sizeof(struct tagBufIO));
272:
273: if (!*base) {
1.7 misho 274: *base = e_malloc(basesize);
1.2 misho 275: if (!*base) {
276: LOGERR;
1.7 misho 277: e_free(buf);
1.2 misho 278: return NULL;
279: } else
280: memset(*base, 0, basesize);
281:
282: buf->buf_mode = BUFIO_MODE_INFINIT;
1.9.8.2 ! misho 283: } else
1.9.8.1 misho 284: buf->buf_mode = BUFIO_MODE_LIMIT;
1.9.8.2 ! misho 285:
! 286: buf->buf_base = *base;
! 287: buf->buf_size = basesize;
1.2 misho 288:
1.9.8.1 misho 289: #ifndef __linux__
1.4 misho 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
1.2 misho 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_);
1.4 misho 312: #endif
1.9.8.1 misho 313: #else
1.9.8.2 ! misho 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);
1.9.8.1 misho 327: #endif
1.2 misho 328: if (!f) {
329: LOGERR;
330: if (buf->buf_mode == BUFIO_MODE_INFINIT) {
1.7 misho 331: e_free(*base);
1.2 misho 332: *base = NULL;
333: }
1.7 misho 334: e_free(buf);
1.2 misho 335: return NULL;
336: }
337:
338: return f;
339: }
340:
341: /*
1.5 misho 342: * io_fmapopen() - File buffered stream operations over MMAP block
1.2 misho 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;
1.9.8.2 ! misho 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
1.2 misho 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:
1.7 misho 403: buf = e_malloc(sizeof(struct tagBufIO));
1.2 misho 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:
1.9.8.1 misho 416: #ifndef __linux__
1.4 misho 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
1.2 misho 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_);
1.9.8.1 misho 427: #endif
428: #else
1.9.8.2 ! misho 429: f = fopencookie(buf, "r+", cookie);
1.4 misho 430: #endif
1.2 misho 431: if (!f) {
432: LOGERR;
1.7 misho 433: e_free(buf);
1.2 misho 434: munmap(base, basesize);
435: return NULL;
436: }
437:
438: return f;
439: }
440:
441: /*
1.5 misho 442: * io_dumbFile() - Create empry or dumb file with fixed size
1.2 misho 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: /*
1.5 misho 475: * io_fd2buf() - Convert open file handle to buffered file I/O
1.2 misho 476: *
477: * @fd = File handle
478: * @mode = Permissions for new buffered file I/O
479: * return: NULL error or open buffered file
480: */
1.8 misho 481: FILE *
1.2 misho 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>