Added an extra parameter for unix_convert. If present this is the
authorSamba Release Account <samba-bugs@samba.org>
Mon, 13 Jan 1997 19:41:08 +0000 (19:41 +0000)
committerSamba Release Account <samba-bugs@samba.org>
Mon, 13 Jan 1997 19:41:08 +0000 (19:41 +0000)
last component of the modified pathname before modification. This
is needed due to an exceptional condition in reply_mv when the
filesystem is case preserving, but not case sensitive and the
user wants to change the case of a filename. Code for this is
also added to reply.c
Jeremy (jra@cygnus.com).
(This used to be commit cdafa35f9dba6eb0073700e3a214348c432a3e84)

source3/include/proto.h
source3/smbd/pipes.c
source3/smbd/reply.c
source3/smbd/server.c
source3/smbd/trans2.c

index bbe74e32702933469cfadade444fdd7db6597da2..7f6c7d38929fff0fa381181a1597c183719d360a 100644 (file)
@@ -662,7 +662,7 @@ int reply_getattrE(char *inbuf,char *outbuf);
 mode_t unix_mode(int cnum,int dosmode);
 int dos_mode(int cnum,char *path,struct stat *sbuf);
 int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st);
-BOOL unix_convert(char *name,int cnum);
+BOOL unix_convert(char *name,int cnum,char *);
 int disk_free(char *path,int *bsize,int *dfree,int *dsize);
 int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize);
 BOOL check_name(char *name,int cnum);
index cb498a619547b113034e821e0b5c312d9266d1b5..efa6a68b9d736eaad7406b704b7d4b1e8502df9a 100644 (file)
@@ -114,7 +114,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   Connections[cnum].read_only = 0;
   smb_ofun |= 0x10;            /* Add Create it not exists flag */
 
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
     
   fnum = find_free_file();
   if (fnum < 0)
index 812618b2c70ca81db4c2d5f6b6979f9163d04679..3698787ba462f304bce843b363c3bc6c6a614b59 100644 (file)
@@ -36,6 +36,7 @@ extern char magic_char;
 extern connection_struct Connections[];
 extern files_struct Files[];
 extern BOOL case_sensitive;
+extern BOOL case_preserve;
 extern pstring sesssetup_user;
 extern int Client;
 
@@ -528,7 +529,7 @@ int reply_chkpth(char *inbuf,char *outbuf)
   cnum = SVAL(inbuf,smb_tid);
   
   strcpy(name,smb_buf(inbuf) + 1);
-  unix_convert(name,cnum);
+  unix_convert(name,cnum,0);
 
   mode = SVAL(inbuf,smb_vwv0);
 
@@ -563,7 +564,7 @@ int reply_getatr(char *inbuf,char *outbuf)
   cnum = SVAL(inbuf,smb_tid);
 
   strcpy(fname,smb_buf(inbuf) + 1);
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
 
   /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
      under WfWg - weird! */
@@ -629,7 +630,7 @@ int reply_setatr(char *inbuf,char *outbuf)
   cnum = SVAL(inbuf,smb_tid);
   
   strcpy(fname,smb_buf(inbuf) + 1);
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
 
   mode = SVAL(inbuf,smb_vwv0);
   mtime = make_unix_date3(inbuf+smb_vwv1);
@@ -732,7 +733,7 @@ int reply_search(char *inbuf,char *outbuf)
 
       strcpy(directory,smb_buf(inbuf)+1);
       strcpy(dir2,smb_buf(inbuf)+1);
-      unix_convert(directory,cnum);
+      unix_convert(directory,cnum,0);
       unix_format(dir2);
 
       if (!check_name(directory,cnum))
@@ -966,7 +967,7 @@ int reply_open(char *inbuf,char *outbuf)
   share_mode = SVAL(inbuf,smb_vwv0);
 
   strcpy(fname,smb_buf(inbuf)+1);
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
     
   fnum = find_free_file();
   if (fnum < 0)
@@ -1042,7 +1043,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   /* XXXX we need to handle passed times, sattr and flags */
 
   strcpy(fname,smb_buf(inbuf));
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
     
   /* now add create and trunc bits */
   if (smb_ofun & 0x10)
