#include 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 (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_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); } 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; }