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

📄 hpfs_fs.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 3 页
字号:
		goto bail1;	/*	 * Fill in the info from the directory if this is a newly created	 * inode.	 */	if (!inode->i_atime) {		inode->i_atime = local_to_gmt(de->read_date);		inode->i_mtime = local_to_gmt(de->write_date);		inode->i_ctime = local_to_gmt(de->creation_date);		if (de->read_only)			inode->i_mode &= ~0222;		if (!de->directory) {			inode->i_size = de->file_size;			/*			 * i_blocks should count the fnode and any anodes.			 * We count 1 for the fnode and don't bother about			 * anodes -- the disk heads are on the directory band			 * and we want them to stay there.			 */			inode->i_blocks = 1 + ((inode->i_size + 511) >> 9);		}	}	brelse4(&qbh);	/*	 * Made it.	 */	*result = inode;	iput(dir);	return 0;	/*	 * Didn't.	 */ bail1:	brelse4(&qbh); bail:	iput(dir);	return -ENOENT;}/* * Compare two counted strings ignoring case. * HPFS directory order sorts letters as if they're upper case. */static inline int memcasecmp(const unsigned char *s1, const unsigned char *s2,			     unsigned n){	int t;	if (n != 0)		do {			unsigned c1 = *s1++;			unsigned c2 = *s2++;			if (c1 - 'a' < 26)				c1 -= 040;			if (c2 - 'a' < 26)				c2 -= 040;			if ((t = c1 - c2) != 0)				return t;		} while (--n != 0);	return 0;}/* * Search a directory for the given name, return a pointer to its dir entry * and a pointer to the buffer containing it. */static struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno,				      const unsigned char *name, unsigned len,				      struct quad_buffer_head *qbh){	struct dnode *dnode;	struct hpfs_dirent *de;	struct hpfs_dirent *de_end;	int t, l;	/*	 * read the dnode at the root of our subtree	 */	dnode = map_dnode(inode->i_dev, dno, qbh);	if (!dnode)		return 0;	/*	 * get pointers to start and end+1 of dir entries	 */	de = dnode_first_de(dnode);	de_end = dnode_end_de(dnode);	/*	 * look through the entries for the name we're after	 */	for ( ; de < de_end; de = de_next_de(de)) {		/*		 * compare names		 */		l = len < de->namelen ? len : de->namelen;		t = memcasecmp(name, de->name, l);		/*		 * initial substring matches, compare lengths		 */		if (t == 0) {			t = len - de->namelen;			/* bingo */			if (t == 0)				return de;		}		/*		 * wanted name .lt. dir name => not present.		 */		if (t < 0) {			/*			 * if there is a subtree, search it.			 */			if (de->down) {				dnode_secno sub_dno = de_down_pointer(de);				brelse4(qbh);				return map_dirent(inode, sub_dno,						  name, len, qbh);			}			else				break;		}		/*		 * de->last is set on the last name in the dnode (it's always		 * a "\377" pseudo entry).  de->length == 0 means we're about		 * to infinite loop. This test does nothing in a well-formed		 * dnode.		 */		if (de->last || de->length == 0)			break;	}	/*	 * name not found.	 */	return 0;}/* * readdir.  Return exactly 1 dirent.  (I tried and tried, but currently * the interface with libc just does not permit more than 1.  If it gets * fixed, throw this out and just walk the tree and write records into * the user buffer.) * * We keep track of our position in the dnode tree with a sort of * dewey-decimal record of subtree locations.  Like so: * *   (1 (1.1 1.2 1.3) 2 3 (3.1 (3.1.1 3.1.2) 3.2 3.3 (3.3.1)) 4) * * Subtrees appear after their file, out of lexical order, * which would be before their file.  It's easier. * * A directory can't hold more than 56 files, so 6 bits are used for * position numbers.  If the tree is so deep that the position encoding * doesn't fit, I'm sure something absolutely fascinating happens. * * The actual sequence of f_pos values is *     0 => .   -1 => ..   1 1.1 ... 8.9 9 => files  -2 => eof * * The directory inode caches one position-to-dnode correspondence so * we won't have to repeatedly scan the top levels of the tree.  */static int hpfs_readdir(struct inode *inode, struct file *filp,			struct dirent *dirent, int likely_story){	struct quad_buffer_head qbh;	struct hpfs_dirent *de;	int namelen, lc;	ino_t ino;	if (inode == 0	    || inode->i_sb == 0	    || !S_ISDIR(inode->i_mode))		return -EBADF;	lc = inode->i_sb->s_hpfs_lowercase;	switch (filp->f_pos) {	case 0:		write_one_dirent(dirent, ".", 1, inode->i_ino, lc);		filp->f_pos = -1;		return 1;	case -1:		write_one_dirent(dirent, "..", 2,				 inode->i_hpfs_parent_dir, lc);		filp->f_pos = 1;		return 2;	case -2:		return 0;	default:		de = map_pos_dirent(inode, &filp->f_pos, &qbh);		if (!de) {			filp->f_pos = -2;			return 0;		}		namelen = de->namelen;		if (de->directory)			ino = dir_ino(de->fnode);		else			ino = file_ino(de->fnode);		write_one_dirent(dirent, de->name, namelen, ino, lc);		brelse4(&qbh);		return namelen;	}}/* * Send the given name and ino off to the user dirent struct at *dirent. * Blam it to lowercase if the mount option said to. * * Note that Linux d_reclen is the length of the file name, and has nothing * to do with the length of the dirent record. */static void write_one_dirent(struct dirent *dirent, const unsigned char *name,			     unsigned namelen, ino_t ino, int lowercase){	unsigned n;	put_fs_long(ino, &dirent->d_ino);	put_fs_word(namelen, &dirent->d_reclen);	if (lowercase)		for (n = namelen; n != 0;) {			unsigned t = name[--n];			if (t - 'A' < 26)				t += 040;			put_fs_byte(t, &dirent->d_name[n]);		}	else		memcpy_tofs(dirent->d_name, name, namelen);	put_fs_byte(0, &dirent->d_name[namelen]);}/* * Map the dir entry at subtree coordinates given by *posp, and * increment *posp to point to the following dir entry.  */static struct hpfs_dirent *map_pos_dirent(struct inode *inode, off_t *posp,					  struct quad_buffer_head *qbh){	unsigned pos, q, r;	dnode_secno dno;	struct hpfs_dirent *de;	/*	 * Get the position code and split off the rightmost index r	 */	pos = *posp;	q = pos >> 6;	r = pos & 077;	/*	 * Get the sector address of the dnode	 * pointed to by the leading part q	 */	dno = dir_subdno(inode, q);	if (!dno)		return 0;	/*	 * Get the entry at index r in dnode q	 */	de = map_nth_dirent(inode->i_dev, dno, r, qbh);	/*	 * If none, we're out of files in this dnode.  Ascend.	 */	if (!de) {		if (q == 0)			return 0;		*posp = q + 1;		return map_pos_dirent(inode, posp, qbh);	}	/*	 * If a subtree is here, descend.	 */	if (de->down)		*posp = pos << 6 | 1;	else		*posp = pos + 1;	/*	 * Don't return the ^A^A and \377 entries.	 */	if (de->first || de->last) {		brelse4(qbh);		return map_pos_dirent(inode, posp, qbh);	}	else		return de;}/* * Return the address of the dnode with subtree coordinates given by pos. */static dnode_secno dir_subdno(struct inode *inode, unsigned pos){	struct hpfs_dirent *de;	struct quad_buffer_head qbh;	/*	 * 0 is the root dnode	 */	if (pos == 0)		return inode->i_hpfs_dno;	/*	 * we have one pos->dnode translation cached in the inode	 */	else if (pos == inode->i_hpfs_dpos)		return inode->i_hpfs_dsubdno;	/*	 * otherwise go look	 */	else {		unsigned q = pos >> 6;		unsigned r = pos & 077;		dnode_secno dno;		/*		 * dnode at position q		 */		dno = dir_subdno(inode, q);		if (dno == 0)			return 0;		/*		 * entry at index r		 */		de = map_nth_dirent(inode->i_dev, dno, r, &qbh);		if (!de || !de->down)			return 0;		/*		 * get the dnode down pointer		 */		dno = de_down_pointer(de);		brelse4(&qbh);		/*		 * cache it for next time		 */		inode->i_hpfs_dpos = pos;		inode->i_hpfs_dsubdno = dno;		return dno;	}}/* * Return the dir entry at index n in dnode dno, or 0 if there isn't one */static struct hpfs_dirent *map_nth_dirent(dev_t dev, dnode_secno dno,					  int n,					  struct quad_buffer_head *qbh){	int i;	struct hpfs_dirent *de, *de_end;	struct dnode *dnode = map_dnode(dev, dno, qbh);	de = dnode_first_de(dnode);	de_end = dnode_end_de(dnode);	for (i = 1; de < de_end; i++, de = de_next_de(de)) {		if (i == n)			return de;		if (de->last || de->length == 0)			break;	}	brelse4(qbh);	return 0;}static int hpfs_dir_read(struct inode *inode, struct file *filp,			 char *buf, int count){	return -EISDIR;}/* Return the dnode pointer in a directory fnode */static dnode_secno fnode_dno(dev_t dev, ino_t ino){	struct buffer_head *bh;	struct fnode *fnode;	dnode_secno dno;	fnode = map_fnode(dev, ino, &bh);	if (!fnode)		return 0;	dno = fnode->u.external[0].disk_secno;	brelse(bh);	return dno;}/* Map an fnode into a buffer and return pointers to it and to the buffer. */static struct fnode *map_fnode(dev_t dev, ino_t ino, struct buffer_head **bhp){	struct fnode *fnode;	if (ino == 0) {		printk("HPFS: missing fnode\n");		return 0;	}	fnode = map_sector(dev, ino_secno(ino), bhp);	if (fnode)		if (fnode->magic != FNODE_MAGIC) {			printk("HPFS: map_fnode: bad fnode pointer\n");			brelse(*bhp);			return 0;		}	return fnode;}/* Map an anode into a buffer and return pointers to it and to the buffer. */static struct anode *map_anode(dev_t dev, unsigned secno,			       struct buffer_head **bhp){	struct anode *anode;	if (secno == 0) {		printk("HPFS: missing anode\n");		return 0;	}	anode = map_sector(dev, secno, bhp);	if (anode)		if (anode->magic != ANODE_MAGIC || anode->self != secno) {			printk("HPFS: map_anode: bad anode pointer\n");			brelse(*bhp);			return 0;		}	return anode;}/* Map a dnode into a buffer and return pointers to it and to the buffer. */static struct dnode *map_dnode(dev_t dev, unsigned secno,			       struct quad_buffer_head *qbh){	struct dnode *dnode;	if (secno == 0) {		printk("HPFS: missing dnode\n");		return 0;	}	dnode = map_4sectors(dev, secno, qbh);	if (dnode)		if (dnode->magic != DNODE_MAGIC || dnode->self != secno) {			printk("HPFS: map_dnode: bad dnode pointer\n");			brelse4(qbh);			return 0;		}	return dnode;}/* Map a sector into a buffer and return pointers to it and to the buffer. */static void *map_sector(dev_t dev, unsigned secno, struct buffer_head **bhp){	struct buffer_head *bh;	if ((*bhp = bh = bread(dev, secno, 512)) != 0)		return bh->b_data;	else {		printk("HPFS: map_sector: read error\n");		return 0;	}}/* Map 4 sectors into a 4buffer and return pointers to it and to the buffer. */static void *map_4sectors(dev_t dev, unsigned secno,			  struct quad_buffer_head *qbh){	struct buffer_head *bh;	char *data;	if (secno & 3) {		printk("HPFS: map_4sectors: unaligned read\n");		return 0;	}	qbh->data = data = kmalloc(2048, GFP_KERNEL);	if (!data)		goto bail;	qbh->bh[0] = bh = breada(dev,				 secno, secno + 1, secno + 2, secno + 3, -1);	if (!bh)		goto bail0;	memcpy(data, bh->b_data, 512);	qbh->bh[1] = bh = bread(dev, secno + 1, 512);	if (!bh)		goto bail1;	memcpy(data + 512, bh->b_data, 512);	qbh->bh[2] = bh = bread(dev, secno + 2, 512);	if (!bh)		goto bail2;	memcpy(data + 2 * 512, bh->b_data, 512);	qbh->bh[3] = bh = bread(dev, secno + 3, 512);	if (!bh)		goto bail3;	memcpy(data + 3 * 512, bh->b_data, 512);	return data; bail3:	brelse(qbh->bh[2]); bail2:	brelse(qbh->bh[1]); bail1:	brelse(qbh->bh[0]); bail0:	kfree_s(data, 2048); bail:	printk("HPFS: map_4sectors: read error\n");	return 0;}/* Deallocate a 4-buffer block */static void brelse4(struct quad_buffer_head *qbh){	brelse(qbh->bh[3]);	brelse(qbh->bh[2]);	brelse(qbh->bh[1]);	brelse(qbh->bh[0]);	kfree_s(qbh->data, 2048);}

⌨️ 快捷键说明

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