Module Name: src Committed By: sjg Date: Thu Dec 9 22:30:17 UTC 2010
Modified Files: src/usr.bin/make: main.c meta.c nonints.h Log Message: meta_oodate(): we should track 'latestdir' on a per process basis. Also, only consider target out of date if a not-found file is outside 'CWD'. Ignore anything in "/tmp/" or tmpdir. To generate a diff of this commit: cvs rdiff -u -r1.190 -r1.191 src/usr.bin/make/main.c cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/meta.c cvs rdiff -u -r1.60 -r1.61 src/usr.bin/make/nonints.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/main.c diff -u src/usr.bin/make/main.c:1.190 src/usr.bin/make/main.c:1.191 --- src/usr.bin/make/main.c:1.190 Mon Sep 13 15:36:57 2010 +++ src/usr.bin/make/main.c Thu Dec 9 22:30:16 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $ */ +/* $NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1993 @@ -69,7 +69,7 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $"; +static char rcsid[] = "$NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $"; #else #include <sys/cdefs.h> #ifndef lint @@ -81,7 +81,7 @@ #if 0 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: main.c,v 1.190 2010/09/13 15:36:57 sjg Exp $"); +__RCSID("$NetBSD: main.c,v 1.191 2010/12/09 22:30:16 sjg Exp $"); #endif #endif /* not lint */ #endif @@ -1966,20 +1966,10 @@ } } -/* - * Create and open a temp file using "pattern". - * If "fnamep" is provided set it to a copy of the filename created. - * Otherwise unlink the file once open. - */ -int -mkTempFile(const char *pattern, char **fnamep) +char * +getTmpdir(void) { static char *tmpdir = NULL; - char tfile[MAXPATHLEN]; - int fd; - - if (!pattern) - pattern = TMPPAT; if (!tmpdir) { struct stat st; @@ -1994,6 +1984,25 @@ tmpdir = bmake_strdup(_PATH_TMP); } } + return tmpdir; +} + +/* + * Create and open a temp file using "pattern". + * If "fnamep" is provided set it to a copy of the filename created. + * Otherwise unlink the file once open. + */ +int +mkTempFile(const char *pattern, char **fnamep) +{ + static char *tmpdir = NULL; + char tfile[MAXPATHLEN]; + int fd; + + if (!pattern) + pattern = TMPPAT; + if (!tmpdir) + tmpdir = getTmpdir(); if (pattern[0] == '/') { snprintf(tfile, sizeof(tfile), "%s", pattern); } else { Index: src/usr.bin/make/meta.c diff -u src/usr.bin/make/meta.c:1.4 src/usr.bin/make/meta.c:1.5 --- src/usr.bin/make/meta.c:1.4 Sat Nov 27 05:02:35 2010 +++ src/usr.bin/make/meta.c Thu Dec 9 22:30:17 2010 @@ -695,15 +695,24 @@ /* * 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. + * We have to track the latestdir on a per-process basis. */ +#define LDIR_VNAME_FMT ".meta.%d.ldir" + Boolean meta_oodate(GNode *gn, Boolean oodate) { + static char *tmpdir = NULL; + char ldir_vname[64]; + char cwd[MAXPATHLEN]; char latestdir[MAXPATHLEN]; char fname[MAXPATHLEN]; char fname1[MAXPATHLEN]; + char fname2[MAXPATHLEN]; char *p; char *cp; + size_t cwdlen; + size_t tmplen = 0; FILE *fp; Boolean ignoreOODATE = FALSE; @@ -718,7 +727,7 @@ */ Make_DoAllVar(gn); - if (getcwd(latestdir, sizeof(latestdir)) == NULL) + if (getcwd(cwd, sizeof(cwd)) == NULL) err(1, "Could not get current working directory"); meta_name(gn, fname, sizeof(fname), NULL, NULL); @@ -727,6 +736,8 @@ static char *buf = NULL; static size_t bufsz; int lineno = 0; + int lastpid = 0; + int pid; int f = 0; int x; LstNode ln; @@ -736,10 +747,17 @@ bufsz = 8 * BUFSIZ; buf = bmake_malloc(bufsz); } - + + if (!tmpdir) { + tmpdir = getTmpdir(); + tmplen = strlen(tmpdir); + } + /* we want to track all the .meta we read */ Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL); + cwdlen = strlen(cwd); + ln = Lst_First(gn->commands); while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) { lineno++; @@ -764,28 +782,102 @@ p = buf; strsep(&p, " "); if (f) { + /* + * We are in the 'filemon' output section. + * Each record from filemon follows the general form: + * + * <key> <pid> <data> + * + * Where: + * <key> is a single letter, denoting the syscall. + * <pid> is the process that made the syscall. + * <data> is the arguments (of interest). + */ + switch(buf[0]) { + case '#': /* comment */ + case 'V': /* version */ + break; + default: + /* + * We need to track pathnames per-process. + * + * Each process run by make, starts off in the 'CWD' + * recorded in the .meta file, if it chdirs ('C') + * elsewhere we need to track that - but only for + * that process. If it forks ('F'), we initialize + * the child to have the same cwd as its parent. + * + * We also need to track the 'latestdir' of + * interest. This is usually the same as cwd, but + * not if a process is reading directories. + * + * Each time we spot a different process ('pid') + * we save the current value of 'latestdir' in a + * variable qualified by 'lastpid', and + * re-initialize 'latestdir' to any pre-saved + * value for the current 'pid' and 'CWD' if none. + */ + pid = atoi(p); + if (pid > 0 && pid != lastpid) { + char *ldir; + char *tp; + + if (lastpid > 0) { + /* We need to remember this. */ + Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0); + } + snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid); + lastpid = pid; + ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp); + if (ldir) { + strlcpy(latestdir, ldir, sizeof(latestdir)); + if (tp) + free(tp); + } else + strlcpy(latestdir, cwd, sizeof(latestdir)); + } + /* Skip past the pid. */ + if (strsep(&p, " ") == NULL) + continue; + break; + } + /* Process according to record type. */ switch (buf[0]) { - case 'C': - /* Skip the pid. */ - if (strsep(&p, " ") == NULL) - break; + case 'X': /* eXit */ + Var_Delete(ldir_vname, VAR_GLOBAL); + lastpid = 0; /* no need to save ldir_vname */ + break; + case 'F': /* [v]Fork */ + { + char cldir[64]; + int child; + + child = atoi(p); + if (child > 0) { + snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child); + Var_Set(cldir, latestdir, VAR_GLOBAL, 0); + } + } + break; + + case 'C': /* Chdir */ /* Update the latest directory. */ strlcpy(latestdir, p, sizeof(latestdir)); break; - case 'R': - case 'E': - /* Skip the pid. */ - if (strsep(&p, " ") == NULL) - break; - + case 'R': /* Read */ + case 'E': /* Exec */ /* * Check for runtime files that can't * be part of the dependencies because * they are _expected_ to change. */ + if (strncmp(p, "/tmp/", 5) == 0 || + strncmp(p, tmpdir, tmplen) == 0) + break; + if (strncmp(p, "/var/", 5) == 0) break; @@ -798,39 +890,69 @@ break; /* - * The rest of the record is the - * file name. - * Check if it's not an absolute - * path. + * The rest of the record is the file name. + * Check if it's not an absolute path. */ - if (*p != '/') { - /* Use the latest path seen. */ - snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p); - p = fname1; - } + { + char *sdirs[4]; + char **sdp; + int sdx = 0; + int found = 0; + + if (*p == '/') { + sdirs[sdx++] = p; /* done */ + } else { + if (strcmp(".", p) == 0) + continue; /* no point */ + + /* Check vs latestdir */ + 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); + sdirs[sdx++] = fname2; + } + } + sdirs[sdx++] = NULL; - if (stat(p, &fs) == 0) { - if (!S_ISDIR(fs.st_mode) && - fs.st_mtime > gn->mtime) { + for (sdp = sdirs; *sdp && !found; sdp++) { + if (stat(*sdp, &fs) == 0) { + found = 1; + p = *sdp; + } + } + if (found) { + if (!S_ISDIR(fs.st_mode) && + fs.st_mtime > gn->mtime) { + if (DEBUG(META)) + fprintf(debug_file, "%s: %d: file '%s' is newer than the target...\n", fname, lineno, p); + oodate = TRUE; + } else if (S_ISDIR(fs.st_mode)) { + /* Update the latest directory. */ + realpath(p, latestdir); + } + } else if (errno == ENOENT && *p == '/' && + strncmp(p, cwd, cwdlen) != 0) { + /* + * A referenced file outside of CWD is missing. + * We cannot catch every eventuality here... + */ if (DEBUG(META)) - fprintf(debug_file, "%s: %d: file '%s' is newer than the target...\n", fname, lineno, p); + fprintf(debug_file, "%s: %d: file '%s' may have moved?...\n", fname, lineno, p); oodate = TRUE; } - } else if (errno == ENOENT) { - if (DEBUG(META)) - fprintf(debug_file, "%s: %d: file '%s' may have moved?...\n", fname, lineno, p); - oodate = TRUE; } break; default: break; } - + } else if (strcmp(buf, "CMD") == 0) { /* * Compare the current command with the one in the * meta data file. */ - } else if (strcmp(buf, "CMD") == 0) { if (ln == NULL) { if (DEBUG(META)) fprintf(debug_file, "%s: %d: there were more build commands in the meta data file than there are now...\n", fname, lineno); Index: src/usr.bin/make/nonints.h diff -u src/usr.bin/make/nonints.h:1.60 src/usr.bin/make/nonints.h:1.61 --- src/usr.bin/make/nonints.h:1.60 Sat Aug 7 06:44:08 2010 +++ src/usr.bin/make/nonints.h Thu Dec 9 22:30:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: nonints.h,v 1.60 2010/08/07 06:44:08 sjg Exp $ */ +/* $NetBSD: nonints.h,v 1.61 2010/12/09 22:30:17 sjg Exp $ */ /*- * Copyright (c) 1988, 1989, 1990, 1993 @@ -124,6 +124,7 @@ void Finish(int); int eunlink(const char *); void execError(const char *, const char *); +char *getTmpdir(void); /* parse.c */ void Parse_Error(int, const char *, ...)