#include "includes.h"
#include "ntioctl.h"
#include "system/filesys.h"
+#include "lib/util/time_basic.h"
#include "version.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
#include "lib/util_ea.h"
#include "lib/readdir_attr.h"
#include "messages.h"
+#include "smb1_utils.h"
+#include "libcli/smb/smb2_posix.h"
#define DIR_ENTRY_SAFETY_MARGIN 4096
uint32_t share_access = FILE_SHARE_READ|
FILE_SHARE_WRITE|
FILE_SHARE_DELETE;
+ struct smb2_create_blobs *posx = NULL;
+
/*
* Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
* but set reasonable defaults.
*/
- uint32_t file_attributes = 0664|FILE_FLAG_POSIX_SEMANTICS;
+ uint32_t file_attributes = 0664;
uint32_t oplock = NO_OPLOCK;
uint32_t create_options = FILE_NON_DIRECTORY_FILE;
* Only FILE_FLAG_POSIX_SEMANTICS matters on existing
* directories, but set reasonable defaults.
*/
- file_attributes = 0775|FILE_FLAG_POSIX_SEMANTICS;
+ file_attributes = 0775;
create_options = FILE_DIRECTORY_FILE;
}
smb_fname_tmp = cp_smb_filename(talloc_tos(),
smb_fname);
if (smb_fname_tmp == NULL) {
- return NT_STATUS_NO_MEMORY;
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ status = make_smb2_posix_create_ctx(
+ talloc_tos(), &posx, file_attributes);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
+ nt_errstr(status));
+ goto done;
}
status = SMB_VFS_CREATE_FILE(
NULL, /* ea_list */
ret_fsp, /* result */
NULL, /* pinfo */
- NULL, /* in_context */
+ posx, /* in_context */
NULL); /* out_context */
+done:
+ TALLOC_FREE(posx);
TALLOC_FREE(smb_fname_tmp);
return status;
}
#endif
/********************************************************************
- The canonical "check access" based on object handle or path function.
+ The canonical "check access" based on path.
********************************************************************/
static NTSTATUS check_access(connection_struct *conn,
- files_struct *fsp,
- const struct smb_filename *smb_fname,
- uint32_t access_mask)
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ uint32_t access_mask)
{
- NTSTATUS status;
-
- if (fsp) {
- status = check_access_fsp(fsp, access_mask);
- } else {
- status = smbd_check_access_rights(conn, smb_fname,
- false, access_mask);
- }
-
- return status;
+ SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
+ return smbd_check_access_rights(conn,
+ dirfsp,
+ smb_fname,
+ false,
+ access_mask);
}
/********************************************************************
return val;
}
-/********************************************************************
- Create a 64 bit FileIndex. If the file is on the same device as
- the root of the share, just return the 64-bit inode. If it isn't,
- mangle as we used to do.
-********************************************************************/
-
-uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
-{
- uint64_t file_index;
- if (conn->sconn->aapl_zero_file_id) {
- return 0;
- }
- if (conn->base_share_dev == psbuf->st_ex_dev) {
- return (uint64_t)psbuf->st_ex_ino;
- }
- file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
- file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
- return file_index;
-}
-
-
-/********************************************************************
- Globally (for this connection / multi-channel) disable file-ID
- calculation. This is required to be global because it serves
- Macs in AAPL mode, which is globally set.
-********************************************************************/
-void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
-{
- sconn->aapl_zero_file_id = true;
-}
-
/****************************************************************************
Utility functions for dealing with extended attributes.
****************************************************************************/
return status;
}
- status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
+ if (fsp != NULL) {
+ status = check_access_fsp(fsp, FILE_WRITE_EA);
+ } else {
+ status = check_access(conn,
+ conn->cwd_fsp,
+ smb_fname,
+ FILE_WRITE_EA);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* We have re-scheduled this call. */
goto out;
}
- reply_openerror(req, status);
- goto out;
+
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ reply_openerror(req, status);
+ goto out;
+ }
+
+ fsp = fcb_or_dos_open(
+ req,
+ smb_fname,
+ access_mask,
+ create_options,
+ private_flags);
+ if (fsp == NULL) {
+ bool ok = defer_smb1_sharing_violation(req);
+ if (ok) {
+ goto out;
+ }
+ reply_openerror(req, status);
+ goto out;
+ }
+
+ smb_action = FILE_WAS_OPENED;
}
size = get_file_size_stat(&smb_fname->st);
Map wire perms onto standard UNIX permissions. Obey share restrictions.
****************************************************************************/
-enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
-
-static NTSTATUS unix_perms_from_wire( connection_struct *conn,
- const SMB_STRUCT_STAT *psbuf,
- uint32_t perms,
- enum perm_type ptype,
- mode_t *ret_perms)
+NTSTATUS unix_perms_from_wire(connection_struct *conn,
+ const SMB_STRUCT_STAT *psbuf,
+ uint32_t perms,
+ enum perm_type ptype,
+ mode_t *ret_perms)
{
mode_t ret = 0;
uint32_t reskey=0;
uint64_t file_size = 0;
uint64_t allocation_size = 0;
- uint64_t file_index = 0;
+ uint64_t file_id = 0;
size_t len = 0;
struct timespec mdate_ts = {0};
struct timespec adate_ts = {0};
}
}
- file_index = get_FileIndex(conn, &smb_fname->st);
+ file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
mdate_ts = smb_fname->st.st_ex_mtime;
adate_ts = smb_fname->st.st_ex_atime;
was_8_3 = mangle_is_8_3(fname, True, conn->params);
p += 4;
SIVAL(p,0,reskey); p += 4;
- 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;
+ put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
+ put_long_date_full_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,mode); p += 4;
DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
p += 4;
SIVAL(p,0,reskey); p += 4;
- 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;
+ put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
+ put_long_date_full_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,mode); p += 4;
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(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;
+ put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
+ put_long_date_full_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,mode); p += 4;
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(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;
+ put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
+ put_long_date_full_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,mode); p += 4;
}
p += 4;
SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
- SBVAL(p,0,file_index); p += 8;
+ SBVAL(p,0,file_id); p += 8;
status = srvstr_push(base_data, flags2, p,
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII, &len);
was_8_3 = mangle_is_8_3(fname, True, conn->params);
p += 4;
SIVAL(p,0,reskey); p += 4;
- 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;
+ put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
+ put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
+ put_long_date_full_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,mode); p += 4;
}
p += 2;
- SBVAL(p,0,file_index); p += 8;
+ SBVAL(p,0,file_id); p += 8;
status = srvstr_push(base_data, flags2, p,
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII, &len);
bool mask_contains_wcard = False;
struct ea_list *ea_list = NULL;
NTSTATUS ntstatus = NT_STATUS_OK;
- bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
- struct dptr_struct *dirptr = NULL;
+ bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
struct smbd_server_connection *sconn = req->sconn;
- uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
+ uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
ucf_flags_from_smb_request(req);
bool backup_priv = false;
bool as_root = false;
+ files_struct *fsp = NULL;
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+ int ret;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
goto out;
}
- mask = smb_dname->original_lcomp;
+ mask = get_original_lcomp(talloc_tos(),
+ conn,
+ directory,
+ ucf_flags);
+ if (mask == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ goto out;
+ }
directory = smb_dname->base_name;
}
params = *pparams;
+ /*
+ * As we've cut off the last component from
+ * smb_fname we need to re-stat smb_dname
+ * so FILE_OPEN disposition knows the directory
+ * exists.
+ */
+ if (req->posix_pathnames) {
+ ret = SMB_VFS_LSTAT(conn, smb_dname);
+ } else {
+ ret = SMB_VFS_STAT(conn, smb_dname);
+ }
+
+ if (ret == -1) {
+ ntstatus = map_nt_error_from_unix(errno);
+ reply_nterror(req, ntstatus);
+ goto out;
+ }
+
+ /*
+ * Open an fsp on this directory for the dptr.
+ */
+ ntstatus = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ smb_dname, /* dname */
+ FILE_LIST_DIRECTORY, /* access_mask */
+ FILE_SHARE_READ|
+ FILE_SHARE_WRITE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ FILE_DIRECTORY_FILE, /* create_options */
+ FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
+ NO_OPLOCK, /* oplock_request */
+ NULL, /* lease */
+ 0, /* allocation_size */
+ 0, /* private_flags */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL, /* pinfo */
+ NULL, /* in_context */
+ NULL);/* out_context */
+
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ DBG_ERR("failed to open directory %s\n",
+ smb_fname_str_dbg(smb_dname));
+ reply_nterror(req, ntstatus);
+ goto out;
+ }
+
/* 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,
req,
- NULL, /* fsp */
- smb_dname,
+ fsp, /* fsp */
False,
True,
req->smbpid,
mask,
mask_contains_wcard,
dirtype,
- &dirptr);
+ &fsp->dptr);
if (!NT_STATUS_IS_OK(ntstatus)) {
+ /*
+ * Use NULL here for the first parameter (req)
+ * as this is not a client visible handle so
+ * can'tbe part of an SMB1 chain.
+ */
+ close_file(NULL, fsp, NORMAL_CLOSE);
+ fsp = NULL;
reply_nterror(req, ntstatus);
goto out;
}
if (backup_priv) {
/* Remember this in case we have
to do a findnext. */
- dptr_set_priv(dirptr);
+ dptr_set_priv(fsp->dptr);
}
- dptr_num = dptr_dnum(dirptr);
+ dptr_num = dptr_dnum(fsp->dptr);
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
+ directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
if (in_list(directory,
- lp_dont_descend(talloc_tos(), SNUM(conn)),
+ lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
conn->case_sensitive)) {
dont_descend = True;
}
} else {
ntstatus = get_lanman2_dir_entry(talloc_tos(),
conn,
- dirptr,
+ fsp->dptr,
req->flags2,
mask,dirtype,info_level,
requires_resume_key,dont_descend,
/* Check if we can close the dirptr */
if(close_after_first || (finished && close_if_end)) {
DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
- dptr_close(sconn, &dptr_num);
+ dptr_num = -1;
+ close_file(NULL, fsp, NORMAL_CLOSE);
+ fsp = NULL;
}
/*
*/
if(numentries == 0) {
- dptr_close(sconn, &dptr_num);
+ dptr_num = -1;
+ /*
+ * We may have already closed the file in the
+ * close_after_first or finished case above.
+ */
+ if (fsp != NULL) {
+ close_file(NULL, fsp, NORMAL_CLOSE);
+ fsp = NULL;
+ }
if (get_Protocol() < PROTOCOL_NT1) {
reply_force_doserror(req, ERRDOS, ERRnofiles);
goto out;
int space_remaining;
struct ea_list *ea_list = NULL;
NTSTATUS ntstatus = NT_STATUS_OK;
- bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
+ bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
TALLOC_CTX *ctx = talloc_tos();
- struct dptr_struct *dirptr;
struct smbd_server_connection *sconn = req->sconn;
bool backup_priv = false;
bool as_root = false;
+ files_struct *fsp = NULL;
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
params = *pparams;
/* Check that the dptr is valid */
- if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
+ fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
+ if (fsp == NULL) {
reply_nterror(req, STATUS_NO_MORE_FILES);
return;
}
/* Get the attr mask from the dptr */
dirtype = dptr_attr(sconn, dptr_num);
- backup_priv = dptr_get_priv(dirptr);
+ backup_priv = dptr_get_priv(fsp->dptr);
DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
"backup_priv = %d\n",
dptr_num, mask, dirtype,
- (long)dirptr,
- dptr_TellDir(dirptr),
+ (long)fsp->dptr,
+ dptr_TellDir(fsp->dptr),
(int)backup_priv));
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dont_descend(ctx, SNUM(conn))));
- if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
+ directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
+ if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
dont_descend = True;
p = pdata;
* should already be at the correct place.
*/
- finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
+ finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
} /* end if resume_name && !continue_bit */
for (i=0;(i<(int)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 fsp->dptr except when
absolutely necessary. It allows for a filename of about 40 chars */
if (space_remaining < DIRLEN_GUESS && numentries > 0) {
out_of_space = True;
} else {
ntstatus = get_lanman2_dir_entry(ctx,
conn,
- dirptr,
+ fsp->dptr,
req->flags2,
mask,dirtype,info_level,
requires_resume_key,dont_descend,
smb_fn_name(req->cmd),
mask, directory, dirtype, numentries ) );
- /* Check if we can close the dirptr */
+ /* Check if we can close the fsp->dptr */
if(close_after_request || (finished && close_if_end)) {
DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
- dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
+ dptr_num = -1;
+ close_file(NULL, fsp, NORMAL_CLOSE);
+ fsp = NULL;
}
if (as_root) {
unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
{
- E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
+
+ E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
return objid;
}
char **ppdata,
int *ret_data_len)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
char *pdata, *end_data;
int data_len = 0;
size_t len = 0;
* Add volume serial number - hash of a combination of
* the called hostname and the service name.
*/
- SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
+ SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
/*
* Win2k3 and previous mess this up by sending a name length
* one byte short. I believe only older clients (OS/2 Win9x) use
* Add volume serial number - hash of a combination of
* the called hostname and the service name.
*/
- SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
+ SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
(str_checksum(get_local_machine_name())<<16));
/* Max label len is 32 characters. */
DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
(int)strlen(vname),vname,
- lp_servicename(talloc_tos(), snum)));
+ lp_servicename(talloc_tos(), lp_sub, snum)));
if (max_data_bytes >= 24 && data_len > max_data_bytes) {
/* the client only requested a portion of the
volume label */
if (get_current_uid(conn) != 0) {
DEBUG(0,("get_user_quota: access_denied "
"service [%s] user [%s]\n",
- lp_servicename(talloc_tos(), SNUM(conn)),
+ lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
conn->session_info->unix_info->unix_name));
return NT_STATUS_ACCESS_DENIED;
}
status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
NULL, "as);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
+ DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
return status;
}
data_len = 48;
DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
- lp_servicename(talloc_tos(), SNUM(conn))));
+ lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
/* Unknown1 24 NULL bytes*/
SBIG_UINT(pdata,0,(uint64_t)0);
return NT_STATUS_INVALID_LEVEL;
#endif /* EOPNOTSUPP */
} else {
- DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
+ DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
return NT_STATUS_DOS(ERRSRV, ERRerror);
}
break;
files_struct *fsp,
const DATA_BLOB *qdata)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
NTSTATUS status;
SMB_NTQUOTA_STRUCT quotas;
/* access check */
if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
- lp_servicename(talloc_tos(), SNUM(conn)),
+ lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
conn->session_info->unix_info->unix_name));
return NT_STATUS_ACCESS_DENIED;
}
/* now set the quotas */
if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
- lp_servicename(talloc_tos(), SNUM(conn))));
+ lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
status = map_nt_error_from_unix(errno);
} else {
status = NT_STATUS_OK;
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
struct smbXsrv_connection *xconn = req->xconn;
char *pdata = *ppdata;
char *params = *pparams;
uint16_t info_level;
DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
- lp_servicename(talloc_tos(), SNUM(conn))));
+ lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
/* */
if (total_params < 4) {
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(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 */
+ put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
+ put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
+ put_long_date_full_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(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
+ put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
pdata += 8;
map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
unsigned int size_needed = 0;
NTSTATUS status;
bool ok;
- bool close_fsp;
+ bool close_fsp = false;
/*
* Ensure we always operate on a file descriptor, not just
* We can only have default POSIX ACLs on
* directories.
*/
- if (!fsp->is_directory) {
+ if (!fsp->fsp_flags.is_directory) {
DBG_INFO("Non-directory open %s\n",
fsp_str_dbg(fsp));
status = NT_STATUS_INVALID_HANDLE;
uint64_t file_size = 0;
uint64_t pos = 0;
uint64_t allocation_size = 0;
- uint64_t file_index = 0;
+ uint64_t file_id = 0;
uint32_t access_mask = 0;
size_t len = 0;
dstart = pdata;
dend = dstart + data_size - 1;
- if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
+ if (!is_omit_timespec(&write_time_ts) &&
+ !INFO_LEVEL_IS_UNIX(info_level))
+ {
update_stat_ex_mtime(psbuf, write_time_ts);
}
I think this causes us to fail the IFSKIT
BasicFileInformationTest. -tpot */
- file_index = get_FileIndex(conn, psbuf);
+ file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
*fixed_portion = 0;
data_size = 40;
SIVAL(pdata,36,0);
}
- 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 */
+ put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
+ put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
SIVAL(pdata,32,mode);
DEBUG(5,("SMB_QFBI - "));
{
char *nfname = NULL;
- if (!fsp->conn->sconn->using_smb2) {
+ if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
return NT_STATUS_INVALID_LEVEL;
}
unsigned int ea_size =
estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
- 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 */
+ put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
+ put_long_date_full_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);
DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
- 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 */
+ put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
+ put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
SIVAL(pdata, 0x20, mode);
SIVAL(pdata, 0x24, 0); /* padding. */
SBVAL(pdata, 0x28, allocation_size);
SCVAL(pdata, 0x3C, delete_pending);
SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
SSVAL(pdata, 0x3E, 0); /* padding */
- SBVAL(pdata, 0x40, file_index);
+ SBVAL(pdata, 0x40, file_id);
SIVAL(pdata, 0x48, ea_size);
SIVAL(pdata, 0x4C, access_mask);
SBVAL(pdata, 0x50, pos);
case SMB_FILE_INTERNAL_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
- SBVAL(pdata, 0, file_index);
+ SBVAL(pdata, 0, file_id);
data_size = 8;
*fixed_portion = 8;
break;
case SMB_FILE_NETWORK_OPEN_INFORMATION:
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
- 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 */
+ put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
+ put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
+ put_long_date_full_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);
#else
return NT_STATUS_DOS(ERRDOS, ERRbadlink);
#endif
- link_len = SMB_VFS_READLINK(conn,
- smb_fname,
- buffer, PATH_MAX);
+ link_len = SMB_VFS_READLINKAT(conn,
+ conn->cwd_fsp,
+ smb_fname,
+ buffer,
+ PATH_MAX);
+
if (link_len == -1) {
return map_nt_error_from_unix(errno);
}
/* We have re-scheduled this call. */
return;
}
+ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ bool ok = defer_smb1_sharing_violation(req);
+ if (ok) {
+ return;
+ }
+ }
reply_nterror(req, status);
return;
}
struct smb_filename *smb_fname_new)
{
NTSTATUS status = NT_STATUS_OK;
+ int ret;
bool ok;
/* source must already exist. */
DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
smb_fname_old->base_name, smb_fname_new->base_name));
- if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
+ ret = SMB_VFS_LINKAT(conn,
+ conn->cwd_fsp,
+ smb_fname_old,
+ conn->cwd_fsp,
+ smb_fname_new,
+ 0);
+
+ if (ret != 0) {
status = map_nt_error_from_unix(errno);
DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
nt_errstr(status), smb_fname_old->base_name,
bool setting_write_time)
{
struct smb_filename smb_fname_base;
+ struct timeval_buf tbuf[4];
uint32_t action =
FILE_NOTIFY_CHANGE_LAST_ACCESS
|FILE_NOTIFY_CHANGE_LAST_WRITE
}
/* get some defaults (no modifications) if any info is zero or -1. */
- if (null_timespec(ft->create_time)) {
+ if (is_omit_timespec(&ft->create_time)) {
action &= ~FILE_NOTIFY_CHANGE_CREATION;
}
- if (null_timespec(ft->atime)) {
+ if (is_omit_timespec(&ft->atime)) {
action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if (null_timespec(ft->mtime)) {
+ if (is_omit_timespec(&ft->mtime)) {
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
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 ",
- time_to_asc(convert_timespec_to_time_t(ft->mtime))));
- DEBUG(5,("smb_set_filetime: ctime: %s\n ",
- time_to_asc(convert_timespec_to_time_t(ft->ctime))));
- DEBUG(5,("smb_set_file_time: createtime: %s\n ",
- time_to_asc(convert_timespec_to_time_t(ft->create_time))));
+ DBG_DEBUG("smb_set_filetime: actime: %s\n ",
+ timespec_string_buf(&ft->atime, true, &tbuf[0]));
+ DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
+ timespec_string_buf(&ft->mtime, true, &tbuf[1]));
+ DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
+ timespec_string_buf(&ft->ctime, true, &tbuf[2]));
+ DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
+ timespec_string_buf(&ft->create_time, true, &tbuf[3]));
if (setting_write_time) {
/*
* away and will set it on file close and after a write. JRA.
*/
- DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
- time_to_asc(convert_timespec_to_time_t(ft->mtime))));
+ DBG_DEBUG("setting pending modtime to %s\n",
+ timespec_string_buf(&ft->mtime, true, &tbuf[0]));
if (fsp != NULL) {
if (fsp->base_fsp) {
get_file_size_stat(psbuf));
if (size == get_file_size_stat(psbuf)) {
+ if (fsp == NULL) {
+ return NT_STATUS_OK;
+ }
+ if (!fsp->fsp_flags.modified) {
+ return NT_STATUS_OK;
+ }
+ trigger_write_time_update_immediate(fsp);
return NT_STATUS_OK;
}
{
char *link_target = NULL;
TALLOC_CTX *ctx = talloc_tos();
+ int ret;
/* Set a symbolic link. */
/* Don't allow this if follow links is false. */
DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
new_smb_fname->base_name, link_target ));
- if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
+ ret = SMB_VFS_SYMLINKAT(conn,
+ link_target,
+ conn->cwd_fsp,
+ new_smb_fname);
+ if (ret != 0) {
return map_nt_error_from_unix(errno);
}
uint32_t len;
char *newname = NULL;
struct smb_filename *smb_fname_dst = NULL;
- uint32_t ucf_flags = UCF_SAVE_LCOMP |
- ucf_flags_from_smb_request(req);
+ const char *dst_original_lcomp = NULL;
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
NTSTATUS status = NT_STATUS_OK;
TALLOC_CTX *ctx = talloc_tos();
status = NT_STATUS_NO_MEMORY;
goto out;
}
+ }
- /*
- * Set the original last component, since
- * rename_internals_fsp() requires it.
- */
- smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
- newname);
- if (smb_fname_dst->original_lcomp == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
-
+ /*
+ * Set the original last component, since
+ * rename_internals_fsp() requires it.
+ */
+ dst_original_lcomp = get_original_lcomp(smb_fname_dst,
+ conn,
+ newname,
+ ucf_flags);
+ if (dst_original_lcomp == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
}
DEBUG(10,("smb2_file_rename_information: "
"SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
- status = rename_internals_fsp(conn, fsp, smb_fname_dst,
+ status = rename_internals_fsp(conn,
+ fsp,
+ smb_fname_dst,
+ dst_original_lcomp,
(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
overwrite);
char *newname = NULL;
struct smb_filename *smb_fname_dst = NULL;
NTSTATUS status = NT_STATUS_OK;
- uint32_t ucf_flags = UCF_SAVE_LCOMP |
- ucf_flags_from_smb_request(req);
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
TALLOC_CTX *ctx = talloc_tos();
if (!fsp) {
uint32_t len;
char *newname = NULL;
struct smb_filename *smb_fname_dst = NULL;
+ const char *dst_original_lcomp = NULL;
bool dest_has_wcard = False;
NTSTATUS status = NT_STATUS_OK;
char *p;
DEBUG(10,("smb_file_rename_information: got name |%s|\n",
newname));
- if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
- status = resolve_dfspath_wcard(ctx, conn,
- newname,
- UCF_COND_ALLOW_WCARD_LCOMP,
- !conn->sconn->using_smb2,
- &newname,
- &dest_has_wcard);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- }
-
/* Check the new name has no '/' characters. */
if (strchr_m(newname, '/')) {
return NT_STATUS_NOT_SUPPORTED;
}
/*
- * Set the original last component, since
+ * Get the original last component, since
* rename_internals_fsp() requires it.
*/
- smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
- newname);
- if (smb_fname_dst->original_lcomp == NULL) {
+ dst_original_lcomp = get_original_lcomp(smb_fname_dst,
+ conn,
+ newname,
+ 0);
+ if (dst_original_lcomp == NULL) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
* the newname instead.
*/
char *base_name = NULL;
- uint32_t ucf_flags = UCF_SAVE_LCOMP |
- ucf_flags_from_smb_request(req);
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
if (dest_has_wcard) {
ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
return NT_STATUS_NO_MEMORY;
}
- status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
- ucf_flags);
+ status = filename_convert(ctx,
+ conn,
+ base_name,
+ ucf_flags,
+ NULL,
+ NULL,
+ &smb_fname_dst);
/* If an error we expect this to be
* NT_STATUS_OBJECT_PATH_NOT_FOUND */
goto out;
}
}
+ dst_original_lcomp = get_original_lcomp(smb_fname_dst,
+ conn,
+ newname,
+ ucf_flags);
+ if (dst_original_lcomp == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
}
if (fsp) {
"SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
- status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
- overwrite);
+ status = rename_internals_fsp(conn,
+ fsp,
+ smb_fname_dst,
+ dst_original_lcomp,
+ 0,
+ overwrite);
} else {
DEBUG(10,("smb_file_rename_information: "
"SMB_FILE_RENAME_INFORMATION %s -> %s\n",
smb_fname_str_dbg(smb_fname_src),
smb_fname_str_dbg(smb_fname_dst)));
- status = rename_internals(ctx, conn, req, smb_fname_src,
- smb_fname_dst, 0, overwrite, false,
- dest_has_wcard,
- FILE_WRITE_ATTRIBUTES);
+ status = rename_internals(ctx,
+ conn,
+ req,
+ smb_fname_src,
+ smb_fname_dst,
+ dst_original_lcomp,
+ 0,
+ overwrite,
+ false,
+ dest_has_wcard,
+ FILE_WRITE_ATTRIBUTES);
}
out:
TALLOC_FREE(smb_fname_dst);
}
/* If we have a default acl, this *must* be a directory. */
- if (valid_def_acls && !fsp->is_directory) {
+ if (valid_def_acls && !fsp->fsp_flags.is_directory) {
DBG_INFO("Can't set default acls on "
"non-directory %s\n",
fsp_str_dbg(fsp));
break;
case POSIX_LOCK_TYPE_WRITE:
/* Return the right POSIX-mappable error code for files opened read-only. */
- if (!fsp->can_write) {
+ if (!fsp->fsp_flags.can_write) {
return NT_STATUS_INVALID_HANDLE;
}
lock_type = WRITE_LOCK;
if (lock_type == UNLOCK_LOCK) {
struct smbd_lock_element l = {
+ .req_guid = smbd_request_guid(req, 0),
.smblctx = smblctx,
.brltype = UNLOCK_LOCK,
.offset = offset,
}
*lck = (struct smbd_lock_element) {
+ .req_guid = smbd_request_guid(req, 0),
.smblctx = smblctx,
.brltype = lock_type,
.count = count,
subreq = smbd_smb1_do_locks_send(
fsp,
req->sconn->ev_ctx,
- req->sconn->msg_ctx,
&req,
fsp,
blocking_lock ? UINT32_MAX : 0,
uint32_t dosmode = 0;
NTSTATUS status = NT_STATUS_OK;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (total_data < 36) {
return NT_STATUS_INVALID_PARAMETER;
}
- status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
+ if (fsp != NULL) {
+ status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
+ } else {
+ status = check_access(conn,
+ conn->cwd_fsp,
+ smb_fname,
+ FILE_WRITE_ATTRIBUTES);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
}
/* create time */
- ft.create_time = interpret_long_date(pdata);
+ ft.create_time = pull_long_date_full_timespec(pdata);
/* access time */
- ft.atime = interpret_long_date(pdata+8);
+ ft.atime = pull_long_date_full_timespec(pdata+8);
/* write time. */
- ft.mtime = interpret_long_date(pdata+16);
+ ft.mtime = pull_long_date_full_timespec(pdata+16);
/* change time. */
- ft.ctime = interpret_long_date(pdata+24);
+ ft.ctime = pull_long_date_full_timespec(pdata+24);
DEBUG(10, ("smb_set_file_basic_info: file %s\n",
smb_fname_str_dbg(smb_fname)));
- return smb_set_file_time(conn, fsp, smb_fname, &ft,
- true);
+ status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (fsp != NULL && fsp->fsp_flags.modified) {
+ trigger_write_time_update_immediate(fsp);
+ }
+ return NT_STATUS_OK;
}
/****************************************************************************
NTSTATUS status;
struct smb_file_time ft;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (total_data < 12) {
return NT_STATUS_INVALID_PARAMETER;
}
/* create time */
- ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
+ ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
/* access time */
- ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
+ ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
/* write time */
- ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
+ ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
DEBUG(10,("smb_set_info_standard: file %s\n",
smb_fname_str_dbg(smb_fname)));
- status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
+ if (fsp != NULL) {
+ status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
+ } else {
+ status = check_access(conn,
+ conn->cwd_fsp,
+ smb_fname,
+ FILE_WRITE_ATTRIBUTES);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- return smb_set_file_time(conn,
- fsp,
- smb_fname,
- &ft,
- true);
+ status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (fsp != NULL && fsp->fsp_flags.modified) {
+ trigger_write_time_update_immediate(fsp);
+ }
+ return NT_STATUS_OK;
}
/****************************************************************************
uint32_t raw_unixmode = IVAL(pdata,84);
NTSTATUS status;
mode_t unixmode;
+ int ret;
if (total_data < 100) {
return NT_STATUS_INVALID_PARAMETER;
#endif
switch (file_type) {
+ /* We can't create other objects here. */
+ case UNIX_TYPE_FILE:
+ case UNIX_TYPE_DIR:
+ case UNIX_TYPE_SYMLINK:
+ return NT_STATUS_ACCESS_DENIED;
#if defined(S_IFIFO)
case UNIX_TYPE_FIFO:
unixmode |= S_IFIFO;
#endif
#if defined(S_IFCHR)
case UNIX_TYPE_CHARDEV:
+ /* This is only allowed for root. */
+ if (get_current_uid(conn) != sec_initial_uid()) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
unixmode |= S_IFCHR;
break;
#endif
#if defined(S_IFBLK)
case UNIX_TYPE_BLKDEV:
+ if (get_current_uid(conn) != sec_initial_uid()) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
unixmode |= S_IFBLK;
break;
#endif
(unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
/* Ok - do the mknod. */
- if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
+ ret = SMB_VFS_MKNODAT(conn,
+ conn->cwd_fsp,
+ smb_fname,
+ unixmode,
+ dev);
+
+ if (ret != 0) {
return map_nt_error_from_unix(errno);
}
*/
if (lp_inherit_permissions(SNUM(conn))) {
- char *parent;
- if (!parent_dirname(talloc_tos(), smb_fname->base_name,
- &parent, NULL)) {
+ struct smb_filename *parent_fname = NULL;
+ bool ok;
+
+ ok = parent_smb_fname(talloc_tos(),
+ smb_fname,
+ &parent_fname,
+ NULL);
+ if (!ok) {
return NT_STATUS_NO_MEMORY;
}
- inherit_access_posix_acl(conn, parent, smb_fname,
+ inherit_access_posix_acl(conn,
+ parent_fname,
+ smb_fname,
unixmode);
- TALLOC_FREE(parent);
+ TALLOC_FREE(parent_fname);
}
return NT_STATUS_OK;
uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
NTSTATUS status = NT_STATUS_OK;
- bool delete_on_fail = False;
enum perm_type ptype;
files_struct *all_fsps = NULL;
bool modify_mtime = true;
struct file_id id;
- struct smb_filename *smb_fname_tmp = NULL;
SMB_STRUCT_STAT sbuf;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (total_data < 100) {
return NT_STATUS_INVALID_PARAMETER;
size |= (((off_t)IVAL(pdata,4)) << 32);
}
- ft.atime = interpret_long_date(pdata+24); /* access_time */
- ft.mtime = interpret_long_date(pdata+32); /* modification_time */
+ ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
+ ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
set_owner = (uid_t)IVAL(pdata,40);
set_grp = (gid_t)IVAL(pdata,48);
raw_unixmode = IVAL(pdata,84);
* a new info level should be used for mknod. JRA.
*/
- status = smb_unix_mknod(conn,
+ return smb_unix_mknod(conn,
pdata,
total_data,
smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
- if (smb_fname_tmp == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
- status = map_nt_error_from_unix(errno);
- TALLOC_FREE(smb_fname_tmp);
- SMB_VFS_UNLINK(conn, smb_fname);
- return status;
- }
-
- sbuf = smb_fname_tmp->st;
- smb_fname = smb_fname_tmp;
-
- /* Ensure we don't try and change anything else. */
- raw_unixmode = SMB_MODE_NO_CHANGE;
- size = get_file_size_stat(&sbuf);
- ft.atime = sbuf.st_ex_atime;
- ft.mtime = sbuf.st_ex_mtime;
- /*
- * We continue here as we might want to change the
- * owner uid/gid.
- */
- delete_on_fail = True;
}
#if 1
if (ret != 0) {
status = map_nt_error_from_unix(errno);
- if (delete_on_fail) {
- SMB_VFS_UNLINK(conn, smb_fname);
- }
return status;
}
}
}
if (ret != 0) {
status = map_nt_error_from_unix(errno);
- if (delete_on_fail) {
- SMB_VFS_UNLINK(conn, smb_fname);
- }
return status;
}
}
/* Deal with any size changes. */
- status = smb_set_file_size(conn, req,
- fsp,
- smb_fname,
- &sbuf,
- size,
- false);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (S_ISREG(sbuf.st_ex_mode)) {
+ status = smb_set_file_size(conn, req,
+ fsp,
+ smb_fname,
+ &sbuf,
+ size,
+ false);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
/* Deal with any time changes. */
- if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
+ if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
/* No change, don't cancel anything. */
return status;
}
* We're setting the time explicitly for UNIX.
* Cancel any pending changes over all handles.
*/
- all_fsps->update_write_time_on_close = false;
+ all_fsps->fsp_flags.update_write_time_on_close = false;
TALLOC_FREE(all_fsps->update_write_time_event);
}
* we need. Just remember if we modified
* mtime and send the notify ourselves.
*/
- if (null_timespec(ft.mtime)) {
+ if (is_omit_timespec(&ft.mtime)) {
modify_mtime = false;
}
{
NTSTATUS status = NT_STATUS_OK;
uint32_t raw_unixmode = 0;
- uint32_t mod_unixmode = 0;
mode_t unixmode = (mode_t)0;
files_struct *fsp = NULL;
uint16_t info_level_return = 0;
int info;
char *pdata = *ppdata;
+ struct smb2_create_blobs *posx = NULL;
if (total_data < 18) {
return NT_STATUS_INVALID_PARAMETER;
return status;
}
- mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+ status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
+ nt_errstr(status));
+ return status;
+ }
DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
FILE_SHARE_NONE, /* share_access */
FILE_CREATE, /* create_disposition*/
FILE_DIRECTORY_FILE, /* create_options */
- mod_unixmode, /* file_attributes */
+ 0, /* file_attributes */
0, /* oplock_request */
NULL, /* lease */
0, /* allocation_size */
NULL, /* ea_list */
&fsp, /* result */
&info, /* pinfo */
- NULL, NULL); /* create context */
+ posx, /* in_context_blobs */
+ NULL); /* out_context_blobs */
+
+ TALLOC_FREE(posx);
if (NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
uint32_t flags = 0;
uint32_t wire_open_mode = 0;
uint32_t raw_unixmode = 0;
- uint32_t mod_unixmode = 0;
+ uint32_t attributes = 0;
uint32_t create_disp = 0;
uint32_t access_mask = 0;
uint32_t create_options = FILE_NON_DIRECTORY_FILE;
int oplock_request = 0;
int info = 0;
uint16_t info_level_return = 0;
+ struct smb2_create_blobs *posx = NULL;
if (total_data < 18) {
return NT_STATUS_INVALID_PARAMETER;
return status;
}
- mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+ status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
+ nt_errstr(status));
+ return status;
+ }
if (wire_open_mode & SMB_O_SYNC) {
create_options |= FILE_WRITE_THROUGH;
access_mask |= FILE_APPEND_DATA;
}
if (wire_open_mode & SMB_O_DIRECT) {
- mod_unixmode |= FILE_FLAG_NO_BUFFERING;
+ attributes |= FILE_FLAG_NO_BUFFERING;
}
if ((wire_open_mode & SMB_O_DIRECTORY) ||
FILE_SHARE_DELETE),
create_disp, /* create_disposition*/
create_options, /* create_options */
- mod_unixmode, /* file_attributes */
+ attributes, /* file_attributes */
oplock_request, /* oplock_request */
NULL, /* lease */
0, /* allocation_size */
NULL, /* ea_list */
&fsp, /* result */
&info, /* pinfo */
- NULL, NULL); /* create context */
+ posx, /* in_context_blobs */
+ NULL); /* out_context_blobs */
+
+ TALLOC_FREE(posx);
if (!NT_STATUS_IS_OK(status)) {
return status;
int total_data,
struct smb_filename *smb_fname)
{
- struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
uint16_t flags = 0;
int create_options = 0;
struct share_mode_lock *lck = NULL;
bool other_nonposix_opens;
+ struct smb2_create_blobs *posx = NULL;
if (total_data < 2) {
return NT_STATUS_INVALID_PARAMETER;
create_options |= FILE_DIRECTORY_FILE;
}
+ status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
+ nt_errstr(status));
+ return status;
+ }
+
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
FILE_SHARE_DELETE),
FILE_OPEN, /* create_disposition*/
create_options, /* create_options */
- FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
+ 0, /* file_attributes */
0, /* oplock_request */
NULL, /* lease */
0, /* allocation_size */
NULL, /* ea_list */
&fsp, /* result */
&info, /* pinfo */
- NULL, NULL); /* create context */
+ posx, /* in_context_blobs */
+ NULL); /* out_context_blobs */
+
+ TALLOC_FREE(posx);
if (!NT_STATUS_IS_OK(status)) {
return status;
return NT_STATUS_INVALID_PARAMETER;
}
- other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
+ other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
if (other_nonposix_opens) {
/* Fail with sharing violation. */
TALLOC_FREE(lck);
/* We have re-scheduled this call. */
return;
}
+ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ bool ok = defer_smb1_sharing_violation(req);
+ if (ok) {
+ return;
+ }
+ }
if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
/* We have re-scheduled this call. */
return;
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
+ const struct loadparm_substitution *lp_sub =
+ loadparm_s3_global_substitution();
char *pdata = *ppdata;
files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
NTSTATUS status;
return;
}
status = srvstr_push(pdata, req->flags2, pdata+18,
- lp_servicename(talloc_tos(), SNUM(conn)), 13,
+ lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
STR_ASCII|STR_TERMINATE, &len); /* Service name */
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
{
int dptr_num;
struct smbd_server_connection *sconn = req->sconn;
+ files_struct *fsp = NULL;
START_PROFILE(SMBfindclose);
DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
- dptr_close(sconn, &dptr_num);
+ /*
+ * OS/2 seems to use -1 to indicate "close all directories"
+ * This has to mean on this specific connection struct.
+ */
+ if (dptr_num == -1) {
+ dptr_closecnum(req->conn);
+ } else {
+ fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
+ dptr_num = -1;
+ if (fsp != NULL) {
+ close_file(NULL, fsp, NORMAL_CLOSE);
+ fsp = NULL;
+ }
+ }
reply_outbuf(req, 0, 0);