*/
#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
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;
}
- 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 (!(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;
(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(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 */
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);
}
}
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) {
if (fsp->base_fsp) {
- set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
+ set_sticky_write_time_fsp(fsp->base_fsp,
+ ft->mtime);
} else {
- set_sticky_write_time_fsp(fsp, ts[1]);
+ 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);
}
}
fname = fsp->base_fsp->fsp_name;
}
- if(file_ntimes(conn, fname, ts)!=0) {
+ 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;
}
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);
+
+ /* create time */
+ ft.create_time = interpret_long_date(pdata);
- if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
- ts[1] = write_time;
+ 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);
}
}
/* 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);
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);
}
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 & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
+ create_disp = FILE_OPEN;
} else {
DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
(unsigned int)wire_open_mode ));
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
- static uint16 fnf_handle = 257;
char *params = *pparams;
uint16 info_level;
}
}
+ SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
+
/* Now we must call the relevant TRANS2 function */
switch(state->call) {
case TRANSACT2_OPEN: