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

📄 library.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)library.c	8.1 (Berkeley) 6/4/93";#endif /* not lint */#include <sys/param.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/mount.h>#include <sys/types.h>#include <sys/mman.h>#include <ufs/ufs/dinode.h>#include <ufs/lfs/lfs.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "clean.h"void	 add_blocks __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,	     daddr_t, daddr_t));void	 add_inodes __P((FS_INFO *, BLOCK_INFO *, int *, SEGSUM *, caddr_t,	     daddr_t));int	 bi_compare __P((const void *, const void *));int	 bi_toss __P((const void *, const void *, const void *));void	 get_ifile __P((FS_INFO *, int));int	 get_superblock __P((FS_INFO *, struct lfs *));int	 pseg_valid __P((FS_INFO *, SEGSUM *));/* * This function will get information on a a filesystem which matches * the name and type given.  If a "name" is in a filesystem of the given * type, then buf is filled with that filesystem's info, and the * a non-zero value is returned. */intfs_getmntinfo(buf, name, type)	struct	statfs	**buf;	char	*name;	int	type;{	/* allocate space for the filesystem info */	*buf = (struct statfs *)malloc(sizeof(struct statfs));	if (*buf == NULL)		return 0;	/* grab the filesystem info */	if (statfs(name, *buf) < 0) {		free(*buf);		return 0;	}	/* check to see if it's the one we want */	if (((*buf)->f_type != type) ||	    strncmp(name, (*buf)->f_mntonname, MNAMELEN)) {		/* "this is not the filesystem you're looking for */		free(*buf);		return 0;	}	return 1;}/* * Get all the information available on an LFS file system. * Returns an pointer to an FS_INFO structure, NULL on error. */FS_INFO *get_fs_info (lstatfsp, use_mmap)	struct statfs *lstatfsp;	/* IN: pointer to statfs struct */	int use_mmap;			/* IN: mmap or read */{	FS_INFO	*fsp;	int	i;		fsp = (FS_INFO *)malloc(sizeof(FS_INFO));	if (fsp == NULL)		return NULL;	bzero(fsp, sizeof(FS_INFO));	fsp->fi_statfsp = lstatfsp;	if (get_superblock (fsp, &fsp->fi_lfs))		err(1, "get_fs_info: get_superblock failed");	fsp->fi_daddr_shift =	     fsp->fi_lfs.lfs_bshift - fsp->fi_lfs.lfs_fsbtodb;	get_ifile (fsp, use_mmap);	return (fsp);}/* * If we are reading the ifile then we need to refresh it.  Even if * we are mmapping it, it might have grown.  Finally, we need to  * refresh the file system information (statfs) info. */voidreread_fs_info(fsp, use_mmap)	FS_INFO *fsp;	/* IN: prointer fs_infos to reread */	int use_mmap;{	int i;		if (statfs(fsp->fi_statfsp->f_mntonname, fsp->fi_statfsp))		err(1, "reread_fs_info: statfs failed");	get_ifile (fsp, use_mmap);}/*  * Gets the superblock from disk (possibly in face of errors)  */intget_superblock (fsp, sbp)	FS_INFO *fsp;		/* local file system info structure */	struct lfs *sbp;{	char mntfromname[MNAMELEN+1];        int fid;	strcpy(mntfromname, "/dev/r");	strcat(mntfromname, fsp->fi_statfsp->f_mntfromname+5);	if ((fid = open(mntfromname, O_RDONLY, (mode_t)0)) < 0) {		err(0, "get_superblock: bad open");		return (-1);	}	get(fid, LFS_LABELPAD, sbp, sizeof(struct lfs));	close (fid);		return (0);}/*  * This function will map the ifile into memory.  It causes a * fatal error on failure. */voidget_ifile (fsp, use_mmap)	FS_INFO	*fsp;	int use_mmap;{	struct stat file_stat;	caddr_t ifp;	char *ifile_name;	int count, fid;	ifp = NULL;	ifile_name = malloc(strlen(fsp->fi_statfsp->f_mntonname) +	    strlen(IFILE_NAME)+2);	strcat(strcat(strcpy(ifile_name, fsp->fi_statfsp->f_mntonname), "/"),	    IFILE_NAME);	if ((fid = open(ifile_name, O_RDWR, (mode_t)0)) < 0)		err(1, "get_ifile: bad open");	if (fstat (fid, &file_stat))		err(1, "get_ifile: fstat failed");	if (use_mmap && file_stat.st_size == fsp->fi_ifile_length) {		(void) close(fid);		return;	}	/* get the ifile */	if (use_mmap) {		if (fsp->fi_cip)			munmap((caddr_t)fsp->fi_cip, fsp->fi_ifile_length);		ifp = mmap ((caddr_t)0, file_stat.st_size,		    PROT_READ|PROT_WRITE, 0, fid, (off_t)0);		if (ifp ==  (caddr_t)(-1))			err(1, "get_ifile: mmap failed");	} else {		if (fsp->fi_cip)			free(fsp->fi_cip);		if (!(ifp = malloc (file_stat.st_size)))			err (1, "get_ifile: malloc failed"); redo_read:		count = read (fid, ifp, (size_t) file_stat.st_size);		if (count < 0)			err(1, "get_ifile: bad ifile read"); 		else if (count < file_stat.st_size) {			err(0, "get_ifile");			if (lseek(fid, 0, SEEK_SET) < 0)				err(1, "get_ifile: bad ifile lseek"); 			goto redo_read;		}	}	fsp->fi_ifile_length = file_stat.st_size;	close (fid);	fsp->fi_cip = (CLEANERINFO *)ifp;	fsp->fi_segusep = (SEGUSE *)(ifp + CLEANSIZE(fsp));	fsp->fi_ifilep  = (IFILE *)((caddr_t)fsp->fi_segusep + SEGTABSIZE(fsp));	/*	 * The number of ifile entries is equal to the number of blocks	 * blocks in the ifile minus the ones allocated to cleaner info	 * and segment usage table multiplied by the number of ifile	 * entries per page.	 */	fsp->fi_ifile_count = (fsp->fi_ifile_length >> fsp->fi_lfs.lfs_bshift -	    fsp->fi_lfs.lfs_cleansz - fsp->fi_lfs.lfs_segtabsz) *	    fsp->fi_lfs.lfs_ifpb;	free (ifile_name);}/* * This function will scan a segment and return a list of * <inode, blocknum> pairs which indicate which blocks were * contained as live data within the segment when the segment * summary was read (it may have "died" since then).  Any given * pair will be listed at most once. */int lfs_segmapv(fsp, seg, seg_buf, blocks, bcount)	FS_INFO *fsp;		/* pointer to local file system information */	int seg;		/* the segment number */	caddr_t seg_buf;	/* the buffer containing the segment's data */	BLOCK_INFO **blocks;	/* OUT: array of block_info for live blocks */	int *bcount;		/* OUT: number of active blocks in segment */{	BLOCK_INFO *bip;	SEGSUM *sp;	SEGUSE *sup;	FINFO *fip;	struct lfs *lfsp;	caddr_t s, segend;	daddr_t pseg_addr, seg_addr;	int i, nelem, nblocks, sumsize;	time_t timestamp;	lfsp = &fsp->fi_lfs;	nelem = 2 * lfsp->lfs_ssize;	if (!(bip = malloc(nelem * sizeof(BLOCK_INFO))))		goto err0;	sup = SEGUSE_ENTRY(lfsp, fsp->fi_segusep, seg);	s = seg_buf + (sup->su_flags & SEGUSE_SUPERBLOCK ? LFS_SBPAD : 0);	seg_addr = sntoda(lfsp, seg);	pseg_addr = seg_addr + (sup->su_flags & SEGUSE_SUPERBLOCK ? btodb(LFS_SBPAD) : 0);#ifdef VERBOSE		printf("\tsegment buffer at: 0x%x\tseg_addr 0x%x\n", s, seg_addr);#endif /* VERBOSE */	*bcount = 0;	for (segend = seg_buf + seg_size(lfsp), timestamp = 0; s < segend; ) {		sp = (SEGSUM *)s;#ifdef VERBOSE		printf("\tpartial at: 0x%x\n", pseg_addr);		print_SEGSUM(lfsp, sp);		fflush(stdout);#endif /* VERBOSE */		nblocks = pseg_valid(fsp, sp);		if (nblocks <= 0)			break;		/* Check if we have hit old data */		if (timestamp > ((SEGSUM*)s)->ss_create)			break;		timestamp = ((SEGSUM*)s)->ss_create;#ifdef DIAGNOSTIC		/* Verfiy size of summary block */		sumsize = sizeof(SEGSUM) +		    (sp->ss_ninos + INOPB(lfsp) - 1) / INOPB(lfsp);		for (fip = (FINFO *)(sp + 1); i < sp->ss_nfinfo; ++i) {			sumsize += sizeof(FINFO) +			    (fip->fi_nblocks - 1) * sizeof(daddr_t);			fip = (FINFO *)(&fip->fi_blocks[fip->fi_nblocks]);		}		if (sumsize > LFS_SUMMARY_SIZE) {			fprintf(stderr,			    "Segment %d summary block too big: %d\n",			    seg, sumsize);			exit(1);		}#endif		if (*bcount + nblocks + sp->ss_ninos > nelem) {			nelem = *bcount + nblocks + sp->ss_ninos;			bip = realloc (bip, nelem * sizeof(BLOCK_INFO));			if (!bip)				goto err0;		}		add_blocks(fsp, bip, bcount, sp, seg_buf, seg_addr, pseg_addr);		add_inodes(fsp, bip, bcount, sp, seg_buf, seg_addr);		pseg_addr += fsbtodb(lfsp, nblocks) +		    bytetoda(fsp, LFS_SUMMARY_SIZE);		s += (nblocks << lfsp->lfs_bshift) + LFS_SUMMARY_SIZE;	}	qsort(bip, *bcount, sizeof(BLOCK_INFO), bi_compare);	toss(bip, bcount, sizeof(BLOCK_INFO), bi_toss, NULL);#ifdef VERBOSE	{		BLOCK_INFO *_bip;		int i;

⌨️ 快捷键说明

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