ref: 0a5f81a44230cbd562b6d71a0a5be018e24a5ba6
dir: /sys/src/ape/cmd/make/files.c/
/* POSIX DEPENDENT PROCEDURES */ #include "defs.h" #include <sys/stat.h> #include <ar.h> #define NAMESPERBLOCK 32 /* DEFAULT RULES FOR POSIX */ char *dfltmacro[] = { ".SUFFIXES : .o .c .y .l .a .sh .f", "MAKE=make", "AR=ar", "ARFLAGS=rv", "YACC=yacc", "YFLAGS=", "LEX=lex", "LFLAGS=", "LDFLAGS=", "CC=c89", "CFLAGS=-O", "FC=fort77", "FFLAGS=-O 1", 0 }; char *dfltpat[] = { "%.o : %.c", "\t$(CC) $(CFLAGS) -c $<", "%.o : %.y", "\t$(YACC) $(YFLAGS) $<", "\t$(CC) $(CFLAGS) -c y.tab.c", "\trm y.tab.c", "\tmv y.tab.o $@", "%.o : %.l", "\t$(LEX) $(LFLAGS) $<", "\t$(CC) $(CFLAGS) -c lex.yy.c", "\trm lex.yy.c", "\tmv lex.yy.o $@", "%.c : %.y", "\t$(YACC) $(YFLAGS) $<", "\tmv y.tab.c $@", "%.c : %.l", "\t$(LEX) $(LFLAGS) $<", "\tmv lex.yy.c $@", "% : %.o", "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<", "% : %.c", "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<", 0 }; char *dfltsuff[] = { ".SUFFIXES : .o .c .y .l .a .sh .f", ".c.o :", "\t$(CC) $(CFLAGS) -c $<", ".f.o :", "\t$(FC) $(FFLAGS) -c $<", ".y.o :", "\t$(YACC) $(YFLAGS) $<", "\t$(CC) $(CFLAGS) -c y.tab.c", "\trm -f y.tab.c", "\tmv y.tab.o $@", ".l.o :", "\t$(LEX) $(LFLAGS) $<", "\t$(CC) $(CFLAGS) -c lex.yy.c", "\trm -f lex.yy.c", "\tmv lex.yy.o $@", ".y.c :", "\t$(YACC) $(YFLAGS) $<", "\tmv y.tab.c $@", ".l.c :", "\t$(LEX) $(LFLAGS) $<", "\tmv lex.yy.c $@", ".c.a:", "\t$(CC) -c $(CFLAGS) $<", "\t$(AR) $(ARFLAGS) $@ $*.o", "\trm -f $*.o", ".f.a:", "\t$(FC) -c $(FFLAGS) $<", "\t$(AR) $(ARFLAGS) $@ $*.o", "\trm -f $*.o", ".c:", "\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<", ".f:", "\t$(FC) $(FFLAGS) $(LDFLAGS) -o $@ $<", ".sh:", "\tcp $< $@", "\tchmod a+x $@", 0 }; static struct dirhd *opdir(char *, int); static void cldir(struct dirhd *, int); static int amatch(char *, char *); static int umatch(char *, char *); static void clarch(void); static int openarch(char *); static int getarch(void); time_t exists(char *filename) { struct stat buf; char *s; for(s = filename ; *s!='\0' && *s!='(' && *s!=')' ; ++s) ; if(*s != '\0') return lookarch(filename); if(stat(filename,&buf) < 0) return 0; else return buf.st_mtime; } time_t prestime(void) { time_t t; time(&t); return t; } static char nmtemp[MAXNAMLEN+1]; /* guarantees a null after the name */ static char *tempend = nmtemp + MAXNAMLEN; depblkp srchdir(char *pat, int mkchain, depblkp nextdbl) { DIR *dirf; struct dirhd *dirptr; char *dirname, *dirpref, *endir, *filepat, *p, temp[100]; char fullname[100]; nameblkp q; depblkp thisdbl; struct pattern *patp; struct dirent *dptr; thisdbl = 0; if(mkchain == NO) for(patp=firstpat ; patp ; patp = patp->nxtpattern) if(equal(pat, patp->patval)) return 0; patp = ALLOC(pattern); patp->nxtpattern = firstpat; firstpat = patp; patp->patval = copys(pat); endir = 0; for(p=pat; *p!='\0'; ++p) if(*p=='/') endir = p; if(endir==0) { dirname = "."; dirpref = ""; filepat = pat; } else { dirname = pat; *endir = '\0'; dirpref = concat(dirname, "/", temp); filepat = endir+1; } dirptr = opdir(dirname,YES); dirf = dirptr->dirfc; for( dptr = readdir(dirf) ; dptr ; dptr = readdir(dirf) ) { char *p1, *p2; p1 = dptr->d_name; p2 = nmtemp; while( (p2<tempend) && (*p2++ = *p1++)!='\0') ; if( amatch(nmtemp,filepat) ) { concat(dirpref,nmtemp,fullname); if( (q=srchname(fullname)) ==0) q = makename(copys(fullname)); if(mkchain) { thisdbl = ALLOC(depblock); thisdbl->nxtdepblock = nextdbl; thisdbl->depname = q; nextdbl = thisdbl; } } } if(endir) *endir = '/'; cldir(dirptr, YES); return thisdbl; } static struct dirhd * opdir(char *dirname, int stopifbad) { struct dirhd *od; for(od = firstod; od; od = od->nxtdirhd) if(equal(dirname, od->dirn) ) break; if(od == NULL) { ++nopdir; od = ALLOC(dirhd); od->nxtdirhd = firstod; firstod = od; od->dirn = copys(dirname); } if(od->dirfc==NULL && (od->dirfc = opendir(dirname)) == NULL && stopifbad) { fprintf(stderr, "Directory %s: ", dirname); fatal("Cannot open"); } return od; } static void cldir(struct dirhd *dp, int used) { if(nopdir >= MAXDIR) { closedir(dp->dirfc); dp->dirfc = NULL; } else if(used) rewinddir(dp->dirfc); /* start over at the beginning */ } /* stolen from glob through find */ static int amatch(char *s, char *p) { int cc, scc, k; int c, lc; scc = *s; lc = 077777; switch (c = *p) { case '[': k = 0; while (cc = *++p) { switch (cc) { case ']': if (k) return amatch(++s, ++p); else return 0; case '-': k |= (lc <= scc) & (scc <= (cc=p[1]) ) ; } if (scc==(lc=cc)) k++; } return 0; case '?': caseq: if(scc) return amatch(++s, ++p); return 0; case '*': return umatch(s, ++p); case 0: return !scc; } if (c==scc) goto caseq; return 0; } static int umatch(char *s, char *p) { if(*p==0) return 1; while(*s) if (amatch(s++,p)) return 1; return 0; } #ifdef METERFILE #include <pwd.h> int meteron = 0; /* default: metering off */ extern void meter(char *file) { time_t tvec; char *p; FILE * mout; struct passwd *pwd; if(file==0 || meteron==0) return; pwd = getpwuid(getuid()); time(&tvec); if( mout = fopen(file,"a") ) { p = ctime(&tvec); p[16] = '\0'; fprintf(mout, "User %s, %s\n", pwd->pw_name, p+4); fclose(mout); } } #endif /* look inside archives for notation a(b) a(b) is file member b in archive a */ static long arflen; static long arfdate; static char arfname[16]; FILE *arfd; long int arpos, arlen; time_t lookarch(char *filename) { char *p, *q, *send, s[15], pad; int i, nc, nsym; for(p = filename; *p!= '(' ; ++p) ; *p = '\0'; if( ! openarch(filename) ) { *p = '('; return 0L; } *p++ = '('; nc = 14; pad = ' '; send = s + nc; for( q = s ; q<send && *p!='\0' && *p!=')' ; *q++ = *p++ ) ; if(p[0]==')' && p[1]!='\0') /* forbid stuff after the paren */ { clarch(); return 0L; } while(q < send) *q++ = pad; while(getarch()) { if( !strncmp(arfname, s, nc)) { clarch(); /*TEMP fprintf(stderr, "found archive member %14s, time=%d\n", s, arfdate); */ return arfdate; } } clarch(); return 0L; } static void clarch(void) { fclose( arfd ); } static int openarch(char *f) { char magic[SARMAG]; int word; struct stat buf; nameblkp p; stat(f, &buf); arlen = buf.st_size; arfd = fopen(f, "r"); if(arfd == NULL) return NO; /* fatal1("cannot open %s", f); */ fread( (char *) &word, sizeof(word), 1, arfd); fseek(arfd, 0L, 0); fread(magic, SARMAG, 1, arfd); arpos = SARMAG; if( strncmp(magic, ARMAG, SARMAG) ) fatal1("%s is not an archive", f); if( !(p = srchname(f)) ) p = makename( copys(f) ); p->isarch = YES; arflen = 0; return YES; } static int getarch(void) { struct ar_hdr arhead; arpos += (arflen + 1) & ~1L; /* round archived file length up to even */ if(arpos >= arlen) return 0; fseek(arfd, arpos, 0); fread( (char *) &arhead, sizeof(arhead), 1, arfd); arpos += sizeof(arhead); arflen = atol(arhead.ar_size); arfdate = atol(arhead.ar_date); strncpy(arfname, arhead.ar_name, sizeof(arhead.ar_name)); return 1; } /* find the directory containing name. read it into the hash table if it hasn't been used before or if if might have changed since last reference */ void dirsrch(char *name) { DIR *dirf; struct dirhd *dirp; time_t dirt, objt; int dirused, hasparen; char *dirname, *lastslash; char *fullname, *filepart, *fileend, *s; struct dirent *dptr; lastslash = NULL; hasparen = NO; for(s=name; *s; ++s) if(*s == '/') lastslash = s; else if(*s=='(' || *s==')') hasparen = YES; if(hasparen) { if(objt = lookarch(name)) makename(name)->modtime = objt; return; } if(lastslash) { dirname = name; *lastslash = '\0'; } else dirname = "."; dirused = NO; dirp = opdir(dirname, NO); dirf = dirp->dirfc; if(dirp->dirok || !dirf) goto ret; dirt = exists(dirname); if(dirp->dirtime == dirt) goto ret; dirp->dirok = YES; dirp->dirtime = dirt; dirused = YES; /* allocate buffer to hold full file name */ if(lastslash) { fullname = (char *) ckalloc(strlen(dirname)+MAXNAMLEN+2); concat(dirname, "/", fullname); filepart = fullname + strlen(fullname); } else filepart = fullname = (char *) ckalloc(MAXNAMLEN+1); fileend = filepart + MAXNAMLEN; *fileend = '\0'; for(dptr = readdir(dirf) ; dptr ; dptr = readdir(dirf) ) { char *p1, *p2; p1 = dptr->d_name; p2 = filepart; while( (p2<fileend) && (*p2++ = *p1++)!='\0') ; if( ! srchname(fullname) ) (void) makename(copys(fullname)); } free(fullname); ret: cldir(dirp, dirused); if(lastslash) *lastslash = '/'; } void baddirs(void) { struct dirhd *od; for(od = firstod; od; od = od->nxtdirhd) od->dirok = NO; }