Annotation of libaitio/src/bufio.c, revision 1.9.8.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.9.8.1 ! misho       6: * $Id: bufio.c,v 1.9 2014/02/08 22:06:17 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: 
1.9.8.1 ! misho      56: #ifndef __linux__
1.2       misho      57: static int
                     58: cf_(struct tagBufIO *buf)
                     59: {
                     60:        if (!buf) {
                     61:                io_SetErr(EINVAL, "Invalid arguments ...");
                     62:                return -1;
                     63:        }
                     64: 
                     65:        if (buf->buf_mode == BUFIO_MODE_INFINIT)
1.7       misho      66:                e_free(buf->buf_base);
1.2       misho      67:        else if (buf->buf_unmap)
                     68:                buf->buf_unmap(buf);
                     69: 
1.7       misho      70:        e_free(buf);
1.2       misho      71:        return 0;
                     72: }
                     73: 
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.2       misho      81: {
                     82:        if (!buf)
                     83:                goto err;
                     84: 
                     85:        switch (w) {
                     86:                case SEEK_SET:
                     87:                        if (buf->buf_size < pos || pos < 0)
                     88:                                goto err;
                     89:                        buf->buf_offset = pos;
                     90:                        break;
                     91:                case SEEK_CUR:
                     92:                        if (buf->buf_size < (buf->buf_offset + pos) || (buf->buf_offset + pos) < 0)
                     93:                                goto err;
                     94:                        buf->buf_offset += pos;
                     95:                        break;
                     96:                case SEEK_END:
                     97:                        if (buf->buf_size < (buf->buf_size + pos) || (buf->buf_size + pos) < 0)
                     98:                                goto err;
                     99:                        buf->buf_offset = buf->buf_size + pos;
                    100:                        break;
                    101:                default:
                    102:                        goto err;
                    103:        }
                    104: 
                    105:        return buf->buf_offset;
                    106: err:
                    107:        io_SetErr(EINVAL, "Invalid arguments ...");
                    108:        return -1;
                    109: }
                    110: 
                    111: static int
                    112: rf_lim(struct tagBufIO *buf, char *dat, int siz)
                    113: {
                    114:        if (!buf || !dat) {
                    115:                io_SetErr(EINVAL, "Invalid arguments ...");
                    116:                return -1;
                    117:        }
                    118: 
                    119:        if (buf->buf_offset + siz > buf->buf_size)
                    120:                siz = buf->buf_size - buf->buf_offset;
                    121: 
                    122:        memcpy(dat, buf->buf_base + buf->buf_offset, siz);
                    123:        buf->buf_offset += siz;
                    124:        return siz;
                    125: }
                    126: 
                    127: static int
                    128: wf_lim(struct tagBufIO *buf, const char *dat, int siz)
                    129: {
                    130:        if (!buf || !dat) {
                    131:                io_SetErr(EINVAL, "Invalid arguments ...");
                    132:                return -1;
                    133:        }
                    134: 
                    135:        if (buf->buf_offset + siz > buf->buf_size)
                    136:                siz = buf->buf_size - buf->buf_offset;
                    137: 
                    138:        memcpy(buf->buf_base + buf->buf_offset, dat, siz);
                    139:        buf->buf_offset += siz;
                    140:        return siz;
                    141: }
                    142: 
1.4       misho     143: #ifdef __NetBSD__
                    144: static off_t
                    145: sf_inf(struct tagBufIO *buf, off_t pos, int w)
                    146: #else
1.2       misho     147: static fpos_t
                    148: sf_inf(struct tagBufIO *buf, fpos_t pos, int w)
