as obelix would say "these romans are crazy"
authorAndrew Tridgell <tridge@samba.org>
Sun, 16 Jan 2000 12:26:42 +0000 (12:26 +0000)
committerAndrew Tridgell <tridge@samba.org>
Sun, 16 Jan 2000 12:26:42 +0000 (12:26 +0000)
I've finally got the access table code right for the case where the
two opens are on the same connection. It is _incredibly_ complex, but
now all 1296 test cases pass.

I'll be very surprised if anyone by MS and us gets this right at
CIFS2000

source/smbd/open.c

index 7558954ec6b938fead83edac3715a88a2ce80056..d0a48ced4b33d874bcf383b076e90e1cd53fd2bb 100644 (file)
@@ -623,15 +623,49 @@ reproduce the share mode access table
 static int access_table(int new_deny,int old_deny,int old_mode,
                        pid_t share_pid,char *fname)
 {
-  if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
-
-  if (old_deny == DENY_DOS || new_deny == DENY_DOS || 
-      old_deny == DENY_FCB || new_deny == DENY_FCB) {
+         pid_t pid = getpid();
+         BOOL isexe = False;
+         
          if ((fname = strrchr(fname,'.'))) {
                  if (strequal(fname,".com") ||
                      strequal(fname,".dll") ||
                      strequal(fname,".exe") ||
                      strequal(fname,".sym")) {
+                         isexe = True;
+                 }
+         }
+
+         if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
+
+         if (share_pid == pid) {
+                 if (isexe && old_mode == O_RDONLY && 
+                     old_deny == DENY_DOS && new_deny == DENY_READ) {
+                         return AFAIL;
+                 }
+                 if (!isexe && old_mode == O_RDONLY && 
+                     old_deny == DENY_DOS && new_deny == DENY_DOS) {
+                         return AREAD;
+                 }
+                 if (new_deny == DENY_FCB && old_deny == DENY_DOS) {
+                         if (isexe) return AFAIL;
+                         if (old_mode == DOS_OPEN_RDONLY) return AFAIL;
+                         return AALL;
+                 }
+                 if (old_mode == O_RDONLY && old_deny == DENY_DOS) {
+                         if (new_deny == DENY_FCB || new_deny == DENY_READ) {
+                                 if (isexe) return AREAD;
+                                 return AFAIL;
+                         }
+                 }
+                 if (old_deny == DENY_FCB) {
+                         if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL;
+                         return AFAIL;
+                 }
+         }
+
+         if (old_deny == DENY_DOS || new_deny == DENY_DOS || 
+             old_deny == DENY_FCB || new_deny == DENY_FCB) {
+                 if (isexe) {
                          if (old_deny == DENY_FCB || new_deny == DENY_FCB) {
                                  return AFAIL;
                          }
@@ -652,10 +686,7 @@ static int access_table(int new_deny,int old_deny,int old_mode,
                          if (old_deny == DENY_READ) return AWRITE;
                          if (old_deny == DENY_WRITE) return AREAD;
                  }
-         }
-         /* it isn't a exe, dll, sym or com file */
-         {
-                 pid_t pid = getpid();
+                 /* it isn't a exe, dll, sym or com file */
                  if (old_deny == new_deny && share_pid == pid) 
                          return(AALL);    
 
@@ -664,27 +695,26 @@ static int access_table(int new_deny,int old_deny,int old_mode,
                  
                  return(AFAIL);
          }
-  }
-
-  switch (new_deny) 
-    {
-    case DENY_WRITE:
-      if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD);
-      if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE);
-      if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL);
-      return(AFAIL);
-    case DENY_READ:
-      if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD);
-      if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE);
-      if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL);
-      return(AFAIL);
-    case DENY_NONE:
-      if (old_deny==DENY_WRITE) return(AREAD);
-      if (old_deny==DENY_READ) return(AWRITE);
-      if (old_deny==DENY_NONE) return(AALL);
-      return(AFAIL);      
-    }
-  return(AFAIL);      
+         
+         switch (new_deny) 
+                 {
+                 case DENY_WRITE:
+                         if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD);
+                         if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE);
+                         if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL);
+                         return(AFAIL);
+                 case DENY_READ:
+                         if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD);
+                         if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE);
+                         if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL);
+                         return(AFAIL);
+                 case DENY_NONE:
+                         if (old_deny==DENY_WRITE) return(AREAD);
+                         if (old_deny==DENY_READ) return(AWRITE);
+                         if (old_deny==DENY_NONE) return(AALL);
+                         return(AFAIL);      
+                 }
+         return(AFAIL);      
 }
 
 /****************************************************************************
@@ -712,17 +742,6 @@ static int check_share_mode( share_mode_entry *share, int deny_mode,
     return False;
   }
 
-  if (old_deny_mode > 4 || old_open_mode > 2)
-  {
-    DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
-               deny_mode,old_deny_mode,old_open_mode,fname));
-
-    unix_ERR_class = ERRDOS;
-    unix_ERR_code = ERRbadshare;
-
-    return False;
-  }
-
   {
     int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
                                      share->pid,fname);