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

📄 dir.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",		dentry->d_parent->d_name.name, dentry->d_name.name,		(int) filp->f_pos);	result = -EIO;	if (!ncp_conn_valid(server))		goto out;	result = 0;	if (filp->f_pos == 0) {		if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))			goto out;		filp->f_pos = 1;	}	if (filp->f_pos == 1) {		if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))			goto out;		filp->f_pos = 2;	}	page = grab_cache_page(&inode->i_data, 0);	if (!page)		goto read_really;	ctl.cache = cache = kmap(page);	ctl.head  = cache->head;	if (!PageUptodate(page) || !ctl.head.eof)		goto init_cache;	if (filp->f_pos == 2) {		if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))			goto init_cache;		mtime = ncp_obtain_mtime(dentry);		mtime_valid = 1;		if ((!mtime) || (mtime != ctl.head.mtime))			goto init_cache;	}	if (filp->f_pos > ctl.head.end)		goto finished;	ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);	ctl.ofs  = ctl.fpos / NCP_DIRCACHE_SIZE;	ctl.idx  = ctl.fpos % NCP_DIRCACHE_SIZE;	for (;;) {		if (ctl.ofs != 0) {			ctl.page = find_lock_page(&inode->i_data, ctl.ofs);			if (!ctl.page)				goto invalid_cache;			ctl.cache = kmap(ctl.page);			if (!PageUptodate(ctl.page))				goto invalid_cache;		}		while (ctl.idx < NCP_DIRCACHE_SIZE) {			struct dentry *dent;			int res;			dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],						dentry, filp->f_pos);			if (!dent)				goto invalid_cache;			res = filldir(dirent, dent->d_name.name,					dent->d_name.len, filp->f_pos,					dent->d_inode->i_ino, DT_UNKNOWN);			dput(dent);			if (res)				goto finished;			filp->f_pos += 1;			ctl.idx += 1;			if (filp->f_pos > ctl.head.end)				goto finished;		}		if (ctl.page) {			kunmap(ctl.page);			SetPageUptodate(ctl.page);			unlock_page(ctl.page);			page_cache_release(ctl.page);			ctl.page = NULL;		}		ctl.idx  = 0;		ctl.ofs += 1;	}invalid_cache:	if (ctl.page) {		kunmap(ctl.page);		unlock_page(ctl.page);		page_cache_release(ctl.page);		ctl.page = NULL;	}	ctl.cache = cache;init_cache:	ncp_invalidate_dircache_entries(dentry);	if (!mtime_valid) {		mtime = ncp_obtain_mtime(dentry);		mtime_valid = 1;	}	ctl.head.mtime = mtime;	ctl.head.time = jiffies;	ctl.head.eof = 0;	ctl.fpos = 2;	ctl.ofs = 0;	ctl.idx = NCP_DIRCACHE_START;	ctl.filled = 0;	ctl.valid  = 1;read_really:	if (ncp_is_server_root(inode)) {		ncp_read_volume_list(filp, dirent, filldir, &ctl);	} else {		ncp_do_readdir(filp, dirent, filldir, &ctl);	}	ctl.head.end = ctl.fpos - 1;	ctl.head.eof = ctl.valid;finished:	if (page) {		cache->head = ctl.head;		kunmap(page);		SetPageUptodate(page);		unlock_page(page);		page_cache_release(page);	}	if (ctl.page) {		kunmap(ctl.page);		SetPageUptodate(ctl.page);		unlock_page(ctl.page);		page_cache_release(ctl.page);	}out:	unlock_kernel();	return result;}static intncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry){	struct dentry *newdent, *dentry = filp->f_path.dentry;	struct inode *newino, *inode = dentry->d_inode;	struct ncp_cache_control ctl = *ctrl;	struct qstr qname;	int valid = 0;	int hashed = 0;	ino_t ino = 0;	__u8 __name[NCP_MAXPATHLEN + 1];	qname.len = sizeof(__name);	if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,			entry->i.entryName, entry->i.nameLen,			!ncp_preserve_entry_case(inode, entry->i.NSCreator)))		return 1; /* I'm not sure */	qname.name = __name;	qname.hash = full_name_hash(qname.name, qname.len);	if (dentry->d_op && dentry->d_op->d_hash)		if (dentry->d_op->d_hash(dentry, &qname) != 0)			goto end_advance;	newdent = d_lookup(dentry, &qname);	if (!newdent) {		newdent = d_alloc(dentry, &qname);		if (!newdent)			goto end_advance;	} else {		hashed = 1;		memcpy((char *) newdent->d_name.name, qname.name,							newdent->d_name.len);	}	if (!newdent->d_inode) {		entry->opened = 0;		entry->ino = iunique(inode->i_sb, 2);		newino = ncp_iget(inode->i_sb, entry);		if (newino) {			newdent->d_op = &ncp_dentry_operations;			d_instantiate(newdent, newino);			if (!hashed)				d_rehash(newdent);		}	} else		ncp_update_inode2(newdent->d_inode, entry);	if (newdent->d_inode) {		ino = newdent->d_inode->i_ino;		newdent->d_fsdata = (void *) ctl.fpos;		ncp_new_dentry(newdent);	}	if (ctl.idx >= NCP_DIRCACHE_SIZE) {		if (ctl.page) {			kunmap(ctl.page);			SetPageUptodate(ctl.page);			unlock_page(ctl.page);			page_cache_release(ctl.page);		}		ctl.cache = NULL;		ctl.idx  -= NCP_DIRCACHE_SIZE;		ctl.ofs  += 1;		ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);		if (ctl.page)			ctl.cache = kmap(ctl.page);	}	if (ctl.cache) {		ctl.cache->dentry[ctl.idx] = newdent;		valid = 1;	}	dput(newdent);end_advance:	if (!valid)		ctl.valid = 0;	if (!ctl.filled && (ctl.fpos == filp->f_pos)) {		if (!ino)			ino = find_inode_number(dentry, &qname);		if (!ino)			ino = iunique(inode->i_sb, 2);		ctl.filled = filldir(dirent, qname.name, qname.len,				     filp->f_pos, ino, DT_UNKNOWN);		if (!ctl.filled)			filp->f_pos += 1;	}	ctl.fpos += 1;	ctl.idx  += 1;	*ctrl = ctl;	return (ctl.valid || !ctl.filled);}static voidncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,			struct ncp_cache_control *ctl){	struct dentry *dentry = filp->f_path.dentry;	struct inode *inode = dentry->d_inode;	struct ncp_server *server = NCP_SERVER(inode);	struct ncp_volume_info info;	struct ncp_entry_info entry;	int i;	DPRINTK("ncp_read_volume_list: pos=%ld\n",			(unsigned long) filp->f_pos);	for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {		if (ncp_get_volume_info_with_number(server, i, &info) != 0)			return;		if (!strlen(info.volume_name))			continue;		DPRINTK("ncp_read_volume_list: found vol: %s\n",			info.volume_name);		if (ncp_lookup_volume(server, info.volume_name,					&entry.i)) {			DPRINTK("ncpfs: could not lookup vol %s\n",				info.volume_name);			continue;		}		entry.volume = entry.i.volNumber;		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))			return;	}}static voidncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,						struct ncp_cache_control *ctl){	struct dentry *dentry = filp->f_path.dentry;	struct inode *dir = dentry->d_inode;	struct ncp_server *server = NCP_SERVER(dir);	struct nw_search_sequence seq;	struct ncp_entry_info entry;	int err;	void* buf;	int more;	size_t bufsize;	DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",		dentry->d_parent->d_name.name, dentry->d_name.name,		(unsigned long) filp->f_pos);	PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",		dentry->d_name.name, NCP_FINFO(dir)->volNumber,		NCP_FINFO(dir)->dirEntNum);	err = ncp_initialize_search(server, dir, &seq);	if (err) {		DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);		return;	}	/* We MUST NOT use server->buffer_size handshaked with server if we are	   using UDP, as for UDP server uses max. buffer size determined by	   MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 	   So we use 128KB, just to be sure, as there is no way how to know	   this value in advance. */	bufsize = 131072;	buf = vmalloc(bufsize);	if (!buf)		return;	do {		int cnt;		char* rpl;		size_t rpls;		err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);		if (err)		/* Error */			break;		if (!cnt)		/* prevent endless loop */			break;		while (cnt--) {			size_t onerpl;						if (rpls < offsetof(struct nw_info_struct, entryName))				break;	/* short packet */			ncp_extract_file_info(rpl, &entry.i);			onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;			if (rpls < onerpl)				break;	/* short packet */			(void)ncp_obtain_nfs_info(server, &entry.i);			rpl += onerpl;			rpls -= onerpl;			entry.volume = entry.i.volNumber;			if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))				break;		}	} while (more);	vfree(buf);	return;}int ncp_conn_logged_in(struct super_block *sb){	struct ncp_server* server = NCP_SBP(sb);	int result;	if (ncp_single_volume(server)) {		int len;		struct dentry* dent;		__u32 volNumber;		__le32 dirEntNum;		__le32 DosDirNum;		__u8 __name[NCP_MAXPATHLEN + 1];		len = sizeof(__name);		result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,				    strlen(server->m.mounted_vol), 1);		if (result)			goto out;		result = -ENOENT;		if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {			PPRINTK("ncp_conn_logged_in: %s not found\n",				server->m.mounted_vol);			goto out;		}		dent = sb->s_root;		if (dent) {			struct inode* ino = dent->d_inode;			if (ino) {				NCP_FINFO(ino)->volNumber = volNumber;				NCP_FINFO(ino)->dirEntNum = dirEntNum;				NCP_FINFO(ino)->DosDirNum = DosDirNum;			} else {				DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");			}		} else {			DPRINTK("ncpfs: sb->s_root == NULL!\n");		}	}	result = 0;out:	return result;}static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){	struct ncp_server *server = NCP_SERVER(dir);	struct inode *inode = NULL;	struct ncp_entry_info finfo;	int error, res, len;	__u8 __name[NCP_MAXPATHLEN + 1];	lock_kernel();	error = -EIO;	if (!ncp_conn_valid(server))		goto finished;	PPRINTK("ncp_lookup: server lookup for %s/%s\n",		dentry->d_parent->d_name.name, dentry->d_name.name);	len = sizeof(__name);	if (ncp_is_server_root(dir)) {		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,				 dentry->d_name.len, 1);		if (!res)			res = ncp_lookup_volume(server, __name, &(finfo.i));	} else {		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,				 dentry->d_name.len, !ncp_preserve_case(dir));		if (!res)			res = ncp_obtain_info(server, dir, __name, &(finfo.i));	}	PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",		dentry->d_parent->d_name.name, __name, res);	/*	 * If we didn't find an entry, make a negative dentry.	 */	if (res)		goto add_entry;	/*	 * Create an inode for the entry.	 */	finfo.opened = 0;	finfo.ino = iunique(dir->i_sb, 2);

⌨️ 快捷键说明

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