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

📄 sftmp.c

📁 su 的源代码库
💻 C
字号:
/* Copyright (c) Colorado School of Mines, 2006.*//* All rights reserved.                       */#include	"sfhdr.h"/*	Create a temporary stream for read/write.**	The stream is originally created as a memory-resident stream.**	When this memory is exceeded, a real temp file will be created.**	The temp file creation sequence is somewhat convoluted so that**	pool/stack/discipline will work correctly.****	Written by David Korn and Kiem-Phong Vo.*/#if _tmp_rmfail	/* File not removable while there is an open file descriptor.** To ensure that temp files are properly removed, we need:** 1. A discipline to remove a file when the corresponding stream is closed.**    Care must be taken to close the file descriptor before removing the**    file because systems such as NT do not allow file removal while**    there is an open file handle.** 2. An atexit() function is set up to close temp files when process exits.** 3. On systems with O_TEMPORARY (e.g., NT), this is used to further ensure**    that temp files will be removed after the last handle is closed.*/typedef struct _file_s		File_t;struct _file_s{	File_t*	next;		/* link list		*/	Sfio_t*	f;		/* associated stream	*/	char	name[1];	/* temp file name	*/};static File_t*	File;		/* list pf temp files	*/#if __STD_Cstatic int _tmprmfile(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)#elsestatic int _tmprmfile(f, type, val, disc)Sfio_t*		f;int		type;Void_t*		val;Sfdisc_t*	disc;#endif{	reg File_t	*ff, *last;	NOTUSED(val);	if(type == SF_DPOP)	/* don't allow this to pop */		return -1;	if(type == SF_CLOSING)	{		(void)vtmtxlock(_Sfmutex);		for(last = NIL(File_t*), ff = File; ff; last = ff, ff = ff->next)			if(ff->f == f)				break;		if(ff)		{	if(!last)				File = ff->next;			else	last->next = ff->next;			if(_Sfnotify)				(*_Sfnotify)(f,SF_CLOSING,f->file);			CLOSE(f->file);			f->file = -1;			while(sysremovef(ff->name) < 0 && errno == EINTR)				errno = 0;			free((Void_t*)ff);		}		(void)vtmtxunlock(_Sfmutex);	}	return 0;}#if __STD_Cstatic void _rmfiles(void)#elsestatic void _rmfiles()#endif{	reg File_t	*ff, *next;	(void)vtmtxlock(_Sfmutex);	for(ff = File; ff; ff = next)	{	next = ff->next;		_tmprmfile(ff->f, SF_CLOSING, NIL(Void_t*), ff->f->disc);	}	(void)vtmtxunlock(_Sfmutex);}static Sfdisc_t	Rmdisc =	{ NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmprmfile, NIL(Sfdisc_t*) };#endif /*_tmp_rmfail*/#if __STD_Cstatic int _rmtmp(Sfio_t* f, char* file)#elsestatic int _rmtmp(f, file)Sfio_t*	f;char*	file;#endif{#if _tmp_rmfail	/* remove only when stream is closed */	reg File_t*	ff;	if(!File)		atexit(_rmfiles);	if(!(ff = (File_t*)malloc(sizeof(File_t)+strlen(file))) )		return -1;	(void)vtmtxlock(_Sfmutex);	ff->f = f;	strcpy(ff->name,file);	ff->next = File;	File = ff;	(void)vtmtxunlock(_Sfmutex);#else	/* can remove now */	while(sysremovef(file) < 0 && errno == EINTR)		errno = 0;#endif	return 0;}#if !_PACKAGE_ast#define		TMPDFLT		"/tmp"static char	**Tmppath, **Tmpcur;#if __STD_Cchar** _sfgetpath(char* path)#elsechar** _sfgetpath(path)char*	path;#endif{	reg char	*p, **dirs;	reg int		n;	if(!(path = getenv(path)) )		return NIL(char**);	for(p = path, n = 0;;)	/* count number of directories */	{	while(*p == ':')			++p;		if(*p == 0)			break;		n += 1;		while(*p && *p != ':')	/* skip dir name */			++p;	}	if(n == 0 || !(dirs = (char**)malloc((n+1)*sizeof(char*))) )		return NIL(char**);	if(!(p = (char*)malloc(strlen(path)+1)) )	{	free(dirs);		return NIL(char**);	}	strcpy(p,path);	for(n = 0;; ++n)	{	while(*p == ':')			++p;		if(*p == 0)			break;		dirs[n] = p;		while(*p && *p != ':')			++p;		if(*p == ':')			*p++ = 0;	}	dirs[n] = NIL(char*);	return dirs;}#endif /*!_PACKAGE_ast*/#if __STD_Cstatic int _tmpfd(Sfio_t* f)#elsestatic int _tmpfd(f)Sfio_t*	f;#endif{	reg char*	file;	int		fd;#if _PACKAGE_ast	if(!(file = pathtemp(NiL,PATH_MAX,NiL,"sf",&fd)))		return -1;	_rmtmp(f, file);	free(file);#else	int		t;	/* set up path of dirs to create temp files */	if(!Tmppath && !(Tmppath = _sfgetpath("TMPPATH")) )	{	if(!(Tmppath = (char**)malloc(2*sizeof(char*))) )			return -1;		if(!(file = getenv("TMPDIR")) )			file = TMPDFLT;		if(!(Tmppath[0] = (char*)malloc(strlen(file)+1)) )		{	free(Tmppath);			Tmppath = NIL(char**);			return -1;		}		strcpy(Tmppath[0],file);		Tmppath[1] = NIL(char*);	}	/* set current directory to create this temp file */	if(Tmpcur)		Tmpcur += 1;	if(!Tmpcur || !Tmpcur[0])		Tmpcur = Tmppath;	fd = -1;	for(t = 0; t < 10; ++t)	{	/* compute a random name */		static ulong	Key, A;		if(A == 0 || t > 0)	/* get a quasi-random coefficient */		{	reg int	r;			A = (ulong)time(NIL(time_t*)) ^ (((ulong)(&t)) >> 3);			if(Key == 0)				Key = (A >> 16) | ((A&0xffff)<<16);			A ^= Key;			if((r = (A-1) & 03) != 0) /* Knuth vol.2, page.16, Thm.A */				A += 4-r;		}		Key = A*Key + 987654321;		file = sfprints("%s/sf%3.3.32lu.%3.3.32lu",				Tmpcur[0], (Key>>15)&0x7fff, Key&0x7fff);		if(!file)			return -1;#if _has_oflags		if((fd = sysopenf(file,O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY,SF_CREATMODE)) >= 0)			break;#else		if((fd = sysopenf(file,O_RDONLY)) >= 0)		{	/* file already exists */			CLOSE(fd);			fd = -1;		}		else if((fd = syscreatf(file,SF_CREATMODE)) >= 0)		{	/* reopen for read and write */			CLOSE(fd);			if((fd = sysopenf(file,O_RDWR)) >= 0)				break;			/* don't know what happened but must remove file */			while(sysremovef(file) < 0 && errno == EINTR)				errno = 0;		}#endif /* _has_oflags */	}	if(fd >= 0)		_rmtmp(f, file);#endif /* _PACKAGE_ast */	return fd;}#if __STD_Cstatic int _tmpexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc)#elsestatic int _tmpexcept(f,type,val,disc)Sfio_t*		f;int		type;Void_t*		val;Sfdisc_t*	disc;#endif{	reg int		fd, m;	reg Sfio_t*	sf;	Sfio_t		newf, savf;	void		(*notifyf)_ARG_((Sfio_t*, int, int));	NOTUSED(val);	/* the discipline needs to change only under the following exceptions */	if(type != SF_WRITE && type != SF_SEEK &&	   type != SF_DPUSH && type != SF_DPOP && type != SF_DBUFFER)		return 0;	/* notify function */	notifyf = _Sfnotify;	/* try to create the temp file */	SFCLEAR(&newf,NIL(Vtmutex_t*));	newf.flags = SF_STATIC;	newf.mode = SF_AVAIL;	if((fd = _tmpfd(f)) < 0 )		return -1;	/* make sure that the notify function won't be called here since	   we are only interested in creating the file, not the stream */	_Sfnotify = 0;	sf = sfnew(&newf,NIL(Void_t*),(size_t)SF_UNBOUND,fd,SF_READ|SF_WRITE);	_Sfnotify = notifyf;	if(!sf)		return -1;	if(newf.mutex) /* don't need a mutex for this stream */	{	(void)vtmtxclrlock(newf.mutex);		(void)vtmtxclose(newf.mutex);		newf.mutex = NIL(Vtmutex_t*);	}	/* make sure that new stream has the same mode */	if((m = f->flags&(SF_READ|SF_WRITE)) != (SF_READ|SF_WRITE))		sfset(sf, ((~m)&(SF_READ|SF_WRITE)), 0);	sfset(sf, (f->mode&(SF_READ|SF_WRITE)), 1);	/* now remake the old stream into the new image */	memcpy((Void_t*)(&savf), (Void_t*)f, sizeof(Sfio_t));	memcpy((Void_t*)f, (Void_t*)sf, sizeof(Sfio_t));	f->push = savf.push;	f->pool = savf.pool;	f->rsrv = savf.rsrv;	f->proc = savf.proc;	f->mutex = savf.mutex;	f->stdio = savf.stdio;	if(savf.data)	{	SFSTRSIZE(&savf);		if(!(savf.flags&SF_MALLOC) )			(void)sfsetbuf(f,(Void_t*)savf.data,savf.size);		if(savf.extent > 0)			(void)sfwrite(f,(Void_t*)savf.data,(size_t)savf.extent);		(void)sfseek(f,(Sfoff_t)(savf.next - savf.data),0);		if((savf.flags&SF_MALLOC) )			free((Void_t*)savf.data);	}	/* announce change of status */	if(notifyf)		(*notifyf)(f,SF_NEW,f->file);	f->disc = disc->disc;	/* erase all traces of newf */	newf.data = newf.endb = newf.endr = newf.endw = NIL(uchar*);	newf.file = -1;	sfclose(&newf);	return 1;}#if __STD_CSfio_t* sftmp(reg size_t s)#elseSfio_t* sftmp(s)reg size_t	s;#endif{	reg Sfio_t*	f;	static Sfdisc_t	Tmpdisc = 			{ NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmpexcept,#if _tmp_rmfail				  &Rmdisc#else			NIL(Sfdisc_t*)#endif			};	/* start with a memory resident stream */	if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),s,-1,SF_STRING|SF_READ|SF_WRITE)) )		return NIL(Sfio_t*);	if(s != (size_t)SF_UNBOUND)	/* set up a discipline for out-of-bound, etc. */		f->disc = &Tmpdisc;	/* make the file now */	if(s == 0 && _tmpexcept(f,SF_DPOP,NIL(Void_t*),f->disc) < 0)	{	sfclose(f);		return NIL(Sfio_t*);	}	return f;}

⌨️ 快捷键说明

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