/* @(#)/usr/src/cmd/make/files.c 3.4 */ #include "defs" #include <sys/types.h> #include <sys/stat.h> #include <sys/dir.h> #include <pwd.h> #include <ar.h> #include <a.out.h> /* UNIX DEPENDENT PROCEDURES */ char archmem[16]; char archname[64]; /* name of archive library */ TIMETYPE exists(pname) NAMEBLOCK pname; { register CHARSTAR s; struct stat buf; TIMETYPE lookarch(); CHARSTAR filename; filename = pname->namep; if(any(filename, LPAREN)) return(lookarch(filename)); if(stat(filename,&buf) < 0) { s = findfl(filename); if(s != (CHARSTAR )-1) { pname->alias = copys(s); if(stat(pname->alias, &buf) == 0) return(buf.st_mtime); } return(0); } else return(buf.st_mtime); } TIMETYPE prestime() { TIMETYPE t; time(&t); return(t); } FSTATIC char n15[15]; FSTATIC CHARSTAR n15end = &n15[14]; DEPBLOCK srchdir(pat, mkchain, nextdbl) register CHARSTAR pat; /* pattern to be matched in directory */ int mkchain; /* nonzero if results to be remembered */ DEPBLOCK nextdbl; /* final value for chain */ { FILE * dirf; int i, nread; CHARSTAR dirname, dirpref, endir, filepat, p; char temp[100]; char fullname[100]; CHARSTAR p1, p2; NAMEBLOCK q; DEPBLOCK thisdbl; OPENDIR od; int dirofl = 0; static opendirs = 0; PATTERN patp; struct direct entry[32]; thisdbl = 0; if(mkchain == NO) for(patp=firstpat ; patp!=0 ; patp = patp->nextpattern) if(equal(pat,patp->patval)) return(0); patp = ALLOC(pattern); patp->nextpattern = firstpat; firstpat = patp; patp->patval = copys(pat); endir = 0; for(p=pat; *p!=CNULL; ++p) if(*p==SLASH) endir = p; if(endir==0) { dirname = "."; dirpref = ""; filepat = pat; } else { *endir = CNULL; dirpref = concat(pat, "/", temp); filepat = endir+1; dirname = temp; } dirf = NULL; for(od=firstod ; od!=0; od = od->nextopendir) if(equal(dirname, od->dirn)) { dirf = od->dirfc; fseek(dirf,0L,0); /* start over at the beginning */ break; } if(dirf == NULL) { dirf = fopen(dirname, "r"); if(++opendirs < MAXODIR) { od = ALLOC(opendir); od->nextopendir = firstod; firstod = od; od->dirfc = dirf; od->dirn = copys(dirname); } else dirofl = 1; } if(dirf == NULL) { fprintf(stderr, "Directory %s: ", dirname); fatal("Cannot open"); } else do { nread = fread(entry,sizeof(entry[0]),32,dirf) ; for(i=0; i<nread; ++i) if(entry[i].d_ino!= 0) { p1 = entry[i].d_name; p2 = n15; while( (p2<n15end) && (*p2++ = *p1++)!=CNULL ); if( amatch(n15,filepat) ) { concat(dirpref,n15,fullname); if( (q=srchname(fullname)) ==0) q = makename(copys(fullname)); if(mkchain) { thisdbl = ALLOC(depblock); thisdbl->nextdep = nextdbl; thisdbl->depname = q; nextdbl = thisdbl; } } } } while(nread==32); if(endir != 0) *endir = SLASH; if(dirofl) fclose(dirf); return(thisdbl); } /* stolen from glob through find */ amatch(s, p) CHARSTAR s, p; { register int cc, scc, k; int c, lc; scc = *s; lc = 077777; switch (c = *p) { case LSQUAR: k = 0; while (cc = *++p) { switch (cc) { case RSQUAR: if (k) return(amatch(++s, ++p)); else return(0); case MINUS: k |= lc <= scc & scc <= (cc=p[1]); } if(scc==(lc=cc)) k++; } return(0); case QUESTN: caseq: if(scc) return(amatch(++s, ++p)); return(0); case STAR: return(umatch(s, ++p)); case 0: return(!scc); } if(c==scc) goto caseq; return(0); } umatch(s, p) register CHARSTAR s, p; { if(*p==0) return(1); while(*s) if(amatch(s++,p)) return(1); return(0); } #ifdef METERFILE int meteron 0; /* default: metering off */ meter(file) CHARSTAR file; { TIMETYPE tvec; CHARSTAR p, ctime(); FILE * mout; struct passwd *pwd, *getpwuid(); if(file==0 || meteron==0) return; pwd = getpwuid(getuid()); time(&tvec); if( (mout=fopen(file,"a")) != NULL ) { p = ctime(&tvec); p[16] = CNULL; fprintf(mout,"User %s, %s\n",pwd->pw_name,p+4); fclose(mout); } } #endif /* look inside archives for notations a(b) and a((b)) a(b) is file member b in archive a a((b)) is entry point _b in object archive a */ static struct ar_hdr arhead; FILE *arfd; long int arpos, arlen; static struct exec objhead; static struct nlist objentry; TIMETYPE lookarch(filename) register CHARSTAR filename; { register int i; CHARSTAR p, q, send; char s[15]; int nc, nsym, objarch; for(p = filename; *p!= LPAREN ; ++p); q = p++; if(*p == LPAREN) { objarch = YES; nc = 8; ++p; } else { objarch = NO; nc = 14; for(i = 0; i < 14; i++) { if(p[i] == RPAREN) { i--; break; } archmem[i] = p[i]; } archmem[++i] = 0; if(archmem[0] == CNULL) fatal1("Null archive member name `%s'", filename); } *q = CNULL; copstr(archname, filename); if(archname[0] == CNULL) fatal1("Null archive name `%s'", archmem); i = openarch(filename); *q = LPAREN; if(i == -1) return(0); send = s + nc; for( q = s ; q<send && *p!=CNULL && *p!=RPAREN ; *q++ = *p++ ); while(q < send) *q++ = CNULL; while(getarch()) { if(objarch) { getobj(); nsym = objhead.a_syms / sizeof(objentry); for(i = 0; i<nsym ; ++i) { fread(&objentry, sizeof(objentry),1,arfd); if( (objentry.n_type & N_EXT) && eqstr(objentry.n_name,s,nc)) { for(i = 0; i < 14; i++) archmem[i] = arhead.ar_name[i]; archmem[++i] = 0; out: clarch(); return(arhead.ar_date); } } } else if( eqstr(arhead.ar_name, s, nc)) goto out; } clarch(); return( 0L); } clarch() { fclose( arfd ); } openarch(f) register CHARSTAR f; { int word = 0; struct stat buf; if(stat(f, &buf) == -1) return(-1); arlen = buf.st_size; arfd = fopen(f, "r"); if(arfd == NULL) return(-1); fread(&word, sizeof(word), 1, arfd); if(word != ARMAG) fatal1("%s is not an archive", f); /* * trick getarch() into jumping to the first archive member. */ arpos = sizeof(word); arhead.ar_size = -(int)sizeof(arhead); return(0); } getarch() { arpos += sizeof(arhead); arpos += (arhead.ar_size + 1 ) & ~1L; if(arpos >= arlen) return(0); fseek(arfd, arpos, 0); fread(&arhead, sizeof(arhead), 1, arfd); return(1); } getobj() { long int skip; fread(&objhead, sizeof(objhead), 1, arfd); if( objhead.a_magic != A_MAGIC1 && objhead.a_magic != A_MAGIC2 && objhead.a_magic != A_MAGIC3 ) fatal1("%s is not an object module", arhead.ar_name); skip = objhead.a_text + objhead.a_data; #if vax || u370 skip += objhead.a_trsize + objhead.a_drsize; #else if(! objhead.a_flag ) skip *= 2; #endif fseek(arfd, skip, 1); } eqstr(a,b,n) register CHARSTAR a, b; register int n; { register int i; for(i = 0 ; i < n ; ++i) if(*a++ != *b++) return(NO); return(YES); } /* * Used when unlinking files. If file cannot be stat'ed or it is * a directory, then do not remove it. */ isdir(p) char *p; { struct stat statbuf; if(stat(p, &statbuf) == -1) return(1); /* no stat, no remove */ if((statbuf.st_mode&S_IFMT) == S_IFDIR) return(1); return(0); }