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

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

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