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

📄 dir.c

📁 UnixBSD、SunOs、FreeBSD、NetBSD、OpenBSD和NeXTStep文件系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	for (n = 0; n <= npages; n++) {		char *dir_end;		page = ufs_get_page(dir, n);		err = PTR_ERR(page);		if (IS_ERR(page))			goto out;		lock_page(page);		kaddr = page_address(page);		dir_end = kaddr + ufs_last_byte(dir, n);		de = (struct ufs_dir_entry *)kaddr;		kaddr += PAGE_CACHE_SIZE - reclen;		while ((char *)de <= kaddr) {			if ((char *)de == dir_end) {				/* We hit i_size */				name_len = 0;				rec_len = chunk_size;				de->d_reclen = cpu_to_fs16(sb, chunk_size);				de->d_ino = 0;				goto got_it;			}			if (de->d_reclen == 0) {				ufs_error(dir->i_sb, __func__,					  "zero-length directory entry");				err = -EIO;				goto out_unlock;			}			err = -EEXIST;			if (ufs_match(sb, namelen, name, de))				goto out_unlock;			name_len = UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de));			rec_len = fs16_to_cpu(sb, de->d_reclen);			if (!de->d_ino && rec_len >= reclen)				goto got_it;			if (rec_len >= name_len + reclen)				goto got_it;			de = (struct ufs_dir_entry *) ((char *) de + rec_len);		}		unlock_page(page);		ufs_put_page(page);	}	BUG();	return -EINVAL;got_it:	pos = page_offset(page) +			(char*)de - (char*)page_address(page);	err = __ufs_write_begin(NULL, page->mapping, pos, rec_len,				AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);	if (err)		goto out_unlock;	if (de->d_ino) {		struct ufs_dir_entry *de1 =			(struct ufs_dir_entry *) ((char *) de + name_len);		de1->d_reclen = cpu_to_fs16(sb, rec_len - name_len);		de->d_reclen = cpu_to_fs16(sb, name_len);		de = de1;	}	ufs_set_de_namlen(sb, de, namelen);	memcpy(de->d_name, name, namelen + 1);	de->d_ino = cpu_to_fs32(sb, inode->i_ino);	ufs_set_de_type(sb, de, inode->i_mode);	err = ufs_commit_chunk(page, pos, rec_len);	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;	mark_inode_dirty(dir);	/* OFFSET_CACHE */out_put:	ufs_put_page(page);out:	return err;out_unlock:	unlock_page(page);	goto out_put;}static inline unsignedufs_validate_entry(struct super_block *sb, char *base,		   unsigned offset, unsigned mask){	struct ufs_dir_entry *de = (struct ufs_dir_entry*)(base + offset);	struct ufs_dir_entry *p = (struct ufs_dir_entry*)(base + (offset&mask));	while ((char*)p < (char*)de) {		if (p->d_reclen == 0)			break;		p = ufs_next_entry(sb, p);	}	return (char *)p - base;}/* * This is blatantly stolen from ext2fs */static intufs_readdir(struct file *filp, void *dirent, filldir_t filldir){	loff_t pos = filp->f_pos;	struct inode *inode = filp->f_path.dentry->d_inode;	struct super_block *sb = inode->i_sb;	unsigned int offset = pos & ~PAGE_CACHE_MASK;	unsigned long n = pos >> PAGE_CACHE_SHIFT;	unsigned long npages = ufs_dir_pages(inode);	unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);	int need_revalidate = filp->f_version != inode->i_version;	unsigned flags = UFS_SB(sb)->s_flags;	UFSD("BEGIN\n");	if (pos > inode->i_size - UFS_DIR_REC_LEN(1))		return 0;	for ( ; n < npages; n++, offset = 0) {		char *kaddr, *limit;		struct ufs_dir_entry *de;		struct page *page = ufs_get_page(inode, n);		if (IS_ERR(page)) {			ufs_error(sb, __func__,				  "bad page in #%lu",				  inode->i_ino);			filp->f_pos += PAGE_CACHE_SIZE - offset;			return -EIO;		}		kaddr = page_address(page);		if (unlikely(need_revalidate)) {			if (offset) {				offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask);				filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;			}			filp->f_version = inode->i_version;			need_revalidate = 0;		}		de = (struct ufs_dir_entry *)(kaddr+offset);		limit = kaddr + ufs_last_byte(inode, n) - UFS_DIR_REC_LEN(1);		for ( ;(char*)de <= limit; de = ufs_next_entry(sb, de)) {			if (de->d_reclen == 0) {				ufs_error(sb, __func__,					"zero-length directory entry");				ufs_put_page(page);				return -EIO;			}			if (de->d_ino) {				int over;				unsigned char d_type = DT_UNKNOWN;				offset = (char *)de - kaddr;				UFSD("filldir(%s,%u)\n", de->d_name,				      fs32_to_cpu(sb, de->d_ino));				UFSD("namlen %u\n", ufs_get_de_namlen(sb, de));				if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)					d_type = de->d_u.d_44.d_type;				over = filldir(dirent, de->d_name,					       ufs_get_de_namlen(sb, de),						(n<<PAGE_CACHE_SHIFT) | offset,					       fs32_to_cpu(sb, de->d_ino), d_type);				if (over) {					ufs_put_page(page);					return 0;				}			}			filp->f_pos += fs16_to_cpu(sb, de->d_reclen);		}		ufs_put_page(page);	}	return 0;}/* * ufs_delete_entry deletes a directory entry by merging it with the * previous entry. */int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,		     struct page * page){	struct super_block *sb = inode->i_sb;	struct address_space *mapping = page->mapping;	char *kaddr = page_address(page);	unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);	unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen);	loff_t pos;	struct ufs_dir_entry *pde = NULL;	struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from);	int err;	UFSD("ENTER\n");	UFSD("ino %u, reclen %u, namlen %u, name %s\n",	      fs32_to_cpu(sb, de->d_ino),	      fs16_to_cpu(sb, de->d_reclen),	      ufs_get_de_namlen(sb, de), de->d_name);	while ((char*)de < (char*)dir) {		if (de->d_reclen == 0) {			ufs_error(inode->i_sb, __func__,				  "zero-length directory entry");			err = -EIO;			goto out;		}		pde = de;		de = ufs_next_entry(sb, de);	}	if (pde)		from = (char*)pde - (char*)page_address(page);	pos = page_offset(page) + from;	lock_page(page);	err = __ufs_write_begin(NULL, mapping, pos, to - from,				AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);	BUG_ON(err);	if (pde)		pde->d_reclen = cpu_to_fs16(sb, to - from);	dir->d_ino = 0;	err = ufs_commit_chunk(page, pos, to - from);	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;	mark_inode_dirty(inode);out:	ufs_put_page(page);	UFSD("EXIT\n");	return err;}int ufs_make_empty(struct inode * inode, struct inode *dir){	struct super_block * sb = dir->i_sb;	struct address_space *mapping = inode->i_mapping;	struct page *page = grab_cache_page(mapping, 0);	const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize;	struct ufs_dir_entry * de;	char *base;	int err;	if (!page)		return -ENOMEM;	err = __ufs_write_begin(NULL, mapping, 0, chunk_size,				AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);	if (err) {		unlock_page(page);		goto fail;	}	kmap(page);	base = (char*)page_address(page);	memset(base, 0, PAGE_CACHE_SIZE);	de = (struct ufs_dir_entry *) base;	de->d_ino = cpu_to_fs32(sb, inode->i_ino);	ufs_set_de_type(sb, de, inode->i_mode);	ufs_set_de_namlen(sb, de, 1);	de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1));	strcpy (de->d_name, ".");	de = (struct ufs_dir_entry *)		((char *)de + fs16_to_cpu(sb, de->d_reclen));	de->d_ino = cpu_to_fs32(sb, dir->i_ino);	ufs_set_de_type(sb, de, dir->i_mode);	de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1));	ufs_set_de_namlen(sb, de, 2);	strcpy (de->d_name, "..");	kunmap(page);	err = ufs_commit_chunk(page, 0, chunk_size);fail:	page_cache_release(page);	return err;}/* * routine to check that the specified directory is empty (for rmdir) */int ufs_empty_dir(struct inode * inode){	struct super_block *sb = inode->i_sb;	struct page *page = NULL;	unsigned long i, npages = ufs_dir_pages(inode);	for (i = 0; i < npages; i++) {		char *kaddr;		struct ufs_dir_entry *de;		page = ufs_get_page(inode, i);		if (IS_ERR(page))			continue;		kaddr = page_address(page);		de = (struct ufs_dir_entry *)kaddr;		kaddr += ufs_last_byte(inode, i) - UFS_DIR_REC_LEN(1);		while ((char *)de <= kaddr) {			if (de->d_reclen == 0) {				ufs_error(inode->i_sb, __func__,					"zero-length directory entry: "					"kaddr=%p, de=%p\n", kaddr, de);				goto not_empty;			}			if (de->d_ino) {				u16 namelen=ufs_get_de_namlen(sb, de);				/* check for . and .. */				if (de->d_name[0] != '.')					goto not_empty;				if (namelen > 2)					goto not_empty;				if (namelen < 2) {					if (inode->i_ino !=					    fs32_to_cpu(sb, de->d_ino))						goto not_empty;				} else if (de->d_name[1] != '.')					goto not_empty;			}			de = ufs_next_entry(sb, de);		}		ufs_put_page(page);	}	return 1;not_empty:	ufs_put_page(page);	return 0;}const struct file_operations ufs_dir_operations = {	.read		= generic_read_dir,	.readdir	= ufs_readdir,	.fsync		= file_fsync,	.llseek		= generic_file_llseek,};

⌨️ 快捷键说明

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