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

📄 dir.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   fs/cifs/dir.c * *   vfs operations that deal with dentries * *   Copyright (C) International Business Machines  Corp., 2002,2005 *   Author(s): Steve French (sfrench@us.ibm.com) * *   This library is free software; you can redistribute it and/or modify *   it under the terms of the GNU Lesser General Public License as published *   by the Free Software Foundation; either version 2.1 of the License, or *   (at your option) any later version. * *   This library is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See *   the GNU Lesser General Public License for more details. * *   You should have received a copy of the GNU Lesser General Public License *   along with this library; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <linux/fs.h>#include <linux/stat.h>#include <linux/slab.h>#include <linux/version.h>#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)#include <linux/namei.h>#endif#include "cifsfs.h"#include "cifspdu.h"#include "cifsglob.h"#include "cifsproto.h"#include "cifs_debug.h"#include "cifs_fs_sb.h"#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)#include <linux/ctype.h>#endifstatic voidrenew_parental_timestamps(struct dentry *direntry){	/* BB check if there is a way to get the kernel to do this or if we	   really need this */	do {		direntry->d_time = jiffies;		direntry = direntry->d_parent;	} while (!IS_ROOT(direntry));}/* Note: caller must free return buffer */char *build_path_from_dentry(struct dentry *direntry){	struct dentry *temp;	int namelen;	int pplen;	char *full_path;	char dirsep;	if (direntry == NULL)		return NULL;  /* not much we can do if dentry is freed and		we need to reopen the file after it was closed implicitly		when the server crashed */	dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));	pplen = CIFS_SB(direntry->d_sb)->prepathlen;cifs_bp_rename_retry:	namelen = pplen;	for (temp = direntry; !IS_ROOT(temp);) {		namelen += (1 + temp->d_name.len);		temp = temp->d_parent;		if (temp == NULL) {			cERROR(1, ("corrupt dentry"));			return NULL;		}	}	full_path = kmalloc(namelen+1, GFP_KERNEL);	if (full_path == NULL)		return full_path;	full_path[namelen] = 0;	/* trailing null */	for (temp = direntry; !IS_ROOT(temp);) {		namelen -= 1 + temp->d_name.len;		if (namelen < 0) {			break;		} else {			full_path[namelen] = dirsep;			strncpy(full_path + namelen + 1, temp->d_name.name,				temp->d_name.len);			cFYI(0, ("name: %s", full_path + namelen));		}		temp = temp->d_parent;		if (temp == NULL) {			cERROR(1, ("corrupt dentry"));			kfree(full_path);			return NULL;		}	}	if (namelen != pplen) {		cERROR(1,		       ("did not end path lookup where expected namelen is %d",			namelen));		/* presumably this is only possible if racing with a rename		of one of the parent directories  (we can not lock the dentries		above us to prevent this, but retrying should be harmless) */		kfree(full_path);		goto cifs_bp_rename_retry;	}	/* DIR_SEP already set for byte  0 / vs \ but not for	   subsequent slashes in prepath which currently must	   be entered the right way - not sure if there is an alternative	   since the '\' is a valid posix character so we can not switch	   those safely to '/' if any are found in the middle of the prepath */	/* BB test paths to Windows with '/' in the midst of prepath */	strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);	return full_path;}/* char * build_wildcard_path_from_dentry(struct dentry *direntry){	if(full_path == NULL)		return full_path;	full_path[namelen] = '\\';	full_path[namelen+1] = '*';	full_path[namelen+2] = 0;BB remove above eight lines BB *//* Inode operations in similar order to how they appear in Linux file fs.h */int#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)cifs_create(struct inode *inode, struct dentry *direntry, int mode,		struct nameidata *nd)#elsecifs_create(struct inode *inode, struct dentry *direntry, int mode)#endif{	int rc = -ENOENT;	int xid;	int oplock = 0;	int desiredAccess = GENERIC_READ | GENERIC_WRITE;	__u16 fileHandle;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	char *full_path = NULL;	FILE_ALL_INFO *buf = NULL;	struct inode *newinode = NULL;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	struct cifsFileInfo *pCifsFile = NULL;	struct cifsInodeInfo *pCifsInode;	int write_only = FALSE;#endif	int disposition = FILE_OVERWRITE_IF;		xid = GetXid();	cifs_sb = CIFS_SB(inode->i_sb);	pTcon = cifs_sb->tcon;	full_path = build_path_from_dentry(direntry);	if (full_path == NULL) {		FreeXid(xid);		return -ENOMEM;	}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	if(nd && (nd->flags & LOOKUP_OPEN)) {#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,5) /* SUSE included Lustre patch */		int oflags = nd->intent.it_flags;#else		int oflags = nd->intent.open.flags;#endif		desiredAccess = 0;		if (oflags & FMODE_READ)			desiredAccess |= GENERIC_READ;		if (oflags & FMODE_WRITE) {			desiredAccess |= GENERIC_WRITE;			if (!(oflags & FMODE_READ))				write_only = TRUE;		}		if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))			disposition = FILE_CREATE;		else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))			disposition = FILE_OVERWRITE_IF;		else if ((oflags & O_CREAT) == O_CREAT)			disposition = FILE_OPEN_IF;		else {			cFYI(1, ("Create flag not set in create function"));		}	}	/* BB add processing to set equivalent of mode - e.g. via CreateX with	   ACLs */	if (oplockEnabled)		oplock = REQ_OPLOCK;#else	desiredAccess = GENERIC_WRITE;#endif	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);	if (buf == NULL) {		kfree(full_path);		FreeXid(xid);		return -ENOMEM;	}	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)		rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,			 desiredAccess, CREATE_NOT_DIR,			 &fileHandle, &oplock, buf, cifs_sb->local_nls,			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);	else		rc = -EIO; /* no NT SMB support fall into legacy open below */	if (rc == -EIO) {		/* old server, retry the open legacy style */		rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,			desiredAccess, CREATE_NOT_DIR,			&fileHandle, &oplock, buf, cifs_sb->local_nls,			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);	}	if (rc) {		cFYI(1, ("cifs_create returned 0x%x", rc));	} else {		/* If Open reported that we actually created a file		then we now have to set the mode if possible */		if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {			mode &= ~current->fs->umask;			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,					(__u64)current->fsuid,					(__u64)current->fsgid,					0 /* dev */,					cifs_sb->local_nls,					cifs_sb->mnt_cifs_flags &						CIFS_MOUNT_MAP_SPECIAL_CHR);			} else {				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,					(__u64)-1,					(__u64)-1,					0 /* dev */,					cifs_sb->local_nls,					cifs_sb->mnt_cifs_flags &						CIFS_MOUNT_MAP_SPECIAL_CHR);			}		} else {			/* BB implement mode setting via Windows security			   descriptors e.g. */			/* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/			/* Could set r/o dos attribute if mode & 0222 == 0 */		}		/* server might mask mode so we have to query for it */		if (pTcon->unix_ext)			rc = cifs_get_inode_info_unix(&newinode, full_path,						 inode->i_sb, xid);		else {			rc = cifs_get_inode_info(&newinode, full_path,						 buf, inode->i_sb, xid);			if (newinode) {				newinode->i_mode = mode;				if ((oplock & CIFS_CREATE_ACTION) &&				    (cifs_sb->mnt_cifs_flags &				     CIFS_MOUNT_SET_UID)) {					newinode->i_uid = current->fsuid;					newinode->i_gid = current->fsgid;				}			}		}		if (rc != 0) {			cFYI(1,			     ("Create worked but get_inode_info failed rc = %d",			      rc));		} else {			if (pTcon->nocase)				direntry->d_op = &cifs_ci_dentry_ops;			else				direntry->d_op = &cifs_dentry_ops;			d_instantiate(direntry, newinode);		}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)		if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||			((nd->flags & LOOKUP_OPEN) == FALSE)) {			/* mknod case - do not leave file open */			CIFSSMBClose(xid, pTcon, fileHandle);		} else if (newinode) {			pCifsFile =			   kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);			if (pCifsFile == NULL)				goto cifs_create_out;			pCifsFile->netfid = fileHandle;			pCifsFile->pid = current->tgid;			pCifsFile->pInode = newinode;			pCifsFile->invalidHandle = FALSE;			pCifsFile->closePend     = FALSE;			init_MUTEX(&pCifsFile->fh_sem);#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)			mutex_init(&pCifsFile->lock_mutex);#else			init_MUTEX(&pCifsFile->lock_mutex);#endif			INIT_LIST_HEAD(&pCifsFile->llist);			atomic_set(&pCifsFile->wrtPending, 0);			/* set the following in open now				pCifsFile->pfile = file; */			write_lock(&GlobalSMBSeslock);			list_add(&pCifsFile->tlist, &pTcon->openFileList);			pCifsInode = CIFS_I(newinode);			if (pCifsInode) {				/* if readable file instance put first in list*/				if (write_only == TRUE) {					list_add_tail(&pCifsFile->flist,						&pCifsInode->openFileList);				} else {					list_add(&pCifsFile->flist,						&pCifsInode->openFileList);				}				if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {					pCifsInode->clientCanCacheAll = TRUE;					pCifsInode->clientCanCacheRead = TRUE;					cFYI(1, ("Exclusive Oplock inode %p",

⌨️ 快捷键说明

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