@@ -1145,7 +1146,7 @@ int reply_mknew(char *inbuf,char *outbuf)
 
   createmode = SVAL(inbuf,smb_vwv0);
   strcpy(fname,smb_buf(inbuf)+1);
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
 
   if (createmode & aVOLID)
     {
@@ -1199,7 +1200,7 @@ int reply_ctemp(char *inbuf,char *outbuf)
   cnum = SVAL(inbuf,smb_tid);
   createmode = SVAL(inbuf,smb_vwv0);
   sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1);
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
   
   unixmode = unix_mode(cnum,createmode);
   
@@ -1281,7 +1282,7 @@ int reply_unlink(char *inbuf,char *outbuf)
    
   DEBUG(3,("reply_unlink : %s\n",name));
    
-  unix_convert(name,cnum);
+  unix_convert(name,cnum,0);
 
   p = strrchr(name,'/');
   if (!p) {
@@ -2393,7 +2394,7 @@ int reply_mkdir(char *inbuf,char *outbuf)
   
   strcpy(directory,smb_buf(inbuf) + 1);
   cnum = SVAL(inbuf,smb_tid);
-  unix_convert(directory,cnum);
+  unix_convert(directory,cnum,0);
   
   if (check_name(directory,cnum))
     ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
@@ -2421,7 +2422,7 @@ int reply_rmdir(char *inbuf,char *outbuf)
   
   cnum = SVAL(inbuf,smb_tid);
   strcpy(directory,smb_buf(inbuf) + 1);
-  unix_convert(directory,cnum);
+  unix_convert(directory,cnum,0);
   
   if (check_name(directory,cnum))
     {
@@ -2532,6 +2533,7 @@ int reply_mv(char *inbuf,char *outbuf)
   int cnum;
   pstring directory;
   pstring mask,newname;
+  pstring newname_last_component;
   char *p;
   int count=0;
   int error = ERRnoaccess;
@@ -2547,8 +2549,8 @@ int reply_mv(char *inbuf,char *outbuf)
    
   DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
    
-  unix_convert(name,cnum);
-  unix_convert(newname,cnum);
+  unix_convert(name,cnum,0);
+  unix_convert(newname,cnum,newname_last_component);
 
   p = strrchr(name,'/');
   if (!p) {
@@ -2558,6 +2560,7 @@ int reply_mv(char *inbuf,char *outbuf)
     *p = 0;
     strcpy(directory,name);
     strcpy(mask,p+1);
+    *p = '/'; /* Replace needed for exceptional test below. */
   }
 
   if (is_mangled(mask))
@@ -2568,10 +2571,50 @@ int reply_mv(char *inbuf,char *outbuf)
   if (!has_wild) {
     strcat(directory,"/");
     strcat(directory,mask);
+
+    DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, name = %s, newname = %s, newname_last_component = %s\n", case_sensitive, case_preserve, name, newname, newname_last_component));
+
+    /*
+     * Check for special case with case preserving and not
+     * case sensitive, if name and newname are identical,
+     * and the old last component differs from the original
+     * last component only by case, then we should allow
+     * the rename (user is trying to change the case of the
+     * filename).
+     */
+    if((case_sensitive == False) && (case_preserve == True) &&
+       strcsequal(name, newname)) {
+      pstring newname_modified_last_component;
+
+      /*
+       * Get the last component of the modified name.
+       */
+      p = strrchr(newname,'/');
+      if (!p)
+       strcpy(newname_modified_last_component,name);
+      else
+       strcpy(newname_modified_last_component,p+1);
+
+      if(strcsequal(newname_modified_last_component, 
+                   newname_last_component) == False) {
+       /*
+        * Replace the modified last component with
+        * the original.
+        */
+       if(p)
+         strcpy(p+1, newname_last_component);
+       else
+         strcpy(newname, newname_last_component);
+      }
+    }
+
     if (resolve_wildcards(directory,newname) && 
        can_rename(directory,cnum) && 
        !file_exist(newname,NULL) &&
        !sys_rename(directory,newname)) count++;
+
+    DEBUG(3,("reply_mv : doing rename on %s -> %s\n",directory,newname));
+
     if (!count) exists = file_exist(directory,NULL);
     if (!count && exists && file_exist(newname,NULL)) {
       exists = True;
@@ -2727,8 +2770,8 @@ int reply_copy(char *inbuf,char *outbuf)
     return(ERROR(ERRSRV,ERRinvdevice));
   }
 
-  unix_convert(name,cnum);
-  unix_convert(newname,cnum);
+  unix_convert(name,cnum,0);
+  unix_convert(newname,cnum,0);
 
   target_is_directory = directory_exist(newname,NULL);
 
index 75e7279e6daf0a28ac114751e56547b4ece507be..623a3fb2bdfc905324dc287615740e6e4c473e41 100644 (file)
@@ -378,14 +378,21 @@ for this service.
 
 The function will return False if some part of the name except for the last
 part cannot be resolved
+
+If the saved_last_component != 0, then the unmodified last component
+of the pathname is returned there. This is used in an exceptional
+case in reply_mv (so far). If saved_last_component == 0 then nothing
+is returned there.
 ****************************************************************************/
-BOOL unix_convert(char *name,int cnum)
+BOOL unix_convert(char *name,int cnum,pstring saved_last_component)
 {
   struct stat st;
   char *start, *end;
   pstring dirpath;
 
   *dirpath = 0;
+  if(saved_last_component)
+    *saved_last_component = 0;
 
   /* convert to basic unix format - removing \ chars and cleaning it up */
   unix_format(name);
@@ -415,6 +422,17 @@ BOOL unix_convert(char *name,int cnum)
       return(True);
     }
 
+  /*
+   * Ensure saved_last_component is valid even if file exists.
+   */
+  if(saved_last_component) {
+    end = strrchr(name, '/');
+    if(end)
+      strcpy(saved_last_component, end + 1);
+    else
+      strcpy(saved_last_component, name);
+  }
+
   /* stat the name - if it exists then we are all done! */
   if (sys_stat(name,&st) == 0)
     return(True);
@@ -442,7 +460,10 @@ BOOL unix_convert(char *name,int cnum)
       end = strchr(start, '/');
 
       /* chop the name at this point */
-      if (end) *end = 0;
+      if (end)         *end = 0;
+
+      if(saved_last_component != 0)
+       strcpy(saved_last_component, end ? end + 1 : start);
 
       /* check if the name exists up to this point */
       if (sys_stat(name, &st) == 0) 
@@ -467,7 +488,6 @@ BOOL unix_convert(char *name,int cnum)
             later */
          if (end) strcpy(rest,end+1);
 
-
          /* try to find this part of the path in the directory */
          if (strchr(start,'?') || strchr(start,'*') ||
              !scan_directory(dirpath, start, SNUM(cnum), end?True:False))
index b2bee17eead3709e5fdff75e5ba2f00637d3c7cb..94c4f26359eb333323eba114b983cc0c5e325cb9 100644 (file)
@@ -192,7 +192,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
 
   /* XXXX we need to handle passed times, sattr and flags */
 
-  unix_convert(fname,cnum);
+  unix_convert(fname,cnum,0);
     
   fnum = find_free_file();
   if (fnum < 0)
@@ -581,7 +581,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum
 
   DEBUG(5,("path=%s\n",directory));
 
-  unix_convert(directory,cnum);
+  unix_convert(directory,cnum,0);
   if(!check_name(directory,cnum)) {
     return(ERROR(ERRDOS,ERRbadpath));
   }
@@ -1024,7 +1024,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
     info_level = SVAL(params,0);
     fname = &fname1[0];
     strcpy(fname,&params[6]);
-    unix_convert(fname,cnum);
+    unix_convert(fname,cnum,0);
     if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
       return(UNIXERROR(ERRDOS,ERRbadpath));
@@ -1219,7 +1219,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
     info_level = SVAL(params,0);    
     fname = fname1;
     strcpy(fname,&params[6]);
-    unix_convert(fname,cnum);
+    unix_convert(fname,cnum,0);
     if(!check_name(fname, cnum))
       return(ERROR(ERRDOS,ERRbadpath));
     
@@ -1353,7 +1353,7 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
 
   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
 
-  unix_convert(directory,cnum);
+  unix_convert(directory,cnum,0);
   if (check_name(directory,cnum))
     ret = sys_mkdir(directory,unix_mode(cnum,aDIR));