Annotation of libaitio/src/bufio.c, revision 1.6

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.6     ! misho       6: * $Id: bufio.c,v 1.5.6.2 2012/05/23 14:06:08 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: 
                     15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
                     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.6     ! misho      65:                io_free(buf->buf_base);
1.2       misho      66:        else if (buf->buf_unmap)
                     67:                buf->buf_unmap(buf);
                     68: 
1.6     ! misho      69:        io_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.6     ! misho     160:                                b = io_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.6     ! misho     176:                                b = io_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.6     ! misho     193:                                b = io_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.6     ! misho     227:                b = io_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.6     ! misho     263:        buf = io_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.6     ! misho     271:                *base = io_malloc(basesize);
1.2       misho     272:                if (!*base) {
                    273:                        LOGERR;
1.6     ! misho     274:                        io_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.6     ! misho     312:                        io_free(*base);
1.2       misho     313:                        *base = NULL;
                    314:                }
1.6     ! misho     315:                io_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.6     ! misho     376:        buf = io_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.6     ! misho     402:                io_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:  */
                    450: inline FILE *
                    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>