summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h2
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/smbd/nttrans.c19
-rw-r--r--source3/smbd/reply.c27
4 files changed, 44 insertions, 7 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 2c377bfb56..6d9d083bc1 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1779,7 +1779,7 @@ int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
-int rename_internals(char *inbuf, char *outbuf, char *name, char *newname);
+int rename_internals(char *inbuf, char *outbuf, char *name, char *newname, BOOL replace_if_exists);
int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 697caa349d..e58fcc034d 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1118,6 +1118,9 @@ struct parm_struct
#define OPEN_ALWAYS 4
#define TRUNCATE_EXISTING 5
+/* Flag for NT transact rename call. */
+#define RENAME_REPLACE_IF_EXISTS 1
+
/* Filesystem Attributes. */
#define FILE_CASE_SENSITIVE_SEARCH 0x1
#define FILE_CASE_PRESERVED_NAMES 0x2
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index c452e945c7..fa47bc7a17 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -469,6 +469,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
set_posix_case_semantics(file_attributes);
StrnCpy(fname,smb_buf(inbuf),fname_len);
+ fname[fname_len] = '\0';
unix_convert(fname,cnum,0,&bad_path);
fnum = find_free_file();
@@ -622,6 +623,7 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int c
set_posix_case_semantics(file_attributes);
StrnCpy(fname,params+53,fname_len);
+ fname[fname_len] = '\0';
unix_convert(fname,cnum,0,&bad_path);
fnum = find_free_file();
@@ -753,16 +755,27 @@ static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int c
{
char *params = *pparams;
pstring new_name;
- pstring old_name;
int fnum = SVAL(params, 0);
- uint16 rename_flags = SVAL(params,2);
+ BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)),
((uint32)sizeof(fname)-1));
+ int outsize = 0;
+ CHECK_FNUM(fnum, cnum);
StrnCpy(new_name,params+4,fname_len);
- unix_convert(new_name,cnum,0,&bad_path);
+ new_name[fname_len] = '\0';
+
+ outsize = rename_internals(inbuf, outbuf, Files[fnum].name, newname, replace_if_exists);
+ if(outsize == 0) {
+ /*
+ * Rename was successful.
+ */
+ send_nt_replies(outbuf, bufsize, NULL, 0, NULL, 0);
+ outsize = -1;
+ }
+ return(outsize);
}
/****************************************************************************
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index ec3ad84c9a..cb659e3ef9 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3156,7 +3156,7 @@ static BOOL can_rename(char *fname,int cnum)
code.
****************************************************************************/
-int rename_internals(char *inbuf, char *outbuf, char *name, char *newname)
+int rename_internals(char *inbuf, char *outbuf, char *name, char *newname, BOOL replace_if_exists)
{
int cnum;
pstring directory;
@@ -3203,6 +3203,9 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname)
has_wild = strchr(mask,'*') || strchr(mask,'?');
if (!has_wild) {
+ /*
+ * No wildcards - just process the one file.
+ */
BOOL is_short_name = is_8_3(name, True);
/* Add a terminating '/' to the directory name. */
@@ -3253,6 +3256,18 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname)
}
}
+ if(replace_if_exists) {
+ /*
+ * NT SMB specific flag - we must remove a target
+ * file with the same name before continuing.
+ */
+ if(resolve_wildcards(directory,newname) &&
+ can_rename(directory,cnum) &&
+ file_exist(newname,NULL)) {
+ sys_unlink(newname);
+ }
+ }
+
if (resolve_wildcards(directory,newname) &&
can_rename(directory,cnum) &&
!file_exist(newname,NULL) &&
@@ -3268,6 +3283,9 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname)
error = 183;
}
} else {
+ /*
+ * Wildcards - process each file that matches.
+ */
void *dirptr = NULL;
char *dname;
pstring destname;
@@ -3301,11 +3319,14 @@ int rename_internals(char *inbuf, char *outbuf, char *name, char *newname)
continue;
}
- if (file_exist(destname,NULL)) {
+ if (replace_if_exists && file_exist(destname,NULL)) {
+ sys_unlink(destname);
+ } else if(file_exist(destname,NULL)) {
DEBUG(6,("file_exist %s\n", destname));
error = 183;
continue;
}
+
if (!sys_rename(fname,destname))
count++;
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
@@ -3344,7 +3365,7 @@ int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
- outsize = rename_internals(inbuf, outbuf, name, newname);
+ outsize = rename_internals(inbuf, outbuf, name, newname, False);
if(outsize == 0)
outsize = set_message(outbuf,0,0,True);