mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +03:00
Added client "hardlink" commant to test doing NT rename with hard links.
Added hardlink_internals() code - UNIX extensions now use this too. Jeremy. (This used to be commit aad6eb2240393931940c982e25a981ce32264f38)
This commit is contained in:
parent
fba5a72249
commit
f0039da196
@ -1773,13 +1773,11 @@ static int cmd_rename(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
This will become a hard link call. JRA.
|
||||
/****************************************************************************
|
||||
Rename some file using the NT call.
|
||||
Hard link files using the NT call.
|
||||
****************************************************************************/
|
||||
|
||||
static int cmd_ntrename(void)
|
||||
static int cmd_hardlink(void)
|
||||
{
|
||||
pstring src,dest;
|
||||
fstring buf,buf2;
|
||||
@ -1789,21 +1787,20 @@ static int cmd_ntrename(void)
|
||||
|
||||
if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
|
||||
!next_token_nr(NULL,buf2,NULL, sizeof(buf2))) {
|
||||
d_printf("ntrename <src> <dest>\n");
|
||||
d_printf("hardlink <src> <dest>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pstrcat(src,buf);
|
||||
pstrcat(dest,buf2);
|
||||
|
||||
if (!cli_ntrename(cli, src, dest)) {
|
||||
d_printf("%s doing an NT rename of files\n",cli_errstr(cli));
|
||||
if (!cli_nt_hardlink(cli, src, dest)) {
|
||||
d_printf("%s doing an NT hard link of files\n",cli_errstr(cli));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
Toggle the prompt flag.
|
||||
@ -2191,6 +2188,7 @@ static struct
|
||||
{"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
|
||||
{"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
|
||||
{"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
|
||||
{"hardlink",cmd_hardlink,"<src> <dest> create a Windows hard link",{COMPL_REMOTE,COMPL_REMOTE}},
|
||||
{"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
|
||||
{"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
|
||||
{"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
|
||||
@ -2204,10 +2202,6 @@ static struct
|
||||
{"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},
|
||||
{"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
|
||||
{"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
|
||||
#if 0
|
||||
/* This call will eventually morph into a hard link call. JRA */
|
||||
{"ntrename",cmd_ntrename,"<src> <dest> NT rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
|
||||
#endif
|
||||
{"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
|
||||
{"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
|
||||
{"printmode",cmd_printmode,"<graphics or text> set the print mode",{COMPL_NONE,COMPL_NONE}},
|
||||
|
@ -36,16 +36,18 @@ static BOOL cli_link_internal(struct cli_state *cli, const char *fname_src, cons
|
||||
pstring data;
|
||||
char *rparam=NULL, *rdata=NULL;
|
||||
char *p;
|
||||
size_t srclen = 2*(strlen(fname_src)+1);
|
||||
size_t destlen = 2*(strlen(fname_dst) + 1);
|
||||
|
||||
memset(param, 0, sizeof(param));
|
||||
SSVAL(param,0,hard_link ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
|
||||
p = ¶m[6];
|
||||
|
||||
p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
|
||||
p += clistr_push(cli, p, fname_src, MIN(srclen, sizeof(param)-6), STR_TERMINATE);
|
||||
param_len = PTR_DIFF(p, param);
|
||||
|
||||
p = data;
|
||||
p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
|
||||
p += clistr_push(cli, p, fname_dst, MIN(destlen,sizeof(data)), STR_TERMINATE);
|
||||
data_len = PTR_DIFF(p, data);
|
||||
|
||||
if (!cli_send_trans(cli, SMBtrans2,
|
||||
@ -261,6 +263,44 @@ BOOL cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fnam
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
NT hardlink a file.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
|
||||
{
|
||||
char *p;
|
||||
|
||||
memset(cli->outbuf,'\0',smb_size);
|
||||
memset(cli->inbuf,'\0',smb_size);
|
||||
|
||||
set_message(cli->outbuf, 4, 0, True);
|
||||
|
||||
SCVAL(cli->outbuf,smb_com,SMBntrename);
|
||||
SSVAL(cli->outbuf,smb_tid,cli->cnum);
|
||||
cli_setup_packet(cli);
|
||||
|
||||
SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN | aDIR);
|
||||
SSVAL(cli->outbuf,smb_vwv1, RENAME_FLAG_HARD_LINK);
|
||||
|
||||
p = smb_buf(cli->outbuf);
|
||||
*p++ = 4;
|
||||
p += clistr_push(cli, p, fname_src, -1, STR_TERMINATE);
|
||||
*p++ = 4;
|
||||
p += clistr_push(cli, p, fname_dst, -1, STR_TERMINATE);
|
||||
|
||||
cli_setup_bcc(cli, p);
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
|
||||
if (cli_is_error(cli))
|
||||
return False;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Delete a file.
|
||||
****************************************************************************/
|
||||
|
@ -1521,7 +1521,7 @@ int reply_ntrename(connection_struct *conn,
|
||||
|
||||
START_PROFILE(SMBntrename);
|
||||
|
||||
if (rename_type != RENAME_FLAG_RENAME) {
|
||||
if ((rename_type != RENAME_FLAG_RENAME) && (rename_type != RENAME_FLAG_HARD_LINK)) {
|
||||
END_PROFILE(SMBntrename);
|
||||
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
|
||||
}
|
||||
@ -1551,7 +1551,12 @@ int reply_ntrename(connection_struct *conn,
|
||||
|
||||
DEBUG(3,("reply_ntrename : %s -> %s\n",name,newname));
|
||||
|
||||
status = rename_internals(conn, name, newname, attrs, False);
|
||||
if (rename_type == RENAME_FLAG_RENAME) {
|
||||
status = rename_internals(conn, name, newname, attrs, False);
|
||||
} else {
|
||||
status = hardlink_internals(conn, name, newname);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
END_PROFILE(SMBntrename);
|
||||
return ERROR_NT(status);
|
||||
|
@ -2477,6 +2477,82 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Set a hard link (called by UNIX extensions and by NT rename with HARD link
|
||||
code.
|
||||
****************************************************************************/
|
||||
|
||||
NTSTATUS hardlink_internals(connection_struct *conn, char *name, char *newname)
|
||||
{
|
||||
BOOL bad_path_src = False;
|
||||
BOOL bad_path_dest = False;
|
||||
SMB_STRUCT_STAT sbuf1, sbuf2;
|
||||
BOOL rc, rcdest;
|
||||
pstring last_component_src;
|
||||
pstring last_component_dest;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
|
||||
ZERO_STRUCT(sbuf1);
|
||||
ZERO_STRUCT(sbuf2);
|
||||
|
||||
/* No wildcards. */
|
||||
if (ms_has_wild(name) || ms_has_wild(newname)) {
|
||||
return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
|
||||
}
|
||||
|
||||
rc = unix_convert(name,conn,last_component_src,&bad_path_src,&sbuf1);
|
||||
if (!rc && bad_path_src) {
|
||||
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Quick check for "." and ".." */
|
||||
if (last_component_src[0] == '.') {
|
||||
if (!last_component_src[1] || (last_component_src[1] == '.' && !last_component_src[2])) {
|
||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* source must already exist. */
|
||||
if (!VALID_STAT(sbuf1)) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
rcdest = unix_convert(newname,conn,last_component_dest,&bad_path_dest,&sbuf2);
|
||||
if (!rcdest && bad_path_dest) {
|
||||
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Quick check for "." and ".." */
|
||||
if (last_component_dest[0] == '.') {
|
||||
if (!last_component_dest[1] || (last_component_dest[1] == '.' && !last_component_dest[2])) {
|
||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disallow if already exists. */
|
||||
if (VALID_STAT(sbuf2)) {
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
/* No links from a directory. */
|
||||
if (S_ISDIR(sbuf1.st_mode)) {
|
||||
return NT_STATUS_FILE_IS_A_DIRECTORY;
|
||||
}
|
||||
|
||||
if (ensure_link_is_safe(conn, newname, newname) != 0)
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
|
||||
DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", name, newname ));
|
||||
|
||||
if (SMB_VFS_LINK(conn,name,newname) != 0) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
DEBUG(3,("hardlink_internals: Error %s link %s -> %s\n",
|
||||
nt_errstr(status), name,newname));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a TRANS2_SETFILEINFO (set file info by fileid).
|
||||
****************************************************************************/
|
||||
@ -2964,10 +3040,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
if (!lp_symlinks(SNUM(conn)))
|
||||
return(ERROR_DOS(ERRDOS,ERRnoaccess));
|
||||
|
||||
/* Disallow if already exists. */
|
||||
if (VALID_STAT(sbuf))
|
||||
return(ERROR_DOS(ERRDOS,ERRbadpath));
|
||||
|
||||
srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
@ -2991,24 +3063,19 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
pstring link_dest;
|
||||
|
||||
/* Set a hard link. */
|
||||
|
||||
/* Disallow if already exists. */
|
||||
if (VALID_STAT(sbuf))
|
||||
return(ERROR_DOS(ERRDOS,ERRbadpath));
|
||||
|
||||
srvstr_get_path(inbuf, link_dest, pdata, sizeof(link_dest), -1, STR_TERMINATE, &status);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
if (ensure_link_is_safe(conn, link_dest, link_dest) != 0)
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
|
||||
DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
|
||||
fname, link_dest ));
|
||||
|
||||
if (SMB_VFS_LINK(conn,link_dest,fname) != 0)
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
status = hardlink_internals(conn, fname, link_dest);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
SSVAL(params,0,0);
|
||||
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
|
||||
return(-1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user