Annotation of coherent/b/lib/libc/stdio/_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:  *     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: #include "stdio.int.h"
                     30: 
                     31: #define        RMODE   0
                     32: #define        WMODE   1
                     33: #define        RWMODE  2
                     34: #define        CRMODE  0666    /* default access permissions on create */
                     35: 
                     36: FILE *
                     37: _fopen(name, type, fp, fd) char *name, *type; register FILE *fp; register int fd;
                     38: {
                     39:        register _FILE2 *f2p;
                     40:        register int    mode;
                     41:        int             truncate, append, ascii;
                     42:        char            c, cn;
                     43: 
                     44:        /* Parse the type string and set flags accordingly. */
                     45:        mode = WMODE;
                     46:        ascii = 1;
                     47:        truncate = append = 0;
                     48:        cn = 'r';
                     49:        if ((c = *type++) == 'r') {
                     50:                mode = RMODE;
                     51:                cn = 'w';
                     52:        } else if (c=='w')
                     53:                truncate++;
                     54:        else if (c=='a')
                     55:                append++;
                     56:        else
                     57:                return NULL;
                     58:        if ((c = *type) != '\0') {
                     59:                if (c == 'b') {
                     60:                        ascii = 0;
                     61:                        c = *++type;
                     62:                }
                     63:                if (c == '+') {
                     64:                        mode = RWMODE;
                     65:                        c = *++type;
                     66:                }
                     67:                if (c == cn) {
                     68:                        mode = RWMODE;
                     69:                        c = *++type;
                     70:                }
                     71:                if (c == 'b') {
                     72:                        ascii = 0;
                     73:                        c = *++type;
                     74:                }
                     75:                if (c != '\0')
                     76:                        return NULL;
                     77:        }
                     78: 
                     79: #if    _ASCII
                     80:        /*
                     81:         * Beware of ASCII files ending with ASCII EOF character in append mode.
                     82:         * Open for r+w, to allow checking last character.
                     83:         */
                     84:        if (append
                     85:         && ascii
                     86:         && (fd >= 0 || (fd = open(name, RWMODE)) >=0)) {
                     87:                if (lseek(fd, -1L, SEEK_END) != -1L) {  /* seek to end-1 */
                     88:                        if (read(fd, &c, 1) == 1        /* read last char */
                     89:                         && c == _EOFCHAR)              /* last char is EOF */
                     90:                                lseek(fd, -1L, SEEK_CUR); /* so unread it */
                     91:                } else                                  /* might be empty */
                     92:                        lseek(fd, 0L, SEEK_END);
                     93:        }
                     94: #endif
                     95: 
                     96:        /* Try opening existing file, unless truncation is specified. */
                     97:        if (fd < 0 && !truncate)
                     98:                fd = open(name, mode);
                     99: 
                    100:        /*
                    101:         * If "r" or "r+" and the open above failed, return an error.
                    102:         * If "w" or "w+", create the file.
                    103:         * If "a" or "a+" and the open above, create the file.
                    104:         * If "w+" or "a+", close it and reopen with the desired mode.
                    105:         */
                    106:        if (fd < 0
                    107:         && (truncate || append)
                    108:         && (fd = creat(name, CRMODE)) >= 0
                    109:         && mode != WMODE) {
                    110:                close(fd);
                    111:                fd = open(name, mode);
                    112:        }
                    113:        if (fd < 0)
                    114:                return NULL;                    /* Open failed */
                    115: 
                    116: #if    _ASCII
                    117:        if (append && !ascii)                   /* ASCII append seek above */
                    118: #else
                    119:        if (append)
                    120: #endif
                    121:                lseek(fd, 0L, SEEK_END);        /* Seek to end */
                    122: 
                    123:        /* Allocate a FILE if necessary, die on failure. */
                    124:        if (fp == NULL) {
                    125:                if ((fp = (FILE *)malloc(sizeof(FILE)+sizeof(_FILE2))) == NULL) {
                    126:                        close(fd);
                    127:                        return NULL;
                    128:                }
                    129:                fp->_f2p = (char *)fp + sizeof(FILE);
                    130:        }
                    131: 
                    132:        /* Initialize the FILE. */
                    133:        fp->_cc = 0;
                    134:        fp->_cp = NULL;
                    135:        fp->_ff1 = 0;
                    136:        fp->_fd = fd;
                    137:        fp->_ff2 = _FINUSE;
                    138:        fp->_mode = _MODE_UNINIT;
                    139:        f2p = fp->_f2p;
                    140:        f2p->_gt = &_fginit;
                    141:        f2p->_pt = &_fpinit;
                    142:        f2p->_bp = f2p->_dp = f2p->_ep = f2p->_nm = NULL;
                    143:        f2p->_uc = 0;
                    144:        if (append)
                    145:                fp->_ff2 |= _FAPPND;
                    146: #if    _ASCII
                    147:        if (ascii)
                    148:                fp->_ff2 |= _FASCII;
                    149: #if    MSDOS
                    150:        else
                    151:                _setraw(fd);
                    152: #endif
                    153: #endif
                    154:        if (mode == RMODE) {
                    155:                fp->_ff1 |= _FRONLY;
                    156:                f2p->_pt = &_fpute;
                    157:        } else if (mode == WMODE) {
                    158:                fp->_ff1 |= _FWONLY;
                    159:                f2p->_gt = &_fgete;
                    160:        } else if (mode == RWMODE)
                    161:                fp->_ff1 |= _FRW;
                    162:        return fp;
                    163: }
                    164: 
                    165: /* 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.