diff options
author | joerg <joerg@pkgsrc.org> | 2015-05-19 21:36:43 +0000 |
---|---|---|
committer | joerg <joerg@pkgsrc.org> | 2015-05-19 21:36:43 +0000 |
commit | 41f4d684ea949e703f7e4cdb02fffeb278231228 (patch) | |
tree | 2b7216a215b93c3db4db0c3a78c3ab11b8eaec34 /devel/bmake/files/meta.c | |
parent | 7cb16bb66575467ac59352068eaec344242b439a (diff) | |
download | pkgsrc-41f4d684ea949e703f7e4cdb02fffeb278231228.tar.gz |
Import bmake-20150505
Diffstat (limited to 'devel/bmake/files/meta.c')
-rw-r--r-- | devel/bmake/files/meta.c | 315 |
1 files changed, 236 insertions, 79 deletions
diff --git a/devel/bmake/files/meta.c b/devel/bmake/files/meta.c index cacb9a40626..7a7816f4105 100644 --- a/devel/bmake/files/meta.c +++ b/devel/bmake/files/meta.c @@ -1,4 +1,4 @@ -/* $NetBSD: meta.c,v 1.1.1.1 2011/06/18 22:18:04 bsiegert Exp $ */ +/* $NetBSD: meta.c,v 1.1.1.2 2015/05/19 21:36:44 joerg Exp $ */ /* * Implement 'meta' mode. @@ -55,7 +55,12 @@ #endif static BuildMon Mybm; /* for compat */ -static Lst metaBailiwick; /* our scope of control */ +static Lst metaBailiwick; /* our scope of control */ +static Lst metaIgnorePaths; /* paths we deliberately ignore */ + +#ifndef MAKE_META_IGNORE_PATHS +#define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS" +#endif Boolean useMeta = FALSE; static Boolean useFilemon = FALSE; @@ -64,9 +69,11 @@ static Boolean metaEnv = FALSE; /* don't save env unless asked */ static Boolean metaVerbose = FALSE; static Boolean metaIgnoreCMDs = FALSE; /* ignore CMDs in .meta files */ static Boolean metaCurdirOk = FALSE; /* write .meta in .CURDIR Ok? */ +static Boolean metaSilent = FALSE; /* if we have a .meta be SILENT */ extern Boolean forceJobs; extern Boolean comatMake; +extern char **environ; #define MAKE_META_PREFIX ".MAKE.META.PREFIX" @@ -148,8 +155,8 @@ filemon_open(BuildMon *pbm) static void filemon_read(FILE *mfp, int fd) { - FILE *fp; char buf[BUFSIZ]; + int n; /* Check if we're not writing to a meta data file.*/ if (mfp == NULL) { @@ -158,18 +165,15 @@ filemon_read(FILE *mfp, int fd) return; } /* rewind */ - lseek(fd, SEEK_SET, 0); - if ((fp = fdopen(fd, "r")) == NULL) - err(1, "Could not read build monitor file '%d'", fd); + (void)lseek(fd, (off_t)0, SEEK_SET); - fprintf(mfp, "-- filemon acquired metadata --\n"); + fprintf(mfp, "\n-- filemon acquired metadata --\n"); - while (fgets(buf, sizeof(buf), fp)) { - fprintf(mfp, "%s", buf); + while ((n = read(fd, buf, sizeof(buf))) > 0) { + fwrite(buf, 1, n, mfp); } fflush(mfp); - clearerr(fp); - fclose(fp); + close(fd); } #endif @@ -387,7 +391,6 @@ printCMD(void *cmdp, void *mfpp) static FILE * meta_create(BuildMon *pbm, GNode *gn) { - extern char **environ; meta_file_t mf; char buf[MAXPATHLEN]; char objdir[MAXPATHLEN]; @@ -510,7 +513,11 @@ meta_create(BuildMon *pbm, GNode *gn) Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL); Var_Append(".MAKE.META.CREATED", fname, VAR_GLOBAL); - + + gn->type |= OP_META; /* in case anyone wants to know */ + if (metaSilent) { + gn->type |= OP_SILENT; + } out: for (i--; i >= 0; i--) { if (p[i]) @@ -534,8 +541,24 @@ boolValue(char *s) return TRUE; } +/* + * Initialization we need before reading makefiles. + */ +void +meta_init(void) +{ +#ifdef USE_FILEMON + /* this allows makefiles to test if we have filemon support */ + Var_Set(".MAKE.PATH_FILEMON", _PATH_FILEMON, VAR_GLOBAL, 0); +#endif +} + + +/* + * Initialization we need after reading makefiles. + */ void -meta_init(const char *make_mode) +meta_mode_init(const char *make_mode) { static int once = 0; char *cp; @@ -556,6 +579,9 @@ meta_init(const char *make_mode) if ((cp = strstr(make_mode, "curdirok="))) { metaCurdirOk = boolValue(&cp[9]); } + if ((cp = strstr(make_mode, "silent="))) { + metaSilent = boolValue(&cp[7]); + } if (strstr(make_mode, "ignore-cmd")) metaIgnoreCMDs = TRUE; /* for backwards compatability */ @@ -583,6 +609,17 @@ meta_init(const char *make_mode) if (cp) { str2Lst_Append(metaBailiwick, cp, NULL); } + /* + * We ignore any paths that start with ${.MAKE.META.IGNORE_PATHS} + */ + metaIgnorePaths = Lst_Init(FALSE); + Var_Append(MAKE_META_IGNORE_PATHS, + "/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL); + cp = Var_Subst(NULL, + "${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL, 0); + if (cp) { + str2Lst_Append(metaIgnorePaths, cp, NULL); + } } /* @@ -622,17 +659,21 @@ meta_job_child(Job *job) { #ifdef USE_FILEMON BuildMon *pbm; - pid_t pid; if (job != NULL) { pbm = &job->bm; } else { pbm = &Mybm; } - pid = getpid(); - if (pbm->mfp != NULL && useFilemon) { - if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) { - err(1, "Could not set filemon pid!"); + if (pbm->mfp != NULL) { + close(fileno(pbm->mfp)); + if (useFilemon) { + pid_t pid; + + pid = getpid(); + if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) { + err(1, "Could not set filemon pid!"); + } } } #endif @@ -767,7 +808,7 @@ fgetLine(char **bufp, size_t *szp, int o, FILE *fp) newsz = ROUNDUP(fs.st_size, BUFSIZ); if (DEBUG(META)) fprintf(debug_file, "growing buffer %u -> %u\n", - bufsz, newsz); + (unsigned)bufsz, (unsigned)newsz); p = bmake_realloc(buf, newsz); if (p) { *bufp = buf = p; @@ -804,27 +845,51 @@ string_match(const void *p, const void *q) /* * When running with 'meta' functionality, a target can be out-of-date - * if any of the references in it's meta data file is more recent. + * if any of the references in its meta data file is more recent. * We have to track the latestdir on a per-process basis. */ +#define LCWD_VNAME_FMT ".meta.%d.lcwd" #define LDIR_VNAME_FMT ".meta.%d.ldir" +/* + * It is possible that a .meta file is corrupted, + * if we detect this we want to reproduce it. + * Setting oodate TRUE will have that effect. + */ +#define CHECK_VALID_META(p) if (!(p && *p)) { \ + warnx("%s: %d: malformed", fname, lineno); \ + oodate = TRUE; \ + continue; \ + } + +#define DEQUOTE(p) if (*p == '\'') { \ + char *ep; \ + p++; \ + if ((ep = strchr(p, '\''))) \ + *ep = '\0'; \ + } + Boolean meta_oodate(GNode *gn, Boolean oodate) { static char *tmpdir = NULL; static char cwd[MAXPATHLEN]; + char lcwd_vname[64]; char ldir_vname[64]; + char lcwd[MAXPATHLEN]; char latestdir[MAXPATHLEN]; char fname[MAXPATHLEN]; char fname1[MAXPATHLEN]; char fname2[MAXPATHLEN]; + char fname3[MAXPATHLEN]; char *p; char *cp; + char *link_src; + char *move_target; static size_t cwdlen = 0; static size_t tmplen = 0; FILE *fp; - Boolean ignoreOODATE = FALSE; + Boolean needOODATE = FALSE; Lst missingFiles; if (oodate) @@ -868,6 +933,8 @@ meta_oodate(GNode *gn, Boolean oodate) err(1, "Could not get current working directory"); cwdlen = strlen(cwd); } + strlcpy(lcwd, cwd, sizeof(lcwd)); + strlcpy(latestdir, cwd, sizeof(latestdir)); if (!tmpdir) { tmpdir = getTmpdir(); @@ -882,9 +949,13 @@ meta_oodate(GNode *gn, Boolean oodate) lineno++; if (buf[x - 1] == '\n') buf[x - 1] = '\0'; - else + else { warnx("%s: %d: line truncated at %u", fname, lineno, x); - + oodate = TRUE; + break; + } + link_src = NULL; + move_target = NULL; /* Find the start of the build monitor section. */ if (!f) { if (strncmp(buf, "-- filemon", 10) == 0) { @@ -940,15 +1011,18 @@ meta_oodate(GNode *gn, Boolean oodate) * re-initialize 'latestdir' to any pre-saved * value for the current 'pid' and 'CWD' if none. */ + CHECK_VALID_META(p); pid = atoi(p); if (pid > 0 && pid != lastpid) { char *ldir; char *tp; if (lastpid > 0) { - /* We need to remember this. */ + /* We need to remember these. */ + Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0); Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0); } + snprintf(lcwd_vname, sizeof(lcwd_vname), LCWD_VNAME_FMT, pid); snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid); lastpid = pid; ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp); @@ -956,22 +1030,32 @@ meta_oodate(GNode *gn, Boolean oodate) strlcpy(latestdir, ldir, sizeof(latestdir)); if (tp) free(tp); - } else - strlcpy(latestdir, cwd, sizeof(latestdir)); + } + ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp); + if (ldir) { + strlcpy(lcwd, ldir, sizeof(lcwd)); + if (tp) + free(tp); + } } /* Skip past the pid. */ if (strsep(&p, " ") == NULL) continue; #ifdef DEBUG_META_MODE if (DEBUG(META)) - fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, latestdir); + fprintf(debug_file, "%s: %d: %d: %c: cwd=%s lcwd=%s ldir=%s\n", + fname, lineno, + pid, buf[0], cwd, lcwd, latestdir); #endif break; } + CHECK_VALID_META(p); + /* Process according to record type. */ switch (buf[0]) { case 'X': /* eXit */ + Var_Delete(lcwd_vname, VAR_GLOBAL); Var_Delete(ldir_vname, VAR_GLOBAL); lastpid = 0; /* no need to save ldir_vname */ break; @@ -983,28 +1067,48 @@ meta_oodate(GNode *gn, Boolean oodate) child = atoi(p); if (child > 0) { + snprintf(cldir, sizeof(cldir), LCWD_VNAME_FMT, child); + Var_Set(cldir, lcwd, VAR_GLOBAL, 0); snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child); Var_Set(cldir, latestdir, VAR_GLOBAL, 0); +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: %d: cwd=%s lcwd=%s ldir=%s\n", + fname, lineno, + child, cwd, lcwd, latestdir); +#endif } } break; case 'C': /* Chdir */ - /* Update the latest directory. */ - strlcpy(latestdir, p, sizeof(latestdir)); + /* Update lcwd and latest directory. */ + strlcpy(latestdir, p, sizeof(latestdir)); + strlcpy(lcwd, p, sizeof(lcwd)); + Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0); + Var_Set(ldir_vname, lcwd, VAR_GLOBAL, 0); +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, lcwd); +#endif break; case 'M': /* renaMe */ - if (Lst_IsEmpty(missingFiles)) - break; + /* + * For 'M'oves we want to check + * the src as for 'R'ead + * and the target as for 'W'rite. + */ + cp = p; /* save this for a second */ + /* now get target */ + if (strsep(&p, " ") == NULL) + continue; + CHECK_VALID_META(p); + move_target = p; + p = cp; /* 'L' and 'M' put single quotes around the args */ - if (*p == '\'') { - char *ep; - - p++; - if ((ep = strchr(p, '\''))) - *ep = '\0'; - } + DEQUOTE(p); + DEQUOTE(move_target); /* FALLTHROUGH */ case 'D': /* unlink */ if (*p == '/' && !Lst_IsEmpty(missingFiles)) { @@ -1013,23 +1117,42 @@ meta_oodate(GNode *gn, Boolean oodate) char *tp = Lst_Datum(ln); Lst_Remove(missingFiles, ln); free(tp); + ln = NULL; /* we're done with it */ } } + if (buf[0] == 'M') { + /* the target of the mv is a file 'W'ritten */ +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "meta_oodate: M %s -> %s\n", + p, move_target); +#endif + p = move_target; + goto check_write; + } break; case 'L': /* Link */ - /* we want the target */ + /* + * For 'L'inks check + * the src as for 'R'ead + * and the target as for 'W'rite. + */ + link_src = p; + /* now get target */ if (strsep(&p, " ") == NULL) continue; + CHECK_VALID_META(p); /* 'L' and 'M' put single quotes around the args */ - if (*p == '\'') { - char *ep; - - p++; - if ((ep = strchr(p, '\''))) - *ep = '\0'; - } + DEQUOTE(p); + DEQUOTE(link_src); +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "meta_oodate: L %s -> %s\n", + link_src, p); +#endif /* FALLTHROUGH */ case 'W': /* Write */ + check_write: /* * If a file we generated within our bailiwick * but outside of .OBJDIR is missing, @@ -1061,6 +1184,14 @@ meta_oodate(GNode *gn, Boolean oodate) Lst_AtEnd(missingFiles, bmake_strdup(p)); } break; + check_link_src: + p = link_src; + link_src = NULL; +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "meta_oodate: L src %s\n", p); +#endif + /* FALLTHROUGH */ case 'R': /* Read */ case 'E': /* Exec */ /* @@ -1068,20 +1199,25 @@ meta_oodate(GNode *gn, Boolean oodate) * be part of the dependencies because * they are _expected_ to change. */ - if (strncmp(p, "/tmp/", 5) == 0 || - (tmplen > 0 && strncmp(p, tmpdir, tmplen) == 0)) - break; - - if (strncmp(p, "/var/", 5) == 0) - break; - - /* Ignore device files. */ - if (strncmp(p, "/dev/", 5) == 0) + if (*p == '/' && + Lst_ForEach(metaIgnorePaths, prefix_match, p)) { +#ifdef DEBUG_META_MODE + if (DEBUG(META)) + fprintf(debug_file, "meta_oodate: ignoring: %s\n", + p); +#endif break; + } - /* Ignore /etc/ files. */ - if (strncmp(p, "/etc/", 5) == 0) - break; + if ((cp = strrchr(p, '/'))) { + cp++; + /* + * We don't normally expect to see this, + * but we do expect it to change. + */ + if (strcmp(cp, makeDependfile) == 0) + break; + } /* * The rest of the record is the file name. @@ -1103,11 +1239,16 @@ meta_oodate(GNode *gn, Boolean oodate) snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p); sdirs[sdx++] = fname1; - if (strcmp(latestdir, cwd) != 0) { - /* Check vs cwd */ - snprintf(fname2, sizeof(fname2), "%s/%s", cwd, p); + if (strcmp(latestdir, lcwd) != 0) { + /* Check vs lcwd */ + snprintf(fname2, sizeof(fname2), "%s/%s", lcwd, p); sdirs[sdx++] = fname2; } + if (strcmp(lcwd, cwd) != 0) { + /* Check vs cwd */ + snprintf(fname3, sizeof(fname3), "%s/%s", cwd, p); + sdirs[sdx++] = fname3; + } } sdirs[sdx++] = NULL; @@ -1146,10 +1287,16 @@ meta_oodate(GNode *gn, Boolean oodate) oodate = TRUE; } } + if (buf[0] == 'E') { + /* previous latestdir is no longer relevant */ + strlcpy(latestdir, lcwd, sizeof(latestdir)); + } break; default: break; } + if (!oodate && buf[0] == 'L' && link_src != NULL) + goto check_link_src; } else if (strcmp(buf, "CMD") == 0) { /* * Compare the current command with the one in the @@ -1161,17 +1308,19 @@ meta_oodate(GNode *gn, Boolean oodate) oodate = TRUE; } else { char *cmd = (char *)Lst_Datum(ln); - - if (!ignoreOODATE) { - if (strstr(cmd, "$?")) - ignoreOODATE = TRUE; - else if ((cp = strstr(cmd, ".OODATE"))) { - /* check for $[{(].OODATE[)}] */ - if (cp > cmd + 2 && cp[-2] == '$') - ignoreOODATE = TRUE; - } - if (ignoreOODATE && DEBUG(META)) - fprintf(debug_file, "%s: %d: cannot compare commands using .OODATE\n", fname, lineno); + Boolean hasOODATE = FALSE; + + if (strstr(cmd, "$?")) + hasOODATE = TRUE; + else if ((cp = strstr(cmd, ".OODATE"))) { + /* check for $[{(].OODATE[:)}] */ + if (cp > cmd + 2 && cp[-2] == '$') + hasOODATE = TRUE; + } + if (hasOODATE) { + needOODATE = TRUE; + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno); } cmd = Var_Subst(NULL, cmd, gn, TRUE); @@ -1200,7 +1349,7 @@ meta_oodate(GNode *gn, Boolean oodate) if (buf[x - 1] == '\n') buf[x - 1] = '\0'; } - if (!ignoreOODATE && + if (!hasOODATE && !(gn->type & OP_NOMETA_CMP) && strcmp(p, cmd) != 0) { if (DEBUG(META)) @@ -1237,15 +1386,23 @@ meta_oodate(GNode *gn, Boolean oodate) oodate = TRUE; Lst_Destroy(missingFiles, (FreeProc *)free); } + } else { + if ((gn->type & OP_META)) { + if (DEBUG(META)) + fprintf(debug_file, "%s: required but missing\n", fname); + oodate = TRUE; + } } - if (oodate && ignoreOODATE) { + if (oodate && needOODATE) { /* - * Target uses .OODATE, so we need to re-compute it. - * We need to clean up what Make_DoAllVar() did. + * Target uses .OODATE which is empty; or we wouldn't be here. + * We have decided it is oodate, so .OODATE needs to be set. + * All we can sanely do is set it to .ALLSRC. */ - Var_Delete(ALLSRC, gn); Var_Delete(OODATE, gn); - gn->flags &= ~DONE_ALLSRC; + Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn, 0); + if (cp) + free(cp); } return oodate; } |