mirror of
https://github.com/samba-team/samba.git
synced 2025-02-26 21:57:41 +03:00
Implement missing info level SMB_FILE_LINK_INFORMATION.
Fix bug #7435 - SMB2 hardlink fails (invalid level). Found at the Microsoft plugsharing plugfest. Jeremy.
This commit is contained in:
parent
c7982074a7
commit
572e5dec1b
@ -6368,8 +6368,10 @@ void send_trans2_replies(connection_struct *conn,
|
||||
unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16]);
|
||||
NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
|
||||
connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
bool overwrite_if_exists,
|
||||
const struct smb_filename *smb_fname_old,
|
||||
const struct smb_filename *smb_fname_new);
|
||||
struct smb_filename *smb_fname_new);
|
||||
NTSTATUS smb_set_file_time(connection_struct *conn,
|
||||
files_struct *fsp,
|
||||
const struct smb_filename *smb_fname,
|
||||
|
@ -1550,6 +1550,8 @@ void reply_ntrename(struct smb_request *req)
|
||||
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
|
||||
} else {
|
||||
status = hardlink_internals(ctx, conn,
|
||||
req,
|
||||
false,
|
||||
smb_fname_old,
|
||||
smb_fname_new);
|
||||
}
|
||||
|
@ -5348,8 +5348,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
|
||||
|
||||
NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
|
||||
connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
bool overwrite_if_exists,
|
||||
const struct smb_filename *smb_fname_old,
|
||||
const struct smb_filename *smb_fname_new)
|
||||
struct smb_filename *smb_fname_new)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
|
||||
@ -5358,9 +5360,23 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Disallow if newname already exists. */
|
||||
if (VALID_STAT(smb_fname_new->st)) {
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
if (overwrite_if_exists) {
|
||||
if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
|
||||
return NT_STATUS_FILE_IS_A_DIRECTORY;
|
||||
}
|
||||
status = unlink_internals(conn,
|
||||
req,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
smb_fname_new,
|
||||
false);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
/* Disallow if newname already exists. */
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
}
|
||||
|
||||
/* No links from a directory. */
|
||||
@ -5870,7 +5886,7 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
|
||||
static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
const char *pdata, int total_data,
|
||||
const struct smb_filename *smb_fname_new)
|
||||
struct smb_filename *smb_fname_new)
|
||||
{
|
||||
char *oldname = NULL;
|
||||
struct smb_filename *smb_fname_old = NULL;
|
||||
@ -5902,7 +5918,8 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
|
||||
return status;
|
||||
}
|
||||
|
||||
return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
|
||||
return hardlink_internals(ctx, conn, req, false,
|
||||
smb_fname_old, smb_fname_new);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -6006,6 +6023,75 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS smb_file_link_information(connection_struct *conn,
|
||||
struct smb_request *req,
|
||||
const char *pdata,
|
||||
int total_data,
|
||||
files_struct *fsp,
|
||||
struct smb_filename *smb_fname_src)
|
||||
{
|
||||
bool overwrite;
|
||||
uint32_t len;
|
||||
char *newname = NULL;
|
||||
struct smb_filename *smb_fname_dst = NULL;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
|
||||
if (!fsp) {
|
||||
return NT_STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (total_data < 20) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
overwrite = (CVAL(pdata,0) ? true : false);
|
||||
len = IVAL(pdata,16);
|
||||
|
||||
if (len > (total_data - 20) || (len == 0)) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
srvstr_get_path(ctx, pdata, req->flags2, &newname,
|
||||
&pdata[20], len, STR_TERMINATE,
|
||||
&status);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_file_link_information: got name |%s|\n",
|
||||
newname));
|
||||
|
||||
status = filename_convert(ctx,
|
||||
conn,
|
||||
req->flags2 & FLAGS2_DFS_PATHNAMES,
|
||||
newname,
|
||||
0,
|
||||
NULL,
|
||||
&smb_fname_dst);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (fsp->base_fsp) {
|
||||
/* No stream names. */
|
||||
return NT_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_file_link_information: "
|
||||
"SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
|
||||
fsp->fnum, fsp_str_dbg(fsp),
|
||||
smb_fname_str_dbg(smb_fname_dst)));
|
||||
status = hardlink_internals(ctx,
|
||||
conn,
|
||||
req,
|
||||
overwrite,
|
||||
fsp->fsp_name,
|
||||
smb_fname_dst);
|
||||
|
||||
TALLOC_FREE(smb_fname_dst);
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Deal with SMB_FILE_RENAME_INFORMATION.
|
||||
@ -7609,6 +7695,14 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
|
||||
break;
|
||||
}
|
||||
|
||||
case SMB_FILE_LINK_INFORMATION:
|
||||
{
|
||||
status = smb_file_link_information(conn, req,
|
||||
pdata, total_data,
|
||||
fsp, smb_fname);
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(HAVE_POSIX_ACLS)
|
||||
case SMB_SET_POSIX_ACL:
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user