Annotation of coherent/b/lib/libc/XSTDIO/_fopen.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * libc/stdio/_fopen.c
                      3:  * ANSI-compliant C standard i/o library internals.
                      4:  * _fopen()
                      5:  * Open a file.
                      6:  */
                      7: 
                      8: /*
                      9:  * The recognized mode strings are as follows:
                     10: n *    mode a.k.a.  notfound   found   mode   truncate append
                     11:  *     r               error   read    RMODE   0       0
                     12:  *     w               create  trunc.  WMODE   1       0
                     13:  *     a               create  append  WMODE   0       1
                     14:  *     r+   rw r+w     error   rd.&wr. RWMODE  0       0
                     15:  *     w+   wr w+r     create  trunc.  RWMODE  1       0
                     16:  *     a+   ar a+r     create  app.&rd RWMODE  0       1
                     17:  * In all cases, a trailing 'b' means ascii==1, otherwise ascii==0.
                     18:  * ANSI 4.9.5.3 requires only the first mode forms above (e.g. "r+")
                     19:  * but tolerates the alternate forms (e.g. "r+w" or "rw",
                     20:  * see code involving local 'cn' below).
                     21:  * Use the given FILE if fp is not NULL, otherwise allocate a new FILE.
                     22:  * Use the given fd if nonnegative.
                     23:  * The get and put function pointers in the FILE are initialized
                     24:  * later, possibly after a setvbuf() call specifying desired buffering.
                     25:  */
                     26: 
                     27: #include <stdio.h>
                     28: #include <stdlib.h>
                     29: 
                     30: #define        RMODE   0
                     31: #define        WMODE   1
                     32: #define        RWMODE  2
                     33: #define        CRMODE  0666    /* default access permissions on create */
                     34: 
                     35: FILE *
                     36: _fopen(name, type, fp, fd) char *name, *type; register FILE *fp; register int fd;
                     37: {
                     38:        register _FILE2 *f2p;
                     39:        register int    mode;
                     40:        int             truncate, append, ascii;
                     41:        char            c, cn;
                     42: 
                     43:        /* Parse the type string and set flags accordingly. */
                     44:        mode = WMODE;
                     45:        ascii = 1;
                     46:        truncate = append = 0;
                     47:        cn = 'r';
                     48:        if ((c = *type++) == 'r') {
                     49:                mode = RMODE;
                     50:                cn = 'w';
                     51:        } else if (c=='w')
                     52:                truncate++;
                     53:        else if (c=='a')
                     54:                append++;
                     55:        else
                     56:                return NULL;
                     57:        if ((c = *type) != '\0') {
                     58:                if (c == 'b') {
                     59:                        ascii = 0;
                     60:                        c = *++type;
                     61:                }
                     62:                if (c == '+') {
                     63:                        mode = RWMODE;
                     64:                        c = *++type;
                     65:                }
                     66:                if (c == cn) {
                     67:                        mode = RWMODE;
                     68:                        c = *++type;
                     69:                }
                     70:                if (c == 'b') {
                     71:                        ascii = 0;
                     72:                        c = *++type;
                     73:                }
                     74:                if (c != '\0')
                     75:                        return NULL;
                     76:        }
                     77: 
                     78: #if    _ASCII
                     79:        /*
                     80:         * Beware of ASCII files ending with ASCII EOF character in append mode.
                     81:         * Open for r+w, to allow checking last character.
                     82:         */
                     83:        if (append
                     84:         && ascii
                     85:         && (fd >= 0 || (fd = open(name, RWMODE)) >=0)) {
                     86:                if (lseek(fd, -1L, SEEK_END) != -1L) {  /* seek to end-1 */
                     87:                        if (read(fd, &c, 1) == 1        /* read last char */
                     88:                         && c == _EOFCHAR)              /* last char is EOF */
                     89:                                lseek(fd, -1L, SEEK_CUR); /* so unread it */
                     90:                } else                                  /* might be empty */
                     91:                        lseek(fd, 0L, SEEK_END);
                     92:        }
                     93: #endif
                     94: 
                     95:        /* Try opening existing file, unless truncation is specified. */
                     96:        if (fd < 0 && !truncate)
                     97:                fd = open(name, mode);
                     98: 
                     99:        /*
                    100:         * If "r" or "r+" and the open above failed, return an error.
                    101:         * If "w" or "w+", create the file.
                    102:         * If "a" or "a+" and the open above, create the file.
                    103:         * If "w+" or "a+", close it and reopen with the desired mode.
                    104:         */
                    105:        if (fd < 0
                    106:         && (truncate || append)
                    107:         && (fd = creat(name, CRMODE)) >= 0
                    108:         && mode != WMODE) {
                    109:                close(fd);
                    110:                fd = open(name, mode);
                    111:        }
                    112:        if (fd < 0)
                    113:                return NULL;                    /* Open failed */
                    114: 
                    115: #if    _ASCII
                    116:        if (append && !ascii)                   /* ASCII append seek above */
                    117: #else
                    118:        if (append)
                    119: #endif
                    120:                lseek(fd, 0L, SEEK_END);        /* Seek to end */
                    121: 
                    122:        /* Allocate a FILE if necessary, die on failure. */
                    123:        if (fp == NULL) {
                    124:                if ((fp = (FILE *)malloc(sizeof(FILE)+sizeof(_FILE2))) == NULL) {
                    125:                        close(fd);
                    126:                        return NULL;
                    127:                }
                    128:                fp->_f2p = (char *)fp + sizeof(FILE);
                    129:        }
                    130: 
                    131:        /* Initialize the FILE. */
                    132:        fp->_cc = 0;
                    133:        fp->_cp = NULL;
                    134:        fp->_ff1 = 0;
                    135:        fp->_fd = fd;
                    136:        fp->_ff2 = _FINUSE;
                    137:        fp->_mode = _MODE_UNINIT;
                    138:        f2p = fp->_f2p;
                    139:        f2p->_gt = &_fginit;
                    140:        f2p->_pt = &_fpinit;
                    141:        f2p->_bp = f2p->_dp = f2p->_ep = f2p->_nm = NULL;
                    142:        f2p->_uc = 0;
                    143:        if (append)
                    144:                fp->_ff2 |= _FAPPND;
                    145: #if    _ASCII
                    146:        if (ascii)
                    147:                fp->_ff2 |= _FASCII;
                    148: #if    MSDOS
                    149:        else
                    150:                _setraw(fd);
                    151: #endif
                    152: #endif
                    153:        if (mode == RMODE) {
                    154:                fp->_ff1 |= _FRONLY;
                    155:                f2p->_pt = &_fpute;
                    156:        } else if (mode == WMODE) {
                    157:                fp->_ff1 |= _FWONLY;
                    158:                f2p->_gt = &_fgete;
                    159:        } else if (mode == RWMODE)
                    160:                fp->_ff1 |= _FRW;
                    161:        return fp;
                    162: }
                    163: 
                    164: /* end of libc/stdio/_fopen.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.