trans2.c

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

C
2,183
字号
			p += 4;			SIVAL(p,0,reskey); p += 4;			put_long_date(p,cdate); p += 8;			put_long_date(p,adate); p += 8;			put_long_date(p,mdate); p += 8;			put_long_date(p,mdate); p += 8;			SOFF_T(p,0,file_size); p += 8;			SOFF_T(p,0,allocation_size); p += 8;			SIVAL(p,0,nt_extmode); p += 4;			q = p; p += 4; /* q is placeholder for name length. */			{				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);				SIVAL(p,0,ea_size); /* Extended attributes */				p += 4;			}			/* Clear the short name buffer. This is			 * IMPORTANT as not doing so will trigger			 * a Win2k client bug. JRA.			 */			if (!was_8_3 && check_mangled_names) {				pstring mangled_name;				pstrcpy(mangled_name, fname);				mangle_map(mangled_name,True,True,SNUM(conn));				mangled_name[12] = 0;				len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);				if (len < 24) {					memset(p + 2 + len,'\0',24 - len);				}				SSVAL(p, 0, len);			} else {				memset(p,'\0',26);			}			p += 2 + 24;			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);			SIVAL(q,0,len);			p += len;			SIVAL(p,0,0); /* Ensure any padding is null. */			len = PTR_DIFF(p, pdata);			len = (len + 3) & ~3;			SIVAL(pdata,0,len);			p = pdata + len;			break;		case SMB_FIND_FILE_DIRECTORY_INFO:			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));			p += 4;			SIVAL(p,0,reskey); p += 4;			put_long_date(p,cdate); p += 8;			put_long_date(p,adate); p += 8;			put_long_date(p,mdate); p += 8;			put_long_date(p,mdate); p += 8;			SOFF_T(p,0,file_size); p += 8;			SOFF_T(p,0,allocation_size); p += 8;			SIVAL(p,0,nt_extmode); p += 4;			len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);			SIVAL(p,0,len);			p += 4 + len;			SIVAL(p,0,0); /* Ensure any padding is null. */			len = PTR_DIFF(p, pdata);			len = (len + 3) & ~3;			SIVAL(pdata,0,len);			p = pdata + len;			break;      		case SMB_FIND_FILE_FULL_DIRECTORY_INFO:			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));			p += 4;			SIVAL(p,0,reskey); p += 4;			put_long_date(p,cdate); p += 8;			put_long_date(p,adate); p += 8;			put_long_date(p,mdate); p += 8;			put_long_date(p,mdate); p += 8;			SOFF_T(p,0,file_size); p += 8;			SOFF_T(p,0,allocation_size); p += 8;			SIVAL(p,0,nt_extmode); p += 4;			q = p; p += 4; /* q is placeholder for name length. */			{				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);				SIVAL(p,0,ea_size); /* Extended attributes */				p +=4;			}			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);			SIVAL(q, 0, len);			p += len;			SIVAL(p,0,0); /* Ensure any padding is null. */			len = PTR_DIFF(p, pdata);			len = (len + 3) & ~3;			SIVAL(pdata,0,len);			p = pdata + len;			break;		case SMB_FIND_FILE_NAMES_INFO:			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));			p += 4;			SIVAL(p,0,reskey); p += 4;			p += 4;			/* this must *not* be null terminated or w2k gets in a loop trying to set an			   acl on a dir (tridge) */			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);			SIVAL(p, -4, len);			p += len;			SIVAL(p,0,0); /* Ensure any padding is null. */			len = PTR_DIFF(p, pdata);			len = (len + 3) & ~3;			SIVAL(pdata,0,len);			p = pdata + len;			break;		case SMB_FIND_ID_FULL_DIRECTORY_INFO:			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));			p += 4;			SIVAL(p,0,reskey); p += 4;			put_long_date(p,cdate); p += 8;			put_long_date(p,adate); p += 8;			put_long_date(p,mdate); p += 8;			put_long_date(p,mdate); p += 8;			SOFF_T(p,0,file_size); p += 8;			SOFF_T(p,0,allocation_size); p += 8;			SIVAL(p,0,nt_extmode); p += 4;			q = p; p += 4; /* q is placeholder for name length. */			{				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);				SIVAL(p,0,ea_size); /* Extended attributes */				p +=4;			}			SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */			SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */			SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);			SIVAL(q, 0, len);			p += len; 			SIVAL(p,0,0); /* Ensure any padding is null. */			len = PTR_DIFF(p, pdata);			len = (len + 3) & ~3;			SIVAL(pdata,0,len);			p = pdata + len;			break;		case SMB_FIND_ID_BOTH_DIRECTORY_INFO:			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));			was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));			p += 4;			SIVAL(p,0,reskey); p += 4;			put_long_date(p,cdate); p += 8;			put_long_date(p,adate); p += 8;			put_long_date(p,mdate); p += 8;			put_long_date(p,mdate); p += 8;			SOFF_T(p,0,file_size); p += 8;			SOFF_T(p,0,allocation_size); p += 8;			SIVAL(p,0,nt_extmode); p += 4;			q = p; p += 4; /* q is placeholder for name length */			{				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);				SIVAL(p,0,ea_size); /* Extended attributes */				p +=4;			}			/* Clear the short name buffer. This is			 * IMPORTANT as not doing so will trigger			 * a Win2k client bug. JRA.			 */			if (!was_8_3 && check_mangled_names) {				pstring mangled_name;				pstrcpy(mangled_name, fname);				mangle_map(mangled_name,True,True,SNUM(conn));				mangled_name[12] = 0;				len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);				SSVAL(p, 0, len);				if (len < 24) {					memset(p + 2 + len,'\0',24 - len);				}				SSVAL(p, 0, len);			} else {				memset(p,'\0',26);			}			p += 26;			SSVAL(p,0,0); p += 2; /* Reserved ? */			SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */			SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);			SIVAL(q,0,len);			p += len;			SIVAL(p,0,0); /* Ensure any padding is null. */			len = PTR_DIFF(p, pdata);			len = (len + 3) & ~3;			SIVAL(pdata,0,len);			p = pdata + len;			break;		/* CIFS UNIX Extension. */		case SMB_FIND_FILE_UNIX:			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));			p+= 4;			SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */			/* Begin of SMB_QUERY_FILE_UNIX_BASIC */			SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */			p+= 8;			SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */			p+= 8;			put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */			put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */			put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */			p+= 24;			SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */			SIVAL(p,4,0);			p+= 8;			SIVAL(p,0,sbuf.st_gid);               /* group id of owner */			SIVAL(p,4,0);			p+= 8;			SIVAL(p,0,unix_filetype(sbuf.st_mode));			p+= 4;			SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */			SIVAL(p,4,0);			p+= 8;			SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */			SIVAL(p,4,0);			p+= 8;			SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */			p+= 8;			SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */			SIVAL(p,4,0);			p+= 8;			SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */			SIVAL(p,4,0);			p+= 8;			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);			p += len;			SIVAL(p,0,0); /* Ensure any padding is null. */			len = PTR_DIFF(p, pdata);			len = (len + 3) & ~3;			SIVAL(pdata,0,len);	/* Offset from this structure to the beginning of the next one */			p = pdata + len;			/* End of SMB_QUERY_FILE_UNIX_BASIC */			break;		default:      			return(False);	}	if (PTR_DIFF(p,pdata) > space_remaining) {		/* Move the dirptr back to prev_dirpos */		dptr_SeekDir(conn->dirptr, prev_dirpos);		*out_of_space = True;		DEBUG(9,("get_lanman2_dir_entry: out of space\n"));		return False; /* Not finished - just out of space */	}	/* Setup the last entry pointer, as an offset from base_data */	*last_entry_off = PTR_DIFF(last_entry_ptr,base_data);	/* Advance the data pointer to the next slot */	*ppdata = p;	return(found);}/**************************************************************************** Reply to a TRANS2_FINDFIRST.****************************************************************************/static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, 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;	uint32 dirtype = SVAL(params,0);	int maxentries = SVAL(params,2);	uint16 findfirst_flags = SVAL(params,4);	BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);	BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);	BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);	int info_level = SVAL(params,6);	pstring directory;	pstring mask;	char *p;	int last_entry_off=0;	int dptr_num = -1;	int numentries = 0;	int i;	BOOL finished = False;	BOOL dont_descend = False;	BOOL out_of_space = False;	int space_remaining;	BOOL bad_path = False;	BOOL mask_contains_wcard = False;	SMB_STRUCT_STAT sbuf;	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);	}	*directory = *mask = 0;	DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",		(unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,		info_level, max_data_bytes));	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));	}	srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);	if (!NT_STATUS_IS_OK(ntstatus)) {		return ERROR_NT(ntstatus);	}	RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);	unix_convert(directory,conn,0,&bad_path,&sbuf);	if (bad_path) {		return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);	}	if(!check_name(directory,conn)) {		return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);	}	p = strrchr_m(directory,'/');	if(p == NULL) {		/* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */		if((directory[0] == '.') && (directory[1] == '\0')) {			pstrcpy(mask,"*");			mask_contains_wcard = True;		} else {			pstrcpy(mask,directory);		}		pstrcpy(directory,"./");	} else {		pstrcpy(mask,p+1);		*p = 0;	}	DEBUG(5,("dir=%s, mask = %s\n",directory, mask));	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_trans2findfirst: 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, 10);	if (params == NULL) {		talloc_destroy(ea_ctx);		return ERROR_NT(NT_STATUS_NO_MEMORY);	}	*pparams = params;	/* Save the wildcard match and attribs we are using on this directory - 		needed as lanman2 assumes these are being saved between calls */	dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);	if (dptr_num < 0) {		talloc_destroy(ea_ctx);		return(UNIXERROR(ERRDOS,ERRbadfile));	}	DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));	/* We don't need to check for VOL here as this is returned by 		a different TRANS2 call. */

⌨️ 快捷键说明

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