#include "smbd/globals.h"
#include "../libcli/auth/libcli_auth.h"
-extern enum protocol_types Protocol;
-
#define DIR_ENTRY_SAFETY_MARGIN 4096
static char *store_file_unix_basic(connection_struct *conn,
SAMBA_POSIX_INHERITANCE_EA_NAME,
SAMBA_XATTR_DOS_ATTRIB,
SAMBA_XATTR_DOSTIMESTAMPS,
+ SAMBA_XATTR_MARKER,
NULL
};
ssize_t sizeret = -1;
if (!lp_ea_support(SNUM(conn))) {
- *pnames = NULL;
+ if (pnames) {
+ *pnames = NULL;
+ }
*pnum_names = 0;
return NT_STATUS_OK;
}
if (sizeret == 0) {
TALLOC_FREE(names);
- *pnames = NULL;
+ if (pnames) {
+ *pnames = NULL;
+ }
*pnum_names = 0;
return NT_STATUS_OK;
}
names[num_names++] = p;
}
- *pnames = names;
+ if (pnames) {
+ *pnames = names;
+ } else {
+ TALLOC_FREE(names);
+ }
*pnum_names = num_names;
return NT_STATUS_OK;
}
pad -= off;
off += pad;
/* initialize padding to 0 */
- memset(pdata, 0, pad);
+ if (pad) {
+ memset(pdata, 0, pad);
+ }
space_remaining -= pad;
pdata += pad;
switch (info_level) {
case SMB_FIND_INFO_STANDARD:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
+ DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
if(requires_resume_key) {
SIVAL(p,0,reskey);
p += 4;
break;
case SMB_FIND_EA_SIZE:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
+ DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
if (requires_resume_key) {
SIVAL(p,0,reskey);
p += 4;
struct ea_list *file_list = NULL;
size_t ea_len = 0;
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
+ DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
if (!name_list) {
return false;
}
/* 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"));
+ DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
return False; /* Not finished - just out of space */
}
}
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
+ DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,cdate_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;
break;
case SMB_FIND_FILE_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
+ DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,cdate_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;
break;
case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
+ DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,cdate_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;
break;
case SMB_FIND_FILE_NAMES_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
+ DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
p += 4;
SIVAL(p,0,reskey); p += 4;
p += 4;
break;
case SMB_FIND_ID_FULL_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
+ DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,cdate_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;
break;
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
+ DEBUG(10,("smbd_marshall_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,cdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res,p,cdate_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;
/* 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"));
+ DEBUG(10,("smbd_marshall_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"));
+ DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
p = store_file_unix_basic_info2(conn, p,
NULL, &smb_fname->st);
nameptr = p;
if (PTR_DIFF(p,pdata) > space_remaining) {
*out_of_space = true;
- DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
+ DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
return false; /* Not finished - just out of space */
}
const char *path_mask,
uint32 dirtype,
int info_level,
- int requires_resume_key,
+ bool requires_resume_key,
bool dont_descend,
bool ask_sharemode,
char **ppdata,
int *last_entry_off,
struct ea_list *name_list)
{
- bool resume_key = false;
- const uint8_t align = 4;
+ uint8_t align = 4;
const bool do_pad = true;
- if (requires_resume_key) {
- resume_key = true;
+ if (info_level >= 1 && info_level <= 3) {
+ /* No alignment on earlier info levels. */
+ align = 1;
}
return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
path_mask, dirtype, info_level,
- resume_key, dont_descend, ask_sharemode,
+ requires_resume_key, dont_descend, ask_sharemode,
align, do_pad,
ppdata, base_data, end_data,
space_remaining,
if(numentries == 0) {
dptr_close(sconn, &dptr_num);
- if (Protocol < PROTOCOL_NT1) {
+ if (get_Protocol() < PROTOCOL_NT1) {
reply_doserror(req, ERRDOS, ERRnofiles);
goto out;
} else {
requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
- srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
+ if (!continue_bit) {
+ /* We only need resume_name if continue_bit is zero. */
+ srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
params+12,
total_params - 12, STR_TERMINATE, &ntstatus,
&mask_contains_wcard);
- if (!NT_STATUS_IS_OK(ntstatus)) {
- /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
- complain (it thinks we're asking for the directory above the shared
- path or an invalid name). Catch this as the resume name is only compared, never used in
- a file access. JRA. */
- srvstr_pull_talloc(ctx, params, req->flags2,
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
+ complain (it thinks we're asking for the directory above the shared
+ path or an invalid name). Catch this as the resume name is only compared, never used in
+ a file access. JRA. */
+ srvstr_pull_talloc(ctx, params, req->flags2,
&resume_name, params+12,
total_params - 12,
STR_TERMINATE);
- if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
- reply_nterror(req, ntstatus);
- return;
+ if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
+ reply_nterror(req, ntstatus);
+ return;
+ }
}
}
close_after_request=%d, close_if_end = %d requires_resume_key = %d \
resume_key = %d resume name = %s continue=%d level = %d\n",
dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
- requires_resume_key, resume_key, resume_name, continue_bit, info_level));
+ requires_resume_key, resume_key,
+ resume_name ? resume_name : "(NULL)", continue_bit, info_level));
if (!maxentries) {
/* W2K3 seems to treat zero as 1. */
* depend on the last file name instead.
*/
- if(*resume_name && !continue_bit) {
+ if(!continue_bit && resume_name && *resume_name) {
SMB_STRUCT_STAT st;
long current_pos = 0;
/* Capabilities are filled in at connection time through STATVFS call */
additional_flags |= conn->fs_capabilities;
+ additional_flags |= lp_parm_int(conn->params->service,
+ "share", "fake_fscaps",
+ 0);
SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
pdata += 8;
- put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
- put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
- put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
pdata += 24;
SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
/* Create (birth) time 64 bit */
- put_long_date_timespec(pdata, psbuf->st_ex_btime);
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
pdata += 8;
map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
{
+ /* This is FileFullEaInformation - 0xF which maps to
+ * 1015 (decimal) in smbd_do_setfilepathinfo. */
+
/* We have data_size bytes to put EA's into. */
size_t total_ea_len = 0;
struct ea_list *ea_file_list = NULL;
data_size = 40;
SIVAL(pdata,36,0);
}
- put_long_date_timespec(pdata,create_time_ts);
- put_long_date_timespec(pdata+8,atime_ts);
- put_long_date_timespec(pdata+16,mtime_ts); /* write time */
- put_long_date_timespec(pdata+24,ctime_ts); /* change time */
+ put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
+ put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
+ put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
SIVAL(pdata,32,mode);
DEBUG(5,("SMB_QFBI - "));
unsigned int ea_size =
estimate_ea_size(conn, fsp, smb_fname->base_name);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
- put_long_date_timespec(pdata,create_time_ts);
- put_long_date_timespec(pdata+8,atime_ts);
- put_long_date_timespec(pdata+16,mtime_ts); /* write time */
- put_long_date_timespec(pdata+24,ctime_ts); /* change time */
+ put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
+ put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
+ put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
SIVAL(pdata,32,mode);
SIVAL(pdata,36,0); /* padding. */
pdata += 40;
unsigned int ea_size =
estimate_ea_size(conn, fsp, smb_fname->base_name);
DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
- put_long_date_timespec(pdata+0x00,create_time_ts);
- put_long_date_timespec(pdata+0x08,atime_ts);
- put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
- put_long_date_timespec(pdata+0x18,ctime_ts); /* change time */
+ put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
+ put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
+ put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
+ put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
SIVAL(pdata, 0x20, mode);
SIVAL(pdata, 0x24, 0); /* padding. */
SBVAL(pdata, 0x28, allocation_size);
case SMB_FILE_NETWORK_OPEN_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
- put_long_date_timespec(pdata,create_time_ts);
- put_long_date_timespec(pdata+8,atime_ts);
- put_long_date_timespec(pdata+16,mtime_ts); /* write time */
- put_long_date_timespec(pdata+24,ctime_ts); /* change time */
+ put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
+ put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
+ put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
SOFF_T(pdata,32,allocation_size);
SOFF_T(pdata,40,file_size);
SIVAL(pdata,48,mode);
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
+ /* Ensure the resolution is the correct for
+ * what we can store on this filesystem. */
+
+ round_timespec(conn->ts_res, &ft->create_time);
+ round_timespec(conn->ts_res, &ft->ctime);
+ round_timespec(conn->ts_res, &ft->atime);
+ round_timespec(conn->ts_res, &ft->mtime);
+
DEBUG(5,("smb_set_filetime: actime: %s\n ",
time_to_asc(convert_timespec_to_time_t(ft->atime))));
DEBUG(5,("smb_set_filetime: modtime: %s\n ",
return status;
}
+/****************************************************************************
+ Deal with SMB_FILE_FULL_EA_INFORMATION set.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp)
+{
+ struct ea_list *ea_list = NULL;
+ NTSTATUS status;
+
+ if (!fsp) {
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ if (!lp_ea_support(SNUM(conn))) {
+ DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
+ "EA's not supported.\n",
+ (unsigned int)total_data));
+ return NT_STATUS_EAS_NOT_SUPPORTED;
+ }
+
+ if (total_data < 10) {
+ DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
+ "too small.\n",
+ (unsigned int)total_data));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ ea_list = read_nttrans_ea_list(talloc_tos(),
+ pdata,
+ total_data);
+
+ if (!ea_list) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
+
+ DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
+ smb_fname_str_dbg(fsp->fsp_name),
+ nt_errstr(status) ));
+
+ return status;
+}
+
+
/****************************************************************************
Deal with SMB_SET_FILE_DISPOSITION_INFO.
****************************************************************************/
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ struct smb_filename *smb_fname)
{
NTSTATUS status = NT_STATUS_OK;
bool delete_on_close;
break;
}
+ case SMB_FILE_FULL_EA_INFORMATION:
+ {
+ status = smb_set_file_full_ea_info(conn,
+ pdata,
+ total_data,
+ fsp);
+ break;
+ }
+
/* From tridge Samba4 :
* MODE_INFORMATION in setfileinfo (I have no
* idea what "mode information" on a file is - it takes a value of 0,
static void handle_trans2(connection_struct *conn, struct smb_request *req,
struct trans_state *state)
{
- if (Protocol >= PROTOCOL_NT1) {
+ if (get_Protocol() >= PROTOCOL_NT1) {
req->flags2 |= 0x40; /* IS_LONG_NAME */
SSVAL(req->inbuf,smb_flg2,req->flags2);
}