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

📄 readdir.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *   fs/cifs/readdir.c * *   Directory search handling * *   Copyright (C) International Business Machines  Corp., 2004, 2007 *   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/pagemap.h>#include <linux/stat.h>#include <linux/smp_lock.h>#include "cifspdu.h"#include "cifsglob.h"#include "cifsproto.h"#include "cifs_unicode.h"#include "cifs_debug.h"#include "cifs_fs_sb.h"#include "cifsfs.h"#ifdef CONFIG_CIFS_DEBUG2static void dump_cifs_file_struct(struct file *file, char *label){	struct cifsFileInfo *cf;	if (file) {		cf = file->private_data;		if (cf == NULL) {			cFYI(1, ("empty cifs private file data"));			return;		}		if (cf->invalidHandle) {			cFYI(1, ("invalid handle"));		}		if (cf->srch_inf.endOfSearch) {			cFYI(1, ("end of search"));		}		if (cf->srch_inf.emptyDir) {			cFYI(1, ("empty dir"));		}	}}#endif /* DEBUG2 *//* Returns one if new inode created (which therefore needs to be hashed) *//* Might check in the future if inode number changed so we can rehash inode */static int construct_dentry(struct qstr *qstring, struct file *file,	struct inode **ptmp_inode, struct dentry **pnew_dentry){	struct dentry *tmp_dentry;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	int rc = 0;	cFYI(1, ("For %s", qstring->name));#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	cifs_sb = CIFS_SB(file->f_dentry->d_sb);	pTcon = cifs_sb->tcon;	qstring->hash = full_name_hash(qstring->name, qstring->len);	tmp_dentry = d_lookup(file->f_dentry, qstring);	if (tmp_dentry) {		cFYI(0, ("existing dentry with inode 0x%p",			 tmp_dentry->d_inode));		*ptmp_inode = tmp_dentry->d_inode;/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/		if (*ptmp_inode == NULL) {			*ptmp_inode = new_inode(file->f_dentry->d_sb);#else	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);	pTcon = cifs_sb->tcon;	qstring->hash = full_name_hash(qstring->name, qstring->len);	tmp_dentry = d_lookup(file->f_path.dentry, qstring);	if (tmp_dentry) {		cFYI(0, ("existing dentry with inode 0x%p",			 tmp_dentry->d_inode));		*ptmp_inode = tmp_dentry->d_inode;/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/		if (*ptmp_inode == NULL) {			*ptmp_inode = new_inode(file->f_path.dentry->d_sb);#endif			if (*ptmp_inode == NULL)				return rc;			rc = 1;		}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19)		if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)#else		if (file->f_dentry->d_sb->s_flags & MS_NOATIME)#endif			(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;	} else {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)		tmp_dentry = d_alloc(file->f_dentry, qstring);#else		tmp_dentry = d_alloc(file->f_path.dentry, qstring);#endif		if (tmp_dentry == NULL) {			cERROR(1, ("Failed allocating dentry"));			*ptmp_inode = NULL;			return rc;		}#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)		*ptmp_inode = new_inode(file->f_dentry->d_sb);#else		*ptmp_inode = new_inode(file->f_path.dentry->d_sb);#endif		if (pTcon->nocase)			tmp_dentry->d_op = &cifs_ci_dentry_ops;		else			tmp_dentry->d_op = &cifs_dentry_ops;		if (*ptmp_inode == NULL)			return rc;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19)		if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)#else		if (file->f_dentry->d_sb->s_flags & MS_NOATIME)#endif			(*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;		rc = 2;	}	tmp_dentry->d_time = jiffies;	*pnew_dentry = tmp_dentry;	return rc;}static void AdjustForTZ(struct cifsTconInfo *tcon, struct inode *inode){	if ((tcon) && (tcon->ses) && (tcon->ses->server)) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)		inode->i_ctime.tv_sec += tcon->ses->server->timeAdj;		inode->i_mtime.tv_sec += tcon->ses->server->timeAdj;		inode->i_atime.tv_sec += tcon->ses->server->timeAdj;#else		inode->i_ctime += tcon->ses->server->timeAdj;		inode->i_mtime += tcon->ses->server->timeAdj;		inode->i_atime += tcon->ses->server->timeAdj;#endif	}	return;}static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,			  char *buf, int *pobject_type, int isNewInode){	loff_t local_size;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	struct timespec local_mtime;#else	time_t local_mtime;#endif	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);	__u32 attr;	__u64 allocation_size;	__u64 end_of_file;	/* save mtime and size */	local_mtime = tmp_inode->i_mtime;	local_size  = tmp_inode->i_size;	if (new_buf_type) {		FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;		attr = le32_to_cpu(pfindData->ExtFileAttributes);		allocation_size = le64_to_cpu(pfindData->AllocationSize);		end_of_file = le64_to_cpu(pfindData->EndOfFile);		tmp_inode->i_atime =		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));		tmp_inode->i_mtime =		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));		tmp_inode->i_ctime =		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));	} else { /* legacy, OS2 and DOS style *//*		struct timespec ts;*/		FIND_FILE_STANDARD_INFO * pfindData =			(FIND_FILE_STANDARD_INFO *)buf;		tmp_inode->i_mtime = cnvrtDosUnixTm(				le16_to_cpu(pfindData->LastWriteDate),				le16_to_cpu(pfindData->LastWriteTime));		tmp_inode->i_atime = cnvrtDosUnixTm(				le16_to_cpu(pfindData->LastAccessDate),				le16_to_cpu(pfindData->LastAccessTime));		tmp_inode->i_ctime = cnvrtDosUnixTm(				le16_to_cpu(pfindData->LastWriteDate),				le16_to_cpu(pfindData->LastWriteTime));		AdjustForTZ(cifs_sb->tcon, tmp_inode);		attr = le16_to_cpu(pfindData->Attributes);		allocation_size = le32_to_cpu(pfindData->AllocationSize);		end_of_file = le32_to_cpu(pfindData->DataSize);	}	/* Linux can not store file creation time unfortunately so ignore it */	cifsInfo->cifsAttrs = attr;	cifsInfo->time = jiffies;	/* treat dos attribute of read-only as read-only mode bit e.g. 555? */	/* 2767 perms - indicate mandatory locking */		/* BB fill in uid and gid here? with help from winbind?		   or retrieve from NTFS stream extended attribute */	if (atomic_read(&cifsInfo->inUse) == 0) {		tmp_inode->i_uid = cifs_sb->mnt_uid;		tmp_inode->i_gid = cifs_sb->mnt_gid;		/* set default mode. will override for dirs below */		tmp_inode->i_mode = cifs_sb->mnt_file_mode;	} else {		/* mask off the type bits since it gets set		below and we do not want to get two type		bits set */		tmp_inode->i_mode &= ~S_IFMT;	}	if (attr & ATTR_DIRECTORY) {		*pobject_type = DT_DIR;		/* override default perms since we do not lock dirs */		if (atomic_read(&cifsInfo->inUse) == 0) {			tmp_inode->i_mode = cifs_sb->mnt_dir_mode;		}		tmp_inode->i_mode |= S_IFDIR;	} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&		   (attr & ATTR_SYSTEM)) {		if (end_of_file == 0)  {			*pobject_type = DT_FIFO;			tmp_inode->i_mode |= S_IFIFO;		} else {			/* rather than get the type here, we mark the			inode as needing revalidate and get the real type			(blk vs chr vs. symlink) later ie in lookup */			*pobject_type = DT_REG;			tmp_inode->i_mode |= S_IFREG;			cifsInfo->time = 0;		}/* we no longer mark these because we could not follow them *//*        } else if (attr & ATTR_REPARSE) {		*pobject_type = DT_LNK;		tmp_inode->i_mode |= S_IFLNK; */	} else {		*pobject_type = DT_REG;		tmp_inode->i_mode |= S_IFREG;		if (attr & ATTR_READONLY)			tmp_inode->i_mode &= ~(S_IWUGO);		else if ((tmp_inode->i_mode & S_IWUGO) == 0)			/* the ATTR_READONLY flag may have been changed on   */			/* server -- set any w bits allowed by mnt_file_mode */			tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode);	} /* could add code here - to validate if device or weird share type? */	/* can not fill in nlink here as in qpathinfo version and Unx search */	if (atomic_read(&cifsInfo->inUse) == 0) {		atomic_set(&cifsInfo->inUse, 1);	}	spin_lock(&tmp_inode->i_lock);	if (is_size_safe_to_change(cifsInfo, end_of_file)) {		/* can not safely change the file size here if the		client is writing to it due to potential races */		i_size_write(tmp_inode, end_of_file);	/* 512 bytes (2**9) is the fake blocksize that must be used */	/* for this calculation, even though the reported blocksize is larger */		tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;	}	spin_unlock(&tmp_inode->i_lock);	if (allocation_size < end_of_file)		cFYI(1, ("May be sparse file, allocation less than file size"));	cFYI(1, ("File Size %ld and blocks %llu",		(unsigned long)tmp_inode->i_size,		(unsigned long long)tmp_inode->i_blocks));	if (S_ISREG(tmp_inode->i_mode)) {		cFYI(1, ("File inode"));		tmp_inode->i_op = &cifs_file_inode_ops;		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)				tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;			else				tmp_inode->i_fop = &cifs_file_direct_ops;		} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)			tmp_inode->i_fop = &cifs_file_nobrl_ops;		else			tmp_inode->i_fop = &cifs_file_ops;		if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&		   (cifs_sb->tcon->ses->server->maxBuf <			PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))			tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;		else			tmp_inode->i_data.a_ops = &cifs_addr_ops;		if (isNewInode)			return; /* No sense invalidating pages for new inode				   since have not started caching readahead file				   data yet */		if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&			(local_size == tmp_inode->i_size)) {			cFYI(1, ("inode exists but unchanged"));		} else {			/* file may have changed on server */			cFYI(1, ("invalidate inode, readdir detected change"));			invalidate_remote_inode(tmp_inode);		}	} else if (S_ISDIR(tmp_inode->i_mode)) {		cFYI(1, ("Directory inode"));		tmp_inode->i_op = &cifs_dir_inode_ops;		tmp_inode->i_fop = &cifs_dir_ops;	} else if (S_ISLNK(tmp_inode->i_mode)) {		cFYI(1, ("Symbolic Link inode"));		tmp_inode->i_op = &cifs_symlink_inode_ops;	} else {		cFYI(1, ("Init special inode"));		init_special_inode(tmp_inode, tmp_inode->i_mode,				   tmp_inode->i_rdev);	}}static void unix_fill_in_inode(struct inode *tmp_inode,	FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode){	loff_t local_size;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)	struct timespec local_mtime;#else	time_t local_mtime;#endif	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);	__u32 type = le32_to_cpu(pfindData->Type);	__u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);	cifsInfo->time = jiffies;	atomic_inc(&cifsInfo->inUse);	/* save mtime and size */	local_mtime = tmp_inode->i_mtime;	local_size  = tmp_inode->i_size;	tmp_inode->i_atime =	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));	tmp_inode->i_mtime =	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));	tmp_inode->i_ctime =	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));	tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);	/* since we set the inode type below we need to mask off type	   to avoid strange results if bits above were corrupt */	tmp_inode->i_mode &= ~S_IFMT;	if (type == UNIX_FILE) {		*pobject_type = DT_REG;		tmp_inode->i_mode |= S_IFREG;	} else if (type == UNIX_SYMLINK) {		*pobject_type = DT_LNK;		tmp_inode->i_mode |= S_IFLNK;	} else if (type == UNIX_DIR) {		*pobject_type = DT_DIR;		tmp_inode->i_mode |= S_IFDIR;	} else if (type == UNIX_CHARDEV) {		*pobject_type = DT_CHR;		tmp_inode->i_mode |= S_IFCHR;		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),				le64_to_cpu(pfindData->DevMinor) & MINORMASK);	} else if (type == UNIX_BLOCKDEV) {		*pobject_type = DT_BLK;		tmp_inode->i_mode |= S_IFBLK;		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),				le64_to_cpu(pfindData->DevMinor) & MINORMASK);	} else if (type == UNIX_FIFO) {		*pobject_type = DT_FIFO;		tmp_inode->i_mode |= S_IFIFO;	} else if (type == UNIX_SOCKET) {		*pobject_type = DT_SOCK;		tmp_inode->i_mode |= S_IFSOCK;	} else {

⌨️ 快捷键说明

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