}
}
+/*
+ * TODO: needs to be moved - copied from source3/smbd/files.c
+ */
+static unsigned long get_gen_count(struct smbd_server_connection *sconn)
+{
+ sconn->file_gen_counter += 1;
+ if (sconn->file_gen_counter == 0) {
+ sconn->file_gen_counter += 1;
+ }
+
+ return sconn->file_gen_counter;
+}
+
+static NTSTATUS new_durable_reconnect_fsp(struct smbXsrv_open *op,
+ struct connection_struct *conn,
+ struct smb_filename *smb_fname,
+ TALLOC_CTX *mem_ctx,
+ files_struct **_fsp)
+{
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+ files_struct *fsp = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct smbd_server_connection *sconn = op->connection->sconn;
+
+ fsp = talloc_zero(frame, struct files_struct);
+ if (fsp == NULL) {
+ goto fail;
+ }
+
+ /*
+ * This can't be a child of fsp because the file_handle can be ref'd
+ * when doing a dos/fcb open, which will then share the file_handle
+ * across multiple fsps.
+ */
+ fsp->fh = talloc_zero(frame, struct fd_handle);
+ if (fsp->fh == NULL) {
+ goto fail;
+ }
+
+ status = fsp_set_smb_fname(fsp, smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ fsp->fh->ref_count = 1;
+ fsp->fh->fd = -1;
+ fsp->fh->gen_id = get_gen_count(sconn);
+
+ fsp->conn = conn;
+
+
+ /* success */
+
+ talloc_steal(mem_ctx, fsp);
+ talloc_steal(mem_ctx, fsp->fh);
+ *_fsp = fsp;
+
+ status = NT_STATUS_OK;
+
+fail:
+ talloc_free(frame);
+ return status;
+}
+
static NTSTATUS smb2_create_durable_reconnect(struct smbXsrv_open *op,
+ /* struct smb_request *smb1req, */
+ struct connection_struct *conn,
+ struct smb_filename *smb_fname,
TALLOC_CTX *mem_ctx,
- files_struct **fsp)
+ files_struct **_fsp)
{
struct share_mode_lock *sharemode_lock;
+ files_struct *fsp = NULL;
+ NTSTATUS status;
+
+DEBUG(0, ("OBNOX - durable_reconnect enter: (%s:%s)\n", __location__, __FUNCTION__));
/* 1. check entry in locking.tdb */
/*
* Q: fetch with lock right away?
*/
+/*
sharemode_lock = fetch_share_mode_unlocked(mem_ctx,
op->global->backend_file_id);
+*/
+ sharemode_lock = get_share_mode_lock(mem_ctx,
+ op->global->backend_file_id);
if (sharemode_lock == NULL) {
/* TODO: use/create other fetch func with better error code */
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ /* 2. proceed with opening file */
+
+ /*
+ * refetch with lock and update the pid // fetch with lock right away above
+ */
+/*
+ talloc_free(sharemode_lock);
+ sharemode_lock = get_share_mode_lock(mem_ctx,
+ op->global->backend_file_id);
+ if (sharemode_lock == NULL) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+*/
+
+ sharemode_lock->data->share_modes[0].pid =
+ messaging_server_id(op->connection->sconn->msg_ctx);
+
+ /*
+ * circumstances seems ok, do the open
+ */
+ status = new_durable_reconnect_fsp(op, conn, smb_fname, mem_ctx, &fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+DEBUG(0, ("OBNOX - durable_reconnect: new fsp created (%s:%s)\n", __location__, __FUNCTION__));
+
+ fsp->fh->fd = SMB_VFS_OPEN(conn,
+ smb_fname,
+ fsp,
+ sharemode_lock->data->share_modes[0].flags,
+ 0 /* mode */);
+ if (fsp->fh->fd == -1) {
+ /* ... */
+ return NT_STATUS_UNSUCCESSFUL; // TODO ERROR CODE?
+ }
+
+ /* - release the sharemode lock: this writes the changes */
+ talloc_free(sharemode_lock);
+
+
+ /* Q: do this in fsp creation? */
+ op->fsp = fsp;
+ *_fsp = fsp;
+
/*
- *
- * - refetch with lock and update the pid
- * - reopen the file with SMB_VFS_OPEN()
- * - build a files_struct
- * - release the sharemode lock
- * - update fsp pointer in smbXsrv_open
* - return
*
* ... think about seek()
*/
- /* 2. proceed with opening file */
- return NT_STATUS_NOT_IMPLEMENTED;
+ return NT_STATUS_OK;
}
struct smbd_smb2_create_state {
struct timespec write_time_ts;
struct smb2_create_blobs out_context_blobs;
int requested_oplock_level;
+ bool do_durable_reconnect = false;
+ struct smbXsrv_open *op = NULL;
ZERO_STRUCT(out_context_blobs);
if (dhnc) {
uint64_t persistent_id;
- struct smbXsrv_open *op = NULL;
+
+DEBUG(0, ("OBNOX - dhnc found (%s:%s)\n", __location__, __FUNCTION__));
if (dhnc->data.length != 16) {
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
- // TODO: implement this function..
- status = smb2_create_durable_reconnect(op, mem_ctx, &result);
-
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- // TODO: response construction
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
+ do_durable_reconnect = true;
}
if (alsi) {
smb1req->conn,
smb1req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
- NULL,
+ 0, /* unix_convert flags */
+ NULL, /* ppath_contains_wcards */
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
tevent_req_nterror(req, status);
in_file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
- status = SMB_VFS_CREATE_FILE(smb1req->conn,
- smb1req,
- 0, /* root_dir_fid */
- smb_fname,
- in_desired_access,
- in_share_access,
- in_create_disposition,
- in_create_options,
- in_file_attributes,
- map_smb2_oplock_levels_to_samba(requested_oplock_level),
- allocation_size,
- 0, /* private_flags */
- sec_desc,
- ea_list,
- &result,
- &info);
- if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(smb1req->sconn, smb1req->mid)) {
- return req;
+ /*
+ * For the backend file open procedure, there are
+ * two possible modes: durable_reconnect or not.
+ */
+ if (do_durable_reconnect) {
+ status = smb2_create_durable_reconnect(op,
+ smb1req->conn,
+ smb_fname,
+ mem_ctx,
+ &result);
+
+DEBUG(0, ("OBNOX - durable_reconnect result: %s (%s:%s)\n", nt_errstr(status), __location__, __FUNCTION__));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+ } else {
+ status = SMB_VFS_CREATE_FILE(smb1req->conn,
+ smb1req,
+ 0, /* root_dir_fid */
+ smb_fname,
+ in_desired_access,
+ in_share_access,
+ in_create_disposition,
+ in_create_options,
+ in_file_attributes,
+ map_smb2_oplock_levels_to_samba(requested_oplock_level),
+ allocation_size,
+ 0, /* private_flags */
+ sec_desc,
+ ea_list,
+ &result,
+ &info);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (open_was_deferred(smb1req->sconn, smb1req->mid)) {
+ return req;
+ }
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
}
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
}
if (mxac) {
}
}
- if (dhnq && BATCH_OPLOCK_TYPE(result->oplock_type)) {
+ /*
+ * windows createst a dhnc response blob upon dbnc request.
+ * this seems to contradict the documentation, though
+ * --> TODO:dochelp
+ */
+ if (dhnc || (dhnq && BATCH_OPLOCK_TYPE(result->oplock_type))) {
uint8_t p[8];
DATA_BLOB blob = data_blob_const(p, sizeof(p));