1.4       misho     149: #endif
1.2       misho     150: {
                    151:        void *b;
                    152: 
                    153:        if (!buf)
                    154:                goto err;
                    155: 
                    156:        switch (w) {
                    157:                case SEEK_SET:
                    158:                        if (pos < 0)
                    159:                                goto err;
                    160:                        if (buf->buf_size < pos) {
1.7       misho     161:                                b = e_realloc(buf->buf_base, pos);
1.2       misho     162:                                if (!b) {
                    163:                                        LOGERR;
                    164:                                        return -1;
                    165:                                } else {
                    166:                                        buf->buf_base = b;
                    167:                                        memset(buf->buf_base + buf->buf_size, 0, pos - buf->buf_size);
                    168:                                        buf->buf_size = pos;
                    169:                                }
                    170:                        }
                    171:                        buf->buf_offset = pos;
                    172:                        break;
                    173:                case SEEK_CUR:
                    174:                        if ((buf->buf_offset + pos) < 0)
                    175:                                goto err;
                    176:                        if (buf->buf_size < (buf->buf_offset + pos)) {
1.7       misho     177:                                b = e_realloc(buf->buf_base, buf->buf_offset + 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, 
                    184:                                                        buf->buf_offset + pos - buf->buf_size);
                    185:                                        buf->buf_size = buf->buf_offset + pos;
                    186:                                }
                    187:                        }
                    188:                        buf->buf_offset += pos;
                    189:                        break;
                    190:                case SEEK_END:
                    191:                        if ((buf->buf_size + pos) < 0)
                    192:                                goto err;
                    193:                        if (buf->buf_size < (buf->buf_size + pos)) {
1.7       misho     194:                                b = e_realloc(buf->buf_base, buf->buf_size + pos);
1.2       misho     195:                                if (!b) {
                    196:                                        LOGERR;
                    197:                                        return -1;
                    198:                                } else {
                    199:                                        buf->buf_base = b;
                    200:                                        memset(buf->buf_base + buf->buf_size, 0, pos);
                    201:                                        buf->buf_size += pos;
                    202:                                        buf->buf_offset = buf->buf_size;
                    203:                                }
                    204:                        } else
                    205:                                buf->buf_offset = buf->buf_size + pos;
                    206:                        break;
                    207:                default:
                    208:                        goto err;
                    209:        }
                    210: 
                    211:        return buf->buf_offset;
                    212: err:
                    213:        io_SetErr(EINVAL, "Invalid arguments ...");
                    214:        return -1;
                    215: }
                    216: 
                    217: static int
                    218: wf_inf(struct tagBufIO *buf, const char *dat, int siz)
                    219: {
                    220:        void *b;
                    221: 
                    222:        if (!buf || !dat) {
                    223:                io_SetErr(EINVAL, "Invalid arguments ...");
                    224:                return -1;
                    225:        }
                    226: 
                    227:        if (buf->buf_offset + siz > buf->buf_size) {
1.7       misho     228:                b = e_realloc(buf->buf_base, buf->buf_offset + siz);
1.2       misho     229:                if (!b) {
                    230:                        LOGERR;
                    231:                        return -1;
                    232:                } else {
                    233:                        buf->buf_base = b;
                    234:                        memset(buf->buf_base + buf->buf_size, 0, 
                    235:                                        buf->buf_offset + siz - buf->buf_size);
                    236:                        buf->buf_size = buf->buf_offset + siz;
                    237:                }
                    238:        }
                    239: 
                    240:        memcpy(buf->buf_base + buf->buf_offset, dat, siz);
                    241:        buf->buf_offset += siz;
                    242:        return siz;
                    243: }
1.9.8.1 ! misho     244: #endif
1.2       misho     245: 
                    246: 
                    247: /*
1.5       misho     248:  * io_fmemopen() - File buffered stream operations over memory block
1.2       misho     249:  *
                    250:  * @base = Base address of memory block, if =NULL Infinit length(auto-grow)
                    251:  * @basesize = Size of memory block
                    252:  * return: NULL error or !=NULL Opened file resource
                    253:  */
                    254: FILE *
                    255: io_fmemopen(void ** __restrict base, off_t basesize)
                    256: {
                    257:        FILE *f = NULL;
                    258:        struct tagBufIO *buf;
                    259: 
                    260:        if (!base) {
                    261:                io_SetErr(EINVAL, "Invalid base argument ...");
                    262:                return NULL;
                    263:        }
                    264: 
1.7       misho     265:        buf = e_malloc(sizeof(struct tagBufIO));
1.2       misho     266:        if (!buf) {
                    267:                LOGERR;
                    268:                return NULL;
                    269:        } else
                    270:                memset(buf, 0, sizeof(struct tagBufIO));
                    271: 
                    272:        if (!*base) {
1.9.8.1 ! misho     273: #ifndef __linux__
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: 
1.9.8.1 ! misho     282:                buf->buf_base = *base;
        !           283:                buf->buf_size = basesize;
        !           284: #endif
1.2       misho     285:                buf->buf_mode = BUFIO_MODE_INFINIT;
1.9.8.1 ! misho     286:        } else {
        !           287:                buf->buf_base = *base;
        !           288:                buf->buf_size = basesize;
1.2       misho     289: 
1.9.8.1 ! misho     290:                buf->buf_mode = BUFIO_MODE_LIMIT;
        !           291:        }
1.2       misho     292: 
1.9.8.1 ! misho     293: #ifndef __linux__
1.4       misho     294: #ifdef __NetBSD__
                    295:        if (buf->buf_mode == BUFIO_MODE_INFINIT)
                    296:                f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
                    297:                                (int (*)(void *, char const *, int)) wf_inf, 
                    298:                                (off_t (*)(void *, off_t, int)) sf_inf, 
                    299:                                (int (*)(void *)) cf_);
                    300:        else
                    301:                f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
                    302:                                (int (*)(void *, char const *, int)) wf_lim, 
                    303:                                (off_t (*)(void *, off_t, int)) sf_lim, 
                    304:                                (int (*)(void *)) cf_);
                    305: #else
