access_table() challenge - win a Samba t-shirt!

Michael Glauche mg at plum.de
Sun Jan 16 21:44:07 GMT 2000


Andrew Tridgell wrote:
> 
> I've just spent quite some time re-doing our deny mode code in
> Samba. We now pass (ie. match NT4) on all possible deny mode
> combinations.
> The challenge now is to recode access_table() so that it is as small
> as possible. Right now it is horrendous, but I suspect there is an
> underlying pattern that I have missed.

I give up .. :) at least with the manual "shuffle around" tactics.
I found some simpifications, but the code doesn't look MUCH better 
now ... :( (code IS attached)

Anyone knows some Programs that can generate logics from a bit table ? 
(We have some 10 bit input and 2 bit output ....)
(btw .. 10 bits = 3 old deny, 3 new deny, 2 old_mode ,2 additional) 

IF you want that routine FAST, then we could use some logic arrary ...
:)
it is 1024 bytes small (2^10 = 1024 :)
BUT the code would be MUCH less readable then ...

After writing some rows of that 1024 byte table, I think some optimizion 
potental lives in the ORDER of the enums : 
that line : (old_deny == DENY_DOS || new_deny == DENY_DOS ||
              old_deny == DENY_FCB || new_deny == DENY_FCB) 

Give DENY_DOS = 000 (bit) and DENY_FCB = 100 (bit) then you can use :
((old_entry & 3) == 0) || (new_entry & 3) == 0) 

regards,
   Michael

-- 
Samba NT-Domain howto (in german)
http://www.sambahq.de
-------------- next part --------------
#include <stdio.h>

enum {DENY_DOS, DENY_READ, DENY_WRITE, DENY_FCB, DENY_ALL, DENY_NONE};
enum {AFAIL,AREAD,AWRITE,AALL};
enum {DOS_OPEN_RDONLY, DOS_OPEN_RDWR, DOS_OPEN_WRONLY};
#define BOOL int

/*******************************************************************
reproduce the share mode access table
this is horrendoously complex, and really can't be justified on any
rational grounds except that this is _exactly_ what NT does. See
the DENY1 and DENY2 tests in smbtorture for a comprehensive set of
test routines.
********************************************************************/
static int access_table1(int new_deny,int old_deny,int old_mode,
			 BOOL same_pid, BOOL isexe)
{
	  if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);

	  if (same_pid) {
		  if (isexe && old_mode == DOS_OPEN_RDONLY && 
		      old_deny == DENY_DOS && new_deny == DENY_READ) {
			  return AFAIL;
		  }
		  if (!isexe && old_mode == DOS_OPEN_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 == DOS_OPEN_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;
			  }
			  if (old_deny == DENY_DOS) {
				  if (new_deny == DENY_READ && 
				      (old_mode == DOS_OPEN_RDONLY || 
				       old_mode == DOS_OPEN_RDWR)) {
					  return AFAIL;
				  }
				  if (new_deny == DENY_WRITE && 
				      (old_mode == DOS_OPEN_WRONLY || 
				       old_mode == DOS_OPEN_RDWR)) {
					  return AFAIL;
				  }
				  return AALL;
			  }
			  if (old_deny == DENY_NONE) return AALL;
			  if (old_deny == DENY_READ) return AWRITE;
			  if (old_deny == DENY_WRITE) return AREAD;
		  }
		  /* it isn't a exe, dll, sym or com file */
		  if (old_deny == new_deny && same_pid)
			  return(AALL);    

		  if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL;
		  if (old_mode == DOS_OPEN_RDONLY) return(AREAD);
		  
		  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);      
}



static int access_table2(int new_deny,int old_deny,int old_mode,
			 BOOL same_pid, BOOL isexe)
{
	  if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);

	  if (same_pid) {
		  if (old_deny == DENY_DOS) {
			  if (!isexe && old_mode == DOS_OPEN_RDONLY && 
			    new_deny == DENY_DOS) {
				  return AREAD;
			  }
			  if (new_deny == DENY_FCB) {
				  if (isexe) return AFAIL;
				  if (old_mode == DOS_OPEN_RDONLY) return AFAIL;
				  return AALL;
			  }
		 	  if (old_deny == new_deny)
			  	return(AALL);    
		  }
		  if (old_deny == DENY_FCB) {
			  if ((new_deny == DENY_DOS || new_deny == DENY_FCB) ) return AALL;
			  return AFAIL;
		  }
	  }

	  if (isexe) {
	  	if (old_deny == DENY_DOS ) {
			if (new_deny == DENY_WRITE && (old_mode == DOS_OPEN_WRONLY ||  old_mode == DOS_OPEN_RDWR)) {
				return AFAIL;
			}
			if (new_deny == DENY_READ && (old_mode == DOS_OPEN_RDONLY || old_mode == DOS_OPEN_RDWR)) {
				return AFAIL;
			}
		}
		
		if (old_deny == DENY_FCB || new_deny == DENY_FCB) {
			  return AFAIL;
		}
		if (old_deny == DENY_DOS || new_deny == DENY_DOS ||
		   old_deny == DENY_FCB || new_deny == DENY_FCB) {
		       
			if (old_deny == DENY_DOS || old_deny == DENY_NONE) {
					  return AALL;
			}
			if (old_deny == DENY_READ) return AWRITE;
			if (old_deny == DENY_WRITE) return AREAD;
		}

	  }

	  if (old_deny == DENY_DOS || new_deny == DENY_DOS || 
	      old_deny == DENY_FCB || new_deny == DENY_FCB) {
		  /* it isn't a exe, dll, sym or com file */

		  if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL;
		  if (old_mode == DOS_OPEN_RDONLY) return(AREAD);
		  
		  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);      
}



main()
{
	int od, nd, om, sp, ie;

	for (od=DENY_DOS;od <= DENY_NONE; od++)
	for (nd=DENY_DOS;nd <= DENY_NONE; nd++)
	for (om=DOS_OPEN_RDONLY;om <= DOS_OPEN_WRONLY; om++)
	for (sp=0; sp <= 1; sp++)
	for (ie=0; ie <= 1; ie++) {
		if (access_table1(nd, od, om, sp, ie) != 
		    access_table2(nd, od, om, sp, ie)) {
			printf("failed\n");
			exit(1);
		}
	}
	return 0;
}


More information about the samba-technical mailing list