|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.