1
0
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:
Stefan Metzmacher 2009-08-06 12:15:51 +02:00
parent 59c3f5e3ca
commit 50f54250f4

View File

@ -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;
}