From 44732734cca2328a8aceb2db9b577c923920f644 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Jan 2011 14:23:19 -0800 Subject: Fix bug #7863 - Unlink may unlink wrong file when hardlinks are involved. Do this by keeping a linked list of delete on close tokens, one for each filename that identifies a path to the dev/inode. Use the jenkins hash of the pathname to identify the correct token. --- source3/smbd/trans2.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'source3/smbd/trans2.c') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 60664fd229..5865d05e44 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5103,7 +5103,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); - get_file_infos(fileid, 0, &delete_pending, &write_time_ts); + get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts); } else { /* * Original code - this is an open file. @@ -5120,10 +5120,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn, return; } fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); - get_file_infos(fileid, 0, &delete_pending, &write_time_ts); + get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts); } } else { + uint32_t name_hash; char *fname = NULL; /* qpathinfo */ @@ -5210,10 +5211,19 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } } + status = file_name_hash(conn, + smb_fname_str_dbg(smb_fname_base), + &name_hash); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(smb_fname_base); + reply_nterror(req, status); + return; + } + fileid = vfs_file_id_from_sbuf(conn, &smb_fname_base->st); TALLOC_FREE(smb_fname_base); - get_file_infos(fileid, 0, &delete_pending, NULL); + get_file_infos(fileid, name_hash, &delete_pending, NULL); if (delete_pending) { reply_nterror(req, NT_STATUS_DELETE_PENDING); return; @@ -5244,8 +5254,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } } + status = file_name_hash(conn, + smb_fname_str_dbg(smb_fname), + &name_hash); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); - get_file_infos(fileid, 0, &delete_pending, &write_time_ts); + get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts); if (delete_pending) { reply_nterror(req, NT_STATUS_DELETE_PENDING); return; -- cgit