From ebad4278b72289f10ce7afa72a137f5e3e998b01 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 11 Jul 1998 01:25:02 +0000 Subject: nntrans.c: Fully implemented transact rename. reply.c: Added NT specific rename if exists flag to rename_internals(). smb.h: Added NT rename flag. Jeremy. (This used to be commit b398f7daf58459db6e8d3496502abeb634ac2183) --- source3/include/proto.h | 2 +- source3/include/smb.h | 3 +++ source3/smbd/nttrans.c | 19 ++++++++++++++++--- source3/smbd/reply.c | 27 ++++++++++++++++++++++++--- 4 files changed, 44 insertions(+), 7 deletions(-) (limited to 'source3') 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); -- cgit