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

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