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

📄 hpfs_fs.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 3 页
字号:
		else if (!strcmp(p, "case")) {			if (!strcmp(rhs, "lower"))				*lowercase = 1;			else if (!strcmp(rhs, "asis"))				*lowercase = 0;			else				return 0;		}		else if (!strcmp(p, "conv")) {			if (!strcmp(rhs, "binary"))				*conv = CONV_BINARY;			else if (!strcmp(rhs, "text"))				*conv = CONV_TEXT;			else if (!strcmp(rhs, "auto"))				*conv = CONV_AUTO;			else				return 0;		}		else			return 0;	}	return 1;}/* * read_inode.  This is called with exclusive access to a new inode that * has only (i_dev,i_ino) set.  It is responsible for filling in the rest. * We leave the dates blank, to be filled in from the dir entry. * * NOTE that there must be no sleeping from the return in this routine * until lookup() finishes filling in the inode, otherwise the partly * completed inode would be visible during the sleep. * * It is done in this strange and sinful way because the alternative * is to read the fnode, find the dir pointer in it, read that fnode * to get the dnode pointer, search through that whole directory for * the ino we're reading, and get the dates.  It works that way, but * ls sounds like fsck. */static void hpfs_read_inode(struct inode *inode){	struct super_block *s = inode->i_sb;	/* be ready to bail out */	inode->i_op = 0;	inode->i_mode = 0;	if (inode->i_ino == 0	    || ino_secno(inode->i_ino) >= inode->i_sb->s_hpfs_fs_size) {		printk("HPFS: read_inode: bad ino\n");		return;	}	/*	 * canned stuff	 */	inode->i_uid = s->s_hpfs_uid;	inode->i_gid = s->s_hpfs_gid;	inode->i_mode = s->s_hpfs_mode;	inode->i_hpfs_conv = s->s_hpfs_conv;	inode->i_hpfs_dno = 0;	inode->i_hpfs_n_secs = 0;	inode->i_hpfs_file_sec = 0;	inode->i_hpfs_disk_sec = 0;	inode->i_hpfs_dpos = 0;	inode->i_hpfs_dsubdno = 0;	/*	 * figure out whether we are looking at a directory or a file	 */	if (ino_is_dir(inode->i_ino))		inode->i_mode |= S_IFDIR;	else {		inode->i_mode |= S_IFREG;		inode->i_mode &= ~0111;	}	/*	 * these fields must be filled in from the dir entry, which we don't	 * have but lookup does.  It will fill them in before letting the	 * inode out of its grasp.	 */	inode->i_atime = 0;	inode->i_mtime = 0;	inode->i_ctime = 0;	inode->i_size = 0;	/*	 * fill in the rest	 */	if (S_ISREG(inode->i_mode)) {		inode->i_op = (struct inode_operations *) &hpfs_file_iops;		inode->i_nlink = 1;		inode->i_blksize = 512;	}	else {		unsigned n_dnodes, n_subdirs;		struct buffer_head *bh0;		struct fnode *fnode = map_fnode(inode->i_dev,						inode->i_ino, &bh0);		if (!fnode) {			printk("HPFS: read_inode: no fnode\n");			inode->i_mode = 0;			return;		}		inode->i_hpfs_parent_dir = dir_ino(fnode->up);		inode->i_hpfs_dno = fnode->u.external[0].disk_secno;		brelse(bh0);		n_dnodes = n_subdirs = 0;		count_dnodes(inode, inode->i_hpfs_dno, &n_dnodes, &n_subdirs);		inode->i_op = (struct inode_operations *) &hpfs_dir_iops;		inode->i_blksize = 512;	/* 2048 here confuses ls & du & ... */		inode->i_blocks = 4 * n_dnodes;		inode->i_size = 512 * inode->i_blocks;		inode->i_nlink = 2 + n_subdirs;	}}/* * unmount. */static void hpfs_put_super(struct super_block *s){	lock_super(s);	s->s_dev = 0;	unlock_super(s);}/* * statfs.  For free inode counts we report the count of dnodes in the * directory band -- not exactly right but pretty analagous. */static void hpfs_statfs(struct super_block *s, struct statfs *buf){	/*	 * count the bits in the bitmaps, unless we already have	 */	if (s->s_hpfs_n_free == -1) {		s->s_hpfs_n_free = count_bitmap(s);		s->s_hpfs_n_free_dnodes =		    count_one_bitmap(s->s_dev, s->s_hpfs_dmap);	}	/*	 * fill in the user statfs struct	 */	put_fs_long(s->s_magic, &buf->f_type);	put_fs_long(512, &buf->f_bsize);	put_fs_long(s->s_hpfs_fs_size, &buf->f_blocks);	put_fs_long(s->s_hpfs_n_free, &buf->f_bfree);	put_fs_long(s->s_hpfs_n_free, &buf->f_bavail);	put_fs_long(s->s_hpfs_dirband_size, &buf->f_files);	put_fs_long(s->s_hpfs_n_free_dnodes, &buf->f_ffree);	put_fs_long(254, &buf->f_namelen);}/* * remount.  Don't let read only be turned off. */static int hpfs_remount_fs(struct super_block *s, int *flags, char *data){	if (!(*flags & MS_RDONLY))		return -EINVAL;	return 0;}/* * count the dnodes in a directory, and the subdirs. */static void count_dnodes(struct inode *inode, dnode_secno dno,			 unsigned *n_dnodes, unsigned *n_subdirs){	struct quad_buffer_head qbh;	struct dnode *dnode;	struct hpfs_dirent *de;	struct hpfs_dirent *de_end;	dnode = map_dnode(inode->i_dev, dno, &qbh);	if (!dnode)		return;	de = dnode_first_de(dnode);	de_end = dnode_end_de(dnode);	(*n_dnodes)++;	for (; de < de_end; de = de_next_de(de)) {		if (de->down)			count_dnodes(inode, de_down_pointer(de),				     n_dnodes, n_subdirs);		if (de->directory && !de->first)			(*n_subdirs)++;		if (de->last || de->length == 0)			break;	}	brelse4(&qbh);}/* * count the bits in the free space bit maps */static unsigned count_bitmap(struct super_block *s){	unsigned n, count, n_bands;	secno *bitmaps;	struct quad_buffer_head qbh;	/*	 * there is one bit map for each 16384 sectors	 */	n_bands = (s->s_hpfs_fs_size + 0x3fff) >> 14;	/*	 * their locations are given in an array pointed to by the super	 * block	 */	bitmaps = map_4sectors(s->s_dev, s->s_hpfs_bitmaps, &qbh);	if (!bitmaps)		return 0;	count = 0;	/*	 * map each one and count the free sectors	 */	for (n = 0; n < n_bands; n++)		if (bitmaps[n] == 0)			printk("HPFS: bit map pointer missing\n");		else			count += count_one_bitmap(s->s_dev, bitmaps[n]);	brelse4(&qbh);	return count;}/* * Read in one bit map, count the bits, return the count. */static unsigned count_one_bitmap(dev_t dev, secno secno){	struct quad_buffer_head qbh;	char *bits;	unsigned i, count;	bits = map_4sectors(dev, secno, &qbh);	if (!bits)		return 0;	count = 0;	for (i = 0; i < 8 * 2048; i++)		count += (test_bit(i, bits) != 0);	brelse4(&qbh);	return count;}/* file ops *//* * read.  Read the bytes, put them in buf, return the count. */static int hpfs_file_read(struct inode *inode, struct file *filp,			  char *buf, int count){	unsigned q, r, n, n0;	struct buffer_head *bh;	char *block;	char *start;	if (inode == 0 || !S_ISREG(inode->i_mode))		return -EINVAL;	/*	 * truncate count at EOF	 */	if (count > inode->i_size - filp->f_pos)		count = inode->i_size - filp->f_pos;	start = buf;	while (count > 0) {		/*		 * get file sector number, offset in sector, length to end of		 * sector		 */		q = filp->f_pos >> 9;		r = filp->f_pos & 511;		n = 512 - r;		/*		 * get length to copy to user buffer		 */		if (n > count)			n = count;		/*		 * read the sector, copy to user		 */		block = map_sector(inode->i_dev, hpfs_bmap(inode, q), &bh);		if (!block)			return -EIO;		/*		 * but first decide if it has \r\n, if the mount option said		 * to do that		 */		if (inode->i_hpfs_conv == CONV_AUTO)			inode->i_hpfs_conv = choose_conv(block + r, n);		if (inode->i_hpfs_conv == CONV_BINARY) {			/*			 * regular copy, output length is same as input			 * length			 */			memcpy_tofs(buf, block + r, n);			n0 = n;		}		else {			/*			 * squeeze out \r, output length varies			 */			n0 = convcpy_tofs(buf, block + r, n);			if (count > inode->i_size - filp->f_pos - n + n0)				count = inode->i_size - filp->f_pos - n + n0;		}		brelse(bh);		/*		 * advance input n bytes, output n0 bytes		 */		filp->f_pos += n;		buf += n0;		count -= n0;	}	return buf - start;}/* * This routine implements conv=auto.  Return CONV_BINARY or CONV_TEXT. */static unsigned choose_conv(unsigned char *p, unsigned len){	unsigned tvote, bvote;	unsigned c;	tvote = bvote = 0;	while (len--) {		c = *p++;		if (c < ' ')			if (c == '\r' && len && *p == '\n')				tvote += 10;			else if (c == '\t' || c == '\n');			else				bvote += 5;		else if (c < '\177')			tvote++;		else			bvote += 5;	}	if (tvote > bvote)		return CONV_TEXT;	else		return CONV_BINARY;}/* * This routine implements conv=text.  :s/crlf/nl/ */static unsigned convcpy_tofs(unsigned char *out, unsigned char *in,			     unsigned len){	unsigned char *start = out;	while (len--) {		unsigned c = *in++;		if (c == '\r' && (len == 0 || *in == '\n'));		else			put_fs_byte(c, out++);	}	return out - start;}/* * Return the disk sector number containing a file sector. */static secno hpfs_bmap(struct inode *inode, unsigned file_secno){	unsigned n, disk_secno;	struct fnode *fnode;	struct buffer_head *bh;	/*	 * There is one sector run cached in the inode. See if the sector is	 * in it.	 */	n = file_secno - inode->i_hpfs_file_sec;	if (n < inode->i_hpfs_n_secs)		return inode->i_hpfs_disk_sec + n;	/*	 * No, read the fnode and go find the sector.	 */	else {		fnode = map_fnode(inode->i_dev, inode->i_ino, &bh);		if (!fnode)			return 0;		disk_secno = bplus_lookup(inode, &fnode->btree,					  file_secno, &bh);		brelse(bh);		return disk_secno;	}}/* * Search allocation tree *b for the given file sector number and return * the disk sector number.  Buffer *bhp has the tree in it, and can be * reused for subtrees when access to *b is no longer needed. * *bhp is busy on entry and exit.  */static secno bplus_lookup(struct inode *inode, struct bplus_header *b,			  secno file_secno, struct buffer_head **bhp){	int i;	/*	 * A leaf-level tree gives a list of sector runs.  Find the one	 * containing the file sector we want, cache the map info in the	 * inode for later, and return the corresponding disk sector.	 */	if (!b->internal) {		struct bplus_leaf_node *n = b->u.external;		for (i = 0; i < b->n_used_nodes; i++) {			unsigned t = file_secno - n[i].file_secno;			if (t < n[i].length) {				inode->i_hpfs_file_sec = n[i].file_secno;				inode->i_hpfs_disk_sec = n[i].disk_secno;				inode->i_hpfs_n_secs = n[i].length;				return n[i].disk_secno + t;			}		}	}	/*	 * A non-leaf tree gives a list of subtrees.  Find the one containing	 * the file sector we want, read it in, and recurse to search it.	 */	else {		struct bplus_internal_node *n = b->u.internal;		for (i = 0; i < b->n_used_nodes; i++) {			if (file_secno < n[i].file_secno) {				struct anode *anode;				anode_secno ano = n[i].down;				brelse(*bhp);				anode = map_anode(inode->i_dev, ano, bhp);				if (!anode)					break;				return bplus_lookup(inode, &anode->btree,						    file_secno, bhp);			}		}	}	/*	 * If we get here there was a hole in the file.  As far as I know we	 * never do get here, but falling off the end would be indelicate. So	 * return a pointer to a handy all-zero sector.  This is not a	 * reasonable way to handle files with holes if they really do	 * happen.	 */	printk("HPFS: bplus_lookup: sector not found\n");	return 15;}/* directory ops *//* * lookup.  Search the specified directory for the specified name, set * *result to the corresponding inode. * * lookup uses the inode number to tell read_inode whether it is reading * the inode of a directory or a file -- file ino's are odd, directory * ino's are even.  read_inode avoids i/o for file inodes; everything * needed is up here in the directory.  (And file fnodes are out in * the boondocks.) */static int hpfs_lookup(struct inode *dir, const char *name, int len,		       struct inode **result){	struct quad_buffer_head qbh;	struct hpfs_dirent *de;	struct inode *inode;	ino_t ino;	/* In case of madness */	*result = 0;	if (dir == 0)		return -ENOENT;	if (!S_ISDIR(dir->i_mode))		goto bail;	/*	 * Read in the directory entry. "." is there under the name ^A^A .	 * Always read the dir even for . and .. in case we need the dates.	 */	if (name[0] == '.' && len == 1)		de = map_dirent(dir, dir->i_hpfs_dno, "\001\001", 2, &qbh);	else if (name[0] == '.' && name[1] == '.' && len == 2)		de = map_dirent(dir,				fnode_dno(dir->i_dev, dir->i_hpfs_parent_dir),				"\001\001", 2, &qbh);	else		de = map_dirent(dir, dir->i_hpfs_dno, name, len, &qbh);	/*	 * This is not really a bailout, just means file not found.	 */	if (!de)		goto bail;	/*	 * Get inode number, what we're after.	 */	if (de->directory)		ino = dir_ino(de->fnode);	else		ino = file_ino(de->fnode);	/*	 * Go find or make an inode.	 */	if (!(inode = iget(dir->i_sb, ino)))

⌨️ 快捷键说明

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