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

📄 dir.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 2 页
字号:
						newinode));				} else if ((oplock & 0xF) == OPLOCK_READ)					pCifsInode->clientCanCacheRead = TRUE;			}			write_unlock(&GlobalSMBSeslock);		}	}cifs_create_out:#else /* 2.4 does not pass open flags so must reopen on cifs_open */		CIFSSMBClose(xid, pTcon, fileHandle);	}#endif	kfree(buf);	kfree(full_path);	FreeXid(xid);	return rc;}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,		dev_t device_number)#elseint cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int device_number)#endif{	int rc = -EPERM;	int xid;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	char *full_path = NULL;	struct inode *newinode = NULL;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	if (!old_valid_dev(device_number))		return -EINVAL;#endif	xid = GetXid();	cifs_sb = CIFS_SB(inode->i_sb);	pTcon = cifs_sb->tcon;	full_path = build_path_from_dentry(direntry);	if (full_path == NULL)		rc = -ENOMEM;	else if (pTcon->unix_ext) {		mode &= ~current->fs->umask;		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,				mode, (__u64)current->fsuid,				(__u64)current->fsgid,				device_number, cifs_sb->local_nls,				cifs_sb->mnt_cifs_flags &					CIFS_MOUNT_MAP_SPECIAL_CHR);		} else {			rc = CIFSSMBUnixSetPerms(xid, pTcon,				full_path, mode, (__u64)-1, (__u64)-1,				device_number, cifs_sb->local_nls,				cifs_sb->mnt_cifs_flags &					CIFS_MOUNT_MAP_SPECIAL_CHR);		}		if (!rc) {			rc = cifs_get_inode_info_unix(&newinode, full_path,						inode->i_sb, xid);			if (pTcon->nocase)				direntry->d_op = &cifs_ci_dentry_ops;			else				direntry->d_op = &cifs_dentry_ops;			if (rc == 0)				d_instantiate(direntry, newinode);		}	} else {		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {			int oplock = 0;			u16 fileHandle;			FILE_ALL_INFO * buf;			cFYI(1, ("sfu compat create special file"));			buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);			if (buf == NULL) {				kfree(full_path);				FreeXid(xid);				return -ENOMEM;			}			rc = CIFSSMBOpen(xid, pTcon, full_path,					 FILE_CREATE, /* fail if exists */					 GENERIC_WRITE /* BB would					  WRITE_OWNER | WRITE_DAC be better? */,					 /* Create a file and set the					    file attribute to SYSTEM */					 CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,					 &fileHandle, &oplock, buf,					 cifs_sb->local_nls,					 cifs_sb->mnt_cifs_flags &					    CIFS_MOUNT_MAP_SPECIAL_CHR);			/* BB FIXME - add handling for backlevel servers			   which need legacy open and check for all			   calls to SMBOpen for fallback to SMBLeagcyOpen */			if (!rc) {				/* BB Do not bother to decode buf since no				   local inode yet to put timestamps in,				   but we can reuse it safely */				unsigned int bytes_written;				struct win_dev *pdev;				pdev = (struct win_dev *)buf;				if (S_ISCHR(mode)) {					memcpy(pdev->type, "IntxCHR", 8);					pdev->major =					      cpu_to_le64(MAJOR(device_number));					pdev->minor =					      cpu_to_le64(MINOR(device_number));					rc = CIFSSMBWrite(xid, pTcon,						fileHandle,						sizeof(struct win_dev),						0, &bytes_written, (char *)pdev,						NULL, 0);				} else if (S_ISBLK(mode)) {					memcpy(pdev->type, "IntxBLK", 8);					pdev->major =					      cpu_to_le64(MAJOR(device_number));					pdev->minor =					      cpu_to_le64(MINOR(device_number));					rc = CIFSSMBWrite(xid, pTcon,						fileHandle,						sizeof(struct win_dev),						0, &bytes_written, (char *)pdev,						NULL, 0);				} /* else if(S_ISFIFO */				CIFSSMBClose(xid, pTcon, fileHandle);				d_drop(direntry);			}			kfree(buf);			/* add code here to set EAs */		}	}	kfree(full_path);	FreeXid(xid);	return rc;}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)struct dentry *cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,	    struct nameidata *nd)#elsestruct dentry *cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)#endif{	int xid;	int rc = 0; /* to get around spurious gcc warning, set to zero here */	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	struct inode *newInode = NULL;	char *full_path = NULL;	xid = GetXid();	cFYI(1,	     (" parent inode = 0x%p name is: %s and dentry = 0x%p",	      parent_dir_inode, direntry->d_name.name, direntry));	/* check whether path exists */	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);	pTcon = cifs_sb->tcon;	/*	 * Don't allow the separator character in a path component.	 * The VFS will not allow "/", but "\" is allowed by posix.	 */	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {		int i;		for (i = 0; i < direntry->d_name.len; i++)			if (direntry->d_name.name[i] == '\\') {				cFYI(1, ("Invalid file name"));				FreeXid(xid);				return ERR_PTR(-EINVAL);			}	}	/* can not grab the rename sem here since it would	deadlock in the cases (beginning of sys_rename itself)	in which we already have the sb rename sem */	full_path = build_path_from_dentry(direntry);	if (full_path == NULL) {		FreeXid(xid);		return ERR_PTR(-ENOMEM);	}	if (direntry->d_inode != NULL) {		cFYI(1, (" non-NULL inode in lookup"));	} else {		cFYI(1, (" NULL inode in lookup"));	}	cFYI(1,	     (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));	if (pTcon->unix_ext)		rc = cifs_get_inode_info_unix(&newInode, full_path,					      parent_dir_inode->i_sb, xid);	else		rc = cifs_get_inode_info(&newInode, full_path, NULL,					 parent_dir_inode->i_sb, xid);	if ((rc == 0) && (newInode != NULL)) {		if (pTcon->nocase)			direntry->d_op = &cifs_ci_dentry_ops;		else			direntry->d_op = &cifs_dentry_ops;		d_add(direntry, newInode);		/* since paths are not looked up by component - the parent		   directories are presumed to be good here */		renew_parental_timestamps(direntry);	} else if (rc == -ENOENT) {		rc = 0;		direntry->d_time = jiffies;		if (pTcon->nocase)			direntry->d_op = &cifs_ci_dentry_ops;		else			direntry->d_op = &cifs_dentry_ops;		d_add(direntry, NULL);	/*	if it was once a directory (but how can we tell?) we could do		shrink_dcache_parent(direntry); */	} else {		cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s",			   rc, full_path));		/* BB special case check for Access Denied - watch security		exposure of returning dir info implicitly via different rc		if file exists or not but no access BB */	}	kfree(full_path);	FreeXid(xid);	return ERR_PTR(rc);}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)static intcifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)#elsestatic intcifs_d_revalidate(struct dentry *direntry, int flags)#endif{	int isValid = 1;	if (direntry->d_inode) {		if (cifs_revalidate(direntry)) {			return 0;		}	} else {		cFYI(1, ("neg dentry 0x%p name = %s",			 direntry, direntry->d_name.name));		if (time_after(jiffies, direntry->d_time + HZ) ||			!lookupCacheEnabled) {			d_drop(direntry);			isValid = 0;		}	}	return isValid;}/* static int cifs_d_delete(struct dentry *direntry){	int rc = 0;	cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));	return rc;}     */struct dentry_operations cifs_dentry_ops = {	.d_revalidate = cifs_d_revalidate,/* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */};#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)#define nls_tolower(cp, name) tolower(name)#define nls_strnicmp(cp, name1, name2, len) strnicmp(name1, name2, len)#endifstatic int cifs_ci_hash(struct dentry *dentry, struct qstr *q){	struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;	unsigned long hash;	int i;	hash = init_name_hash();	for (i = 0; i < q->len; i++)		hash = partial_name_hash(nls_tolower(codepage, q->name[i]),					 hash);	q->hash = end_name_hash(hash);	return 0;}static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,			   struct qstr *b){	struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;	if ((a->len == b->len) &&	    (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {		/*		 * To preserve case, don't let an existing negative dentry's		 * case take precedence.  If a is not a negative dentry, this		 * should have no side effects		 */		memcpy((unsigned char *)a->name, b->name, a->len);		return 0;	}	return 1;}struct dentry_operations cifs_ci_dentry_ops = {	.d_revalidate = cifs_d_revalidate,	.d_hash = cifs_ci_hash,	.d_compare = cifs_ci_compare,};

⌨️ 快捷键说明

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