diff options
-rw-r--r-- | source3/include/proto.h | 2 | ||||
-rw-r--r-- | source3/include/smb.h | 11 | ||||
-rw-r--r-- | source3/libsmb/smb_share_modes.c | 36 | ||||
-rw-r--r-- | source3/locking/locking.c | 17 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 9 |
6 files changed, 66 insertions, 11 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index fafcf6be52..cf508e3398 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3068,6 +3068,8 @@ 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, + uint32_t orig_name_hash, + uint32_t new_name_hash, const struct smb_filename *smb_fname); void get_file_infos(struct file_id id, bool *delete_on_close, diff --git a/source3/include/smb.h b/source3/include/smb.h index 6cfb6307d0..5269c2348f 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -685,6 +685,7 @@ struct share_mode_entry { unsigned long share_file_id; uint32 uid; /* uid of file opener. */ uint16 flags; /* See SHARE_MODE_XX above. */ + uint32_t name_hash; /* Jenkins hash of full pathname. */ }; /* oplock break message definition - linearization of share_mode_entry. @@ -704,7 +705,8 @@ Offset Data length. 58 unsigned long file_id 4 bytes 62 uint32 uid 4 bytes 66 uint16 flags 2 bytes -68 +68 uint32 name_hash 4 bytes +72 */ @@ -722,12 +724,13 @@ Offset Data length. #define OP_BREAK_MSG_FILE_ID_OFFSET 58 #define OP_BREAK_MSG_UID_OFFSET 62 #define OP_BREAK_MSG_FLAGS_OFFSET 66 +#define OP_BREAK_MSG_NAME_HASH_OFFSET 68 #ifdef CLUSTER_SUPPORT -#define OP_BREAK_MSG_VNN_OFFSET 68 -#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 72 +#define OP_BREAK_MSG_VNN_OFFSET 72 +#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 76 #else -#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 68 +#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 72 #endif struct share_mode_lock { diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index 9f985501b6..2eda7a499f 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -155,7 +155,8 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, */ static void create_share_mode_entry(struct share_mode_entry *out, - const struct smb_share_mode_entry *in) + const struct smb_share_mode_entry *in, + uint32_t name_hash) { memset(out, '\0', sizeof(struct share_mode_entry)); @@ -170,6 +171,7 @@ static void create_share_mode_entry(struct share_mode_entry *out, out->id.extid = in->extid; out->uid = (uint32)geteuid(); out->flags = 0; + out->name_hash = name_hash; } /* @@ -261,6 +263,26 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, return list_num; } +static uint32_t smb_name_hash(const char *sharepath, const char *filename, int *err) +{ + TDB_DATA key; + char *fullpath = NULL; + int ret; + uint32_t name_hash; + + *err = 0; + ret = asprintf(&fullpath, "%s/%s", sharepath, filename); + if (ret == -1 || fullpath == NULL) { + *err = 1; + return 0; + } + key.dptr = (uint8_t *)fullpath; + key.dsize = strlen(fullpath); + name_hash = tdb_jenkins_hash(&key); + free(fullpath); + return name_hash; +} + /* * Create an entry in the Samba share mode db. */ @@ -281,6 +303,12 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, struct share_mode_entry *shares = NULL; uint8 *new_data_p = NULL; size_t new_data_size = 0; + int err = 0; + uint32_t name_hash = smb_name_hash(sharepath, filename, &err); + + if (err) { + return -1; + } db_data = tdb_fetch(db_ctx->smb_tdb, locking_key); if (!db_data.dptr) { @@ -299,7 +327,7 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, ld->u.s.delete_on_close = 0; ld->u.s.delete_token_size = 0; shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data)); - create_share_mode_entry(shares, new_entry); + create_share_mode_entry(shares, new_entry, name_hash); memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry), sharepath, @@ -338,7 +366,7 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx, shares = (struct share_mode_entry *)(new_data_p + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry))); - create_share_mode_entry(shares, new_entry); + create_share_mode_entry(shares, new_entry, name_hash); ld = (struct locking_data *)new_data_p; ld->u.s.num_share_mode_entries++; @@ -521,7 +549,7 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx, } if (share_mode_entry_equal(set_entry, share)) { - create_share_mode_entry(share, new_entry); + create_share_mode_entry(share, new_entry, share->name_hash); found_entry = 1; break; } diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4a61953176..a65fcbdba8 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -492,7 +492,7 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e) return talloc_asprintf(ctx, "share_mode_entry[%d]: %s " "pid = %s, share_access = 0x%x, private_options = 0x%x, " "access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %lu, " - "uid = %u, flags = %u, file_id %s", + "uid = %u, flags = %u, file_id %s, name_hash = 0x%x", num, e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "", procid_str_static(&e->pid), @@ -500,7 +500,8 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e) e->access_mask, (unsigned long long)e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->uid, (unsigned int)e->flags, - file_id_string_tos(&e->id)); + file_id_string_tos(&e->id), + (unsigned int)e->name_hash); } /******************************************************************* @@ -953,6 +954,8 @@ 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, + uint32_t orig_name_hash, + uint32_t new_name_hash, const struct smb_filename *smb_fname_dst) { size_t sp_len; @@ -1018,6 +1021,15 @@ bool rename_share_filename(struct messaging_context *msg_ctx, if (!is_valid_share_mode_entry(se)) { continue; } + + /* If this is a hardlink to the inode + with a different name, skip this. */ + if (se->name_hash != orig_name_hash) { + continue; + } + + se->name_hash = new_name_hash; + /* But not to ourselves... */ if (procid_is_me(&se->pid)) { continue; @@ -1125,6 +1137,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e, e->share_file_id = fsp->fh->gen_id; e->uid = (uint32)uid; e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0; + e->name_hash = fsp->name_hash; } static void fill_deferred_open_entry(struct share_mode_entry *e, diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 6f4d5780f3..e92fbd43af 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -873,6 +873,7 @@ void share_mode_entry_to_message(char *msg, const struct share_mode_entry *e) SIVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET,e->share_file_id); SIVAL(msg,OP_BREAK_MSG_UID_OFFSET,e->uid); SSVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET,e->flags); + SIVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET,e->name_hash); #ifdef CLUSTER_SUPPORT SIVAL(msg,OP_BREAK_MSG_VNN_OFFSET,e->pid.vnn); #endif @@ -896,6 +897,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg) e->share_file_id = (unsigned long)IVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET); e->uid = (uint32)IVAL(msg,OP_BREAK_MSG_UID_OFFSET); e->flags = (uint16)SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET); + e->name_hash = IVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET); #ifdef CLUSTER_SUPPORT e->pid.vnn = IVAL(msg,OP_BREAK_MSG_VNN_OFFSET); #endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0c3b8980b2..92be257029 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5804,11 +5804,13 @@ static bool resolve_wildcards(TALLOC_CTX *ctx, static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck, + uint32_t orig_name_hash, const struct smb_filename *smb_fname_dst) { files_struct *fsp; bool did_rename = False; NTSTATUS status; + uint32_t new_name_hash; for(fsp = file_find_di_first(conn->sconn, lck->id); fsp; fsp = file_find_di_next(fsp)) { @@ -5819,6 +5821,9 @@ static void rename_open_files(connection_struct *conn, if (!strequal(fsp->conn->connectpath, conn->connectpath)) { continue; } + if (fsp->name_hash != orig_name_hash) { + continue; + } DEBUG(10, ("rename_open_files: renaming file fnum %d " "(file_id %s) from %s -> %s\n", fsp->fnum, file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp), @@ -5827,6 +5832,7 @@ static void rename_open_files(connection_struct *conn, status = fsp_set_smb_fname(fsp, smb_fname_dst); if (NT_STATUS_IS_OK(status)) { did_rename = True; + new_name_hash = fsp->name_hash; } } @@ -5838,6 +5844,7 @@ static void rename_open_files(connection_struct *conn, /* Send messages to all smbd's (not ourself) that the name has changed. */ rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath, + orig_name_hash, new_name_hash, smb_fname_dst); } @@ -6147,7 +6154,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, notify_rename(conn, fsp->is_directory, fsp->fsp_name, smb_fname_dst); - rename_open_files(conn, lck, smb_fname_dst); + rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst); /* * A rename acts as a new file create w.r.t. allowing an initial delete |