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