diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/nttrans.c | 19 | ||||
-rw-r--r-- | source3/smbd/reply.c | 27 |
2 files changed, 40 insertions, 6 deletions
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); |