mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
s3:smbd: split the dir entry marshalling into smbd_marshall_dir_entry()
So that we can reuse it for SMB2 Find. metze
This commit is contained in:
parent
59c3f5e3ca
commit
50f54250f4
@ -1446,6 +1446,475 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
char *p, *q, *pdata = *ppdata;
|
||||
uint32_t reskey=0;
|
||||
uint64_t file_size = 0;
|
||||
uint64_t allocation_size = 0;
|
||||
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_t nt_extmode; /* Used for NT connections instead of mode */
|
||||
|
||||
*out_of_space = false;
|
||||
|
||||
ZERO_STRUCT(mdate_ts);
|
||||
ZERO_STRUCT(adate_ts);
|
||||
ZERO_STRUCT(create_date_ts);
|
||||
|
||||
if (!(mode & aDIR)) {
|
||||
file_size = get_file_size_stat(&smb_fname->st);
|
||||
}
|
||||
allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
|
||||
|
||||
mdate_ts = smb_fname->st.st_ex_mtime;
|
||||
adate_ts = smb_fname->st.st_ex_atime;
|
||||
create_date_ts = smb_fname->st.st_ex_btime;
|
||||
|
||||
if (lp_dos_filetime_resolution(SNUM(conn))) {
|
||||
dos_filetime_timespec(&create_date_ts);
|
||||
dos_filetime_timespec(&mdate_ts);
|
||||
dos_filetime_timespec(&adate_ts);
|
||||
}
|
||||
|
||||
create_date = convert_timespec_to_time_t(create_date_ts);
|
||||
mdate = convert_timespec_to_time_t(mdate_ts);
|
||||
adate = convert_timespec_to_time_t(adate_ts);
|
||||
|
||||
p = pdata;
|
||||
last_entry_ptr = p;
|
||||
|
||||
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);
|
||||
}
|
||||
} 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 */
|
||||
}
|
||||
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) {
|
||||
len -= 1;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
SCVAL(nameptr,0,len);
|
||||
p += len;
|
||||
SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
if (len > 1) {
|
||||
len -= 1;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
SCVAL(nameptr,0,len);
|
||||
p += len + 1;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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 {
|
||||
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;
|
||||
|
||||
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_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_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_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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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. */
|
||||
|
||||
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 */
|
||||
|
||||
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. */
|
||||
|
||||
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) {
|
||||
*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 true;
|
||||
}
|
||||
|
||||
static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
connection_struct *conn,
|
||||
struct dptr_struct *dirptr,
|
||||
@ -1462,27 +1931,18 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
int space_remaining,
|
||||
bool *out_of_space,
|
||||
bool *got_exact_match,
|
||||
int *last_entry_off,
|
||||
int *_last_entry_off,
|
||||
struct ea_list *name_list)
|
||||
{
|
||||
const char *p;
|
||||
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;
|
||||
uint64_t allocation_size = 0;
|
||||
uint32 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 */
|
||||
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;
|
||||
@ -1491,12 +1951,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
state.has_wild = dptr_has_wild(dirptr);
|
||||
state.got_exact_match = false;
|
||||
|
||||
*out_of_space = False;
|
||||
*got_exact_match = False;
|
||||
|
||||
ZERO_STRUCT(mdate_ts);
|
||||
ZERO_STRUCT(adate_ts);
|
||||
ZERO_STRUCT(create_date_ts);
|
||||
*out_of_space = false;
|
||||
*got_exact_match = false;
|
||||
|
||||
p = strrchr_m(path_mask,'/');
|
||||
if(p != NULL) {
|
||||
@ -1528,450 +1984,33 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
|
||||
|
||||
*got_exact_match = state.got_exact_match;
|
||||
|
||||
if (!(mode & aDIR)) {
|
||||
file_size = get_file_size_stat(&smb_fname->st);
|
||||
}
|
||||
allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
|
||||
|
||||
mdate_ts = smb_fname->st.st_ex_mtime;
|
||||
adate_ts = smb_fname->st.st_ex_atime;
|
||||
create_date_ts = smb_fname->st.st_ex_btime;
|
||||
|
||||
if (lp_dos_filetime_resolution(SNUM(conn))) {
|
||||
dos_filetime_timespec(&create_date_ts);
|
||||
dos_filetime_timespec(&mdate_ts);
|
||||
dos_filetime_timespec(&adate_ts);
|
||||
}
|
||||
|
||||
create_date = convert_timespec_to_time_t(create_date_ts);
|
||||
mdate = convert_timespec_to_time_t(mdate_ts);
|
||||
adate = convert_timespec_to_time_t(adate_ts);
|
||||
|
||||
p = pdata;
|
||||
last_entry_ptr = p;
|
||||
|
||||
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);
|
||||
}
|
||||
} 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 */
|
||||
}
|
||||
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) {
|
||||
len -= 1;
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
SCVAL(nameptr,0,len);
|
||||
p += len;
|
||||
SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
|
||||
break;
|
||||
|
||||
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) {
|
||||
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 */
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
SCVAL(nameptr,0,len);
|
||||
p += len + 1;
|
||||
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);
|
||||
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 && 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 {
|
||||
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;
|
||||
|
||||
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_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_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_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 && 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);
|
||||
}
|
||||
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. */
|
||||
|
||||
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 */
|
||||
|
||||
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. */
|
||||
|
||||
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:
|
||||
TALLOC_FREE(fname);
|
||||
TALLOC_FREE(smb_fname);
|
||||
return false;
|
||||
}
|
||||
|
||||
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 (PTR_DIFF(p,pdata) > space_remaining) {
|
||||
/* Move the dirptr back to prev_dirpos */
|
||||
if (*out_of_space) {
|
||||
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 */
|
||||
return false;
|
||||
}
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
*_last_entry_off = last_entry_off;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user