File:  [MW Coherent from dump] / coherent / b / lib / libc / XSTDIO / _fopen.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:36 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * libc/stdio/_fopen.c
 * ANSI-compliant C standard i/o library internals.
 * _fopen()
 * Open a file.
 */

/*
 * The recognized mode strings are as follows:
n *	mode a.k.a.  notfound	found	mode   truncate	append
 *	r		error	read	RMODE	0	0
 *	w		create	trunc.	WMODE	1	0
 *	a		create	append	WMODE	0	1
 *	r+   rw r+w	error	rd.&wr.	RWMODE	0	0
 *	w+   wr w+r	create	trunc.	RWMODE	1	0
 *	a+   ar a+r	create	app.&rd	RWMODE	0	1
 * In all cases, a trailing 'b' means ascii==1, otherwise ascii==0.
 * ANSI 4.9.5.3 requires only the first mode forms above (e.g. "r+")
 * but tolerates the alternate forms (e.g. "r+w" or "rw",
 * see code involving local 'cn' below).
 * Use the given FILE if fp is not NULL, otherwise allocate a new FILE.
 * Use the given fd if nonnegative.
 * The get and put function pointers in the FILE are initialized
 * later, possibly after a setvbuf() call specifying desired buffering.
 */

#include <stdio.h>
#include <stdlib.h>

#define	RMODE	0
#define	WMODE	1
#define	RWMODE	2
#define	CRMODE	0666	/* default access permissions on create */

FILE *
_fopen(name, type, fp, fd) char *name, *type; register FILE *fp; register int fd;
{
	register _FILE2	*f2p;
	register int	mode;
	int		truncate, append, ascii;
	char		c, cn;

	/* Parse the type string and set flags accordingly. */
	mode = WMODE;
	ascii = 1;
	truncate = append = 0;
	cn = 'r';
	if ((c = *type++) == 'r') {
		mode = RMODE;
		cn = 'w';
	} else if (c=='w')
		truncate++;
	else if (c=='a')
		append++;
	else
		return NULL;
	if ((c = *type) != '\0') {
		if (c == 'b') {
			ascii = 0;
			c = *++type;
		}
		if (c == '+') {
			mode = RWMODE;
			c = *++type;
		}
		if (c == cn) {
			mode = RWMODE;
			c = *++type;
		}
		if (c == 'b') {
			ascii = 0;
			c = *++type;
		}
		if (c != '\0')
			return NULL;
	}

#if	_ASCII
	/*
	 * Beware of ASCII files ending with ASCII EOF character in append mode.
	 * Open for r+w, to allow checking last character.
	 */
	if (append
	 && ascii
	 && (fd >= 0 || (fd = open(name, RWMODE)) >=0)) {
		if (lseek(fd, -1L, SEEK_END) != -1L) {	/* seek to end-1 */
			if (read(fd, &c, 1) == 1	/* read last char */
			 && c == _EOFCHAR)		/* last char is EOF */
				lseek(fd, -1L, SEEK_CUR); /* so unread it */
		} else					/* might be empty */
			lseek(fd, 0L, SEEK_END);
	}
#endif

	/* Try opening existing file, unless truncation is specified. */
	if (fd < 0 && !truncate)
		fd = open(name, mode);

	/*
	 * If "r" or "r+" and the open above failed, return an error.
	 * If "w" or "w+", create the file.
	 * If "a" or "a+" and the open above, create the file.
	 * If "w+" or "a+", close it and reopen with the desired mode.
	 */
	if (fd < 0
	 && (truncate || append)
	 && (fd = creat(name, CRMODE)) >= 0
	 && mode != WMODE) {
		close(fd);
		fd = open(name, mode);
	}
	if (fd < 0)
		return NULL;			/* Open failed */

#if	_ASCII
	if (append && !ascii)			/* ASCII append seek above */
#else
	if (append)
#endif
		lseek(fd, 0L, SEEK_END);	/* Seek to end */

	/* Allocate a FILE if necessary, die on failure. */
	if (fp == NULL) {
		if ((fp = (FILE *)malloc(sizeof(FILE)+sizeof(_FILE2))) == NULL) {
			close(fd);
			return NULL;
		}
		fp->_f2p = (char *)fp + sizeof(FILE);
	}

	/* Initialize the FILE. */
	fp->_cc = 0;
	fp->_cp = NULL;
	fp->_ff1 = 0;
	fp->_fd = fd;
	fp->_ff2 = _FINUSE;
	fp->_mode = _MODE_UNINIT;
	f2p = fp->_f2p;
	f2p->_gt = &_fginit;
	f2p->_pt = &_fpinit;
	f2p->_bp = f2p->_dp = f2p->_ep = f2p->_nm = NULL;
	f2p->_uc = 0;
	if (append)
		fp->_ff2 |= _FAPPND;
#if	_ASCII
	if (ascii)
		fp->_ff2 |= _FASCII;
#if	MSDOS
	else
		_setraw(fd);
#endif
#endif
	if (mode == RMODE) {
		fp->_ff1 |= _FRONLY;
		f2p->_pt = &_fpute;
	} else if (mode == WMODE) {
		fp->_ff1 |= _FWONLY;
		f2p->_gt = &_fgete;
	} else if (mode == RWMODE)
		fp->_ff1 |= _FRW;
	return fp;
}

/* 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.