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

📄 readdir.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {		cFYI(1, ("can not return entries pos_in_buf beyond last"));		*num_to_ret = 0;	} else		*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;	return rc;}/* inode num, inode type and filename returned */static int cifs_get_name_from_search_buf(struct qstr *pqst,	char *current_entry, __u16 level, unsigned int unicode,	struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum){	int rc = 0;	unsigned int len = 0;	char *filename;	struct nls_table *nlt = cifs_sb->local_nls;	*pinum = 0;	if (level == SMB_FIND_FILE_UNIX) {		FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;		filename = &pFindData->FileName[0];		if (unicode) {			len = cifs_unicode_bytelen(filename);		} else {			/* BB should we make this strnlen of PATH_MAX? */			len = strnlen(filename, PATH_MAX);		}		/* BB fixme - hash low and high 32 bits if not 64 bit arch BB */		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)			*pinum = pFindData->UniqueId;	} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {		FILE_DIRECTORY_INFO *pFindData =			(FILE_DIRECTORY_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);	} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {		FILE_FULL_DIRECTORY_INFO *pFindData =			(FILE_FULL_DIRECTORY_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);	} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {		SEARCH_ID_FULL_DIR_INFO *pFindData =			(SEARCH_ID_FULL_DIR_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);		*pinum = pFindData->UniqueId;	} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {		FILE_BOTH_DIRECTORY_INFO *pFindData =			(FILE_BOTH_DIRECTORY_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);	} else if (level == SMB_FIND_FILE_INFO_STANDARD) {		FIND_FILE_STANDARD_INFO * pFindData =			(FIND_FILE_STANDARD_INFO *)current_entry;		filename = &pFindData->FileName[0];		/* one byte length, no name conversion */		len = (unsigned int)pFindData->FileNameLength;	} else {		cFYI(1, ("Unknown findfirst level %d", level));		return -EINVAL;	}	if (len > max_len) {		cERROR(1, ("bad search response length %d past smb end", len));		return -EINVAL;	}	if (unicode) {		/* BB fixme - test with long names */		/* Note converted filename can be longer than in unicode */		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)			pqst->len = cifs_convertUCSpath((char *)pqst->name,					(__le16 *)filename, len/2, nlt);		else			pqst->len = cifs_strfromUCS_le((char *)pqst->name,					(__le16 *)filename, len/2, nlt);	} else {		pqst->name = filename;		pqst->len = len;	}	pqst->hash = full_name_hash(pqst->name, pqst->len);/*	cFYI(1, ("filldir on %s",pqst->name));  */	return rc;}static int cifs_filldir(char *pfindEntry, struct file *file,	filldir_t filldir, void *direntry, char *scratch_buf, int max_len){	int rc = 0;	struct qstr qstring;	struct cifsFileInfo *pCifsF;	unsigned obj_type;	ino_t  inum;	struct cifs_sb_info *cifs_sb;	struct inode *tmp_inode;	struct dentry *tmp_dentry;	/* get filename and len into qstring */	/* get dentry */	/* decide whether to create and populate ionde */	if ((direntry == NULL) || (file == NULL))		return -EINVAL;	pCifsF = file->private_data;	if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))		return -ENOENT;	rc = cifs_entry_is_dot(pfindEntry, pCifsF);	/* skip . and .. since we added them first */	if (rc != 0)		return 0;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	cifs_sb = CIFS_SB(file->f_dentry->d_sb);#else	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);#endif	qstring.name = scratch_buf;	rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,			pCifsF->srch_inf.info_level,			pCifsF->srch_inf.unicode, cifs_sb,			max_len,			&inum /* returned */);	if (rc)		return rc;	rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry);	if ((tmp_inode == NULL) || (tmp_dentry == NULL))		return -ENOMEM;	if (rc) {		/* inode created, we need to hash it with right inode number */		if (inum != 0) {			/* BB fixme - hash the 2 32 quantities bits together if			 *  necessary BB */			tmp_inode->i_ino = inum;		}		insert_inode_hash(tmp_inode);	}	/* we pass in rc below, indicating whether it is a new inode,	   so we can figure out whether to invalidate the inode cached	   data if the file has changed */	if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)		unix_fill_in_inode(tmp_inode,				   (FILE_UNIX_INFO *)pfindEntry,				   &obj_type, rc);	else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)		fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,				pfindEntry, &obj_type, rc);	else		fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);	if (rc) /* new inode - needs to be tied to dentry */ {		d_instantiate(tmp_dentry, tmp_inode);		if (rc == 2)			d_rehash(tmp_dentry);	}	rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,		     tmp_inode->i_ino, obj_type);	if (rc) {		cFYI(1, ("filldir rc = %d", rc));		/* we can not return filldir errors to the caller		since they are "normal" when the stat blocksize		is too small - we return remapped error instead */		rc = -EOVERFLOW;	}	dput(tmp_dentry);	return rc;}static int cifs_save_resume_key(const char *current_entry,	struct cifsFileInfo *cifsFile){	int rc = 0;	unsigned int len = 0;	__u16 level;	char *filename;	if ((cifsFile == NULL) || (current_entry == NULL))		return -EINVAL;	level = cifsFile->srch_inf.info_level;	if (level == SMB_FIND_FILE_UNIX) {		FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;		filename = &pFindData->FileName[0];		if (cifsFile->srch_inf.unicode) {			len = cifs_unicode_bytelen(filename);		} else {			/* BB should we make this strnlen of PATH_MAX? */			len = strnlen(filename, PATH_MAX);		}		cifsFile->srch_inf.resume_key = pFindData->ResumeKey;	} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {		FILE_DIRECTORY_INFO *pFindData =			(FILE_DIRECTORY_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);		cifsFile->srch_inf.resume_key = pFindData->FileIndex;	} else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {		FILE_FULL_DIRECTORY_INFO *pFindData =			(FILE_FULL_DIRECTORY_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);		cifsFile->srch_inf.resume_key = pFindData->FileIndex;	} else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {		SEARCH_ID_FULL_DIR_INFO *pFindData =			(SEARCH_ID_FULL_DIR_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);		cifsFile->srch_inf.resume_key = pFindData->FileIndex;	} else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {		FILE_BOTH_DIRECTORY_INFO *pFindData =			(FILE_BOTH_DIRECTORY_INFO *)current_entry;		filename = &pFindData->FileName[0];		len = le32_to_cpu(pFindData->FileNameLength);		cifsFile->srch_inf.resume_key = pFindData->FileIndex;	} else if (level == SMB_FIND_FILE_INFO_STANDARD) {		FIND_FILE_STANDARD_INFO *pFindData =			(FIND_FILE_STANDARD_INFO *)current_entry;		filename = &pFindData->FileName[0];		/* one byte length, no name conversion */		len = (unsigned int)pFindData->FileNameLength;		cifsFile->srch_inf.resume_key = pFindData->ResumeKey;	} else {		cFYI(1, ("Unknown findfirst level %d", level));		return -EINVAL;	}	cifsFile->srch_inf.resume_name_len = len;	cifsFile->srch_inf.presume_name = filename;	return rc;}int cifs_readdir(struct file *file, void *direntry, filldir_t filldir){	int rc = 0;	int xid, i;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	struct cifsFileInfo *cifsFile = NULL;	char *current_entry;	int num_to_fill = 0;	char *tmp_buf = NULL;	char *end_of_smb;	int max_len;	xid = GetXid();#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	cifs_sb = CIFS_SB(file->f_dentry->d_sb);	pTcon = cifs_sb->tcon;	if (pTcon == NULL)		return -EINVAL;	switch ((int) file->f_pos) {	case 0:		if (filldir(direntry, ".", 1, file->f_pos,		     file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {			cERROR(1, ("Filldir for current dir failed"));			rc = -ENOMEM;			break;		}		file->f_pos++;	case 1:		if (filldir(direntry, "..", 2, file->f_pos,		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {#else	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);	pTcon = cifs_sb->tcon;	if (pTcon == NULL)		return -EINVAL;	switch ((int) file->f_pos) {	case 0:		if (filldir(direntry, ".", 1, file->f_pos,		     file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {			cERROR(1, ("Filldir for current dir failed"));			rc = -ENOMEM;			break;		}		file->f_pos++;	case 1:		if (filldir(direntry, "..", 2, file->f_pos,		     file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {#endif			cERROR(1, ("Filldir for parent dir failed"));			rc = -ENOMEM;			break;		}		file->f_pos++;	default:		/* 1) If search is active,			is in current search buffer?			if it before then restart search			if after then keep searching till find it */		if (file->private_data == NULL) {			rc = initiate_cifs_search(xid, file);			cFYI(1, ("initiate cifs search rc %d", rc));			if (rc) {				FreeXid(xid);				return rc;			}		}		if (file->private_data == NULL) {			rc = -EINVAL;			FreeXid(xid);			return rc;		}		cifsFile = file->private_data;		if (cifsFile->srch_inf.endOfSearch) {			if (cifsFile->srch_inf.emptyDir) {				cFYI(1, ("End of search, empty dir"));				rc = 0;				break;			}		} /* else {			cifsFile->invalidHandle = TRUE;			CIFSFindClose(xid, pTcon, cifsFile->netfid);		}		kfree(cifsFile->search_resume_name);		cifsFile->search_resume_name = NULL; */		rc = find_cifs_entry(xid, pTcon, file,				&current_entry, &num_to_fill);		if (rc) {			cFYI(1, ("fce error %d", rc));			goto rddir2_exit;		} else if (current_entry != NULL) {			cFYI(1, ("entry %lld found", file->f_pos));		} else {			cFYI(1, ("could not find entry"));			goto rddir2_exit;		}		cFYI(1, ("loop through %d times filling dir for net buf %p",			num_to_fill, cifsFile->srch_inf.ntwrk_buf_start));		max_len = smbCalcSize((struct smb_hdr *)				cifsFile->srch_inf.ntwrk_buf_start);		end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;		/* To be safe - for UCS to UTF-8 with strings loaded		with the rare long characters alloc more to account for		such multibyte target UTF-8 characters. cifs_unicode.c,		which actually does the conversion, has the same limit */		tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);		for (i = 0; (i < num_to_fill) && (rc == 0); i++) {			if (current_entry == NULL) {				/* evaluate whether this case is an error */				cERROR(1, ("past SMB end,  num to fill %d i %d",					  num_to_fill, i));				break;			}			/* if buggy server returns . and .. late do			we want to check for that here? */			rc = cifs_filldir(current_entry, file,					filldir, direntry, tmp_buf, max_len);			if (rc == -EOVERFLOW) {				rc = 0;				break;			}			file->f_pos++;			if (file->f_pos ==				cifsFile->srch_inf.index_of_last_entry) {				cFYI(1, ("last entry in buf at pos %lld %s",					file->f_pos, tmp_buf));				cifs_save_resume_key(current_entry, cifsFile);				break;			} else				current_entry =					nxt_dir_entry(current_entry, end_of_smb,						cifsFile->srch_inf.info_level);		}		kfree(tmp_buf);		break;	} /* end switch */rddir2_exit:	FreeXid(xid);	return rc;}

⌨️ 快捷键说明

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