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

📄 emd.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * call umsdos_writeentry(). *  * To delete an entry, you find it, zero out the entry (memset) * and call umsdos_writeentry(). *  * All this to say that umsdos_writeentry must be called after this * function since it relies on the f_pos field of info. * * Note: the caller must hold a lock on the parent directory. *//* #Specification: EMD file structure * The EMD file uses a fairly simple layout.  It is made of records * (UMSDOS_REC_SIZE == 64).  When a name can't be written in a single * record, multiple contiguous records are allocated. */static int umsdos_find (struct dentry *demd, struct umsdos_info *info){	struct umsdos_dirent *entry = &info->entry;	int recsize = info->recsize;	struct inode *emd_dir;	int ret = -ENOENT;	struct {		off_t posok;	/* Position available to store the entry */		off_t one;	/* One empty position -> maybe <- large enough */	} empty;	int found = 0;	int empty_size = 0;	struct address_space *mapping;	filler_t *readpage;	struct page *page = NULL;	int index = -1;	int offs = PAGE_CACHE_SIZE,max_offs = PAGE_CACHE_SIZE;	char *p = NULL;	loff_t pos = 0;	/* make sure there's an EMD file ... */	ret = -ENOENT;	emd_dir = demd->d_inode;	if (!emd_dir)		goto out_dput;	mapping = emd_dir->i_mapping;	readpage = (filler_t*)mapping->a_ops->readpage;	empty.posok = emd_dir->i_size;	while (1) {		struct umsdos_dirent *rentry;		int entry_size;		if (offs >= max_offs) {			if (page) {				kunmap(page);				page_cache_release(page);				page = NULL;			}			if (pos >= emd_dir->i_size) {				info->f_pos = empty.posok;				break;			}			if (++index == (emd_dir->i_size>>PAGE_CACHE_SHIFT))				max_offs = emd_dir->i_size & ~PAGE_CACHE_MASK;			offs -= PAGE_CACHE_SIZE;			page = read_cache_page(mapping,index,readpage,NULL);			if (IS_ERR(page))				goto sync_fail;			wait_on_page(page);			if (!Page_Uptodate(page))				goto async_fail;			p = kmap(page);		}		rentry = (struct umsdos_dirent *)(p+offs);		if (rentry->name_len == 0) {			/* We are looking for an empty section at least */			/* as large as recsize. */			if (entry->name_len == 0) {				info->f_pos = pos;				ret = 0;				break;			}			offs += UMSDOS_REC_SIZE;			pos += UMSDOS_REC_SIZE;			if (found)				continue;			if (!empty_size)				empty.one = pos-UMSDOS_REC_SIZE;			empty_size += UMSDOS_REC_SIZE;			if (empty_size == recsize) {				/* Here is a large enough section. */				empty.posok = empty.one;				found = 1;			}			continue;		}		entry_size = umsdos_evalrecsize(rentry->name_len);		if (entry_size > PAGE_CACHE_SIZE)			goto async_fail;		empty_size = 0;		if (entry->name_len != rentry->name_len)			goto skip_it;		if (entry_size + offs > PAGE_CACHE_SIZE) {			/* Sucker spans the page boundary */			int len = (p+PAGE_CACHE_SIZE)-rentry->name;			struct page *next_page;			char *q;			next_page = read_cache_page(mapping,index+1,readpage,NULL);			if (IS_ERR(next_page)) {				page_cache_release(page);				page = next_page;				goto sync_fail;			}			wait_on_page(next_page);			if (!Page_Uptodate(next_page)) {				page_cache_release(page);				page = next_page;				goto async_fail;			}			q = kmap(next_page);			if (memcmp(entry->name, rentry->name, len) ||			    memcmp(entry->name+len, q, entry->name_len-len)) {				kunmap(next_page);				page_cache_release(next_page);				goto skip_it;			}			kunmap(next_page);			page_cache_release(next_page);		} else if (memcmp (entry->name, rentry->name, entry->name_len))			goto skip_it;		info->f_pos = pos;		copy_entry(entry, rentry);		ret = 0;		break;skip_it:		offs+=entry_size;		pos+=entry_size;	}	if (page) {		kunmap(page);		page_cache_release(page);	}	umsdos_manglename (info);out_dput:	dput(demd);	return ret;async_fail:	page_cache_release(page);	page = ERR_PTR(-EIO);sync_fail:	return PTR_ERR(page);}/* * Add a new entry in the EMD file. * Return 0 if OK or a negative error code. * Return -EEXIST if the entry already exists. * * Complete the information missing in info. *  * N.B. What if the EMD file doesn't exist? */int umsdos_newentry (struct dentry *parent, struct umsdos_info *info){	int err, ret = -EEXIST;	struct dentry *demd = umsdos_get_emd_dentry(parent);	ret = PTR_ERR(demd);	if (IS_ERR(demd))		goto out;	err = umsdos_find (demd, info);	if (err && err == -ENOENT) {		ret = umsdos_writeentry (parent, info, 0);		Printk (("umsdos_writeentry EMD ret = %d\n", ret));	}out:	return ret;}/* * Create a new hidden link. * Return 0 if OK, an error code if not. *//* #Specification: hard link / hidden name * When a hard link is created, the original file is renamed * to a hidden name. The name is "..LINKNNN" where NNN is a * number define from the entry offset in the EMD file. */int umsdos_newhidden (struct dentry *parent, struct umsdos_info *info){	int ret;	struct dentry *demd = umsdos_get_emd_dentry(parent);	ret = PTR_ERR(demd);	if (IS_ERR(demd))		goto out;	umsdos_parse ("..LINK", 6, info);	info->entry.name_len = 0;	ret = umsdos_find (demd, info);	if (ret == -ENOENT || ret == 0) {		info->entry.name_len = sprintf (info->entry.name,						"..LINK%ld", info->f_pos);		ret = 0;	}out:	return ret;}/* * Remove an entry from the EMD file. * Return 0 if OK, a negative error code otherwise. *  * Complete the information missing in info. */int umsdos_delentry (struct dentry *parent, struct umsdos_info *info, int isdir){	int ret;	struct dentry *demd = umsdos_get_emd_dentry(parent);	ret = PTR_ERR(demd);	if (IS_ERR(demd))		goto out;	ret = umsdos_find (demd, info);	if (ret)		goto out;	if (info->entry.name_len == 0)		goto out;	if ((isdir != 0) != (S_ISDIR (info->entry.mode) != 0)) {		if (S_ISDIR (info->entry.mode)) {			ret = -EISDIR;		} else {			ret = -ENOTDIR;		}		goto out;	}	ret = umsdos_writeentry (parent, info, 1);out:	return ret;}/* * Verify that an EMD directory is empty. * Return:  * 0 if not empty, * 1 if empty (except for EMD file), * 2 if empty or no EMD file. */int umsdos_isempty (struct dentry *dentry){	struct dentry *demd;	int ret = 2;	loff_t pos = 0;	demd = umsdos_get_emd_dentry(dentry);	if (IS_ERR(demd))		goto out;	/* If the EMD file does not exist, it is certainly empty. :-) */	if (!demd->d_inode)		goto out_dput;	ret = 1;	while (pos < demd->d_inode->i_size) {		struct umsdos_dirent entry;		if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0) {			ret = 0;			break;		}		if (entry.name_len != 0) {			ret = 0;			break;		}	}out_dput:	dput(demd);out:	return ret;}/* * Locate an entry in a EMD directory. * Return 0 if OK, error code if not, generally -ENOENT. * * expect argument: * 	0: anything * 	1: file * 	2: directory */int umsdos_findentry (struct dentry *parent, struct umsdos_info *info,			int expect){			int ret;	struct dentry *demd = umsdos_get_emd_dentry(parent);	ret = PTR_ERR(demd);	if (IS_ERR(demd))		goto out;	ret = umsdos_find (demd, info);	if (ret)		goto out;	switch (expect) {	case 1:		if (S_ISDIR (info->entry.mode))			ret = -EISDIR;		break;	case 2:		if (!S_ISDIR (info->entry.mode))			ret = -ENOTDIR;	}out:	Printk (("umsdos_findentry: returning %d\n", ret));	return ret;}

⌨️ 快捷键说明

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