From 50f54250f4b566e10d0be40dc2d0117c6cb7a73d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Aug 2009 12:15:51 +0200 Subject: s3:smbd: split the dir entry marshalling into smbd_marshall_dir_entry() So that we can reuse it for SMB2 Find. metze --- source3/smbd/trans2.c | 925 ++++++++++++++++++++++++++------------------------ 1 file changed, 482 insertions(+), 443 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9273339b71..780d7d606c 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1446,88 +1446,41 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx, return true; } -static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, - connection_struct *conn, - struct dptr_struct *dirptr, - uint16 flags2, - const char *path_mask, - uint32 dirtype, - int info_level, - int requires_resume_key, - bool dont_descend, - bool ask_sharemode, - char **ppdata, - char *base_data, - char *end_data, - int space_remaining, - bool *out_of_space, - bool *got_exact_match, - int *last_entry_off, - struct ea_list *name_list) +static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + uint16_t flags2, + uint32_t info_level, + struct ea_list *name_list, + bool check_mangled_names, + bool requires_resume_key, + uint32_t mode, + const char *fname, + const struct smb_filename *smb_fname, + uint64_t space_remaining, + char *base_data, + char **ppdata, + char *end_data, + bool *out_of_space, + uint64_t *last_entry_off) { - const char *mask = NULL; char *p, *q, *pdata = *ppdata; - uint32 reskey=0; - long prev_dirpos=0; - uint32 mode=0; - SMB_OFF_T file_size = 0; + uint32_t reskey=0; + uint64_t file_size = 0; uint64_t allocation_size = 0; - uint32 len; + uint32_t len; struct timespec mdate_ts, adate_ts, create_date_ts; time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0; char *nameptr; char *last_entry_ptr; bool was_8_3; - uint32 nt_extmode; /* Used for NT connections instead of mode */ - char *fname = NULL; - struct smb_filename *smb_fname = NULL; - struct smbd_dirptr_lanman2_state state; - bool ok; + uint32_t nt_extmode; /* Used for NT connections instead of mode */ - ZERO_STRUCT(state); - state.conn = conn; - state.info_level = info_level; - state.check_mangled_names = lp_manglednames(conn->params); - state.has_wild = dptr_has_wild(dirptr); - state.got_exact_match = false; - - *out_of_space = False; - *got_exact_match = False; + *out_of_space = false; ZERO_STRUCT(mdate_ts); ZERO_STRUCT(adate_ts); ZERO_STRUCT(create_date_ts); - p = strrchr_m(path_mask,'/'); - if(p != NULL) { - if(p[1] == '\0') { - mask = "*.*"; - } else { - mask = p+1; - } - } else { - mask = path_mask; - } - - ok = smbd_dirptr_get_entry(ctx, - dirptr, - mask, - dirtype, - dont_descend, - ask_sharemode, - smbd_dirptr_lanman2_match_fn, - smbd_dirptr_lanman2_mode_fn, - &state, - &fname, - &smb_fname, - &mode, - &prev_dirpos); - if (!ok) { - return false; - } - - *got_exact_match = state.got_exact_match; - if (!(mode & aDIR)) { file_size = get_file_size_stat(&smb_fname->st); } @@ -1553,418 +1506,405 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) { - case SMB_FIND_INFO_STANDARD: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - p += 23; - nameptr = p; - if (flags2 & FLAGS2_UNICODE_STRINGS) { - p += ucs2_align(base_data, p, 0); - } - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - SCVAL(nameptr, -1, len - 2); - } else { - SCVAL(nameptr, -1, 0); - } + case SMB_FIND_INFO_STANDARD: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 23; + nameptr = p; + if (flags2 & FLAGS2_UNICODE_STRINGS) { + p += ucs2_align(base_data, p, 0); + } + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + SCVAL(nameptr, -1, len - 2); } else { - if (len > 1) { - SCVAL(nameptr, -1, len - 1); - } else { - SCVAL(nameptr, -1, 0); - } - } - p += len; - break; - - case SMB_FIND_EA_SIZE: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - { - unsigned int ea_size = estimate_ea_size(conn, NULL, - smb_fname->base_name); - SIVAL(p,22,ea_size); /* Extended attributes */ + SCVAL(nameptr, -1, 0); } - p += 27; - nameptr = p - 1; - len = srvstr_push(base_data, flags2, - p, fname, PTR_DIFF(end_data, p), - STR_TERMINATE | STR_NOALIGN); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - len -= 2; - } else { - len = 0; - } + } else { + if (len > 1) { + SCVAL(nameptr, -1, len - 1); } else { - if (len > 1) { - len -= 1; - } else { - len = 0; - } + SCVAL(nameptr, -1, 0); } - SCVAL(nameptr,0,len); - p += len; - SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ - break; + } + p += len; + break; - case SMB_FIND_EA_LIST: + case SMB_FIND_EA_SIZE: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); + if (requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); { - struct ea_list *file_list = NULL; - size_t ea_len = 0; - - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); - if (!name_list) { - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - return False; - } - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - srv_put_dos_date2(p,0,create_date); - srv_put_dos_date2(p,4,adate); - srv_put_dos_date2(p,8,mdate); - SIVAL(p,12,(uint32)file_size); - SIVAL(p,16,(uint32)allocation_size); - SSVAL(p,20,mode); - p += 22; /* p now points to the EA area. */ - - file_list = get_ea_list_from_file(ctx, conn, NULL, - smb_fname->base_name, - &ea_len); - name_list = ea_list_union(name_list, file_list, &ea_len); - - /* We need to determine if this entry will fit in the space available. */ - /* Max string size is 255 bytes. */ - if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(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 */ + unsigned int ea_size = estimate_ea_size(conn, NULL, + smb_fname->base_name); + SIVAL(p,22,ea_size); /* Extended attributes */ + } + p += 27; + nameptr = p - 1; + len = srvstr_push(base_data, flags2, + p, fname, PTR_DIFF(end_data, p), + STR_TERMINATE | STR_NOALIGN); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; } - - /* Push the ea_data followed by the name. */ - p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); - nameptr = p; - len = srvstr_push(base_data, flags2, - p + 1, fname, PTR_DIFF(end_data, p+1), - STR_TERMINATE | STR_NOALIGN); - if (flags2 & FLAGS2_UNICODE_STRINGS) { - if (len > 2) { - len -= 2; - } else { - len = 0; - } + } else { + if (len > 1) { + len -= 1; } else { - if (len > 1) { - len -= 1; - } else { - len = 0; - } + len = 0; } - SCVAL(nameptr,0,len); - p += len + 1; - SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ - break; } + SCVAL(nameptr,0,len); + p += len; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); - was_8_3 = mangle_is_8_3(fname, True, conn->params); + case SMB_FIND_EA_LIST: + { + struct ea_list *file_list = NULL; + size_t ea_len = 0; + + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); + if (!name_list) { + return false; + } + if (requires_resume_key) { + SIVAL(p,0,reskey); p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); 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, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p += 4; + } + srv_put_dos_date2(p,0,create_date); + srv_put_dos_date2(p,4,adate); + srv_put_dos_date2(p,8,mdate); + SIVAL(p,12,(uint32)file_size); + SIVAL(p,16,(uint32)allocation_size); + SSVAL(p,20,mode); + p += 22; /* p now points to the EA area. */ + + file_list = get_ea_list_from_file(ctx, conn, NULL, + smb_fname->base_name, + &ea_len); + name_list = ea_list_union(name_list, file_list, &ea_len); + + /* We need to determine if this entry will fit in the space available. */ + /* Max string size is 255 bytes. */ + if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { + *out_of_space = true; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } + + /* Push the ea_data followed by the name. */ + p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list); + nameptr = p; + len = srvstr_push(base_data, flags2, + p + 1, fname, PTR_DIFF(end_data, p+1), + STR_TERMINATE | STR_NOALIGN); + if (flags2 & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; } - /* Clear the short name buffer. This is - * IMPORTANT as not doing so will trigger - * a Win2k client bug. JRA. - */ - if (!was_8_3 && state.check_mangled_names) { - char mangled_name[13]; /* mangled 8.3 name. */ - if (!name_to_8_3(fname,mangled_name,True, - conn->params)) { - /* Error - mangle failed ! */ - memset(mangled_name,'\0',12); - } - mangled_name[12] = 0; - len = srvstr_push(base_data, flags2, - p+2, mangled_name, 24, - STR_UPPER|STR_UNICODE); - if (len < 24) { - memset(p + 2 + len,'\0',24 - len); - } - SSVAL(p, 0, len); + } else { + if (len > 1) { + len -= 1; } else { - memset(p,'\0',26); + len = 0; } - p += 2 + 24; - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - 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; + } + SCVAL(nameptr,0,len); + p += len + 1; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; + } - case SMB_FIND_FILE_DIRECTORY_INFO: - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n")); + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); + was_8_3 = mangle_is_8_3(fname, True, conn->params); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); 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, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); 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; + } + /* 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) { + char mangled_name[13]; /* mangled 8.3 name. */ + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); + } + mangled_name[12] = 0; len = srvstr_push(base_data, flags2, - p + 4, fname, PTR_DIFF(end_data, p+4), - 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_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); 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, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); } - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE_ASCII); - SIVAL(q, 0, len); - p += len; + SSVAL(p, 0, len); + } else { + memset(p,'\0',26); + } + p += 2 + 24; + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + 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; - 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_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); 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(base_data, flags2, + p + 4, fname, PTR_DIFF(end_data, p+4), + 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_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(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - 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_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_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); 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, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + 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_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_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); 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, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; - } - SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ - SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - 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(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + 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_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, conn->params); - p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date_timespec(p,create_date_ts); p += 8; - put_long_date_timespec(p,adate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); p += 8; - put_long_date_timespec(p,mdate_ts); 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, - smb_fname->base_name); - SIVAL(p,0,ea_size); /* Extended attributes */ - p +=4; + 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_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); 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, + smb_fname->base_name); + SIVAL(p,0,ea_size); /* Extended attributes */ + p +=4; + } + SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + 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, conn->params); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date_timespec(p,create_date_ts); p += 8; + put_long_date_timespec(p,adate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); p += 8; + put_long_date_timespec(p,mdate_ts); 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, + smb_fname->base_name); + 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) { + char mangled_name[13]; /* mangled 8.3 name. */ + if (!name_to_8_3(fname,mangled_name,True, + conn->params)) { + /* Error - mangle failed ! */ + memset(mangled_name,'\0',12); } - /* Clear the short name buffer. This is - * IMPORTANT as not doing so will trigger - * a Win2k client bug. JRA. - */ - if (!was_8_3 && state.check_mangled_names) { - char mangled_name[13]; /* mangled 8.3 name. */ - if (!name_to_8_3(fname,mangled_name,True, - conn->params)) { - /* Error - mangle failed ! */ - memset(mangled_name,'\0',12); - } - mangled_name[12] = 0; - len = srvstr_push(base_data, flags2, - 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); + mangled_name[12] = 0; + len = srvstr_push(base_data, flags2, + p+2, mangled_name, 24, + STR_UPPER|STR_UNICODE); + SSVAL(p, 0, len); + if (len < 24) { + memset(p + 2 + len,'\0',24 - len); } - p += 26; - SSVAL(p,0,0); p += 2; /* Reserved ? */ - SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ - SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - 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; + SSVAL(p, 0, len); + } else { + memset(p,'\0',26); + } + p += 26; + SSVAL(p,0,0); p += 2; /* Reserved ? */ + SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */ + SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */ + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + 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. */ + /* CIFS UNIX Extension. */ - case SMB_FIND_FILE_UNIX: - case SMB_FIND_FILE_UNIX_INFO2: - p+= 4; - SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ + case SMB_FIND_FILE_UNIX: + case SMB_FIND_FILE_UNIX_INFO2: + p+= 4; + SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */ - /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ + /* Begin of SMB_QUERY_FILE_UNIX_BASIC */ - if (info_level == SMB_FIND_FILE_UNIX) { - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); - p = store_file_unix_basic(conn, p, - NULL, &smb_fname->st); - len = srvstr_push(base_data, flags2, p, - fname, PTR_DIFF(end_data, p), - STR_TERMINATE); - } else { - DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); - p = store_file_unix_basic_info2(conn, p, - NULL, &smb_fname->st); - nameptr = p; - p += 4; - len = srvstr_push(base_data, flags2, p, fname, - PTR_DIFF(end_data, p), 0); - SIVAL(nameptr, 0, len); - } + if (info_level == SMB_FIND_FILE_UNIX) { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n")); + p = store_file_unix_basic(conn, p, + NULL, &smb_fname->st); + len = srvstr_push(base_data, flags2, p, + fname, PTR_DIFF(end_data, p), + STR_TERMINATE); + } else { + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n")); + p = store_file_unix_basic_info2(conn, p, + NULL, &smb_fname->st); + nameptr = p; + p += 4; + len = srvstr_push(base_data, flags2, p, fname, + PTR_DIFF(end_data, p), 0); + SIVAL(nameptr, 0, len); + } - p += len; - SIVAL(p,0,0); /* Ensure any padding is null. */ + 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 */ + 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; + break; - default: - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - return false; + default: + return false; } - TALLOC_FREE(fname); - TALLOC_FREE(smb_fname); - if (PTR_DIFF(p,pdata) > space_remaining) { - /* Move the dirptr back to prev_dirpos */ - dptr_SeekDir(dirptr, prev_dirpos); - *out_of_space = True; + *out_of_space = true; DEBUG(9,("get_lanman2_dir_entry: out of space\n")); - return False; /* Not finished - just out of space */ + return false; /* Not finished - just out of space */ } /* Setup the last entry pointer, as an offset from base_data */ @@ -1975,6 +1915,105 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, return true; } +static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, + connection_struct *conn, + struct dptr_struct *dirptr, + uint16 flags2, + const char *path_mask, + uint32 dirtype, + int info_level, + int requires_resume_key, + bool dont_descend, + bool ask_sharemode, + char **ppdata, + char *base_data, + char *end_data, + int space_remaining, + bool *out_of_space, + bool *got_exact_match, + int *_last_entry_off, + struct ea_list *name_list) +{ + const char *p; + const char *mask = NULL; + long prev_dirpos = 0; + uint32_t mode = 0; + char *fname = NULL; + struct smb_filename *smb_fname = NULL; + struct smbd_dirptr_lanman2_state state; + bool ok; + uint64_t last_entry_off = 0; + + ZERO_STRUCT(state); + state.conn = conn; + state.info_level = info_level; + state.check_mangled_names = lp_manglednames(conn->params); + state.has_wild = dptr_has_wild(dirptr); + state.got_exact_match = false; + + *out_of_space = false; + *got_exact_match = false; + + p = strrchr_m(path_mask,'/'); + if(p != NULL) { + if(p[1] == '\0') { + mask = "*.*"; + } else { + mask = p+1; + } + } else { + mask = path_mask; + } + + ok = smbd_dirptr_get_entry(ctx, + dirptr, + mask, + dirtype, + dont_descend, + ask_sharemode, + smbd_dirptr_lanman2_match_fn, + smbd_dirptr_lanman2_mode_fn, + &state, + &fname, + &smb_fname, + &mode, + &prev_dirpos); + if (!ok) { + return false; + } + + *got_exact_match = state.got_exact_match; + + ok = smbd_marshall_dir_entry(ctx, + conn, + flags2, + info_level, + name_list, + state.check_mangled_names, + requires_resume_key, + mode, + fname, + smb_fname, + space_remaining, + base_data, + ppdata, + end_data, + out_of_space, + &last_entry_off); + TALLOC_FREE(fname); + TALLOC_FREE(smb_fname); + if (*out_of_space) { + dptr_SeekDir(dirptr, prev_dirpos); + return false; + } + if (!ok) { + return false; + } + + *_last_entry_off = last_entry_off; + return true; +} + /**************************************************************************** Reply to a TRANS2_FINDFIRST. ****************************************************************************/ -- cgit