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

📄 eefile.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	statres = stat(o_name,&statb);	/* Get old file's info (if any) */#if IMAGEN	/* Now, make sure someone hasn't written the file behind our backs */	if ((styp==WF_SBUFF) && !(flags&WF_ASK)	  && b->b_fn && stat(b->b_fn, &s) >= 0)		if (s.st_mtime != b->b_mtime)		  {	char *ans;			ans = ask("Since you last read \"%s\", someone has changed it.\nDo you want to write it anyway (NOT RECOMMENDED!)? ",				   b->b_fn);			if (ans == 0 || upcase(*ans) != 'Y')			  {				ding("I suggest you either read it again, or\nwrite it to a temporary file, and merge the two versions manually.");				if (ans) chkfree(ans);				return(0);			  }			if (ans) chkfree(ans);		  }#endif /*IMAGEN*/  /* Try to get around major UNIX screw of smashing files.   * This still isn't perfect (screws up with long filenames) but...   * 1. Write out to <newname>   * 2. Rename <name> to <oldname> (may have to delete existing <oldname>)   * 3. Rename <newname> to <name>.   */	fncons(oldname,ev_fno1,o_name,ev_fno2);	/* Set up "old" filename */	fncons(newname,ev_fnn1,o_name,ev_fnn2);	/* Set up "new" filename */	unlink(newname);			/* Ensure we don't clobber */	unhoard();				/* Now give up saved FD */#if !(V6)	/* Standard V6 doesn't have access call */	if(statres >= 0)			/* If file exists, */	  {	if(access(o_name, 2) != 0)	/* check for write access */		  {	ferr_wopn();			res = 0;	/* Failure */			goto wdone;		  }	  }#endif /*-V6*/#ifdef STDWRITE	if(flags&WF_ASK)	  {	if((o_file = fopen(newname, "w")) ==0)	/* Create new output file */		  {	ferr_wopn();			res = 0;		/* Failure */			goto wdone;		  }		setbuf(o_file,obuf);	/* Ensure always have buffer */	  }	else	/* New stuff */#endif /*STDWRITE*/	  {#if !(TOPS20)		if((ofd = creat(newname,ev_filmod)) < 0)#else		if((ofd = open(newname,O_WRONLY|O_UNCONVERTED)) < 0)#endif /*TOPS20*/		  {	ferr_wopn();			res = 0;		/* Failure */			goto wdone;		  }	  }	if (styp==WF_SBUFF)		set_fn(o_name);		/* Won, so set default fn for buff */#if IMAGEN	saynow("Writing ");	switch(styp)	  {	case WF_SBUFF:	saytoo(b->b_fn); break;		case WF_SREG:	saytoo("region"); break;#if FX_WLASTKILL		case WF_SKILL:	saytoo("last kill"); break;#endif	  }	sayntoo("...");#else	saynow("Writing...");#endif /*-IMAGEN*/#if !(TOPS20)			/* T20 does all this already */	if(statres >= 0)		/* Get old file's modes */	  {				/* Try to duplicate them */		/* Do chmod first since after changing owner we may not		** have permission to change mode, at least on V6.		*/		chmod(newname,statb.st_mode & 07777);#if V6		chown(newname, (statb.st_gid<<8)|(statb.st_uid&0377));#else		chown(newname,statb.st_uid,statb.st_gid);#endif /*-V6*/	  }#if V6	/* If no old file existed, and we are a V6 system, try to set	 * the modes explicitly.  On V7 we're OK because the user can	 * diddle "umask" to get whatever is desired.	 * On TOPS-20 of course everything is all peachy.	 */	else chmod(newname, ev_filmod);#endif /*V6*/#endif /*TOPS20*/#ifdef STDWRITE	if(flags&WF_ASK)	  {	switch(styp)		  {			case WF_SBUFF:				dotcnt = e_blen();				e_gobob();				break;			case WF_SREG:				if((dotcnt = mark_dot - cur_dot) < 0)				  {	e_goff(dotcnt);					dotcnt = -dotcnt;				  }				else e_gocur();				break;			/* WF_SKILL not implemented here */		  }		while(--dotcnt >= 0)			putc(sb_getc(((SBBUF *)b)), o_file);		e_gocur();		fflush(o_file);			/* Force everything out */		res = ferror(o_file);		/* Save result of stuff */		fclose(o_file);			/* Now flush FD */	  }	else	/* New stuff */#endif /*STDWRITE*/	  {		switch(styp)		  {			case WF_SBUFF:				res = sb_fsave((SBBUF *)b, ofd);				break;			case WF_SREG:				e_gocur();				sd = e_copyn((chroff)(mark_dot - cur_dot));				res = sbx_aout(sd, 2, ofd);				sbs_del(sd);				break;#if FX_WLASTKILL			case WF_SKILL:				res = sbx_aout(kill_ring[kill_ptr], 2, ofd);				break;#endif		  }		close(ofd);	  }	if(errno = res)	  {	ferr(" Output error");		res = 0;		/* Failure */		goto wdone;	  }	else		res = 1;		/* Success so far */	if(styp == WF_SBUFF)		f_bufnotmod();		/* Reset "buffer modified" flag */	/* Here we effect the screw-prevention steps explained earlier. */	/* TOPS-20, with generation numbers, need not worry about this. */#if TOPS20	saynow("Written");#else /*-TOPS20*/#if IMAGEN	/* KLH -- This conditional bracketting is prone to lossage */	/* Only create the .BAK file once per editing session!! */	if ((styp==WF_SBUFF) || !(b->b_flags & B_BACKEDUP))	  {	if (styp==WF_SBUFF)			b->b_flags |= B_BACKEDUP;#endif /*IMAGEN*/	unlink(oldname);	/* remove any existing "old" file */	if(link(o_name,oldname) == 0)	/* Rename current to "old" */	 	unlink(o_name);		/* Here is the critical point... if we stop here, there is no		 * longer any file with the appropriate filename!!!		 */#if IMAGEN	  }	else		unlink(o_name);#endif /*IMAGEN*/	if(link(newname,o_name) == 0)	/* Rename "new" to current */	  {	unlink(newname);#if IMAGEN		sayntoo("OK");#else		saynow("Written");#endif /*-IMAGEN*/	  }	else	  {	dingtoo("rename error!");		res = 0;	  }#endif /*-TOPS20*/#if IMAGEN	/* Update the last-modified time for the file in this buffer */	if ((styp == WF_SBUFF) && b->b_fn)	  {	stat(b->b_fn, &s);		b->b_mtime = s.st_mtime;	  }#endif /*IMAGEN*/wdone:	hoard();			/* Get back a retained FD */	return(res);}/* FNCONS(dest,pre,f_name,post) *	Specialized routine to cons up a filename string into "dest", *	given prefix and postfix strings to be added onto last component of *	filename. */char *fncons(dest, pre, f_name, post)char *dest,*pre,*f_name,*post;{	register char *cp, *cp2;	char *last_fname();	cp = dest;	*cp = 0;			/* Make dest string null initially */	cp2 = last_fname(f_name);	/* Get pointer to beg of last name */	strncat(cp,f_name,cp2-f_name);	/* Copy first part of filename */	if(pre)	strcat(cp, pre);	/* If prefix exists, add it on */	cp = last_fname(cp);		/* Recheck in case levels added */	strcat(cp, cp2);		/* Now add last name */	if(cp2 = post)			/* If there's a postfix, must check */	  {	cp[FNAMELEN-strlen(cp2)] = 0;	/* and cut dest so postfix */		strcat(cp, cp2);		/* will fit on end. */	  }	return(dest);}/* LAST_FNAME(string) *	Get the last component of a file name.  Returns pointer to *	start of component; does NOT copy string! */char *last_fname(f_name)char *f_name;{	register char *cp, *p;	register int c;	p = f_name;		/* pointer to last slash */	cp = p;	while(c = *cp++)		if(c == '/')			p = cp;		/* point to after the slash */	return(p);}/* SET_FN(string) *	Set the default filename for current buffer to "string". */set_fn (string)char *string;{	register struct buffer *b;	register char *str;#if IMAGEN	register char *cp;	register int len;#endif /*IMAGEN*/	char *strdup();	b = cur_buf;	str = strdup(string);		/* Copy now in case copying self */	if(b->b_fn)		chkfree(b->b_fn);	b -> b_fn = str;#if IMAGEN	/* Do mode determination based on file name (HACK HACK) */	len = strlen(str);	b->b_flags &= ~(B_CMODE|B_TEXTMODE);	if (len > 4)	  {	if (strcmp(&str[len - 5], "draft") == 0)			b->b_flags |= B_TEXTMODE;		else		  {	cp = &str[len - 4];			if (strcmp(cp, ".txt") == 0 ||			    strcmp(cp, ".mss") == 0)				b->b_flags |= B_TEXTMODE;		  }	  }	if (len > 2)	  {	cp = &str[len - 2];		if (strcmp(cp, ".h") == 0 || strcmp(cp, ".c") == 0)			b->b_flags |= B_CMODE;	  }#endif /*IMAGEN*/	redp(RD_MODE);}/* SAVEWORLD - Attempt to save all changes user has made. *	Currently this amounts to writing out all modified buffers *	to the files $HOME/+buffername.  If a buffer is given as argument, *	only that buffer is saved. *	This is only called from the error handling routines with *	the TTY either gone or in normal (non-edit) mode.  The "grunt" *	flag says whether to output feedback during the saving process. */saveworld(bp, grunt)struct buffer *bp;int grunt;{	register struct buffer *b;	register int wfd;	char sfname[FNAMSIZ];	struct buffer *sel_mbuf();	unhoard();		/* Ensure a FD is free for writing */	if(b = bp) goto once;	while(!bp && (b = sel_mbuf(b)))	  {	once:	strcat(strcat(strcpy(sfname,homedir),"/+"),b->b_name);		if(grunt) printf("Saving %s...",sfname);#if !(TOPS20)		if((wfd = creat(sfname, ev_filmod)) < 0)#else		if((wfd = open(sfname,O_WRONLY|O_UNCONVERTED)) < 0)#endif /*TOPS20*/		  {	if(grunt)				printf(" error - %s\n", strerror(errno));		  }		else		  {	sb_fsave((SBBUF *)b, wfd);			close(wfd);			if(grunt) printf("\n");		  }		b->b_flags &= ~B_MODIFIED;	  }	hoard();}/* HOARD, UNHOARD - Routines to save a FD for writing, to make sure *	that we can always write out a buffer no matter how many *	file descriptors we are currently using. */hoard()			/* Stash away a FD */{	if(hoardfd <= 0)#if !(TOPS20)		hoardfd = open("nul:", 1);#else		hoardfd = open("/dev/null", 1);#endif}unhoard()		/* Give up our stashed FD so it can be re-used */{	close(hoardfd);	hoardfd = -1;}#if IMAGEN#include <pwd.h>#include <ctype.h>/* * expand_file: expand any ~user-name/ or $env-var/ prefixes in sfn, * producing the full name in dfn */expand_file(dfn, sfn)register char *dfn, *sfn;{	register char *sp, *tp;	register int c;	register struct passwd *pw;	char ts[128];	/* HORRIBLE, GROSS, DISGUSTING HACK: if the destination and	 * source strings are identical (same pointer), then do not	 * do any expansion--this happens to work with the current	 * structure very well, since multiple expansions may happen.	 */	if (dfn == sfn)		return;	ts[0] = 0;	/* If have a leading $, then expand environment variable */	if (*sfn == '$')	  {	++sfn;		tp = ts;		while (*tp++ = *sfn)			if (!isalnum(*sfn))				break;			else				++sfn;		*--tp = 0;		/* Just in case */		strcpy(ts, getenv(ts));	/* MARGINAL!! */	  }	/* If have leading ~, then expand login name (null means $HOME) */	else if (*sfn == '~')	  {	++sfn;		if (*sfn == '/' || *sfn == 0)			strcpy(ts, getenv("HOME"));		else		  {	tp = ts;			while (*sfn && *sfn != '/')				*tp++ = *sfn++;			*tp = 0;			pw = (struct passwd *)getpwnam(ts);			if (! pw)				strcpy(ts, "???");			else				strcpy(ts, pw->pw_dir);		  }	  }	/* Now, ts is either empty or contains the expansion;	 * sfn has been updated correctly.	 */	strcpy(dfn, ts);	strcat(dfn, sfn);}#endif /*IMAGEN*/

⌨️ 快捷键说明

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