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>