⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		fnamebuf[FILESIZE];#ifdef	MAC	if (Macmode) {		if (!(fname = pfile(fnamebuf)))			return;	} else#endif	/* MAC */		fname = ask_file((char *)NULL, curbuf->b_fname, fnamebuf);	/* Don't allow bad characters when creating new files. */	if (!OkayBadChars	&& (curbuf->b_fname==NULL || strcmp(curbuf->b_fname, fnamebuf) != 0))	{#ifdef	UNIX		static const char	badchars[] = "!$^&*()~`{}\"'\\|<>? ";#endif	/* UNIX */#ifdef	MSDOS		static const char	badchars[] = "*|<>? ";#endif	/* MSDOS */#ifdef	MAC		static const char	badchars[] = ":";#endif	/* MAC */		register char	*cp = fnamebuf;		register int	c;		while ((c = *cp++ & CHARMASK) != '\0')	/* avoid sign extension... */			if (c < ' ' || c == '\177' || strchr(badchars, c))				complain("'%p': bad character in filename.", c);	}	chk_mtime(curbuf, fname, "write");	filemunge(fname);	curbuf->b_type = B_FILE;	/* in case it wasn't before */	setfname(curbuf, fname);	file_write(fname, NO);}/* Open file FNAME supplying the buffer IO routine with buffer BUF.   HOW is F_READ, F_WRITE or F_APPEND.  IFBAD == COMPLAIN means that   if we fail at opening the file, call complain.  LOUDNESS says   whether or not to print the "reading ..." message on the message   line.   NOTE:  This opens the pr_name(fname, NO) of fname.  That is, FNAME	  is usually an entire pathname, which can be slow when the	  pathname is long and there are lots of symbolic links along	  the way (which has become very common in my experience).  So,	  this speeds up opens file names in the local directory.  It	  will not speed up things like "../scm/foo.scm" simple because	  by the time we get here that's already been expanded to an	  absolute pathname.  But this is a start.   */File *open_file(fname, buf, how, complainifbad, quiet)register char	*fname;char	*buf;register int	how;int	complainifbad,	quiet;{	register File	*fp;	io_chars = 0;	io_lines = 0;	fp = f_open(pr_name(fname, NO), how, buf, LBSIZE);	if (fp == NULL) {		message(IOerr((how == F_READ) ? "open" : "create", fname));		if (complainifbad)			complain((char *)NULL);	} else {		int	rd_only = FALSE;#ifndef	MAC		if (access(pr_name(fname, NO), W_OK) == -1 && errno != ENOENT) {			rd_only = TRUE;			fp->f_flags |= F_READONLY;		}#endif		if (!quiet) {			fp->f_flags |= F_TELLALL;			f_mess("\"%s\"%s", pr_name(fname, YES),				   rd_only ? " [Read only]" : NullStr);		}	}	return fp;}#ifndef	MSDOS/* Check to see if the file has been modified since it was   last written.  If so, make sure they know what they're   doing.   I hate to use another stat(), but to use confirm we gotta   do this before we open the file.   NOTE: This stats FNAME after converting it to a path-relative	 name.  I can't see why this would cause a problem ...   */voidchk_mtime(thisbuf, fname, how)Buffer	*thisbuf;char	*fname,	*how;{	struct stat	stbuf;	Buffer	*b;	static const char	mesg[] = "Shall I go ahead and %s anyway? ";	if ((thisbuf->b_mtime != 0) &&		/* if we care ... */	    ((b = file_exists(fname)) != NULL) &&		/* we already have this file */	    (b == thisbuf) &&			/* and it's the current buffer */	    (stat(pr_name(fname, NO), &stbuf) != -1) &&	/* and we can stat it */	    (stbuf.st_mtime != b->b_mtime)) {	/* and there's trouble. */		rbell();		redisplay();	/* Ring that bell! */		TOstart("Warning", TRUE);		Typeout("\"%s\" now saved on disk is not what you last", pr_name(fname, YES));		Typeout("visited or saved.  Probably someone else is editing");		Typeout("your file at the same time.");		if (how) {			Typeout("");			Typeout("Type \"y\" if I should %s, anyway.", how);			f_mess(mesg, how);		}		TOstop();		if (how)			confirm(mesg, how);	}}#endif	/* !MSDOS */voidfile_write(fname, app)char	*fname;bool	app;{	File	*fp;#ifdef	BACKUPFILES	if (!app && BkupOnWrite)		file_backup(fname);#endif	fp = open_file(fname, iobuff, app ? F_APPEND : F_WRITE, YES, NO);	if (EndWNewline) {	/* Make sure file ends with a newLine */		Bufpos	save;		DOTsave(&save);		ToLast();		if (length(curline))	/* Not a blank Line */			LineInsert(1);		SetDot(&save);	}	putreg(fp, curbuf->b_first, 0, curbuf->b_last, length(curbuf->b_last), NO);	close_file(fp);	set_ino(curbuf);	unmodify();}voidReadFile(){	Buffer	*bp;	char	*fname,		fnamebuf[FILESIZE];	int	lineno;#ifdef	MAC	if (Macmode) {		if (!(fname = gfile(fnamebuf)))			return;	} else#endif	/* MAC */		fname = ask_file((char *)NULL, curbuf->b_fname, fnamebuf);	chk_mtime(curbuf, fname, "read");	if (IsModified(curbuf)) {		char	*y_or_n;		int	c;		for (;;) {			rbell();			y_or_n = ask(NullStr, "Shall I make your changes to \"%s\" permanent? ", curbuf->b_name);			c = CharUpcase(*y_or_n);			if (c == 'Y' || c == 'N')				break;		}		if (c == 'Y')			SaveFile();	}	if ((bp = file_exists(fnamebuf)) != NULL &&	    (bp == curbuf))		lineno = pnt_line() - 1;	else		lineno = 0;	unmodify();	initlist(curbuf);	setfname(curbuf, fname);	read_file(fname, NO);	SetLine(next_line(curbuf->b_first, lineno));}voidInsFile(){	char	*fname,		fnamebuf[FILESIZE];#ifdef	MAC	if (Macmode) {		if (!(fname = gfile(fnamebuf)))			return;	} else#endif	/* MAC */		fname = ask_file((char *)NULL, curbuf->b_fname, fnamebuf);	read_file(fname, YES);}#include "temp.h"bool	DOLsave = NO;	/* Do Lsave flag.  If lines aren't being saved			   when you think they should have been, this			   flag is probably not being set, or is being			   cleared before lsave() was called. */private int	nleft,	/* number of good characters left in current block */		tmpfd = -1;daddr	DFree = 1;  /* pointer to end of tmp file */private char	*tfname;private voidtmpinit(){	char	buf[FILESIZE];#ifdef	MAC	swritef(buf, sizeof(buf), "%s/%s", HomeDir, d_tempfile);#else	swritef(buf, sizeof(buf), "%s/%s", TmpFilePath, d_tempfile);#endif	tfname = copystr(buf);	tfname = mktemp(tfname);	(void) close(creat(tfname, 0600));#ifndef	MSDOS	tmpfd = open(tfname, 2);#else	/* MSDOS */	tmpfd = open(tfname, 0x8002);	/* MSDOS fix */#endif	/* MSDOS */	if (tmpfd == -1)		complain("Warning: cannot create tmp file! %s", strerror(errno));}/* Close tempfile before execing a child process. * Since we might be vforking, we must not change any variables * (in particular tmpfd). */voidtmpclose(){	if (tmpfd != -1)		(void) close(tmpfd);}/* Close and remove tempfile before exiting. */voidtmpremove(){	if (tmpfd != -1) {		tmpclose();		(void) unlink(tfname);	}}/* get a line at `tl' in the tmp file into `buf' which should be LBSIZE   long */int	Jr_Len;		/* length of Just Read Line */voidgetline(addr, buf)daddr	addr;register char	*buf;{	register char	*bp,			*lp;	lp = buf;	bp = getblock(addr >> 1, FALSE);	do ; while ((*lp++ = *bp++) != '\0');	Jr_Len = (lp - buf) - 1;}/* Put `buf' and return the disk address */daddrputline(buf)char	*buf;{	register char	*bp,			*lp;	register int	nl;	daddr	free_ptr;	lp = buf;	free_ptr = DFree;	bp = getblock(free_ptr, TRUE);	nl = nleft;	free_ptr = blk_round(free_ptr);	while ((*bp = *lp++) != '\0') {		if (*bp++ == '\n') {			*--bp = '\0';			break;		}		if (--nl == 0) {			free_ptr = forward_block(free_ptr);			DFree = free_ptr;			bp = getblock(free_ptr, TRUE);			lp = buf;	/* start over ... */			nl = nleft;		}	}	free_ptr = DFree;	DFree += (((lp - buf) + CH_SIZE - 1) / CH_SIZE);		 /* (lp - buf) includes the null */	return (free_ptr << 1);}/* The theory is that critical section of code inside this procedure   will never cause a problem to occur.  Basically, we need to ensure   that two blocks are in memory at the same time, but I think that   this can never screw up. */#define lockblock(addr)#define unlockblock(addr)private boolf_getputl(line, fp)Line	*line;register File	*fp;{	register char	*bp;	register int	c,			nl,			room = LBSIZE-1;	daddr		free_ptr;	char		*base;	free_ptr = DFree;	base = bp = getblock(free_ptr, TRUE);	nl = nleft;	free_ptr = blk_round(free_ptr);	do {		/* We can't store NUL in our buffer, so ignore it.		 * Of course, with a little ingenuity we could:		 * NUL could be represented by \n!		 */		c = jgetc(fp);		if (c == '\0')			continue;#ifdef	MSDOS		if (c == '\r')			continue;#endif	/* MSDOS */		if (c == EOF || c == '\n')			break;		if (--nl == 0) {			char	*newbp;			size_t	nbytes;			lockblock(free_ptr);			DFree = free_ptr = forward_block(free_ptr);			nbytes = bp - base;			newbp = getblock(free_ptr, TRUE);			nl = nleft;			byte_copy(base, newbp, nbytes);			bp = newbp + nbytes;			base = newbp;			unlockblock(free_ptr);		}		*bp++ = c;	} while (--room > 0);	*bp++ = '\0';	free_ptr = DFree;	DFree += (((bp - base) + CH_SIZE - 1) / CH_SIZE);	line->l_dline = (free_ptr << 1);	if (room == 0) {		add_mess(" [Line too long]");		rbell();		return YES;	}	if (c == EOF) {		if (--bp != base)			add_mess(" [Incomplete last line]");		return YES;	}	io_lines += 1;	return NO;}typedef struct block {	char	b_dirty;	/* (bool) */	short	b_bno;	char	b_buf[JBUFSIZ];	struct block		*b_LRUnext,		*b_LRUprev,		*b_HASHnext;} Block;#define HASHSIZE	7	/* Primes work best (so I'm told) */#define B_HASH(bno)	((bno) % HASHSIZE)#ifdef	MACprivate Block	*b_cache,#elseprivate Block	b_cache[NBUF],#endif		*bht[HASHSIZE],		/* Block hash table. Must be zero initially */		*f_block = NULL,		*l_block = NULL;private int	max_bno = -1,		NBlocks;private void	(*blkio) ptrproto((Block *, int (*) ptrproto((int, UnivPtr, size_t))));#ifdef	MACpublic boolmake_cache()	/* Only 32K of static space on Mac, so... */{	return (b_cache = (Block *) calloc(NBUF,sizeof(Block))) != NULL;}#endif	/* MAC */private voidreal_blkio(b, iofcn)register Block	*b;register int	(*iofcn) ptrproto((int, UnivPtr, size_t));{	(void) lseek(tmpfd, (long) ((unsigned) b->b_bno) * JBUFSIZ, 0);	if ((*iofcn)(tmpfd, (UnivPtr) b->b_buf, (size_t)JBUFSIZ) != JBUFSIZ)		error("[Tmp file %s error: to continue editing would be dangerous]",			(iofcn == read) ? "READ" : "WRITE");}private voidfake_blkio(b, iofcn)register Block	*b;register int	(*iofcn) ptrproto((int, UnivPtr, size_t));{	tmpinit();	blkio = real_blkio;	real_blkio(b, iofcn);}voidd_cache_init(){	register Block	*bp,	/* Block pointer */			**hp;	/* Hash pointer */	register short	bno;	for (bp = b_cache, bno = NBUF; --bno >= 0; bp++) {		NBlocks += 1;		bp->b_dirty = NO;		bp->b_bno = bno;		if (l_block == NULL)			l_block = bp;		bp->b_LRUprev = NULL;		bp->b_LRUnext = f_block;		if (f_block != NULL)			f_block->b_LRUprev = bp;		f_block = bp;		bp->b_HASHnext = *(hp = &bht[B_HASH(bno)]);		*hp = bp;	}	blkio = fake_blkio;}voidSyncTmp(){	register Block	*b;#ifdef	IBMPC	register int	bno = 0;	/* sync the blocks in order, for file systems that don't allow	   holes (MSDOS).  Perhaps this benefits floppy-based file systems. */	for (bno = 0; bno <= max_bno; ) {		if ((b = lookup(bno++)) && b->b_dirty) {			(*blkio)(b, write);			b->b_dirty = NO;		}	}#else	for (b = f_block; b != NULL; b = b->b_LRUnext)		if (b->b_dirty) {			(*blkio)(b, (int (*) ptrproto((int, UnivPtr, size_t)))write);			b->b_dirty = NO;		}#endif}private Block *lookup(bno)register short	bno;{	register Block	*bp;	for (bp = bht[B_HASH(bno)]; bp != NULL; bp = bp->b_HASHnext)		if (bp->b_bno == bno)			break;	return bp;}private voidLRUunlink(b)register Block	*b;{	if (b->b_LRUprev == NULL)		f_block = b->b_LRUnext;	else		b->b_LRUprev->b_LRUnext = b->b_LRUnext;	if (b->b_LRUnext == NULL)		l_block = b->b_LRUprev;	else		b->b_LRUnext->b_LRUprev = b->b_LRUprev;}private Block *b_unlink(bp)register Block	*bp;{	register Block	*hp,			*prev = NULL;	LRUunlink(bp);	/* Now that we have the block, we remove it from its position	   in the hash table, so we can THEN put it somewhere else with	   it's new block assignment. */	for (hp = bht[B_HASH(bp->b_bno)]; hp != NULL; prev = hp, hp = hp->b_HASHnext)		if (hp == bp)			break;	if (hp == NULL) {		writef("\rBlock %d missing!", bp->b_bno);		finish(0);	}	if (prev)		prev->b_HASHnext = hp->b_HASHnext;	else		bht[B_HASH(bp->b_bno)] = hp->b_HASHnext;	if (bp->b_dirty) {	/* do, now, the delayed write */		(*blkio)(bp, (int (*) ptrproto((int, UnivPtr, size_t)))write);		bp->b_dirty = NO;	}	return bp;}/* Get a block which contains at least part of the line with the address   atl.  Returns a pointer to the block and sets the global variable   nleft (number of good characters left in the buffer). */private char *getblock(atl, IsWrite)daddr	atl;bool	IsWrite;{	register int	bno,			off;	register Block	*bp;	static Block	*lastb = NULL;	bno = da_to_bno(atl);	off = da_to_off(atl);	if (da_too_huge(atl))		error("Tmp file too large.  Get help!");	nleft = JBUFSIZ - off;	if (lastb != NULL && lastb->b_bno == bno) {		lastb->b_dirty |= IsWrite;		return lastb->b_buf + off;	}	/* The requested block already lives in memory, so we move	   it to the end of the LRU list (making it Most Recently Used)	   and then return a pointer to it. */	if ((bp = lookup(bno)) != NULL) {		if (bp != l_block) {			LRUunlink(bp);			if (l_block == NULL)				f_block = l_block = bp;			else				l_block->b_LRUnext = bp;			bp->b_LRUprev = l_block;			l_block = bp;			bp->b_LRUnext = NULL;		}		if (bp->b_bno > max_bno)			max_bno = bp->b_bno;		bp->b_dirty |= IsWrite;		lastb = bp;		return bp->b_buf + off;	}	/* The block we want doesn't reside in memory so we take the	   least recently used clean block (if there is one) and use	   it.  */	bp = f_block;	if (bp->b_dirty)	/* The best block is dirty ... */		SyncTmp();	bp = b_unlink(bp);	if (l_block == NULL)		l_block = f_block = bp;	else		l_block->b_LRUnext = bp;	/* Place it at the end ... */	bp->b_LRUprev = l_block;	l_block = bp;	bp->b_LRUnext = NULL;		/* so it's Most Recently Used */	bp->b_dirty = IsWrite;	bp->b_bno = bno;	bp->b_HASHnext = bht[B_HASH(bno)];	bht[B_HASH(bno)] = bp;	/* Get the current contents of the block UNLESS this is a new	   block that's never been looked at before, i.e., it's past	   the end of the tmp file. */	if (bp->b_bno <= max_bno)		(*blkio)(bp, read);	else		max_bno = bno;	lastb = bp;	return bp->b_buf + off;}char *lbptr(line)Line	*line;{	return getblock(line->l_dline >> 1, FALSE);}/* save the current contents of linebuf, if it has changed */voidlsave(){	if (curbuf == NULL || !DOLsave)	/* Nothing modified recently */		return;	if (strcmp(lbptr(curline), linebuf) != 0)		SavLine(curline, linebuf);	/* Put linebuf on the disk. */	DOLsave = NO;}#ifdef	BACKUPFILESprivate voidfile_backup(fname)char *fname;{#ifndef	MSDOS	char	*s;	register int	i;	int	fd1,		fd2;	char	tmp1[JBUFSIZ],		tmp2[JBUFSIZ];	struct stat buf;	int	mode;	strcpy(tmp1, fname);	if ((s = strrchr(tmp1, '/')) == NULL)		swritef(tmp2, sizeof(tmp2), "#%s~", fname);	else {		*s++ = '\0';		swritef(tmp2, sizeof(tmp2), "%s/#%s~", tmp1, s);	}	if ((fd1 = open(fname, 0)) < 0)		return;	/* create backup file with same mode as input file */#ifndef	MAC	if (fstat(fd1, &buf) != 0)		mode = CreatMode;	else#endif		mode = buf.st_mode;	if ((fd2 = creat(tmp2, mode)) < 0) {		(void) close(fd1);		return;	}	while ((i = read(fd1, (UnivPtr) tmp1, sizeof(tmp1))) > 0)		write(fd2, (UnivPtr) tmp1, (size_t) i);#ifdef	BSD4_2	(void) fsync(fd2);#endif	(void) close(fd2);	(void) close(fd1);#else	/* MSDOS */	char	*dot,			*slash,			tmp[FILESIZE];	strcpy(tmp, fname);	slash = basename(tmp);	if (dot = strrchr(slash, '.')) {		if (!stricmp(dot,".bak"))			return;		*dot = '\0';	}	strcat(tmp, ".bak");	unlink(tmp);	rename(fname, tmp);#endif	/* MSDOS */}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -