trans2.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 2,183 行 · 第 1/5 页

C
2,183
字号
  	DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));	if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))		dont_descend = True;    	p = pdata;	space_remaining = max_data_bytes;	out_of_space = False;	for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {		BOOL got_exact_match = False;		/* this is a heuristic to avoid seeking the dirptr except when 			absolutely necessary. It allows for a filename of about 40 chars */		if (space_remaining < DIRLEN_GUESS && numentries > 0) {			out_of_space = True;			finished = False;		} else {			finished = !get_lanman2_dir_entry(conn,					inbuf, outbuf,					mask,dirtype,info_level,					requires_resume_key,dont_descend,					&p,pdata,space_remaining, &out_of_space, &got_exact_match,					&last_entry_off, ea_list, ea_ctx);		}		if (finished && out_of_space)			finished = False;		if (!finished && !out_of_space)			numentries++;		/*		 * As an optimisation if we know we aren't looking		 * for a wildcard name (ie. the name matches the wildcard exactly)		 * then we can finish on any (first) match.		 * This speeds up large directory searches. JRA.		 */		if(got_exact_match)			finished = True;		space_remaining = max_data_bytes - PTR_DIFF(p,pdata);	}  	talloc_destroy(ea_ctx);	/* Check if we can close the dirptr */	if(close_after_first || (finished && close_if_end)) {		DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));		dptr_close(&dptr_num);	}	/* 	 * If there are no matching entries we must return ERRDOS/ERRbadfile - 	 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if	 * the protocol level is less than NT1. Tested with smbclient. JRA.	 * This should fix the OS/2 client bug #2335.	 */	if(numentries == 0) {		dptr_close(&dptr_num);		if (Protocol < PROTOCOL_NT1) {			return ERROR_DOS(ERRDOS,ERRnofiles);		} else {			return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);		}	}	/* At this point pdata points to numentries directory entries. */	/* Set up the return parameter block */	SSVAL(params,0,dptr_num);	SSVAL(params,2,numentries);	SSVAL(params,4,finished);	SSVAL(params,6,0); /* Never an EA error */	SSVAL(params,8,last_entry_off);	send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));	if ((! *directory) && dptr_path(dptr_num))		slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));	DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",		smb_fn_name(CVAL(inbuf,smb_com)), 		mask, directory, dirtype, numentries ) );	/* 	 * Force a name mangle here to ensure that the	 * mask as an 8.3 name is top of the mangled cache.	 * The reasons for this are subtle. Don't remove	 * this code unless you know what you are doing	 * (see PR#13758). JRA.	 */	if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))		mangle_map(mask, True, True, SNUM(conn));	return(-1);}/**************************************************************************** Reply to a TRANS2_FINDNEXT.****************************************************************************/static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,					char **pparams, int total_params, char **ppdata, int total_data,					unsigned int max_data_bytes){	/* We must be careful here that we don't return more than the		allowed number of data bytes. If this means returning fewer than		maxentries then so be it. We assume that the redirector has		enough room for the fixed number of parameter bytes it has		requested. */	char *params = *pparams;	char *pdata = *ppdata;	int dptr_num = SVAL(params,0);	int maxentries = SVAL(params,2);	uint16 info_level = SVAL(params,4);	uint32 resume_key = IVAL(params,6);	uint16 findnext_flags = SVAL(params,10);	BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);	BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);	BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);	BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);	BOOL mask_contains_wcard = False;	pstring resume_name;	pstring mask;	pstring directory;	char *p;	uint16 dirtype;	int numentries = 0;	int i, last_entry_off=0;	BOOL finished = False;	BOOL dont_descend = False;	BOOL out_of_space = False;	int space_remaining;	TALLOC_CTX *ea_ctx = NULL;	struct ea_list *ea_list = NULL;	NTSTATUS ntstatus = NT_STATUS_OK;	if (total_params < 12) {		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);	}	*mask = *directory = *resume_name = 0;	srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);	if (!NT_STATUS_IS_OK(ntstatus)) {		/* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to		   complain (it thinks we're asking for the directory above the shared		   path or an invalid name). Catch this as the resume name is only compared, never used in		   a file access. JRA. */		if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {			pstrcpy(resume_name, "..");		} else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {			pstrcpy(resume_name, ".");		} else {			return ERROR_NT(ntstatus);		}	}	DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \close_after_request=%d, close_if_end = %d requires_resume_key = %d \resume_key = %d resume name = %s continue=%d level = %d\n",		dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 		requires_resume_key, resume_key, resume_name, continue_bit, info_level));	if (!maxentries) {		/* W2K3 seems to treat zero as 1. */		maxentries = 1;	}	switch (info_level) {		case SMB_FIND_INFO_STANDARD:		case SMB_FIND_EA_SIZE:		case SMB_FIND_EA_LIST:		case SMB_FIND_FILE_DIRECTORY_INFO:		case SMB_FIND_FILE_FULL_DIRECTORY_INFO:		case SMB_FIND_FILE_NAMES_INFO:		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:		case SMB_FIND_ID_FULL_DIRECTORY_INFO:		case SMB_FIND_ID_BOTH_DIRECTORY_INFO:			break;		case SMB_FIND_FILE_UNIX:			if (!lp_unix_extensions())				return(ERROR_DOS(ERRDOS,ERRunknownlevel));			break;		default:			return ERROR_DOS(ERRDOS,ERRunknownlevel);	}	if (info_level == SMB_FIND_EA_LIST) {		uint32 ea_size;		if (total_data < 4) {			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}		ea_size = IVAL(pdata,0);		if (ea_size != total_data) {			DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}                                                                                                                                                     		if (!lp_ea_support(SNUM(conn))) {			return ERROR_DOS(ERRDOS,ERReasnotsupported);		}                                                                                                                                                     		if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {			return ERROR_NT(NT_STATUS_NO_MEMORY);		}		/* Pull out the list of names. */		ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);		if (!ea_list) {			talloc_destroy(ea_ctx);			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);		}	}	pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);	if(pdata == NULL) {		talloc_destroy(ea_ctx);		return ERROR_NT(NT_STATUS_NO_MEMORY);	}	*ppdata = pdata;	/* Realloc the params space */	params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);	if( params == NULL ) {		talloc_destroy(ea_ctx);		return ERROR_NT(NT_STATUS_NO_MEMORY);	}	*pparams = params;	/* Check that the dptr is valid */	if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {		talloc_destroy(ea_ctx);		return ERROR_DOS(ERRDOS,ERRnofiles);	}	string_set(&conn->dirpath,dptr_path(dptr_num));	/* Get the wildcard mask from the dptr */	if((p = dptr_wcard(dptr_num))== NULL) {		DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));		talloc_destroy(ea_ctx);		return ERROR_DOS(ERRDOS,ERRnofiles);	}	pstrcpy(mask, p);	pstrcpy(directory,conn->dirpath);	/* Get the attr mask from the dptr */	dirtype = dptr_attr(dptr_num);	DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",		dptr_num, mask, dirtype, 		(long)conn->dirptr,		dptr_TellDir(conn->dirptr)));	/* We don't need to check for VOL here as this is returned by 		a different TRANS2 call. */	DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));	if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))		dont_descend = True;    	p = pdata;	space_remaining = max_data_bytes;	out_of_space = False;	/* 	 * Seek to the correct position. We no longer use the resume key but	 * depend on the last file name instead.	 */	if(*resume_name && !continue_bit) {		SMB_STRUCT_STAT st;		long current_pos = 0;		/*		 * Remember, mangle_map is called by		 * get_lanman2_dir_entry(), so the resume name		 * could be mangled. Ensure we check the unmangled name.		 */		if (mangle_is_mangled(resume_name, SNUM(conn))) {			mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));		}		/*		 * Fix for NT redirector problem triggered by resume key indexes		 * changing between directory scans. We now return a resume key of 0		 * and instead look for the filename to continue from (also given		 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the		 * findfirst/findnext (as is usual) then the directory pointer		 * should already be at the correct place.		 */		finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);	} /* end if resume_name && !continue_bit */	for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {		BOOL got_exact_match = False;		/* this is a heuristic to avoid seeking the dirptr except when 			absolutely necessary. It allows for a filename of about 40 chars */		if (space_remaining < DIRLEN_GUESS && numentries > 0) {			out_of_space = True;			finished = False;		} else {			finished = !get_lanman2_dir_entry(conn,						inbuf, outbuf,						mask,dirtype,info_level,						requires_resume_key,dont_descend,						&p,pdata,space_remaining, &out_of_space, &got_exact_match,						&last_entry_off, ea_list, ea_ctx);		}		if (finished && out_of_space)			finished = False;		if (!finished && !out_of_space)			numentries++;		/*		 * As an optimisation if we know we aren't looking		 * for a wildcard name (ie. the name matches the wildcard exactly)		 * then we can finish on any (first) match.		 * This speeds up large directory searches. JRA.		 */		if(got_exact_match)			finished = True;		space_remaining = max_data_bytes - PTR_DIFF(p,pdata);	}  	talloc_destroy(ea_ctx);	/* Check if we can close the dirptr */	if(close_after_request || (finished && close_if_end)) {		DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));		dptr_close(&dptr_num); /* This frees up the saved mask */	}	/* Set up the return parameter block */	SSVAL(params,0,numentries);	SSVAL(params,2,finished);	SSVAL(params,4,0); /* Never an EA error */	SSVAL(params,6,last_entry_off);	send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));	if ((! *directory) && dptr_path(dptr_num))		slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));	DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",		smb_fn_name(CVAL(inbuf,smb_com)), 		mask, directory, dirtype, numentries ) );	return(-1);}/**************************************************************************** Reply to a TRANS2_QFSINFO (query filesystem info).****************************************************************************/static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,					char **pparams, int total_params, char **ppdata, int total_data,					unsigned int max_data_bytes){	char *pdata = *ppdata;	char *params = *pparams;	uint16 info_level = SVAL(params,0);	int data_len, len;	SMB_STRUCT_STAT st;	char *vname = volume_label(SNUM(conn));	int snum = SNUM(conn);	char *fstype = lp_fstype(SNUM(conn));	int quota_flag = 0;	DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));	if(SMB_VFS_STAT(conn,".",&st)!=0) {		DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));		return ERROR_DOS(ERRSRV,ERRinvdevice);	}	pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);	if ( pdata == NULL ) {		return ERROR_NT(NT_STATUS_NO_MEMORY);	}	*ppdata = pdata;	memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);	switch (info_level) {		case SMB_INFO_ALLOCATION:		{			SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;			data_len = 18;			if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {				return(UNIXERROR(ERRHRD,ERRgeneral));			}			block_size = lp_block_size(snum);			if (bsize < block_size) {				SMB_BIG_UINT factor = block_size/bsize;				bsize = block_size;				dsize /= factor;				dfree /= factor;			}			if (bsize > block_size) {				SMB_BIG_UINT factor = bsize/block_size;				bsize = block_size;				dsize *= factor;				dfree *= factor;			}			bytes_per_sector = 512;			sectors_per_unit = bsize/bytes_per_sector;			DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,				(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));			SIVAL(pdata,l1_idFileSystem,st.st_dev);			SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);			SIVAL(pdata,l1_cUnit,dsize);			SIVAL(pdata

⌨️ 快捷键说明

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