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

📄 tables.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
    bad:	warn(1, "Unable to fix truncated inode/device field when storing %s",	    arcn->name);	warn(0, "Archive may create improper hard links when extracted");	return(0);}/* * directory access/mod time reset table routines (for directories READ by pax) * * The pax -t flag requires that access times of archive files to be the same * before being read by pax. For regular files, access time is restored after * the file has been copied. This database provides the same functionality for * directories read during file tree traversal. Restoring directory access time * is more complex than files since directories may be read several times until * all the descendants in their subtree are visited by fts. Directory access * and modification times are stored during the fts pre-order visit (done * before any descendants in the subtree is visited) and restored after the * fts post-order visit (after all the descendants have been visited). In the * case of premature exit from a subtree (like from the effects of -n), any * directory entries left in this database are reset during final cleanup * operations of pax. Entries are hashed by inode number for fast lookup. *//* * atdir_start() *	create the directory access time database for directories READ by pax. * Return: *	0 is created ok, -1 otherwise. */#if __STDC__intatdir_start(void)#elseintatdir_start()#endif{	if (atab != NULL)		return(0); 	if ((atab = (ATDIR **)calloc(A_TAB_SZ, sizeof(ATDIR *))) == NULL) {                warn(1,"Cannot allocate space for directory access time table");                return(-1);        }	return(0);}/* * atdir_end() *	walk through the directory access time table and reset the access time *	of any directory who still has an entry left in the database. These *	entries are for directories READ by pax */#if __STDC__voidatdir_end(void)#elsevoidatdir_end()#endif{	register ATDIR *pt;	register int i;	if (atab == NULL)		return;	/*	 * for each non-empty hash table entry reset all the directories	 * chained there.	 */	for (i = 0; i < A_TAB_SZ; ++i) {		if ((pt = atab[i]) == NULL)			continue;		/*		 * remember to force the times, set_ftime() looks at pmtime		 * and patime, which only applies to things CREATED by pax,		 * not read by pax. Read time reset is controlled by -t.		 */		for (; pt != NULL; pt = pt->fow)			set_ftime(pt->name, pt->mtime, pt->atime, 1);	}}/* * add_atdir() *	add a directory to the directory access time table. Table is hashed *	and chained by inode number. This is for directories READ by pax */#if __STDC__voidadd_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)#elsevoidadd_atdir(fname, dev, ino, mtime, atime)	char *fname;	dev_t dev;	ino_t ino;	time_t mtime;	time_t atime;#endif{	register ATDIR *pt;	register u_int indx;	if (atab == NULL)		return;	/*	 * make sure this directory is not already in the table, if so just 	 * return (the older entry always has the correct time). The only	 * way this will happen is when the same subtree can be traversed by	 * different args to pax and the -n option is aborting fts out of a	 * subtree before all the post-order visits have been made).	 */	indx = ((unsigned)ino) % A_TAB_SZ;	if ((pt = atab[indx]) != NULL) {		while (pt != NULL) {			if ((pt->ino == ino) && (pt->dev == dev))				break;			pt = pt->fow;		}		/*		 * oops, already there. Leave it alone.		 */		if (pt != NULL)			return;	}	/*	 * add it to the front of the hash chain	 */	if ((pt = (ATDIR *)malloc(sizeof(ATDIR))) != NULL) {		if ((pt->name = strdup(fname)) != NULL) {			pt->dev = dev;			pt->ino = ino;			pt->mtime = mtime;			pt->atime = atime;			pt->fow = atab[indx];			atab[indx] = pt;			return;		}		(void)free((char *)pt);	}	warn(1, "Directory access time reset table ran out of memory");	return;}/* * get_atdir() *	look up a directory by inode and device number to obtain the access *	and modification time you want to set to. If found, the modification *	and access time parameters are set and the entry is removed from the *	table (as it is no longer needed). These are for directories READ by *	pax * Return: *	0 if found, -1 if not found. */#if __STDC__intget_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)#elseintget_atdir(dev, ino, mtime, atime)	dev_t dev;	ino_t ino;	time_t *mtime;	time_t *atime;#endif{	register ATDIR *pt;	register ATDIR **ppt;	register u_int indx;	if (atab == NULL)		return(-1);	/*	 * hash by inode and search the chain for an inode and device match	 */	indx = ((unsigned)ino) % A_TAB_SZ;	if ((pt = atab[indx]) == NULL)		return(-1);	ppt = &(atab[indx]);	while (pt != NULL) {		if ((pt->ino == ino) && (pt->dev == dev))			break;		/*		 * no match, go to next one		 */		ppt = &(pt->fow);		pt = pt->fow;	}	/*	 * return if we did not find it.	 */	if (pt == NULL)		return(-1);	/*	 * found it. return the times and remove the entry from the table.	 */	*ppt = pt->fow;	*mtime = pt->mtime;	*atime = pt->atime;	(void)free((char *)pt->name);	(void)free((char *)pt);	return(0);}/* * directory access mode and time storage routines (for directories CREATED * by pax). * * Pax requires that extracted directories, by default, have their access/mod * times and permissions set to the values specified in the archive. During the * actions of extracting (and creating the destination subtree during -rw copy) * directories extracted may be modified after being created. Even worse is * that these directories may have been created with file permissions which * prohibits any descendants of these directories from being extracted. When * directories are created by pax, access rights may be added to permit the * creation of files in their subtree. Every time pax creates a directory, the * times and file permissions specified by the archive are stored. After all * files have been extracted (or copied), these directories have their times * and file modes reset to the stored values. The directory info is restored in * reverse order as entries were added to the data file from root to leaf. To * restore atime properly, we must go backwards. The data file consists of * records with two parts, the file name followed by a DIRDATA trailer. The * fixed sized trailer contains the size of the name plus the off_t location in * the file. To restore we work backwards through the file reading the trailer * then the file name. *//* * dir_start() *	set up the directory time and file mode storage for directories CREATED *	by pax. * Return: *	0 if ok, -1 otherwise */#if __STDC__intdir_start(void)#elseintdir_start()#endif{	char *pt;	if (dirfd != -1)		return(0);	if ((pt = tempnam((char *)NULL, (char *)NULL)) == NULL)		return(-1);	/*	 * unlink the file so it goes away at termination by itself	 */	(void)unlink(pt);	if ((dirfd = open(pt, O_RDWR|O_CREAT, 0600)) >= 0) {		(void)unlink(pt);		return(0);	}	warn(1, "Unable to create temporary file for directory times: %s", pt);	return(-1);}/* * add_dir() *	add the mode and times for a newly CREATED directory *	name is name of the directory, psb the stat buffer with the data in it, *	frc_mode is a flag that says whether to force the setting of the mode *	(ignoring the user set values for preserving file mode). Frc_mode is *	for the case where we created a file and found that the resulting  *	directory was not writeable and the user asked for file modes to NOT *	be preserved. (we have to preserve what was created by default, so we *	have to force the setting at the end. this is stated explicitly in the *	pax spec) */#if __STDC__voidadd_dir(char *name, int nlen, struct stat *psb, int frc_mode)#elsevoidadd_dir(name, nlen, psb, frc_mode)	char *name;	int nlen;	struct stat *psb;	int frc_mode;#endif{	DIRDATA dblk;	if (dirfd < 0)		return;	/*	 * get current position (where file name will start) so we can store it	 * in the trailer	 */	if ((dblk.npos = lseek(dirfd, 0L, SEEK_CUR)) < 0) {		warn(1,"Unable to store mode and times for directory: %s",name);		return;	}	/*	 * write the file name followed by the trailer	 */	dblk.nlen = nlen + 1;	dblk.mode = psb->st_mode & 0xffff;	dblk.mtime = psb->st_mtime;	dblk.atime = psb->st_atime;	dblk.frc_mode = frc_mode;	if ((write(dirfd, name, dblk.nlen) == dblk.nlen) &&	    (write(dirfd, (char *)&dblk, sizeof(dblk)) == sizeof(dblk))) {		++dircnt;		return;	}	warn(1,"Unable to store mode and times for created directory: %s",name);	return;}/* * proc_dir() *	process all file modes and times stored for directories CREATED *	by pax */#if __STDC__voidproc_dir(void)#elsevoidproc_dir()#endif{	char name[PAXPATHLEN+1];	DIRDATA dblk;	u_long cnt;	if (dirfd < 0)		return;	/*	 * read backwards through the file and process each directory	 */	for (cnt = 0; cnt < dircnt; ++cnt) {		/*		 * read the trailer, then the file name, if this fails		 * just give up.		 */		if (lseek(dirfd, -((off_t)sizeof(dblk)), SEEK_CUR) < 0) 			break;		if (read(dirfd,(char *)&dblk, sizeof(dblk)) != sizeof(dblk))			break;		if (lseek(dirfd, dblk.npos, SEEK_SET) < 0) 			break;		if (read(dirfd, name, dblk.nlen) != dblk.nlen)			break;		if (lseek(dirfd, dblk.npos, SEEK_SET) < 0) 			break;		/*		 * frc_mode set, make sure we set the file modes even if		 * the user didn't ask for it (see file_subs.c for more info)		 */		if (pmode || dblk.frc_mode)			set_pmode(name, dblk.mode);		if (patime || pmtime)			set_ftime(name, dblk.mtime, dblk.atime, 0);	}	(void)close(dirfd);	dirfd = -1;	if (cnt != dircnt)		warn(1,"Unable to set mode and times for created directories");	return;}/* * database independent routines *//* * st_hash() *	hashes filenames to a u_int for hashing into a table. Looks at the tail *	end of file, as this provides far better distribution than any other *	part of the name. For performance reasons we only care about the last *	MAXKEYLEN chars (should be at LEAST large enough to pick off the file *	name). Was tested on 500,000 name file tree traversal from the root *	and gave almost a perfectly uniform distribution of keys when used with *	prime sized tables (MAXKEYLEN was 128 in test). Hashes (sizeof int) *	chars at a time and pads with 0 for last addition. * Return: *	the hash value of the string MOD (%) the table size. */#if __STDC__u_intst_hash(char *name, int len, int tabsz)#elseu_intst_hash(name, len, tabsz)	char *name;	int len;	int tabsz;#endif{	register char *pt;	register char *dest;	register char *end;	register int i;	register u_int key = 0;	register int steps;	register int res;	u_int val;	/*	 * only look at the tail up to MAXKEYLEN, we do not need to waste	 * time here (remember these are pathnames, the tail is what will	 * spread out the keys)	 */	if (len > MAXKEYLEN) {                pt = &(name[len - MAXKEYLEN]);		len = MAXKEYLEN;	} else		pt = name;	/*	 * calculate the number of u_int size steps in the string and if	 * there is a runt to deal with	 */	steps = len/sizeof(u_int);	res = len % sizeof(u_int);	/*	 * add up the value of the string in unsigned integer sized pieces	 * too bad we cannot have unsigned int aligned strings, then we	 * could avoid the expensive copy.	 */	for (i = 0; i < steps; ++i) {		end = pt + sizeof(u_int);		dest = (char *)&val;		while (pt < end)			*dest++ = *pt++;		key += val;	}	/*	 * add in the runt padded with zero to the right	 */	if (res) {		val = 0;		end = pt + res;		dest = (char *)&val;		while (pt < end)			*dest++ = *pt++;		key += val;	}	/*	 * return the result mod the table size	 */	return(key % tabsz);}

⌨️ 快捷键说明

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