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

📄 dir.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  dir.c * *  Copyright (C) 1995, 1996 by Volker Lendecke *  Modified for big endian by J.F. Chadima and David S. Miller *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache *  Modified 1998, 1999 Wolfram Pienkoss for NLS *  Modified 1999 Wolfram Pienkoss for directory caching *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info * */#include <linux/time.h>#include <linux/errno.h>#include <linux/stat.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/mm.h>#include <asm/uaccess.h>#include <asm/byteorder.h>#include <linux/smp_lock.h>#include <linux/ncp_fs.h>#include "ncplib_kernel.h"static void ncp_read_volume_list(struct file *, void *, filldir_t,				struct ncp_cache_control *);static void ncp_do_readdir(struct file *, void *, filldir_t,				struct ncp_cache_control *);static int ncp_readdir(struct file *, void *, filldir_t);static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);static int ncp_unlink(struct inode *, struct dentry *);static int ncp_mkdir(struct inode *, struct dentry *, int);static int ncp_rmdir(struct inode *, struct dentry *);static int ncp_rename(struct inode *, struct dentry *,	  	      struct inode *, struct dentry *);static int ncp_mknod(struct inode * dir, struct dentry *dentry,		     int mode, dev_t rdev);#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)extern int ncp_symlink(struct inode *, struct dentry *, const char *);#else#define ncp_symlink NULL#endif		      const struct file_operations ncp_dir_operations ={	.read		= generic_read_dir,	.readdir	= ncp_readdir,	.ioctl		= ncp_ioctl,#ifdef CONFIG_COMPAT	.compat_ioctl	= ncp_compat_ioctl,#endif};const struct inode_operations ncp_dir_inode_operations ={	.create		= ncp_create,	.lookup		= ncp_lookup,	.unlink		= ncp_unlink,	.symlink	= ncp_symlink,	.mkdir		= ncp_mkdir,	.rmdir		= ncp_rmdir,	.mknod		= ncp_mknod,	.rename		= ncp_rename,	.setattr	= ncp_notify_change,};/* * Dentry operations routines */static int ncp_lookup_validate(struct dentry *, struct nameidata *);static int ncp_hash_dentry(struct dentry *, struct qstr *);static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);static int ncp_delete_dentry(struct dentry *);static struct dentry_operations ncp_dentry_operations ={	.d_revalidate	= ncp_lookup_validate,	.d_hash		= ncp_hash_dentry,	.d_compare	= ncp_compare_dentry,	.d_delete	= ncp_delete_dentry,};struct dentry_operations ncp_root_dentry_operations ={	.d_hash		= ncp_hash_dentry,	.d_compare	= ncp_compare_dentry,	.d_delete	= ncp_delete_dentry,};/* * Note: leave the hash unchanged if the directory * is case-sensitive. */static int ncp_hash_dentry(struct dentry *dentry, struct qstr *this){	struct nls_table *t;	unsigned long hash;	int i;	t = NCP_IO_TABLE(dentry);	if (!ncp_case_sensitive(dentry->d_inode)) {		hash = init_name_hash();		for (i=0; i<this->len ; i++)			hash = partial_name_hash(ncp_tolower(t, this->name[i]),									hash);		this->hash = end_name_hash(hash);	}	return 0;}static intncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b){	if (a->len != b->len)		return 1;	if (ncp_case_sensitive(dentry->d_inode))		return strncmp(a->name, b->name, a->len);	return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);}/* * This is the callback from dput() when d_count is going to 0. * We use this to unhash dentries with bad inodes. * Closing files can be safely postponed until iput() - it's done there anyway. */static intncp_delete_dentry(struct dentry * dentry){	struct inode *inode = dentry->d_inode;	if (inode) {		if (is_bad_inode(inode))			return 1;	} else	{	/* N.B. Unhash negative dentries? */	}	return 0;}static inline intncp_single_volume(struct ncp_server *server){	return (server->m.mounted_vol[0] != '\0');}static inline int ncp_is_server_root(struct inode *inode){	return (!ncp_single_volume(NCP_SERVER(inode)) &&		inode == inode->i_sb->s_root->d_inode);}/* * This is the callback when the dcache has a lookup hit. */#ifdef CONFIG_NCPFS_STRONG/* try to delete a readonly file (NW R bit set) */static intncp_force_unlink(struct inode *dir, struct dentry* dentry){        int res=0x9c,res2;	struct nw_modify_dos_info info;	__le32 old_nwattr;	struct inode *inode;	memset(&info, 0, sizeof(info));	        /* remove the Read-Only flag on the NW server */	inode = dentry->d_inode;	old_nwattr = NCP_FINFO(inode)->nwattr;	info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);	res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);	if (res2)		goto leave_me;        /* now try again the delete operation */        res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);        if (res)  /* delete failed, set R bit again */        {		info.attributes = old_nwattr;		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);		if (res2)                        goto leave_me;        }leave_me:        return(res);}#endif	/* CONFIG_NCPFS_STRONG */#ifdef CONFIG_NCPFS_STRONGstatic intncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,                 struct inode *new_dir, struct dentry* new_dentry, char *_new_name){	struct nw_modify_dos_info info;        int res=0x90,res2;	struct inode *old_inode = old_dentry->d_inode;	__le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;	__le32 new_nwattr = 0; /* shut compiler warning */	int old_nwattr_changed = 0;	int new_nwattr_changed = 0;	memset(&info, 0, sizeof(info));	        /* remove the Read-Only flag on the NW server */	info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);	res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);	if (!res2)		old_nwattr_changed = 1;	if (new_dentry && new_dentry->d_inode) {		new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;		info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);		if (!res2)			new_nwattr_changed = 1;	}        /* now try again the rename operation */	/* but only if something really happened */	if (new_nwattr_changed || old_nwattr_changed) {	        res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),        	                                    old_dir, _old_name,                	                            new_dir, _new_name);	} 	if (res)		goto leave_me;	/* file was successfully renamed, so:	   do not set attributes on old file - it no longer exists	   copy attributes from old file to new */	new_nwattr_changed = old_nwattr_changed;	new_nwattr = old_nwattr;	old_nwattr_changed = 0;	leave_me:;	if (old_nwattr_changed) {		info.attributes = old_nwattr;		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);		/* ignore errors */	}	if (new_nwattr_changed)	{		info.attributes = new_nwattr;		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);		/* ignore errors */	}        return(res);}#endif	/* CONFIG_NCPFS_STRONG */static int__ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd){	struct ncp_server *server;	struct dentry *parent;	struct inode *dir;	struct ncp_entry_info finfo;	int res, val = 0, len;	__u8 __name[NCP_MAXPATHLEN + 1];	parent = dget_parent(dentry);	dir = parent->d_inode;	if (!dentry->d_inode)		goto finished;	server = NCP_SERVER(dir);	if (!ncp_conn_valid(server))		goto finished;	/*	 * Inspired by smbfs:	 * The default validation is based on dentry age:	 * We set the max age at mount time.  (But each	 * successful server lookup renews the timestamp.)	 */	val = NCP_TEST_AGE(server, dentry);	if (val)		goto finished;	DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",		dentry->d_parent->d_name.name, dentry->d_name.name,		NCP_GET_AGE(dentry));	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));	}	finfo.volume = finfo.i.volNumber;	DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",		dentry->d_parent->d_name.name, __name, res);	/*	 * If we didn't find it, or if it has a different dirEntNum to	 * what we remember, it's not valid any more.	 */	if (!res) {		if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {			ncp_new_dentry(dentry);			val=1;		} else			DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");		ncp_update_inode2(dentry->d_inode, &finfo);	}finished:	DDPRINTK("ncp_lookup_validate: result=%d\n", val);	dput(parent);	return val;}static intncp_lookup_validate(struct dentry * dentry, struct nameidata *nd){	int res;	lock_kernel();	res = __ncp_lookup_validate(dentry, nd);	unlock_kernel();	return res;}static struct dentry *ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos){	struct dentry *dent = dentry;	struct list_head *next;	if (d_validate(dent, parent)) {		if (dent->d_name.len <= NCP_MAXPATHLEN &&		    (unsigned long)dent->d_fsdata == fpos) {			if (!dent->d_inode) {				dput(dent);				dent = NULL;			}			return dent;		}		dput(dent);	}	/* If a pointer is invalid, we search the dentry. */	spin_lock(&dcache_lock);	next = parent->d_subdirs.next;	while (next != &parent->d_subdirs) {		dent = list_entry(next, struct dentry, d_u.d_child);		if ((unsigned long)dent->d_fsdata == fpos) {			if (dent->d_inode)				dget_locked(dent);			else				dent = NULL;			spin_unlock(&dcache_lock);			goto out;		}		next = next->next;	}	spin_unlock(&dcache_lock);	return NULL;out:	return dent;}static time_t ncp_obtain_mtime(struct dentry *dentry){	struct inode *inode = dentry->d_inode;	struct ncp_server *server = NCP_SERVER(inode);	struct nw_info_struct i;	if (!ncp_conn_valid(server) || ncp_is_server_root(inode))		return 0;	if (ncp_obtain_info(server, inode, NULL, &i))		return 0;	return ncp_date_dos2unix(i.modifyTime, i.modifyDate);}static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir){	struct dentry *dentry = filp->f_path.dentry;	struct inode *inode = dentry->d_inode;	struct page *page = NULL;	struct ncp_server *server = NCP_SERVER(inode);	union  ncp_dir_cache *cache = NULL;	struct ncp_cache_control ctl;	int result, mtime_valid = 0;	time_t mtime = 0;	lock_kernel();	ctl.page  = NULL;	ctl.cache = NULL;

⌨️ 快捷键说明

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