source: trunk/athena/etc/track/except.c @ 13492

Revision 13492, 10.3 KB checked in by danw, 25 years ago (diff)
fix warnings to make Irix n32 cc happy.
Line 
1/*
2 * $Id: except.c,v 4.12 1999-08-13 00:15:11 danw Exp $
3 */
4
5#ifndef lint
6static char *rcsid = "$Id: except.c,v 4.12 1999-08-13 00:15:11 danw Exp $";
7#endif
8
9#include "mit-copyright.h"
10#include "bellcore-copyright.h"
11
12#include "track.h"
13
14void store();
15
16/*
17**      routine to implement exception lists:
18*/
19
20gettail( pathp, type, entnum)
21char **pathp;
22unsigned short type;
23int entnum;
24{
25        static char exc_dir[ LINELEN] = "";
26        List_element **except, *q;
27        char retval = NORMALCASE, *tail, *wholename;
28        unsigned int k;
29        Entry *e = &entries[ entnum], *g = &entries[ 0];
30
31        if (( type == S_IFBLK || type == S_IFCHR) && ! incl_devs)
32                return( DONT_TRACK);
33
34        /* strip fromfile from path:
35         * path   == fromfile/tail
36         * keylen == strlen( fromfile).
37         */
38        wholename = *pathp;
39        *pathp += e->keylen;
40
41        if ( ! **pathp) return( NORMALCASE);
42        while( *++*pathp == '/');       
43
44        /* if exc_dir is not empty, then it holds the most recently excepted
45         * subdir of the current entry. if the wholename starts with exc_dir,
46         * then we count it as an exception, too.
47         * excepted links are handled this way, too, in case they target
48         * directories. exc_dir is a speed hack.
49         */
50        if ( ! *exc_dir);
51        else if ( strncmp( wholename, exc_dir, strlen( exc_dir)))
52                *exc_dir = '\0';
53        else    return( DONT_TRACK);
54
55        k = hash( tail = *pathp);
56
57        if ( e->names.table && ( except = lookup( tail, k, &e->names))) {
58                retval = FLAG( *except);
59        }
60        else if ( g->names.table && ( except = lookup( tail, k, &g->names))) {
61                retval = FLAG( *except);
62        }
63        /*      compare the tail with each pattern in both entries' lists:
64         *      the global list ( g->patterns),
65         *      and the current entry's exception patterns.
66         *      the global list is chained to the end of e->patterns,
67         *      during subscription-list parsing.
68         */
69        else for( q = e->patterns; q; q = NEXT( q))
70                if ( match( TEXT( q), tail)) {
71                        retval = FLAG( q);
72                        break;
73                }
74        /* now, retval has been computed.
75         * if it's not NORMALCASE, we've had a match:
76         * either tail is to be a link to the exporter's filesystem,
77         * or tail is an exception. in either case, if tail is  a dir or
78         * a link to a dir, we don't want to update tail's children.
79         */
80        if ( retval == NORMALCASE);
81        else if ( type == S_IFLNK || type == S_IFDIR)
82                sprintf( exc_dir, "%s/", wholename);
83
84        return( retval);
85}
86
87List_element **
88lookup( name, hashval, ht) char *name; unsigned long hashval; Table *ht; {
89        List_element **ptop;
90
91        /* *ptop is the first element of an alphabetically-sorted
92         * linked-list of relative pathnames.
93         * for speed, we access each list-elt via the beginning of its string;
94         * the elt's first 4 bytes hold the addr of the next list-elt.
95         */
96        for ( ptop = &ht->table[ hashval >> ht->shift];
97             *ptop;
98              ptop = PNEXT( *ptop)) {
99                switch ( SIGN( strcmp( (char *)*ptop, name))) {
100                case -1: continue;
101                case 1:  break;
102                case 0:  return( ptop);
103                }
104                break;
105        }
106        return( NULL);
107}
108
109void
110list2hashtable( p) Table *p; {
111        List_element *names, *wordp;
112        unsigned int tbl_size;
113
114        if ( ! p->shift) {
115                sprintf(errmsg,"parser error: non-empty table has 0 count\n");
116                do_panic();
117        }
118        /* convert names list to hash-table,
119         * using count of list-elements to allocate table:
120         * size is power of 2, s.t. table is at most 2/3 full.
121         * XXX: store hashing shift in caller's copy of list-count.
122         *      parser stored the list-count as a negative #,
123         *      to tell justshow() how to dump.
124         */
125        p->shift *= -1;
126        p->shift = 31 - log2( p->shift + ( p->shift >> 1));
127        names    = (List_element *) p->table;
128        tbl_size = (unsigned) 0x80000000 >> p->shift - 1;
129        if ( ! tbl_size)
130                sprintf( errmsg, "(list2hashtable) null hash table request\n");
131
132        p->table = (List_element **) calloc( tbl_size, sizeof( List_element*));
133        if ( ! p->table) {
134                sprintf( errmsg, "(list2hashtable) calloc( %d, %d) failed.\n",
135                         tbl_size, sizeof( List_element *));
136                do_panic();
137        }
138        do {
139            wordp = names;
140            names = NEXT( names);
141            store( wordp, p);
142        } while ( names);
143        return;
144}
145/* get integer-part of log(base2) of the table-length,
146 * by doing a binary-search for the high-order bit:
147 */
148unsigned short mask[] =
149{       0xffff,0xfffe,0xfffc,0xfff8,0xfff0,0xffe0,0xffc0,0xff80,
150        0xff00,0xfe00,0xfc00,0xf800,0xf000,0xe000,0xc000,0x8000};
151log2( len) unsigned short len; {
152        int i, n = 0;
153        for ( i = 16; i >>= 1; ) if ( len & mask[ n + i]) n += i;
154        return( n);
155}
156
157void
158store( list_elt, p) List_element *list_elt; Table *p; {
159        List_element **collisionp, **nextp;
160
161        collisionp = &p->table[ hash( TEXT( list_elt)) >> p->shift];
162        if ( ! *collisionp) {
163            *collisionp = list_elt;     /* store list-elt in hash table */
164            NEXT( list_elt) = NULL;
165            return;
166        }
167        /* keep list of colliding elt's in alphabetical order.
168         * if list_elt is already present in the table,
169         * ensure that FORCE_LINK overrides DONT_TRACK.
170         */
171        for ( nextp = collisionp; *nextp; nextp = PNEXT( *nextp)) {
172            switch( SIGN( strcmp( (char *)*nextp, (char *)list_elt))) {
173            case -1: continue;
174            case  1: break;                             /* switch */
175            case  0: FLAG( *nextp) |= FLAG( list_elt);
176                     return; /* infequent case last */
177            }
178            break;      /* loop */
179        }
180        NEXT( list_elt) = *nextp;
181        *nextp = list_elt;
182        return;
183}
184List_element *
185add_list_elt( str, flag, top) char *str; char flag; List_element **top; {
186        List_element *p;
187
188        /* this alloc will waste some char's,
189         * since List_element{}'s header is padded to end on a
190         * fullword-boundary.
191         */
192        p = (List_element *) malloc( sizeof( List_element) + strlen( str));
193        if ( !p) {
194                sprintf( errmsg, "(add_list_element) malloc( %d) failed.\n",
195                         sizeof( List_element) + strlen( str));
196                do_panic();
197        }
198        p = (List_element *) p->first_char;
199
200        if ( top) {
201                NEXT( p) = *top;
202                *top = p;
203        }
204        else NEXT( p) = NULL;
205        FLAG( p)   = flag;
206        strcpy( (char *)p, str);
207        return( p);
208}
209#define RATIO ((unsigned)(0.6125423371 * 0x80000000))
210/* this is a multiplicative hash code. for an explanation of RATIO,
211 * see T. A. Standish, Data Structure Techniques, p161-3, or
212 * Knuth, Art of Comp. Prog., v3, p512.
213 * the shifting makes a 17-bit key from several 6-bit bytes.
214 * ( for alphabetic ASCII, the top 2 bits of each byte are redundant. )
215 * the numbers 4, 5 & 12 are carefully chosen, from trial & error.
216 * this hash code has the following advantages over mod-prime hash:
217 * collides slightly less frequently, especially when table is overfull;
218 * doesn't need prime-sized table, so table is easier to build.
219 */
220unsigned long
221hash( p) char *p; {
222        unsigned long key = 0;
223        short s = 4;
224        for ( ; *p ; s += 5) key ^= ( *p++ & 077) << s % 12;
225        return( key * RATIO);
226}
227char *
228next_def_except() {
229        static char *g_except[] = DEF_EXCEPT; /* default GLOBAL exceptions */
230        static int next = 0;
231
232        if ( next < sizeof( g_except) / 4)
233                return ( g_except[ next++]);
234        else return( NULL);
235}
236
237file_pat( ptr)
238char *ptr;
239{
240        return( (strchr(ptr,'*') ||
241                 strchr(ptr,'[') ||
242                 strchr(ptr,']') ||
243                 strchr(ptr,'?')));
244}
245
246#define FASTEQ( a, b) (*(a) == *(b) && a[1] == b[1])
247
248duplicate( word, entnum) char *word; int entnum; {
249        List_element *re;
250
251        for ( re = entries[ entnum].patterns; re; re = NEXT( re)) {
252                    if ( FASTEQ( word, TEXT( re)) &&
253                       ! strcmp( word, TEXT( re)))
254                        return( 1);
255        }
256        /* check the global exceptions list
257         */
258        if ( entnum) return( duplicate( word, 0));
259        return( 0);
260}
261
262/*-
263 * Copyright (c) 1991, 1993
264 *      The Regents of the University of California.  All rights reserved.
265 *
266 * This code is derived from software contributed to Berkeley by
267 * Kenneth Almquist.
268 *
269 * Redistribution and use in source and binary forms, with or without
270 * modification, are permitted provided that the following conditions
271 * are met:
272 * 1. Redistributions of source code must retain the above copyright
273 *    notice, this list of conditions and the following disclaimer.
274 * 2. Redistributions in binary form must reproduce the above copyright
275 *    notice, this list of conditions and the following disclaimer in the
276 *    documentation and/or other materials provided with the distribution.
277 * 3. All advertising materials mentioning features or use of this software
278 *    must display the following acknowledgement:
279 *      This product includes software developed by the University of
280 *      California, Berkeley and its contributors.
281 * 4. Neither the name of the University nor the names of its contributors
282 *    may be used to endorse or promote products derived from this software
283 *    without specific prior written permission.
284 *
285 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
286 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
288 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
289 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
290 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
291 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
292 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
293 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
294 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
295 * SUCH DAMAGE.
296 */
297
298int match(pattern, string)
299        char *pattern;
300        char *string;
301{
302        char *p, *q, c;
303
304        q = string;
305        p = pattern;
306        for (; *p;) {
307                c = *p++;
308                switch (c) {
309                case '\\':
310                        if (*q++ != *p++)
311                                return 0;
312                        break;
313                case '?':
314                        if (*q++ == '\0')
315                                return 0;
316                        break;
317                case '*':
318                        c = *p;
319                        if (c != '\\' && c != '?' && c != '*' && c != '[') {
320                                while (*q != c) {
321                                        if (*q == '\0')
322                                                return 0;
323                                        q++;
324                                }
325                        }
326                        do {
327                                if (match(p, q))
328                                        return 1;
329                        } while (*q++ != '\0');
330                        return 0;
331                case '[': {
332                        char *endp;
333                        int invert, found;
334                        char chr;
335
336                        endp = p;
337                        if (*endp == '!')
338                                endp++;
339                        for (;;) {
340                                if (*endp == '\0')
341                                        goto dft;       /* no matching ] */
342                                if (*endp == '\\')
343                                        endp++;
344                                if (*++endp == ']')
345                                        break;
346                        }
347                        invert = 0;
348                        if (*p == '!') {
349                                invert++;
350                                p++;
351                        }
352                        found = 0;
353                        chr = *q++;
354                        if (chr == '\0')
355                                return 0;
356                        c = *p++;
357                        do {
358                                if (c == '\\')
359                                        c = *p++;
360                                if (*p == '-' && p[1] != ']') {
361                                        p++;
362                                        if (*p == '\\')
363                                                p++;
364                                        if (chr >= c && chr <= *p)
365                                                found = 1;
366                                        p++;
367                                } else {
368                                        if (chr == c)
369                                                found = 1;
370                                }
371                        } while ((c = *p++) != ']');
372                        if (found == invert)
373                                return 0;
374                        break;
375                }
376dft:            default:
377                        if (*q++ != c)
378                                return 0;
379                        break;
380                }
381        }
382        if (*q != '\0')
383                return 0;
384        return 1;
385}
Note: See TracBrowser for help on using the repository browser.