From 3a7d372e2eb5ab00986aafe69ac715a68faa077f Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Wed, 8 Jul 2009 16:22:44 -0700 Subject: s3: Change the share_mode_lock struct to store a base_name and stream_name --- source3/include/proto.h | 10 ++--- source3/include/smb.h | 3 +- source3/locking/locking.c | 93 ++++++++++++++++++++++++++++++-------------- source3/modules/onefs_open.c | 22 ++++------- source3/smbd/open.c | 71 +++++++++++++++++++++------------ source3/smbd/reply.c | 17 ++++---- source3/utils/status.c | 18 +++++++-- 7 files changed, 147 insertions(+), 87 deletions(-) (limited to 'source3') diff --git a/source3/include/proto.h b/source3/include/proto.h index aaedc15726..f887b4e796 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3443,16 +3443,14 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e) struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, const struct file_id id, const char *servicepath, - const char *fname, + const struct smb_filename *smb_fname, const struct timespec *old_write_time); struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, - const struct file_id id, - const char *servicepath, - const char *fname); + const struct file_id id); bool rename_share_filename(struct messaging_context *msg_ctx, struct share_mode_lock *lck, const char *servicepath, - const char *newname); + const struct smb_filename *smb_fname); void get_file_infos(struct file_id id, bool *delete_on_close, struct timespec *write_time); @@ -6581,7 +6579,7 @@ bool open_match_attributes(connection_struct *conn, NTSTATUS fcb_or_dos_open(struct smb_request *req, connection_struct *conn, files_struct *fsp_to_dup_into, - const char *fname, + const struct smb_filename *smb_fname, struct file_id id, uint16 file_pid, uint16 vuid, diff --git a/source3/include/smb.h b/source3/include/smb.h index 87fd2b05cc..9afeb67b00 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -774,7 +774,8 @@ Offset Data length. struct share_mode_lock { const char *servicepath; /* canonicalized. */ - const char *filename; + const char *base_name; + const char *stream_name; struct file_id id; int num_share_modes; struct share_mode_entry *share_modes; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index cf6e02f248..91fe137fdc 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -630,11 +630,17 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck) (lck->num_share_modes * sizeof(struct share_mode_entry)) + data.u.s.delete_token_size; - lck->filename = (const char *)dbuf.dptr + sizeof(struct locking_data) + + lck->base_name = (const char *)dbuf.dptr + sizeof(struct locking_data) + (lck->num_share_modes * sizeof(struct share_mode_entry)) + data.u.s.delete_token_size + strlen(lck->servicepath) + 1; + lck->stream_name = (const char *)dbuf.dptr + sizeof(struct locking_data) + + (lck->num_share_modes * sizeof(struct share_mode_entry)) + + data.u.s.delete_token_size + + strlen(lck->servicepath) + 1 + + strlen(lck->base_name) + 1; + /* * Ensure that each entry has a real process attached. */ @@ -666,7 +672,7 @@ static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck) int i; struct locking_data *data; ssize_t offset; - ssize_t sp_len; + ssize_t sp_len, bn_len, sn_len; uint32 delete_token_size; result.dptr = NULL; @@ -683,6 +689,9 @@ static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck) } sp_len = strlen(lck->servicepath); + bn_len = strlen(lck->base_name); + sn_len = lck->stream_name != NULL ? strlen(lck->stream_name) : 0; + delete_token_size = (lck->delete_token ? (sizeof(uid_t) + sizeof(gid_t) + (lck->delete_token->ngroups*sizeof(gid_t))) : 0); @@ -690,7 +699,8 @@ static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck) lck->num_share_modes * sizeof(struct share_mode_entry) + delete_token_size + sp_len + 1 + - strlen(lck->filename) + 1; + bn_len + 1 + + sn_len + 1; result.dptr = TALLOC_ARRAY(lck, uint8, result.dsize); if (result.dptr == NULL) { @@ -740,7 +750,10 @@ static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck) safe_strcpy((char *)result.dptr + offset, lck->servicepath, result.dsize - offset - 1); offset += sp_len + 1; - safe_strcpy((char *)result.dptr + offset, lck->filename, + safe_strcpy((char *)result.dptr + offset, lck->base_name, + result.dsize - offset - 1); + offset += bn_len + 1; + safe_strcpy((char *)result.dptr + offset, lck->stream_name, result.dsize - offset - 1); if (DEBUGLEVEL >= 10) { @@ -789,7 +802,7 @@ static int share_mode_lock_destructor(struct share_mode_lock *lck) static bool fill_share_mode_lock(struct share_mode_lock *lck, struct file_id id, const char *servicepath, - const char *fname, + const struct smb_filename *smb_fname, TDB_DATA share_mode_data, const struct timespec *old_write_time) { @@ -797,7 +810,8 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, valid even if parse_share_modes fails. */ lck->servicepath = NULL; - lck->filename = NULL; + lck->base_name = NULL; + lck->stream_name = NULL; lck->id = id; lck->num_share_modes = 0; lck->share_modes = NULL; @@ -811,13 +825,20 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, lck->fresh = (share_mode_data.dptr == NULL); if (lck->fresh) { - if (fname == NULL || servicepath == NULL + bool has_stream; + if (smb_fname == NULL || servicepath == NULL || old_write_time == NULL) { return False; } - lck->filename = talloc_strdup(lck, fname); + + has_stream = smb_fname->stream_name != NULL; + + lck->base_name = talloc_strdup(lck, smb_fname->base_name); + lck->stream_name = talloc_strdup(lck, smb_fname->stream_name); lck->servicepath = talloc_strdup(lck, servicepath); - if (lck->filename == NULL || lck->servicepath == NULL) { + if (lck->base_name == NULL || + (has_stream && lck->stream_name == NULL) || + lck->servicepath == NULL) { DEBUG(0, ("talloc failed\n")); return False; } @@ -835,7 +856,7 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, const struct file_id id, const char *servicepath, - const char *fname, + const struct smb_filename *smb_fname, const struct timespec *old_write_time) { struct share_mode_lock *lck; @@ -853,7 +874,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return NULL; } - if (!fill_share_mode_lock(lck, id, servicepath, fname, + if (!fill_share_mode_lock(lck, id, servicepath, smb_fname, lck->record->value, old_write_time)) { DEBUG(3, ("fill_share_mode_lock failed\n")); TALLOC_FREE(lck); @@ -866,9 +887,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, } struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, - const struct file_id id, - const char *servicepath, - const char *fname) + const struct file_id id) { struct share_mode_lock *lck; struct file_id tmp; @@ -886,7 +905,7 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, return NULL; } - if (!fill_share_mode_lock(lck, id, servicepath, fname, data, NULL)) { + if (!fill_share_mode_lock(lck, id, NULL, NULL, data, NULL)) { DEBUG(10, ("fetch_share_mode_unlocked: no share_mode record " "around (file not open)\n")); TALLOC_FREE(lck); @@ -906,37 +925,49 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, bool rename_share_filename(struct messaging_context *msg_ctx, struct share_mode_lock *lck, const char *servicepath, - const char *newname) + const struct smb_filename *smb_fname_dst) { size_t sp_len; - size_t fn_len; + size_t bn_len; + size_t sn_len; size_t msg_len; char *frm = NULL; int i; + bool strip_two_chars = false; + bool has_stream = smb_fname_dst->stream_name != NULL; DEBUG(10, ("rename_share_filename: servicepath %s newname %s\n", - servicepath, newname)); + servicepath, smb_fname_dst->base_name)); /* * rename_internal_fsp() and rename_internals() add './' to * head of newname if newname does not contain a '/'. */ - while (newname[0] && newname[1] && newname[0] == '.' && newname[1] == '/') { - newname += 2; + if (smb_fname_dst->base_name[0] && + smb_fname_dst->base_name[1] && + smb_fname_dst->base_name[0] == '.' && + smb_fname_dst->base_name[1] == '/') { + strip_two_chars = true; } lck->servicepath = talloc_strdup(lck, servicepath); - lck->filename = talloc_strdup(lck, newname); - if (lck->filename == NULL || lck->servicepath == NULL) { + lck->base_name = talloc_strdup(lck, smb_fname_dst->base_name + + (strip_two_chars ? 2 : 0)); + lck->stream_name = talloc_strdup(lck, smb_fname_dst->stream_name); + if (lck->base_name == NULL || + (has_stream && lck->stream_name == NULL) || + lck->servicepath == NULL) { DEBUG(0, ("rename_share_filename: talloc failed\n")); return False; } lck->modified = True; sp_len = strlen(lck->servicepath); - fn_len = strlen(lck->filename); + bn_len = strlen(lck->base_name); + sn_len = has_stream ? strlen(lck->stream_name) : 0; - msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1; + msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + bn_len + 1 + + sn_len + 1; /* Set up the name changed message. */ frm = TALLOC_ARRAY(lck, char, msg_len); @@ -949,7 +980,9 @@ bool rename_share_filename(struct messaging_context *msg_ctx, DEBUG(10,("rename_share_filename: msg_len = %u\n", (unsigned int)msg_len )); safe_strcpy(&frm[24], lck->servicepath, sp_len); - safe_strcpy(&frm[24 + sp_len + 1], lck->filename, fn_len); + safe_strcpy(&frm[24 + sp_len + 1], lck->base_name, bn_len); + safe_strcpy(&frm[24 + sp_len + 1 + bn_len + 1], lck->stream_name, + sn_len); /* Send the messages. */ for (i=0; inum_share_modes; i++) { @@ -962,11 +995,13 @@ bool rename_share_filename(struct messaging_context *msg_ctx, continue; } - DEBUG(10,("rename_share_filename: sending rename message to pid %s " - "file_id %s sharepath %s newname %s\n", + DEBUG(10,("rename_share_filename: sending rename message to " + "pid %s file_id %s sharepath %s base_name %s " + "stream_name %s\n", procid_str_static(&se->pid), file_id_string_tos(&lck->id), - lck->servicepath, lck->filename )); + lck->servicepath, lck->base_name, + has_stream ? lck->stream_name : "")); messaging_send_buf(msg_ctx, se->pid, MSG_SMB_FILE_RENAME, (uint8 *)frm, msg_len); @@ -989,7 +1024,7 @@ void get_file_infos(struct file_id id, ZERO_STRUCTP(write_time); } - if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id, NULL, NULL))) { + if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) { return; } diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index 60a1790f64..52324f8181 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -465,16 +465,9 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, int granted_oplock; uint64_t oplock_callback_id = 0; uint32 createfile_attributes = 0; - char *fname = NULL; ZERO_STRUCT(id); - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (conn->printer) { /* * Printers are handled completely differently. @@ -488,8 +481,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(10, ("onefs_open_file_ntcreate: printer open fname=%s\n", smb_fname_str_dbg(smb_fname))); - return print_fsp_open(req, conn, fname, req->vuid, fsp, - &smb_fname->st); + return print_fsp_open(req, conn, smb_fname->base_name, + req->vuid, fsp, &smb_fname->st); } if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir, @@ -845,7 +838,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname, &old_write_time); + smb_fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("Could not get share mode lock\n")); @@ -936,7 +929,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, id = vfs_file_id_from_sbuf(conn, &smb_fname->st); if (!(lck = get_share_mode_lock(talloc_tos(), - id, conn->connectpath, fname, + id, conn->connectpath, smb_fname, &old_write_time))) { /* * Emergency exit @@ -993,7 +986,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, status = fcb_or_dos_open(req, conn, fsp, - fname, + smb_fname, id, req->smbpid, req->vuid, @@ -1136,7 +1129,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname, &old_write_time); + smb_fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("onefs_open_file_ntcreate: Could not get " @@ -1605,8 +1598,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, * semantics and to make smbstatus more useful. */ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, - conn->connectpath, smb_dname->base_name, - &mtimespec); + conn->connectpath, smb_dname, &mtimespec); if (lck == NULL) { DEBUG(0, ("onefs_open_directory: Could not get share mode " diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e73b3e4fdd..3e7b9d2657 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1139,7 +1139,7 @@ bool open_match_attributes(connection_struct *conn, NTSTATUS fcb_or_dos_open(struct smb_request *req, connection_struct *conn, files_struct *fsp_to_dup_into, - const char *fname, + const struct smb_filename *smb_fname, struct file_id id, uint16 file_pid, uint16 vuid, @@ -1148,9 +1148,16 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req, uint32 create_options) { files_struct *fsp; + char *fname = NULL; + NTSTATUS status; + + status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " - "file %s.\n", fname )); + "file %s.\n", smb_fname_str_dbg(smb_fname))); for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { @@ -1180,7 +1187,7 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req, } /* quite an insane set of semantics ... */ - if (is_executable(fname) && + if (is_executable(smb_fname->base_name) && (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) { DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n")); return NT_STATUS_INVALID_PARAMETER; @@ -1467,17 +1474,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, uint32 open_access_mask = access_mask; NTSTATUS status; int ret_flock; - char *fname = NULL; char *parent_dir; ZERO_STRUCT(id); - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (conn->printer) { /* * Printers are handled completely differently. @@ -1497,8 +1497,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, return NT_STATUS_INTERNAL_ERROR; } - return print_fsp_open(req, conn, fname, req->vuid, fsp, - &smb_fname->st); + return print_fsp_open(req, conn, smb_fname->base_name, + req->vuid, fsp, &smb_fname->st); } if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir, @@ -1785,7 +1785,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname, &old_write_time); + smb_fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("Could not get share mode lock\n")); @@ -1849,7 +1849,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, status = fcb_or_dos_open(req, conn, fsp, - fname, + smb_fname, id, req->smbpid, req->vuid, @@ -2005,7 +2005,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname, &old_write_time); + smb_fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("open_file_ntcreate: Could not get share " @@ -2613,8 +2613,7 @@ static NTSTATUS open_directory(connection_struct *conn, mtimespec = smb_dname->st.st_ex_mtime; lck = get_share_mode_lock(talloc_tos(), fsp->file_id, - conn->connectpath, smb_dname->base_name, - &mtimespec); + conn->connectpath, smb_dname, &mtimespec); if (lck == NULL) { DEBUG(0, ("open_directory: Could not get share mode lock for " @@ -2706,8 +2705,11 @@ void msg_file_was_renamed(struct messaging_context *msg, char *frm = (char *)data->data; struct file_id id; const char *sharepath; - const char *newname; - size_t sp_len; + const char *base_name; + const char *stream_name; + struct smb_filename *smb_fname = NULL; + size_t sp_len, bn_len; + NTSTATUS status; if (data->data == NULL || data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) { @@ -2719,18 +2721,36 @@ void msg_file_was_renamed(struct messaging_context *msg, /* Unpack the message. */ pull_file_id_24(frm, &id); sharepath = &frm[24]; - newname = sharepath + strlen(sharepath) + 1; sp_len = strlen(sharepath); + base_name = sharepath + sp_len + 1; + bn_len = strlen(base_name); + stream_name = sharepath + sp_len + 1 + bn_len + 1; + + status = create_synthetic_smb_fname(talloc_tos(), base_name, + stream_name, NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return; + } DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, " "file_id %s\n", - sharepath, newname, file_id_string_tos(&id))); + sharepath, smb_fname_str_dbg(smb_fname), + file_id_string_tos(&id))); for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { - DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", - fsp->fnum, fsp->fsp_name, newname )); + char *newname = NULL; + + DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", + fsp->fnum, fsp->fsp_name, + smb_fname_str_dbg(smb_fname))); + status = get_full_smb_filename(talloc_tos(), + smb_fname, &newname); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } string_set(&fsp->fsp_name, newname); + TALLOC_FREE(newname); } else { /* TODO. JRA. */ /* Now we have the complete path we can work out if this is @@ -2742,9 +2762,12 @@ void msg_file_was_renamed(struct messaging_context *msg, sharepath, fsp->fnum, fsp->fsp_name, - newname )); + smb_fname_str_dbg(smb_fname))); } } + out: + TALLOC_FREE(smb_fname); + return; } struct case_semantics_state { diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 483f68947e..837d17dc0b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5709,12 +5709,6 @@ static void rename_open_files(connection_struct *conn, char *fname_dst = NULL; NTSTATUS status; - status = get_full_smb_filename(talloc_tos(), smb_fname_dst, - &fname_dst); - if (!NT_STATUS_IS_OK(status)) { - return; - } - for(fsp = file_find_di_first(lck->id); fsp; fsp = file_find_di_next(fsp)) { /* fsp_name is a relative path under the fsp. To change this for other @@ -5728,8 +5722,15 @@ static void rename_open_files(connection_struct *conn, "(file_id %s) from %s -> %s\n", fsp->fnum, file_id_string_tos(&fsp->file_id), fsp->fsp_name, smb_fname_str_dbg(smb_fname_dst))); + + status = get_full_smb_filename(talloc_tos(), smb_fname_dst, + &fname_dst); + if (!NT_STATUS_IS_OK(status)) { + return; + } string_set(&fsp->fsp_name, fname_dst); did_rename = True; + TALLOC_FREE(fname_dst); } if (!did_rename) { @@ -5740,8 +5741,8 @@ static void rename_open_files(connection_struct *conn, /* Send messages to all smbd's (not ourself) that the name has changed. */ rename_share_filename(smbd_messaging_context(), lck, conn->connectpath, - fname_dst); - TALLOC_FREE(fname_dst); + smb_fname_dst); + } /**************************************************************************** diff --git a/source3/utils/status.c b/source3/utils/status.c index cbf0dcb2b5..fa7d1eba2b 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -191,7 +191,7 @@ static void print_brl(struct file_id id, }; const char *desc="X"; const char *sharepath = ""; - const char *fname = ""; + char *fname = NULL; struct share_mode_lock *share_mode; if (count==0) { @@ -201,10 +201,19 @@ static void print_brl(struct file_id id, } count++; - share_mode = fetch_share_mode_unlocked(NULL, id, "__unspecified__", "__unspecified__"); + share_mode = fetch_share_mode_unlocked(NULL, id); if (share_mode) { - sharepath = share_mode->servicepath; - fname = share_mode->filename; + bool has_stream = share_mode->stream_name != NULL; + + fname = talloc_asprintf(NULL, "%s%s%s", share_mode->base_name, + has_stream ? ":" : "", + has_stream ? share_mode->stream_name : + ""); + } else { + fname = talloc_strdup(NULL, ""); + if (fname == NULL) { + return; + } } for (i=0;i