*/
#include "includes.h"
+#include "version.h"
+#include "smbd/globals.h"
-extern int max_send;
extern enum protocol_types Protocol;
-extern uint32 global_client_caps;
-#define get_file_size(sbuf) ((sbuf).st_size)
#define DIR_ENTRY_SAFETY_MARGIN 4096
static char *store_file_unix_basic(connection_struct *conn,
return val;
}
-/********************************************************************
- Given a stat buffer return the allocated size on disk, taking into
- account sparse files.
-********************************************************************/
-
-uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
-{
- uint64_t ret;
-
- if(S_ISDIR(sbuf->st_mode)) {
- return 0;
- }
-
-#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
- ret = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
-#else
- ret = (uint64_t)get_file_size(*sbuf);
-#endif
-
- if (fsp && fsp->initial_allocation_size)
- ret = MAX(ret,fsp->initial_allocation_size);
-
- return smb_roundup(conn, ret);
-}
-
/****************************************************************************
Utility functions for dealing with extended attributes.
****************************************************************************/
static bool samba_private_attr_name(const char *unix_ea_name)
{
- static const char *prohibited_ea_names[] = {
+ static const char * const prohibited_ea_names[] = {
SAMBA_POSIX_INHERITANCE_EA_NAME,
SAMBA_XATTR_DOS_ATTRIB,
NULL
reply_outbuf(req, 10, total_sent_thistime + alignment_offset
+ data_alignment_offset);
+ /*
+ * We might have SMBtrans2s in req which was transferred to
+ * the outbuf, fix that.
+ */
+ SCVAL(req->outbuf, smb_com, SMBtrans2);
+
/* Set total params and data to be sent */
SSVAL(req->outbuf,smb_tprcnt,paramsize);
SSVAL(req->outbuf,smb_tdrcnt,datasize);
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
- IS_CONN_ENCRYPTED(conn)))
+ IS_CONN_ENCRYPTED(conn),
+ &req->pcd))
exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
TALLOC_FREE(req->outbuf);
return;
}
- status = create_file(conn, /* conn */
- req, /* req */
- 0, /* root_dir_fid */
- fname, /* fname */
- access_mask, /* access_mask */
- share_mode, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- open_attr, /* file_attributes */
- oplock_request, /* oplock_request */
- open_size, /* allocation_size */
- NULL, /* sd */
- ea_list, /* ea_list */
- &fsp, /* result */
- &smb_action, /* pinfo */
- &sbuf); /* psbuf */
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ open_attr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ open_size, /* allocation_size */
+ NULL, /* sd */
+ ea_list, /* ea_list */
+ &fsp, /* result */
+ &smb_action, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
return;
}
- size = get_file_size(sbuf);
+ size = get_file_size_stat(&sbuf);
fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
mtime = sbuf.st_mtime;
inode = sbuf.st_ino;
{
if (mask[0] == '.' && mask[1] == 0)
return False;
- if (conn->case_sensitive)
- return strcmp(str,mask)==0;
- if (StrCaseCmp(str,mask) != 0) {
- return False;
- }
if (dptr_has_wild(conn->dirptr)) {
return False;
}
- return True;
+ if (conn->case_sensitive)
+ return strcmp(str,mask)==0;
+ else
+ return StrCaseCmp(str,mask) == 0;
}
/****************************************************************************
return UNIX_TYPE_SOCKET;
#endif
- DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
+ DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
return UNIX_TYPE_UNKNOWN;
}
}
if (!(mode & aDIR)) {
- file_size = get_file_size(sbuf);
+ file_size = get_file_size_stat(&sbuf);
}
- allocation_size = get_allocation_size(conn,NULL,&sbuf);
+ allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
mdate_ts = get_mtimespec(&sbuf);
adate_ts = get_atimespec(&sbuf);
- create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ create_date_ts = get_create_timespec(&sbuf,
+ lp_fake_dir_create_times(SNUM(conn)));
if (ask_sharemode) {
struct timespec write_time_ts;
mdate = convert_timespec_to_time_t(mdate_ts);
adate = convert_timespec_to_time_t(adate_ts);
- DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
+ DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
+ pathreal,fname));
found = True;
/* W2K3 seems to treat zero as 1. */
maxentries = 1;
}
-
+
switch (info_level) {
case SMB_FIND_INFO_STANDARD:
case SMB_FIND_EA_SIZE:
}
params = *pparams;
- /* Save the wildcard match and attribs we are using on this directory -
+ /* Save the wildcard match and attribs we are using on this directory -
needed as lanman2 assumes these are being saved between calls */
ntstatus = dptr_create(conn,
dptr_num = dptr_dnum(conn->dirptr);
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
+ /* Initialize per TRANS2_FIND_FIRST operation data */
+ dptr_init_search_op(conn->dirptr);
+
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
bool got_exact_match = False;
- /* this is a heuristic to avoid seeking the dirptr except when
+ /* this is a heuristic to avoid seeking the dirptr except when
absolutely necessary. It allows for a filename of about 40 chars */
if (space_remaining < DIRLEN_GUESS && numentries > 0) {
out_of_space = True;
}
DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
- smb_fn_name(CVAL(req->inbuf,smb_com)),
+ smb_fn_name(req->cmd),
mask, directory, dirtype, numentries ) );
/*
(long)conn->dirptr,
dptr_TellDir(conn->dirptr)));
+ /* Initialize per TRANS2_FIND_NEXT operation data */
+ dptr_init_search_op(conn->dirptr);
+
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
}
DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
- smb_fn_name(CVAL(req->inbuf,smb_com)),
+ smb_fn_name(req->cmd),
mask, directory, dirtype, numentries ) );
/* Check if we can close the dirptr */
i < conn->server_info->ptok->num_sids; ++i) {
sid_bytes += ndr_size_dom_sid(
&conn->server_info->ptok->user_sids[i],
+ NULL,
0);
}
i < conn->server_info->ptok->num_sids; ++i) {
int sid_len = ndr_size_dom_sid(
&conn->server_info->ptok->user_sids[i],
+ NULL,
0);
sid_linearize(pdata + data_len, sid_len,
max_data_bytes);
DEBUG( 4, ( "%s info_level = %d\n",
- smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
+ smb_fn_name(req->cmd), info_level) );
return;
}
DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
- SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
+ SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
pdata += 8;
- SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
+ 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,get_ctimespec(psbuf)); /* Change Time 64 Bit */
unsigned int i;
unsigned int ofs = 0;
- for (i=0; i<num_streams; i++) {
+ for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
unsigned int next_offset;
size_t namelen;
smb_ucs2_t *namebuf;
namelen -= 2;
- if (ofs + 24 + namelen > max_data_bytes) {
- TALLOC_FREE(namebuf);
- return NT_STATUS_BUFFER_TOO_SMALL;
- }
-
SIVAL(data, ofs+4, namelen);
SOFF_T(data, ofs+8, streams[i].size);
SOFF_T(data, ofs+16, streams[i].alloc_size);
else {
unsigned int align = ndr_align_size(next_offset, 8);
- if (next_offset + align > max_data_bytes) {
- return NT_STATUS_BUFFER_TOO_SMALL;
- }
-
memset(data+next_offset, 0, align);
next_offset += align;
files_struct *fsp = NULL;
struct file_id fileid;
struct ea_list *ea_list = NULL;
- uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
char *lock_data = NULL;
bool ms_dfs_link = false;
TALLOC_CTX *ctx = talloc_tos();
pos = fsp->fh->position_information;
fileid = vfs_file_id_from_sbuf(conn, &sbuf);
get_file_infos(fileid, &delete_pending, &write_time_ts);
- access_mask = fsp->access_mask;
}
} else {
return;
}
+ if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
+ && is_ntfs_stream_name(fname)) {
+ char *base;
+ SMB_STRUCT_STAT bsbuf;
+
+ status = split_ntfs_stream_name(talloc_tos(), fname,
+ &base, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("create_file_unixpath: "
+ "split_ntfs_stream_name failed: %s\n",
+ nt_errstr(status)));
+ reply_nterror(req, status);
+ return;
+ }
+
+ SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
+
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
+ reply_unixerror(req,ERRDOS,ERRbadpath);
+ return;
+ }
+ } else {
+ if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
+ DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
+ reply_unixerror(req,ERRDOS,ERRbadpath);
+ return;
+ }
+ }
+
+ fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
+ get_file_infos(fileid, &delete_pending, NULL);
+ if (delete_pending) {
+ reply_nterror(req, NT_STATUS_DELETE_PENDING);
+ return;
+ }
+ }
+
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
fullpathname = fname;
if (!(mode & aDIR))
- file_size = get_file_size(sbuf);
+ file_size = get_file_size_stat(&sbuf);
/* Pull out any data sent here before we realloc. */
switch (info_level) {
mtime_ts = get_mtimespec(&sbuf);
atime_ts = get_atimespec(&sbuf);
- allocation_size = get_allocation_size(conn,fsp,&sbuf);
+ allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
if (!fsp) {
/* Do we have this path open ? */
fileid = vfs_file_id_from_sbuf(conn, &sbuf);
fsp1 = file_find_di_first(fileid);
if (fsp1 && fsp1->initial_allocation_size) {
- allocation_size = get_allocation_size(conn, fsp1, &sbuf);
+ allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
}
}
case SMB_FILE_ACCESS_INFORMATION:
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
- SIVAL(pdata,0,access_mask);
+ if (fsp) {
+ SIVAL(pdata,0,fsp->access_mask);
+ } else {
+ /* GENERIC_EXECUTE mapping from Windows */
+ SIVAL(pdata,0,0x12019F);
+ }
data_size = 4;
break;
files_struct *fsp,
const char *fname,
const SMB_STRUCT_STAT *psbuf,
- struct timespec ts[2],
+ struct smb_file_time *ft,
bool setting_write_time)
{
uint32 action =
}
/* get some defaults (no modifications) if any info is zero or -1. */
- if (null_timespec(ts[0])) {
- ts[0] = get_atimespec(psbuf);
+ if (null_timespec(ft->atime)) {
+ ft->atime= get_atimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if (null_timespec(ts[1])) {
- ts[1] = get_mtimespec(psbuf);
+ if (null_timespec(ft->mtime)) {
+ ft->mtime = get_mtimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
if (!setting_write_time) {
- /* ts[1] comes from change time, not write time. */
+ /* ft->mtime comes from change time, not write time. */
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
- DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+ 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 ",
+ time_to_asc(convert_timespec_to_time_t(ft->mtime))));
+ if (!null_timespec(ft->create_time)) {
+ DEBUG(5,("smb_set_file_time: createtime: %s\n ",
+ time_to_asc(convert_timespec_to_time_t(ft->create_time))));
+ }
/*
* Try and set the times of this file if
{
struct timespec mts = get_mtimespec(psbuf);
struct timespec ats = get_atimespec(psbuf);
- if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
+ if ((timespec_compare(&ft->atime, &ats) == 0) &&
+ (timespec_compare(&ft->mtime, &mts) == 0)) {
return NT_STATUS_OK;
}
}
*/
DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
- time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+ time_to_asc(convert_timespec_to_time_t(ft->mtime))));
if (fsp != NULL) {
- set_sticky_write_time_fsp(fsp, ts[1]);
+ if (fsp->base_fsp) {
+ set_sticky_write_time_fsp(fsp->base_fsp,
+ ft->mtime);
+ } else {
+ set_sticky_write_time_fsp(fsp, ft->mtime);
+ }
} else {
set_sticky_write_time_path(conn, fname,
vfs_file_id_from_sbuf(conn, psbuf),
- ts[1]);
+ ft->mtime);
}
}
DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
- if(file_ntimes(conn, fname, ts)!=0) {
+ if (fsp && fsp->base_fsp) {
+ fname = fsp->base_fsp->fsp_name;
+ }
+
+ if(file_ntimes(conn, fname, ft)!=0) {
return map_nt_error_from_unix(errno);
}
notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
****************************************************************************/
static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
+ files_struct *fsp,
const char *fname,
SMB_STRUCT_STAT *psbuf,
uint32 dosmode)
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ if (fsp) {
+ if (fsp->base_fsp) {
+ fname = fsp->base_fsp->fsp_name;
+ } else {
+ fname = fsp->fsp_name;
+ }
+ }
+
if (dosmode) {
if (S_ISDIR(psbuf->st_mode)) {
dosmode |= aDIR;
DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
- if (size == get_file_size(*psbuf)) {
+ if (size == get_file_size_stat(psbuf)) {
return NT_STATUS_OK;
}
return NT_STATUS_OK;
}
- status = open_file_ntcreate(conn, req, fname, psbuf,
- FILE_WRITE_ATTRIBUTES,
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- FORCE_OPLOCK_BREAK_TO_NONE,
- NULL, &new_fsp);
-
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ 0, /* create_file_flags */
+ FILE_WRITE_ATTRIBUTES, /* access_mask */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
+ FILE_SHARE_DELETE),
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &new_fsp, /* result */
+ NULL, /* pinfo */
+ psbuf); /* psbuf */
+
if (!NT_STATUS_IS_OK(status)) {
/* NB. We check for open_was_deferred in the caller. */
return status;
char *newname = NULL;
char *base_name = NULL;
bool dest_has_wcard = False;
+ SMB_STRUCT_STAT sbuf;
+ char *newname_last_component = NULL;
NTSTATUS status = NT_STATUS_OK;
char *p;
TALLOC_CTX *ctx = talloc_tos();
return NT_STATUS_INVALID_PARAMETER;
}
+ ZERO_STRUCT(sbuf);
+
overwrite = (CVAL(pdata,0) ? True : False);
root_fid = IVAL(pdata,4);
len = IVAL(pdata,8);
return NT_STATUS_NOT_SUPPORTED;
}
- /* Create the base directory. */
- base_name = talloc_strdup(ctx, fname);
- if (!base_name) {
- return NT_STATUS_NO_MEMORY;
- }
- p = strrchr_m(base_name, '/');
- if (p) {
- p[1] = '\0';
- } else {
- base_name = talloc_strdup(ctx, "./");
+ if (fsp && fsp->base_fsp) {
+ /* newname must be a stream name. */
+ if (newname[0] != ':') {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+ base_name = talloc_asprintf(ctx, "%s%s",
+ fsp->base_fsp->fsp_name,
+ newname);
if (!base_name) {
return NT_STATUS_NO_MEMORY;
}
- }
- /* Append the new name. */
- base_name = talloc_asprintf_append(base_name,
- "%s",
- newname);
- if (!base_name) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (fsp) {
- SMB_STRUCT_STAT sbuf;
- char *newname_last_component = NULL;
+ } else {
+ /* newname must *not* be a stream name. */
+ if (is_ntfs_stream_name(newname)) {
+ return NT_STATUS_NOT_SUPPORTED;
+ }
- ZERO_STRUCT(sbuf);
+ /* Create the base directory. */
+ base_name = talloc_strdup(ctx, fname);
+ if (!base_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ p = strrchr_m(base_name, '/');
+ if (p) {
+ p[1] = '\0';
+ } else {
+ base_name = talloc_strdup(ctx, "./");
+ if (!base_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ /* Append the new name. */
+ base_name = talloc_asprintf_append(base_name,
+ "%s",
+ newname);
+ if (!base_name) {
+ return NT_STATUS_NO_MEMORY;
+ }
status = unix_convert(ctx, conn, newname, False,
- &newname,
- &newname_last_component,
- &sbuf);
+ &newname,
+ &newname_last_component,
+ &sbuf);
/* If an error we expect this to be
* NT_STATUS_OBJECT_PATH_NOT_FOUND */
status)) {
return status;
}
+ }
+ if (fsp) {
DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
fsp->fnum, fsp->fsp_name, base_name ));
status = rename_internals_fsp(conn, fsp, base_name,
****************************************************************************/
static NTSTATUS smb_set_posix_lock(connection_struct *conn,
- const struct smb_request *req,
+ struct smb_request *req,
const char *pdata,
int total_data,
files_struct *fsp)
POSIX_LOCK,
blocking_lock,
&status,
- &block_smbpid);
+ &block_smbpid,
+ NULL);
if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
/*
const char *fname,
const SMB_STRUCT_STAT *psbuf)
{
- struct timespec ts[2];
+ struct smb_file_time ft;
+ ZERO_STRUCT(ft);
if (total_data < 12) {
return NT_STATUS_INVALID_PARAMETER;
}
+ /* create time */
+ ft.create_time = interpret_long_date(pdata);
+
/* access time */
- ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
+ ft.atime = interpret_long_date(pdata + 8);
+
/* write time */
- ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
+ ft.mtime = interpret_long_date(pdata + 16);
DEBUG(10,("smb_set_info_standard: file %s\n",
fname ? fname : fsp->fsp_name ));
fsp,
fname,
psbuf,
- ts,
+ &ft,
true);
}
/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
struct timespec write_time;
struct timespec changed_time;
+ struct smb_file_time ft;
uint32 dosmode = 0;
- struct timespec ts[2];
NTSTATUS status = NT_STATUS_OK;
bool setting_write_time = true;
+ ZERO_STRUCT(ft);
+
if (total_data < 36) {
return NT_STATUS_INVALID_PARAMETER;
}
/* Set the attributes */
dosmode = IVAL(pdata,32);
- status = smb_set_file_dosmode(conn,
- fname,
- psbuf,
- dosmode);
+ status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- /* Ignore create time at offset pdata. */
-
/* access time */
- ts[0] = interpret_long_date(pdata+8);
+ ft.atime = interpret_long_date(pdata+8);
write_time = interpret_long_date(pdata+16);
changed_time = interpret_long_date(pdata+24);
/* mtime */
- ts[1] = timespec_min(&write_time, &changed_time);
+ ft.mtime = timespec_min(&write_time, &changed_time);
- if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
- ts[1] = write_time;
+ /* create time */
+ ft.create_time = interpret_long_date(pdata);
+
+ if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
+ !null_timespec(write_time)) {
+ ft.mtime = write_time;
}
/* Prefer a defined time to an undefined one. */
- if (null_timespec(ts[1])) {
+ if (null_timespec(ft.mtime)) {
if (null_timespec(write_time)) {
- ts[1] = changed_time;
+ ft.mtime = changed_time;
setting_write_time = false;
} else {
- ts[1] = write_time;
+ ft.mtime = write_time;
}
}
fsp,
fname,
psbuf,
- ts,
+ &ft,
setting_write_time);
}
if (fsp && fsp->fh->fd != -1) {
/* Open file handle. */
/* Only change if needed. */
- if (allocation_size != get_file_size(*psbuf)) {
+ if (allocation_size != get_file_size_stat(psbuf)) {
if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
return map_nt_error_from_unix(errno);
}
/* Pathname or stat or directory file. */
- status = open_file_ntcreate(conn, req, fname, psbuf,
- FILE_WRITE_DATA,
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- FORCE_OPLOCK_BREAK_TO_NONE,
- NULL, &new_fsp);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ 0, /* create_file_flags */
+ FILE_WRITE_DATA, /* access_mask */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
+ FILE_SHARE_DELETE),
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &new_fsp, /* result */
+ NULL, /* pinfo */
+ psbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
/* NB. We check for open_was_deferred in the caller. */
}
/* Only change if needed. */
- if (allocation_size != get_file_size(*psbuf)) {
+ if (allocation_size != get_file_size_stat(psbuf)) {
if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
status = map_nt_error_from_unix(errno);
close_file(req, new_fsp, NORMAL_CLOSE);
*/
if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(
- conn, parent_dirname(fname),
- fname, unixmode);
+ char *parent;
+ if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ inherit_access_posix_acl(conn, parent, fname, unixmode);
+ TALLOC_FREE(parent);
}
if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
const char *fname,
SMB_STRUCT_STAT *psbuf)
{
- struct timespec ts[2];
+ struct smb_file_time ft;
uint32 raw_unixmode;
mode_t unixmode;
SMB_OFF_T size = 0;
bool delete_on_fail = False;
enum perm_type ptype;
+ ZERO_STRUCT(ft);
+
if (total_data < 100) {
return NT_STATUS_INVALID_PARAMETER;
}
#endif /* LARGE_SMB_OFF_T */
}
- ts[0] = interpret_long_date(pdata+24); /* access_time */
- ts[1] = interpret_long_date(pdata+32); /* modification_time */
+ ft.atime = interpret_long_date(pdata+24); /* access_time */
+ ft.mtime = interpret_long_date(pdata+32); /* modification_time */
set_owner = (uid_t)IVAL(pdata,40);
set_grp = (gid_t)IVAL(pdata,48);
raw_unixmode = IVAL(pdata,84);
/* Ensure we don't try and change anything else. */
raw_unixmode = SMB_MODE_NO_CHANGE;
- size = get_file_size(*psbuf);
- ts[0] = get_atimespec(psbuf);
- ts[1] = get_mtimespec(psbuf);
+ size = get_file_size_stat(psbuf);
+ ft.atime = get_atimespec(psbuf);
+ ft.mtime = get_mtimespec(psbuf);
/*
* We continue here as we might want to change the
* owner uid/gid.
* */
if (!size) {
- size = get_file_size(*psbuf);
+ size = get_file_size_stat(psbuf);
}
#endif
fsp,
fname,
psbuf,
- ts,
+ &ft,
true);
}
DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
fname, (unsigned int)unixmode ));
- status = open_directory(conn, req,
- fname,
- psbuf,
- FILE_READ_ATTRIBUTES, /* Just a stat open */
- FILE_SHARE_NONE, /* Ignored for stat opens */
- FILE_CREATE,
- 0,
- mod_unixmode,
- &info,
- &fsp);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ 0, /* create_file_flags */
+ FILE_READ_ATTRIBUTES, /* access_mask */
+ FILE_SHARE_NONE, /* share_access */
+ FILE_CREATE, /* create_disposition*/
+ FILE_DIRECTORY_FILE, /* create_options */
+ mod_unixmode, /* file_attributes */
+ 0, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &info, /* pinfo */
+ psbuf); /* psbuf */
if (NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
create_disp = FILE_OVERWRITE_IF;
} else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
create_disp = FILE_OPEN_IF;
+ } else if (wire_open_mode == 0) {
+ create_disp = FILE_OPEN;
} else {
DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
(unsigned int)wire_open_mode ));
(unsigned int)wire_open_mode,
(unsigned int)unixmode ));
- status = open_file_ntcreate(conn, req,
- fname,
- psbuf,
- access_mask,
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- create_disp,
- 0, /* no create options yet. */
- mod_unixmode,
- oplock_request,
- &info,
- &fsp);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ 0, /* create_file_flags */
+ access_mask, /* access_mask */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
+ FILE_SHARE_DELETE),
+ create_disp, /* create_disposition*/
+ 0, /* create_options */
+ mod_unixmode, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &info, /* pinfo */
+ psbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
return status;
uint16 flags = 0;
char del = 1;
int info = 0;
+ int create_options = 0;
int i;
struct share_mode_lock *lck = NULL;
fname));
if (VALID_STAT_OF_DIR(*psbuf)) {
- status = open_directory(conn, req,
- fname,
- psbuf,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_OPEN,
- 0,
- FILE_FLAG_POSIX_SEMANTICS|0777,
- &info,
- &fsp);
- } else {
-
- status = open_file_ntcreate(conn, req,
- fname,
- psbuf,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_OPEN,
- 0,
- FILE_FLAG_POSIX_SEMANTICS|0777,
- 0, /* No oplock, but break existing ones. */
- &info,
- &fsp);
- }
+ create_options |= FILE_DIRECTORY_FILE;
+ }
+
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ 0, /* create_file_flags */
+ DELETE_ACCESS, /* access_mask */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
+ FILE_SHARE_DELETE),
+ FILE_OPEN, /* create_disposition*/
+ create_options, /* create_options */
+ FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
+ 0, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &info, /* pinfo */
+ psbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
return status;
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
- static uint16 fnf_handle = 257;
char *params = *pparams;
uint16 info_level;
unsigned int max_data_bytes)
{
char *pdata = *ppdata;
- files_struct *fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv15));
+ files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
/* check for an invalid fid before proceeding */
return;
}
- if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
- && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
+ if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
+ && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
*ppdata = (char *)SMB_REALLOC(*ppdata, 32);
if (*ppdata == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
- dptr_num = SVALS(req->inbuf,smb_vwv0);
+ dptr_num = SVALS(req->vwv+0, 0);
DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
return;
}
- dptr_num = SVAL(req->inbuf,smb_vwv0);
+ dptr_num = SVAL(req->vwv+0, 0);
DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
}
}
+ SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
+
/* Now we must call the relevant TRANS2 function */
switch(state->call) {
case TRANSACT2_OPEN:
unsigned int psoff;
unsigned int pscnt;
unsigned int tran_call;
- unsigned int size;
- unsigned int av_size;
struct trans_state *state;
NTSTATUS result;
return;
}
- dsoff = SVAL(req->inbuf, smb_dsoff);
- dscnt = SVAL(req->inbuf, smb_dscnt);
- psoff = SVAL(req->inbuf, smb_psoff);
- pscnt = SVAL(req->inbuf, smb_pscnt);
- tran_call = SVAL(req->inbuf, smb_setup0);
- size = smb_len(req->inbuf) + 4;
- av_size = smb_len(req->inbuf);
+ dsoff = SVAL(req->vwv+12, 0);
+ dscnt = SVAL(req->vwv+11, 0);
+ psoff = SVAL(req->vwv+10, 0);
+ pscnt = SVAL(req->vwv+9, 0);
+ tran_call = SVAL(req->vwv+14, 0);
result = allow_new_trans(conn->pending_trans, req->mid);
if (!NT_STATUS_IS_OK(result)) {
state->mid = req->mid;
state->vuid = req->vuid;
- state->setup_count = SVAL(req->inbuf, smb_suwcnt);
+ state->setup_count = SVAL(req->vwv+13, 0);
state->setup = NULL;
- state->total_param = SVAL(req->inbuf, smb_tpscnt);
+ state->total_param = SVAL(req->vwv+0, 0);
state->param = NULL;
- state->total_data = SVAL(req->inbuf, smb_tdscnt);
+ state->total_data = SVAL(req->vwv+1, 0);
state->data = NULL;
- state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
- state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
- state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
- state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
- state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
+ state->max_param_return = SVAL(req->vwv+2, 0);
+ state->max_data_return = SVAL(req->vwv+3, 0);
+ state->max_setup_return = SVAL(req->vwv+4, 0);
+ state->close_on_completion = BITSETW(req->vwv+5, 0);
+ state->one_way = BITSETW(req->vwv+5, 1);
state->call = tran_call;
*/
if ( (state->setup_count == 4)
&& (tran_call == TRANSACT2_IOCTL)
- && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
- && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
+ && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
+ && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
} else {
DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
goto bad_param;
if (state->total_data) {
+
+ if (trans_oob(state->total_data, 0, dscnt)
+ || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
+ goto bad_param;
+ }
+
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
state->data = (char *)SMB_MALLOC(state->total_data);
return;
}
- if (dscnt > state->total_data ||
- dsoff+dscnt < dsoff) {
- goto bad_param;
- }
-
- if (dsoff > av_size ||
- dscnt > av_size ||
- dsoff+dscnt > av_size) {
- goto bad_param;
- }
-
memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
}
if (state->total_param) {
+
+ if (trans_oob(state->total_param, 0, pscnt)
+ || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
+ goto bad_param;
+ }
+
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
state->param = (char *)SMB_MALLOC(state->total_param);
return;
}
- if (pscnt > state->total_param ||
- psoff+pscnt < psoff) {
- goto bad_param;
- }
-
- if (psoff > av_size ||
- pscnt > av_size ||
- psoff+pscnt > av_size) {
- goto bad_param;
- }
-
memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
}
connection_struct *conn = req->conn;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
- unsigned int size;
- unsigned int av_size;
START_PROFILE(SMBtranss2);
return;
}
- size = smb_len(req->inbuf)+4;
- av_size = smb_len(req->inbuf);
-
for (state = conn->pending_trans; state != NULL;
state = state->next) {
if (state->mid == req->mid) {
/* Revise state->total_param and state->total_data in case they have
changed downwards */
- if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
- state->total_param = SVAL(req->inbuf, smb_tpscnt);
- if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
- state->total_data = SVAL(req->inbuf, smb_tdscnt);
+ if (SVAL(req->vwv+0, 0) < state->total_param)
+ state->total_param = SVAL(req->vwv+0, 0);
+ if (SVAL(req->vwv+1, 0) < state->total_data)
+ state->total_data = SVAL(req->vwv+1, 0);
- pcnt = SVAL(req->inbuf, smb_spscnt);
- poff = SVAL(req->inbuf, smb_spsoff);
- pdisp = SVAL(req->inbuf, smb_spsdisp);
+ pcnt = SVAL(req->vwv+2, 0);
+ poff = SVAL(req->vwv+3, 0);
+ pdisp = SVAL(req->vwv+4, 0);
- dcnt = SVAL(req->inbuf, smb_sdscnt);
- doff = SVAL(req->inbuf, smb_sdsoff);
- ddisp = SVAL(req->inbuf, smb_sdsdisp);
+ dcnt = SVAL(req->vwv+5, 0);
+ doff = SVAL(req->vwv+6, 0);
+ ddisp = SVAL(req->vwv+7, 0);
state->received_param += pcnt;
state->received_data += dcnt;
goto bad_param;
if (pcnt) {
- if (pdisp > state->total_param ||
- pcnt > state->total_param ||
- pdisp+pcnt > state->total_param ||
- pdisp+pcnt < pdisp) {
+ if (trans_oob(state->total_param, pdisp, pcnt)
+ || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
goto bad_param;
}
-
- if (poff > av_size ||
- pcnt > av_size ||
- poff+pcnt > av_size ||
- poff+pcnt < poff) {
- goto bad_param;
- }
-
- memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
- pcnt);
+ memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
}
if (dcnt) {
- if (ddisp > state->total_data ||
- dcnt > state->total_data ||
- ddisp+dcnt > state->total_data ||
- ddisp+dcnt < ddisp) {
- goto bad_param;
- }
-
- if (ddisp > av_size ||
- dcnt > av_size ||
- ddisp+dcnt > av_size ||
- ddisp+dcnt < ddisp) {
+ if (trans_oob(state->total_data, ddisp, dcnt)
+ || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
goto bad_param;
}
-
- memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
- dcnt);
+ memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
}
if ((state->received_param < state->total_param) ||
return;
}
- /*
- * construct_reply_common will copy smb_com from inbuf to
- * outbuf. SMBtranss2 is wrong here.
- */
- SCVAL(req->inbuf,smb_com,SMBtrans2);
-
handle_trans2(conn, req, state);
DLIST_REMOVE(conn->pending_trans, state);