source: trunk/athena/etc/track/files.c @ 1471

Revision 1471, 7.6 KB checked in by don, 36 years ago (diff)
bellcore copyright.
Line 
1/*
2 *      $Source: /afs/dev.mit.edu/source/repository/athena/etc/track/files.c,v $
3 *      $Header: /afs/dev.mit.edu/source/repository/athena/etc/track/files.c,v 4.1 1988-09-19 20:25:03 don Exp $
4 *
5 *      $Log: not supported by cvs2svn $
6 * Revision 4.0  88/04/14  16:42:41  don
7 * this version is not compatible with prior versions.
8 * it offers, chiefly, link-exporting, i.e., "->" systax in exception-lists.
9 * it also offers sped-up exception-checking, via hash-tables.
10 * a bug remains in -nopullflag support: if the entry's to-name top-level
11 * dir doesn't exist, update_file doesn't get over it.
12 * the fix should be put into the updated() routine, or possibly dec_entry().
13 *
14 * Revision 3.0  88/03/09  13:17:41  don
15 * this version is incompatible with prior versions. it offers:
16 * 1) checksum-handling for regular files, to detect filesystem corruption.
17 * 2) more concise & readable "updating" messages & error messages.
18 * 3) better update-simulation when nopullflag is set.
19 * 4) more support for non-default comparison-files.
20 * finally, the "currentness" data-structure has replaced the statbufs
21 * used before, so that the notion of currency is more readily extensible.
22 * note: the statfile format has been changed.
23 *
24 * Revision 2.2  88/01/29  18:23:52  don
25 * bug fixes. also, now track can update the root.
26 *
27 * Revision 2.1  87/12/03  17:33:39  don
28 * fixed lint warnings.
29 *
30 * Revision 2.0  87/11/30  15:19:24  don
31 * general rewrite; got rid of stamp data-type, with its attendant garbage,
32 * cleaned up pathname-handling. readstat & writestat now sort overything
33 * by pathname, which simplifies traversals/lookup. should be comprehensible
34 * now.
35 *
36 * Revision 1.1  87/02/12  21:14:49  rfrench
37 * Initial revision
38 *
39 */
40
41#ifndef lint
42static char *rcsid_header_h = "$Header: /afs/dev.mit.edu/source/repository/athena/etc/track/files.c,v 4.1 1988-09-19 20:25:03 don Exp $";
43#endif lint
44
45#include "mit-copyright.h"
46#include "bellcore-copyright.h"
47
48#include "track.h"
49
50/*
51 * Check to see if a file is older than a certain amount of time.
52 */
53
54int
55too_old( name, maxtime)
56char *name;
57long maxtime;
58{
59        struct stat sbuf;
60        long now;
61        int retval;
62
63        time(&now);
64        if(stat(name,&sbuf) == -1){
65                sprintf(errmsg,
66                        "can't find file %s in routine too_old()",
67                        name);
68                do_panic();
69        }
70
71        retval = ((sbuf.st_mtime + maxtime) <= now);
72
73        if (debug)
74                printf("too_old(%s,%ld): %d\n",name,maxtime,retval);
75
76        return (retval);
77}
78
79follow_link( name, retval)
80char *name, *retval;
81{
82        int cc;
83        if (0 >= ( cc = readlink( name, retval, LINELEN))) {
84                sprintf( errmsg, "can't read link: %s\n", name);
85                do_gripe();
86                return( -1);
87        }
88        retval[ cc] = '\0';
89
90        /*
91        if ( verboseflag)
92                fprintf( stderr, "following link: %s -> %s\n", name, retval);
93        */
94
95        return( 0);
96}
97
98char *resolve( name, root)
99char *root, *name;
100{
101        /* return the shortest pathname for the inode returned by stat().
102         * only called during parsing, to trace links provided in entries,
103         * and then only if the entry starts with '!'.
104         * this routine is pretty slow, because it uses getwd().
105         */
106        static char path[ LINELEN];
107        static char home[ LINELEN] = "";
108        static char val[ LINELEN];
109        char *end, *linkval = path;
110        struct stat sbuf;
111
112        sprintf( path, "%s/%s", root, name);
113        if( stat( path, &sbuf)) {
114                sprintf( errmsg, "can't stat %s/%s\n", root, name);
115                do_gripe();
116                return("");
117        }
118        if ( ! *home) getwd( home);
119
120        while ( 1) {
121                if ( lstat( path, &sbuf)) {
122                        sprintf( errmsg, "can't lstat %s\n", path);
123                        do_gripe();
124                        chdir( home);
125                        return("");
126                }
127                if ( S_IFLNK != TYPE( sbuf))
128                        break;
129
130                if ( follow_link( path, val)) {
131                        /* back out. something's broken */
132                        chdir( home);
133                        return( name);
134                }
135                linkval = val;
136                if ( *linkval != '/' && ( end = rindex( path, '/'))) {
137                        /* linkval isn't an absolute pathname, and
138                         * we're not already in path's parent dir.
139                         * relocate to the parent, so we can lstat linkval:
140                         */
141                        *end = '\0';
142                        chdir( path);
143                }
144                strcpy( path, linkval);
145        }
146        /* reduce  linkval to its optimal absolute pathname:
147         * we do this by chdir'ing to linkval's parent-dir,
148         * so that getwd() will optimize for us. note: getwd() is SLOW.
149         */
150        if ( *linkval == '/');
151        else if ( end = rindex( linkval, '/')) {
152                /* make relative path to parent
153                 */
154                *end = '\0';
155                getwd(  path);
156                strcat( path, "/");
157                strcat( path, linkval);
158                if ( chdir( path)) {
159                        sprintf( errmsg, "can't resolve link %s/%s\n",
160                                 fromroot, name);
161                        do_gripe();
162                        chdir( home);
163                        return("");
164                }
165                getwd( path);
166                *end = '/';
167                strcat( path, end);
168                linkval = path;
169        }
170        else {                  /* path is linkval's parent */
171                getwd(  path);
172                strcat( path, "/");
173                strcat( path, linkval);
174                linkval = path;
175        }
176        if ( strncmp( linkval, root, strlen( root))) {
177                sprintf( errmsg, "link %s->%s value not under mountpoint %s\n",
178                         name, linkval, root);
179                do_gripe();
180                linkval = "";
181        }
182        linkval += strlen( fromroot) + 1;
183        chdir( home);
184        return( linkval);
185}
186
187/*
188 * if the parent-dir exists, returns 0.
189 * returns the length of the parent's pathname, otherwise.
190 * this weird returned-value allows makepath
191 * to recurse without lots of strcpy's.
192 */
193int
194findparent(path)
195char *path;
196{
197        char *tmp;
198        int retval;
199
200        /*
201        **      assume / exists
202        */
203        if (! strcmp( path,"/"))
204                return(-1);
205
206        if (!( tmp = rindex( path,'/'))) {
207                sprintf(errmsg,"checkroot can't find / in %s", path);
208                do_gripe();
209                return(-1);
210        }
211        if ( tmp == path) return( 0);   /* root is the parent-dir */
212
213        *tmp = '\0';
214        retval = access( path, 0) ? tmp - path - 1 : 0;
215        *tmp = '/';
216        return( retval);
217}
218
219int makepath( path,s)
220char *path;
221struct stat *s;
222{
223        char parent[ LINELEN];
224        int n, usave;
225
226        if ( 0 < ( n = findparent( path))) {
227                parent[ n] = '\0';
228                if ( makepath( parent, s)) return( -1);
229                parent[ n] = '/';
230        }
231        else if ( 0 > n) return( -1);
232
233        if ( verboseflag)
234                fprintf( stderr,"making root directory %s mode %o\n",
235                         path, MODE( *s));
236
237        usave = umask( 022);
238
239        if ( mkdir( path, MODE( *s))) {
240                sprintf(errmsg, "can't create directory %s", path);
241                do_gripe();
242                umask( usave);
243                return(-1);
244        }
245        umask( usave);
246
247        if ( set_prots( path, s)) return(-1);
248
249        return (0);
250}
251
252int
253removeit(name, type)
254char *name;
255unsigned int type;
256{
257        struct direct *next;
258        DIR *dirp;
259        char *leaf, *type_str = "";
260        struct stat sbuf;
261
262        /* caller can pass us the file-type, if he's got it:
263         */
264        if ( type != 0);
265        else if ( (*statf)( name, &sbuf)) {
266                sprintf( errmsg, "(removeit) can't %s %s\n", statn, name);
267                do_gripe();
268                return(-1);
269        }
270        else type = TYPE( sbuf);
271
272        if (verboseflag) {
273                switch( type) {
274                case S_IFBLK: type_str = "block special device";        break;
275                case S_IFCHR: type_str = "char special device";         break;
276                case S_IFDIR: type_str = "directory";                   break;
277                case S_IFREG: type_str = "regular file";                break;
278                case S_IFLNK: type_str = "symbolic link";               break;
279                }
280                fprintf(stderr,"removing %s %s\n",type_str,name);
281        }
282        if ( type == S_IFDIR);
283        else if ( unlink( name)) {
284                sprintf( errmsg, "can't remove %s %s", type_str, name);
285                do_gripe();
286                return(-1);
287        }
288        else return(0);
289
290        if (!(dirp = (DIR *) opendir( name))) {
291                sprintf(errmsg, "removeit: error from opendir of %s", name);
292                do_gripe();
293                return(-1);
294        }
295        readdir( dirp); readdir( dirp); /* skip . & .. */
296
297        strcat( name,"/");              /* XXX: don't copy for recursive call */
298        leaf =  name + strlen( name);
299        for( next = readdir(dirp); next != NULL; next = readdir(dirp)) {
300                strcpy( leaf, next->d_name);    /* changes name[] */
301                removeit( name, 0);
302        }
303        leaf[-1] = '\0';        /* XXX: see strcat, above */
304
305        if ( rmdir( name) == -1) {
306                sprintf(errmsg, "can't remove directory %s",name);
307                do_gripe();
308                return(-1);
309        }
310        return(0);
311}
Note: See TracBrowser for help on using the repository browser.