1.2       misho     306:        if (buf->buf_mode == BUFIO_MODE_INFINIT)
                    307:                f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
                    308:                                (int (*)(void *, char const *, int)) wf_inf, 
                    309:                                (fpos_t (*)(void *, fpos_t, int)) sf_inf, 
                    310:                                (int (*)(void *)) cf_);
                    311:        else
                    312:                f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
                    313:                                (int (*)(void *, char const *, int)) wf_lim, 
                    314:                                (fpos_t (*)(void *, fpos_t, int)) sf_lim, 
                    315:                                (int (*)(void *)) cf_);
1.4       misho     316: #endif
1.9.8.1 ! misho     317: #else
        !           318:        if (buf->buf_mode == BUFIO_MODE_INFINIT)
        !           319:                f = open_memstream((char**) &buf->buf_base, (size_t*) &buf->buf_size);
        !           320:        else
        !           321:                f = fmemopen(buf->buf_base, buf->buf_size, "r+");
        !           322: #endif
1.2       misho     323:        if (!f) {
                    324:                LOGERR;
1.9.8.1 ! misho     325: #ifndef __linux__
1.2       misho     326:                if (buf->buf_mode == BUFIO_MODE_INFINIT) {
1.7       misho     327:                        e_free(*base);
1.2       misho     328:                        *base = NULL;
                    329:                }
1.9.8.1 ! misho     330: #endif
1.7       misho     331:                e_free(buf);
1.2       misho     332:                return NULL;
                    333:        }
1.9.8.1 ! misho     334: #ifdef __linux__
        !           335:        if (buf->buf_mode == BUFIO_MODE_INFINIT)
        !           336:                *base = buf->buf_base;
        !           337: #endif
1.2       misho     338: 
                    339:        return f;
                    340: }
                    341: 
                    342: /*
1.5       misho     343:  * io_fmapopen() - File buffered stream operations over MMAP block
1.2       misho     344:  *
                    345:  * @csFile = Filename for MMAP, if =NULL private MMAP block
                    346:  * @mode = File open mode
                    347:  * @perm = If file not exists will be created with this access permissions
                    348:  * @prot = MMAP protection
                    349:  * @flags = MMAP mode flags
                    350:  * @offset = Map from file offset, if csFile==NULL then this is size of MMAP private block
                    351:  * return: NULL error or !=NULL Opened file resource
                    352:  */
                    353: FILE *
                    354: io_fmapopen(const char *csFile, int mode, int perm, int prot, int flags, off_t offset)
                    355: {
                    356:        FILE *f;
                    357:        struct tagBufIO *buf;
                    358:        void *base;
                    359:        off_t basesize;
                    360:        int fd = -1;
                    361: 
                    362:        if (csFile) {
                    363:                fd = open(csFile, mode, perm);
                    364:                if (fd == -1) {
                    365:                        LOGERR;
                    366:                        return NULL;
                    367:                }
                    368:                basesize = lseek(fd, 0, SEEK_END);
                    369:                if (basesize == -1) {
                    370:                        LOGERR;
                    371:                        close(fd);
                    372:                        return NULL;
                    373:                } else
                    374:                        lseek(fd, 0, SEEK_SET);
                    375: 
                    376:                base = mmap(NULL, basesize, prot, flags | MAP_FILE, fd, offset);
                    377:                if (base == MAP_FAILED) {
                    378:                        LOGERR;
                    379:                        close(fd);
                    380:                        return NULL;
                    381:                } else
                    382:                        close(fd);
                    383:        } else if (offset) {
                    384:                basesize = offset;
                    385:                base = mmap(NULL, basesize, prot, MAP_ANON, -1, 0);
                    386:                if (base == MAP_FAILED) {
                    387:                        LOGERR;
                    388:                        return NULL;
                    389:                }
                    390:        } else {
                    391:                io_SetErr(EINVAL, "Invalid base argument ...");
                    392:                return NULL;
                    393:        }
                    394: 
                    395: 
1.7       misho     396:        buf = e_malloc(sizeof(struct tagBufIO));
1.2       misho     397:        if (!buf) {
                    398:                LOGERR;
                    399:                munmap(base, basesize);
                    400:                return NULL;
                    401:        } else
                    402:                memset(buf, 0, sizeof(struct tagBufIO));
                    403: 
                    404:        buf->buf_mode = BUFIO_MODE_LIMIT;
                    405:        buf->buf_base = base;
                    406:        buf->buf_size = basesize;
                    407:        buf->buf_unmap = unmap_cf;
                    408: 
1.9.8.1 ! misho     409: #ifndef __linux__
1.4       misho     410: #ifdef __NetBSD__
                    411:        f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
                    412:                        (int (*)(void *, char const *, int)) wf_lim, 
                    413:                        (off_t (*)(void *, off_t, int)) sf_lim, 
                    414:                        (int (*)(void *)) cf_);
                    415: #else
1.2       misho     416:        f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, 
                    417:                        (int (*)(void *, char const *, int)) wf_lim, 
                    418:                        (fpos_t (*)(void *, fpos_t, int)) sf_lim, 
                    419:                        (int (*)(void *)) cf_);
1.9.8.1 ! misho     420: #endif
        !           421: #else
        !           422:        f = fmemopen(buf->buf_base, buf->buf_size, "r+");
1.4       misho     423: #endif
1.2       misho     424:        if (!f) {
                    425:                LOGERR;
1.7       misho     426:                e_free(buf);
1.2       misho     427:                munmap(base, basesize);
                    428:                return NULL;
                    429:        }
                    430: 
                    431:        return f;
                    432: }
                    433: 
                    434: /*
1.5       misho     435:  * io_dumbFile() - Create empry or dumb file with fixed size
1.2       misho     436:  *
                    437:  * @csFile = Filename for create
                    438:  * @mode = File access permissions
                    439:  * @size = File size
                    440:  * return: -1 error or open file handle
                    441:  */
                    442: int
                    443: io_dumbFile(const char *csFile, int mode, off_t size)
                    444: {
                    445:        int fd;
                    446: 
                    447:        fd = open(csFile, O_RDWR | O_CREAT, mode);
                    448:        if (fd == -1) {
                    449:                LOGERR;
                    450:                return -1;
                    451:        }
                    452: 
                    453:        if (lseek(fd, size - 1, SEEK_SET) == -1)
                    454:                goto err;
                    455:        if (write(fd, "", 1) != 1)
                    456:                goto err;
                    457:        else
                    458:                lseek(fd, 0, SEEK_SET);
                    459: 
                    460:        return fd;
                    461: err:
                    462:        LOGERR;
                    463:        close(fd);
                    464:        return -1;
                    465: }
                    466: 
                    467: /*
1.5       misho     468:  * io_fd2buf() - Convert open file handle to buffered file I/O
1.2       misho     469:  *
                    470:  * @fd = File handle
                    471:  * @mode = Permissions for new buffered file I/O
                    472:  * return: NULL error or open buffered file
                    473:  */
1.8       misho     474: FILE *
1.2       misho     475: io_fd2buf(int fd, const char *mode)
                    476: {
                    477:        FILE *f;
                    478: 
                    479:        f = fdopen(fd, mode);
                    480:        if (!f)
                    481:                LOGERR;
                    482: 
                    483:        return f;
                    484: }

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