xref: /dragonfly/contrib/bmake/meta.c (revision e4adeac1)
1 /*      $NetBSD: meta.c,v 1.86 2020/07/11 00:39:53 sjg Exp $ */
2 
3 /*
4  * Implement 'meta' mode.
5  * Adapted from John Birrell's patches to FreeBSD make.
6  * --sjg
7  */
8 /*
9  * Copyright (c) 2009-2016, Juniper Networks, Inc.
10  * Portions Copyright (c) 2009, John Birrell.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #if defined(USE_META)
34 
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38 #include <sys/stat.h>
39 #ifdef HAVE_LIBGEN_H
40 #include <libgen.h>
41 #elif !defined(HAVE_DIRNAME)
42 char * dirname(char *);
43 #endif
44 #include <errno.h>
45 #if !defined(HAVE_CONFIG_H) || defined(HAVE_ERR_H)
46 #include <err.h>
47 #endif
48 
49 #include "make.h"
50 #include "job.h"
51 
52 #ifdef USE_FILEMON
53 #include "filemon/filemon.h"
54 #endif
55 
56 static BuildMon Mybm;			/* for compat */
57 static Lst metaBailiwick;		/* our scope of control */
58 static char *metaBailiwickStr;		/* string storage for the list */
59 static Lst metaIgnorePaths;		/* paths we deliberately ignore */
60 static char *metaIgnorePathsStr;	/* string storage for the list */
61 
62 #ifndef MAKE_META_IGNORE_PATHS
63 #define MAKE_META_IGNORE_PATHS ".MAKE.META.IGNORE_PATHS"
64 #endif
65 #ifndef MAKE_META_IGNORE_PATTERNS
66 #define MAKE_META_IGNORE_PATTERNS ".MAKE.META.IGNORE_PATTERNS"
67 #endif
68 #ifndef MAKE_META_IGNORE_FILTER
69 #define MAKE_META_IGNORE_FILTER ".MAKE.META.IGNORE_FILTER"
70 #endif
71 
72 Boolean useMeta = FALSE;
73 static Boolean useFilemon = FALSE;
74 static Boolean writeMeta = FALSE;
75 static Boolean metaMissing = FALSE;	/* oodate if missing */
76 static Boolean filemonMissing = FALSE;	/* oodate if missing */
77 static Boolean metaEnv = FALSE;		/* don't save env unless asked */
78 static Boolean metaVerbose = FALSE;
79 static Boolean metaIgnoreCMDs = FALSE;	/* ignore CMDs in .meta files */
80 static Boolean metaIgnorePatterns = FALSE; /* do we need to do pattern matches */
81 static Boolean metaIgnoreFilter = FALSE;   /* do we have more complex filtering? */
82 static Boolean metaCurdirOk = FALSE;	/* write .meta in .CURDIR Ok? */
83 static Boolean metaSilent = FALSE;	/* if we have a .meta be SILENT */
84 
85 extern Boolean forceJobs;
86 extern Boolean comatMake;
87 extern char    **environ;
88 
89 #define	MAKE_META_PREFIX	".MAKE.META.PREFIX"
90 
91 #ifndef N2U
92 # define N2U(n, u)   (((n) + ((u) - 1)) / (u))
93 #endif
94 #ifndef ROUNDUP
95 # define ROUNDUP(n, u)   (N2U((n), (u)) * (u))
96 #endif
97 
98 #if !defined(HAVE_STRSEP)
99 # define strsep(s, d) stresep((s), (d), 0)
100 #endif
101 
102 /*
103  * Filemon is a kernel module which snoops certain syscalls.
104  *
105  * C chdir
106  * E exec
107  * F [v]fork
108  * L [sym]link
109  * M rename
110  * R read
111  * W write
112  * S stat
113  *
114  * See meta_oodate below - we mainly care about 'E' and 'R'.
115  *
116  * We can still use meta mode without filemon, but
117  * the benefits are more limited.
118  */
119 #ifdef USE_FILEMON
120 
121 /*
122  * Open the filemon device.
123  */
124 static void
125 meta_open_filemon(BuildMon *pbm)
126 {
127     int dupfd;
128 
129     pbm->mon_fd = -1;
130     pbm->filemon = NULL;
131     if (!useFilemon || !pbm->mfp)
132 	return;
133 
134     pbm->filemon = filemon_open();
135     if (pbm->filemon == NULL) {
136 	useFilemon = FALSE;
137 	warn("Could not open filemon %s", filemon_path());
138 	return;
139     }
140 
141     /*
142      * We use a file outside of '.'
143      * to avoid a FreeBSD kernel bug where unlink invalidates
144      * cwd causing getcwd to do a lot more work.
145      * We only care about the descriptor.
146      */
147     pbm->mon_fd = mkTempFile("filemon.XXXXXX", NULL);
148     if ((dupfd = dup(pbm->mon_fd)) == -1) {
149 	err(1, "Could not dup filemon output!");
150     }
151     (void)fcntl(dupfd, F_SETFD, FD_CLOEXEC);
152     if (filemon_setfd(pbm->filemon, dupfd) == -1) {
153 	err(1, "Could not set filemon file descriptor!");
154     }
155     /* we don't need these once we exec */
156     (void)fcntl(pbm->mon_fd, F_SETFD, FD_CLOEXEC);
157 }
158 
159 /*
160  * Read the build monitor output file and write records to the target's
161  * metadata file.
162  */
163 static int
164 filemon_read(FILE *mfp, int fd)
165 {
166     char buf[BUFSIZ];
167     int n;
168     int error;
169 
170     /* Check if we're not writing to a meta data file.*/
171     if (mfp == NULL) {
172 	if (fd >= 0)
173 	    close(fd);			/* not interested */
174 	return 0;
175     }
176     /* rewind */
177     if (lseek(fd, (off_t)0, SEEK_SET) < 0) {
178 	error = errno;
179 	warn("Could not rewind filemon");
180 	fprintf(mfp, "\n");
181     } else {
182 	error = 0;
183 	fprintf(mfp, "\n-- filemon acquired metadata --\n");
184 
185 	while ((n = read(fd, buf, sizeof(buf))) > 0) {
186 	    if ((int)fwrite(buf, 1, n, mfp) < n)
187 		error = EIO;
188 	}
189     }
190     fflush(mfp);
191     if (close(fd) < 0)
192 	error = errno;
193     return error;
194 }
195 #endif
196 
197 /*
198  * when realpath() fails,
199  * we use this, to clean up ./ and ../
200  */
201 static void
202 eat_dots(char *buf, size_t bufsz, int dots)
203 {
204     char *cp;
205     char *cp2;
206     const char *eat;
207     size_t eatlen;
208 
209     switch (dots) {
210     case 1:
211 	eat = "/./";
212 	eatlen = 2;
213 	break;
214     case 2:
215 	eat = "/../";
216 	eatlen = 3;
217 	break;
218     default:
219 	return;
220     }
221 
222     do {
223 	cp = strstr(buf, eat);
224 	if (cp) {
225 	    cp2 = cp + eatlen;
226 	    if (dots == 2 && cp > buf) {
227 		do {
228 		    cp--;
229 		} while (cp > buf && *cp != '/');
230 	    }
231 	    if (*cp == '/') {
232 		strlcpy(cp, cp2, bufsz - (cp - buf));
233 	    } else {
234 		return;			/* can't happen? */
235 	    }
236 	}
237     } while (cp);
238 }
239 
240 static char *
241 meta_name(char *mname, size_t mnamelen,
242 	  const char *dname,
243 	  const char *tname,
244 	  const char *cwd)
245 {
246     char buf[MAXPATHLEN];
247     char *rp;
248     char *cp;
249     char *tp;
250     char *dtp;
251     size_t ldname;
252 
253     /*
254      * Weed out relative paths from the target file name.
255      * We have to be careful though since if target is a
256      * symlink, the result will be unstable.
257      * So we use realpath() just to get the dirname, and leave the
258      * basename as given to us.
259      */
260     if ((cp = strrchr(tname, '/'))) {
261 	if (cached_realpath(tname, buf)) {
262 	    if ((rp = strrchr(buf, '/'))) {
263 		rp++;
264 		cp++;
265 		if (strcmp(cp, rp) != 0)
266 		    strlcpy(rp, cp, sizeof(buf) - (rp - buf));
267 	    }
268 	    tname = buf;
269 	} else {
270 	    /*
271 	     * We likely have a directory which is about to be made.
272 	     * We pretend realpath() succeeded, to have a chance
273 	     * of generating the same meta file name that we will
274 	     * next time through.
275 	     */
276 	    if (tname[0] == '/') {
277 		strlcpy(buf, tname, sizeof(buf));
278 	    } else {
279 		snprintf(buf, sizeof(buf), "%s/%s", cwd, tname);
280 	    }
281 	    eat_dots(buf, sizeof(buf), 1);	/* ./ */
282 	    eat_dots(buf, sizeof(buf), 2);	/* ../ */
283 	    tname = buf;
284 	}
285     }
286     /* on some systems dirname may modify its arg */
287     tp = bmake_strdup(tname);
288     dtp = dirname(tp);
289     if (strcmp(dname, dtp) == 0)
290 	snprintf(mname, mnamelen, "%s.meta", tname);
291     else {
292 	ldname = strlen(dname);
293 	if (strncmp(dname, dtp, ldname) == 0 && dtp[ldname] == '/')
294 	    snprintf(mname, mnamelen, "%s/%s.meta", dname, &tname[ldname+1]);
295 	else
296 	    snprintf(mname, mnamelen, "%s/%s.meta", dname, tname);
297 
298 	/*
299 	 * Replace path separators in the file name after the
300 	 * current object directory path.
301 	 */
302 	cp = mname + strlen(dname) + 1;
303 
304 	while (*cp != '\0') {
305 	    if (*cp == '/')
306 		*cp = '_';
307 	    cp++;
308 	}
309     }
310     free(tp);
311     return mname;
312 }
313 
314 /*
315  * Return true if running ${.MAKE}
316  * Bypassed if target is flagged .MAKE
317  */
318 static int
319 is_submake(void *cmdp, void *gnp)
320 {
321     static char *p_make = NULL;
322     static int p_len;
323     char  *cmd = cmdp;
324     GNode *gn = gnp;
325     char *mp = NULL;
326     char *cp;
327     char *cp2;
328     int rc = 0;				/* keep looking */
329 
330     if (!p_make) {
331 	p_make = Var_Value(".MAKE", gn, &cp);
332 	p_len = strlen(p_make);
333     }
334     cp = strchr(cmd, '$');
335     if ((cp)) {
336 	mp = Var_Subst(NULL, cmd, gn, VARF_WANTRES);
337 	cmd = mp;
338     }
339     cp2 = strstr(cmd, p_make);
340     if ((cp2)) {
341 	switch (cp2[p_len]) {
342 	case '\0':
343 	case ' ':
344 	case '\t':
345 	case '\n':
346 	    rc = 1;
347 	    break;
348 	}
349 	if (cp2 > cmd && rc > 0) {
350 	    switch (cp2[-1]) {
351 	    case ' ':
352 	    case '\t':
353 	    case '\n':
354 		break;
355 	    default:
356 		rc = 0;			/* no match */
357 		break;
358 	    }
359 	}
360     }
361     free(mp);
362     return rc;
363 }
364 
365 typedef struct meta_file_s {
366     FILE *fp;
367     GNode *gn;
368 } meta_file_t;
369 
370 static int
371 printCMD(void *cmdp, void *mfpp)
372 {
373     meta_file_t *mfp = mfpp;
374     char *cmd = cmdp;
375     char *cp = NULL;
376 
377     if (strchr(cmd, '$')) {
378 	cmd = cp = Var_Subst(NULL, cmd, mfp->gn, VARF_WANTRES);
379     }
380     fprintf(mfp->fp, "CMD %s\n", cmd);
381     free(cp);
382     return 0;
383 }
384 
385 /*
386  * Certain node types never get a .meta file
387  */
388 #define SKIP_META_TYPE(_type) do { \
389     if ((gn->type & __CONCAT(OP_, _type))) {	\
390 	if (verbose) { \
391 	    fprintf(debug_file, "Skipping meta for %s: .%s\n", \
392 		    gn->name, __STRING(_type));		       \
393 	} \
394 	return FALSE; \
395     } \
396 } while (0)
397 
398 
399 /*
400  * Do we need/want a .meta file ?
401  */
402 static Boolean
403 meta_needed(GNode *gn, const char *dname,
404 	     char *objdir, int verbose)
405 {
406     struct stat fs;
407 
408     if (verbose)
409 	verbose = DEBUG(META);
410 
411     /* This may be a phony node which we don't want meta data for... */
412     /* Skip .meta for .BEGIN, .END, .ERROR etc as well. */
413     /* Or it may be explicitly flagged as .NOMETA */
414     SKIP_META_TYPE(NOMETA);
415     /* Unless it is explicitly flagged as .META */
416     if (!(gn->type & OP_META)) {
417 	SKIP_META_TYPE(PHONY);
418 	SKIP_META_TYPE(SPECIAL);
419 	SKIP_META_TYPE(MAKE);
420     }
421 
422     /* Check if there are no commands to execute. */
423     if (Lst_IsEmpty(gn->commands)) {
424 	if (verbose)
425 	    fprintf(debug_file, "Skipping meta for %s: no commands\n",
426 		    gn->name);
427 	return FALSE;
428     }
429     if ((gn->type & (OP_META|OP_SUBMAKE)) == OP_SUBMAKE) {
430 	/* OP_SUBMAKE is a bit too aggressive */
431 	if (Lst_ForEach(gn->commands, is_submake, gn)) {
432 	    if (DEBUG(META))
433 		fprintf(debug_file, "Skipping meta for %s: .SUBMAKE\n",
434 			gn->name);
435 	    return FALSE;
436 	}
437     }
438 
439     /* The object directory may not exist. Check it.. */
440     if (cached_stat(dname, &fs) != 0) {
441 	if (verbose)
442 	    fprintf(debug_file, "Skipping meta for %s: no .OBJDIR\n",
443 		    gn->name);
444 	return FALSE;
445     }
446 
447     /* make sure these are canonical */
448     if (cached_realpath(dname, objdir))
449 	dname = objdir;
450 
451     /* If we aren't in the object directory, don't create a meta file. */
452     if (!metaCurdirOk && strcmp(curdir, dname) == 0) {
453 	if (verbose)
454 	    fprintf(debug_file, "Skipping meta for %s: .OBJDIR == .CURDIR\n",
455 		    gn->name);
456 	return FALSE;
457     }
458     return TRUE;
459 }
460 
461 
462 static FILE *
463 meta_create(BuildMon *pbm, GNode *gn)
464 {
465     meta_file_t mf;
466     char buf[MAXPATHLEN];
467     char objdir[MAXPATHLEN];
468     char **ptr;
469     const char *dname;
470     const char *tname;
471     char *fname;
472     const char *cp;
473     char *p[5];				/* >= possible uses */
474     int i;
475 
476     mf.fp = NULL;
477     i = 0;
478 
479     dname = Var_Value(".OBJDIR", gn, &p[i++]);
480     tname = Var_Value(TARGET, gn, &p[i++]);
481 
482     /* if this succeeds objdir is realpath of dname */
483     if (!meta_needed(gn, dname, objdir, TRUE))
484 	goto out;
485     dname = objdir;
486 
487     if (metaVerbose) {
488 	char *mp;
489 
490 	/* Describe the target we are building */
491 	mp = Var_Subst(NULL, "${" MAKE_META_PREFIX "}", gn, VARF_WANTRES);
492 	if (*mp)
493 	    fprintf(stdout, "%s\n", mp);
494 	free(mp);
495     }
496     /* Get the basename of the target */
497     if ((cp = strrchr(tname, '/')) == NULL) {
498 	cp = tname;
499     } else {
500 	cp++;
501     }
502 
503     fflush(stdout);
504 
505     if (!writeMeta)
506 	/* Don't create meta data. */
507 	goto out;
508 
509     fname = meta_name(pbm->meta_fname, sizeof(pbm->meta_fname),
510 		      dname, tname, objdir);
511 
512 #ifdef DEBUG_META_MODE
513     if (DEBUG(META))
514 	fprintf(debug_file, "meta_create: %s\n", fname);
515 #endif
516 
517     if ((mf.fp = fopen(fname, "w")) == NULL)
518 	err(1, "Could not open meta file '%s'", fname);
519 
520     fprintf(mf.fp, "# Meta data file %s\n", fname);
521 
522     mf.gn = gn;
523 
524     Lst_ForEach(gn->commands, printCMD, &mf);
525 
526     fprintf(mf.fp, "CWD %s\n", getcwd(buf, sizeof(buf)));
527     fprintf(mf.fp, "TARGET %s\n", tname);
528     cp = Var_Value(".OODATE", gn, &p[i++]);
529     if (cp && *cp) {
530 	    fprintf(mf.fp, "OODATE %s\n", cp);
531     }
532     if (metaEnv) {
533 	for (ptr = environ; *ptr != NULL; ptr++)
534 	    fprintf(mf.fp, "ENV %s\n", *ptr);
535     }
536 
537     fprintf(mf.fp, "-- command output --\n");
538     fflush(mf.fp);
539 
540     Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL);
541     Var_Append(".MAKE.META.CREATED", fname, VAR_GLOBAL);
542 
543     gn->type |= OP_META;		/* in case anyone wants to know */
544     if (metaSilent) {
545 	    gn->type |= OP_SILENT;
546     }
547  out:
548     for (i--; i >= 0; i--) {
549 	free(p[i]);
550     }
551 
552     return mf.fp;
553 }
554 
555 static Boolean
556 boolValue(char *s)
557 {
558     switch(*s) {
559     case '0':
560     case 'N':
561     case 'n':
562     case 'F':
563     case 'f':
564 	return FALSE;
565     }
566     return TRUE;
567 }
568 
569 /*
570  * Initialization we need before reading makefiles.
571  */
572 void
573 meta_init(void)
574 {
575 #ifdef USE_FILEMON
576 	/* this allows makefiles to test if we have filemon support */
577 	Var_Set(".MAKE.PATH_FILEMON", filemon_path(), VAR_GLOBAL);
578 #endif
579 }
580 
581 
582 #define get_mode_bf(bf, token) \
583     if ((cp = strstr(make_mode, token))) \
584 	bf = boolValue(&cp[sizeof(token) - 1])
585 
586 /*
587  * Initialization we need after reading makefiles.
588  */
589 void
590 meta_mode_init(const char *make_mode)
591 {
592     static int once = 0;
593     char *cp;
594 
595     useMeta = TRUE;
596     useFilemon = TRUE;
597     writeMeta = TRUE;
598 
599     if (make_mode) {
600 	if (strstr(make_mode, "env"))
601 	    metaEnv = TRUE;
602 	if (strstr(make_mode, "verb"))
603 	    metaVerbose = TRUE;
604 	if (strstr(make_mode, "read"))
605 	    writeMeta = FALSE;
606 	if (strstr(make_mode, "nofilemon"))
607 	    useFilemon = FALSE;
608 	if (strstr(make_mode, "ignore-cmd"))
609 	    metaIgnoreCMDs = TRUE;
610 	if (useFilemon)
611 	    get_mode_bf(filemonMissing, "missing-filemon=");
612 	get_mode_bf(metaCurdirOk, "curdirok=");
613 	get_mode_bf(metaMissing, "missing-meta=");
614 	get_mode_bf(metaSilent, "silent=");
615     }
616     if (metaVerbose && !Var_Exists(MAKE_META_PREFIX, VAR_GLOBAL)) {
617 	/*
618 	 * The default value for MAKE_META_PREFIX
619 	 * prints the absolute path of the target.
620 	 * This works be cause :H will generate '.' if there is no /
621 	 * and :tA will resolve that to cwd.
622 	 */
623 	Var_Set(MAKE_META_PREFIX, "Building ${.TARGET:H:tA}/${.TARGET:T}", VAR_GLOBAL);
624     }
625     if (once)
626 	return;
627     once = 1;
628     memset(&Mybm, 0, sizeof(Mybm));
629     /*
630      * We consider ourselves master of all within ${.MAKE.META.BAILIWICK}
631      */
632     metaBailiwick = Lst_Init(FALSE);
633     metaBailiwickStr = Var_Subst(NULL, "${.MAKE.META.BAILIWICK:O:u:tA}",
634 	VAR_GLOBAL, VARF_WANTRES);
635     if (metaBailiwickStr) {
636 	str2Lst_Append(metaBailiwick, metaBailiwickStr, NULL);
637     }
638     /*
639      * We ignore any paths that start with ${.MAKE.META.IGNORE_PATHS}
640      */
641     metaIgnorePaths = Lst_Init(FALSE);
642     Var_Append(MAKE_META_IGNORE_PATHS,
643 	       "/dev /etc /proc /tmp /var/run /var/tmp ${TMPDIR}", VAR_GLOBAL);
644     metaIgnorePathsStr = Var_Subst(NULL,
645 		   "${" MAKE_META_IGNORE_PATHS ":O:u:tA}", VAR_GLOBAL,
646 		   VARF_WANTRES);
647     if (metaIgnorePathsStr) {
648 	str2Lst_Append(metaIgnorePaths, metaIgnorePathsStr, NULL);
649     }
650 
651     /*
652      * We ignore any paths that match ${.MAKE.META.IGNORE_PATTERNS}
653      */
654     cp = NULL;
655     if (Var_Value(MAKE_META_IGNORE_PATTERNS, VAR_GLOBAL, &cp)) {
656 	metaIgnorePatterns = TRUE;
657 	free(cp);
658     }
659     cp = NULL;
660     if (Var_Value(MAKE_META_IGNORE_FILTER, VAR_GLOBAL, &cp)) {
661 	metaIgnoreFilter = TRUE;
662 	free(cp);
663     }
664 }
665 
666 /*
667  * In each case below we allow for job==NULL
668  */
669 void
670 meta_job_start(Job *job, GNode *gn)
671 {
672     BuildMon *pbm;
673 
674     if (job != NULL) {
675 	pbm = &job->bm;
676     } else {
677 	pbm = &Mybm;
678     }
679     pbm->mfp = meta_create(pbm, gn);
680 #ifdef USE_FILEMON_ONCE
681     /* compat mode we open the filemon dev once per command */
682     if (job == NULL)
683 	return;
684 #endif
685 #ifdef USE_FILEMON
686     if (pbm->mfp != NULL && useFilemon) {
687 	meta_open_filemon(pbm);
688     } else {
689 	pbm->mon_fd = -1;
690 	pbm->filemon = NULL;
691     }
692 #endif
693 }
694 
695 /*
696  * The child calls this before doing anything.
697  * It does not disturb our state.
698  */
699 void
700 meta_job_child(Job __unused *job)
701 {
702 #ifdef USE_FILEMON
703     BuildMon *pbm;
704 
705     if (job != NULL) {
706 	pbm = &job->bm;
707     } else {
708 	pbm = &Mybm;
709     }
710     if (pbm->mfp != NULL) {
711 	close(fileno(pbm->mfp));
712 	if (useFilemon && pbm->filemon) {
713 	    pid_t pid;
714 
715 	    pid = getpid();
716 	    if (filemon_setpid_child(pbm->filemon, pid) == -1) {
717 		err(1, "Could not set filemon pid!");
718 	    }
719 	}
720     }
721 #endif
722 }
723 
724 void
725 meta_job_parent(Job *job, pid_t pid)
726 {
727 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
728     BuildMon *pbm;
729 
730     if (job != NULL) {
731 	pbm = &job->bm;
732     } else {
733 	pbm = &Mybm;
734     }
735     if (useFilemon && pbm->filemon) {
736 	filemon_setpid_parent(pbm->filemon, pid);
737     }
738 #endif
739 }
740 
741 int
742 meta_job_fd(Job *job)
743 {
744 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
745     BuildMon *pbm;
746 
747     if (job != NULL) {
748 	pbm = &job->bm;
749     } else {
750 	pbm = &Mybm;
751     }
752     if (useFilemon && pbm->filemon) {
753 	return filemon_readfd(pbm->filemon);
754     }
755 #endif
756     return -1;
757 }
758 
759 int
760 meta_job_event(Job *job)
761 {
762 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
763     BuildMon *pbm;
764 
765     if (job != NULL) {
766 	pbm = &job->bm;
767     } else {
768 	pbm = &Mybm;
769     }
770     if (useFilemon && pbm->filemon) {
771 	return filemon_process(pbm->filemon);
772     }
773 #endif
774     return 0;
775 }
776 
777 void
778 meta_job_error(Job *job, GNode *gn, int flags, int status)
779 {
780     char cwd[MAXPATHLEN];
781     BuildMon *pbm;
782 
783     if (job != NULL) {
784 	pbm = &job->bm;
785 	if (!gn)
786 	    gn = job->node;
787     } else {
788 	pbm = &Mybm;
789     }
790     if (pbm->mfp != NULL) {
791 	fprintf(pbm->mfp, "\n*** Error code %d%s\n",
792 		status,
793 		(flags & JOB_IGNERR) ?
794 		"(ignored)" : "");
795     }
796     if (gn) {
797 	Var_Set(".ERROR_TARGET", gn->path ? gn->path : gn->name, VAR_GLOBAL);
798     }
799     getcwd(cwd, sizeof(cwd));
800     Var_Set(".ERROR_CWD", cwd, VAR_GLOBAL);
801     if (pbm->meta_fname[0]) {
802 	Var_Set(".ERROR_META_FILE", pbm->meta_fname, VAR_GLOBAL);
803     }
804     meta_job_finish(job);
805 }
806 
807 void
808 meta_job_output(Job *job, char *cp, const char *nl)
809 {
810     BuildMon *pbm;
811 
812     if (job != NULL) {
813 	pbm = &job->bm;
814     } else {
815 	pbm = &Mybm;
816     }
817     if (pbm->mfp != NULL) {
818 	if (metaVerbose) {
819 	    static char *meta_prefix = NULL;
820 	    static int meta_prefix_len;
821 
822 	    if (!meta_prefix) {
823 		char *cp2;
824 
825 		meta_prefix = Var_Subst(NULL, "${" MAKE_META_PREFIX "}",
826 					VAR_GLOBAL, VARF_WANTRES);
827 		if ((cp2 = strchr(meta_prefix, '$')))
828 		    meta_prefix_len = cp2 - meta_prefix;
829 		else
830 		    meta_prefix_len = strlen(meta_prefix);
831 	    }
832 	    if (strncmp(cp, meta_prefix, meta_prefix_len) == 0) {
833 		cp = strchr(cp+1, '\n');
834 		if (!cp++)
835 		    return;
836 	    }
837 	}
838 	fprintf(pbm->mfp, "%s%s", cp, nl);
839     }
840 }
841 
842 int
843 meta_cmd_finish(void __unused *pbmp)
844 {
845     int error = 0;
846     BuildMon *pbm = pbmp;
847 #ifdef USE_FILEMON
848     int x;
849 #endif
850 
851     if (!pbm)
852 	pbm = &Mybm;
853 
854 #ifdef USE_FILEMON
855     if (pbm->filemon) {
856 	while (filemon_process(pbm->filemon) > 0)
857 	    continue;
858 	if (filemon_close(pbm->filemon) == -1)
859 	    error = errno;
860 	x = filemon_read(pbm->mfp, pbm->mon_fd);
861 	if (error == 0 && x != 0)
862 	    error = x;
863 	pbm->mon_fd = -1;
864 	pbm->filemon = NULL;
865     } else
866 #endif
867 	fprintf(pbm->mfp, "\n");	/* ensure end with newline */
868     return error;
869 }
870 
871 int
872 meta_job_finish(Job *job)
873 {
874     BuildMon *pbm;
875     int error = 0;
876     int x;
877 
878     if (job != NULL) {
879 	pbm = &job->bm;
880     } else {
881 	pbm = &Mybm;
882     }
883     if (pbm->mfp != NULL) {
884 	error = meta_cmd_finish(pbm);
885 	x = fclose(pbm->mfp);
886 	if (error == 0 && x != 0)
887 	    error = errno;
888 	pbm->mfp = NULL;
889 	pbm->meta_fname[0] = '\0';
890     }
891     return error;
892 }
893 
894 void
895 meta_finish(void)
896 {
897     Lst_Destroy(metaBailiwick, NULL);
898     free(metaBailiwickStr);
899     Lst_Destroy(metaIgnorePaths, NULL);
900     free(metaIgnorePathsStr);
901 }
902 
903 /*
904  * Fetch a full line from fp - growing bufp if needed
905  * Return length in bufp.
906  */
907 static int
908 fgetLine(char **bufp, size_t *szp, int o, FILE *fp)
909 {
910     char *buf = *bufp;
911     size_t bufsz = *szp;
912     struct stat fs;
913     int x;
914 
915     if (fgets(&buf[o], bufsz - o, fp) != NULL) {
916     check_newline:
917 	x = o + strlen(&buf[o]);
918 	if (buf[x - 1] == '\n')
919 	    return x;
920 	/*
921 	 * We need to grow the buffer.
922 	 * The meta file can give us a clue.
923 	 */
924 	if (fstat(fileno(fp), &fs) == 0) {
925 	    size_t newsz;
926 	    char *p;
927 
928 	    newsz = ROUNDUP((fs.st_size / 2), BUFSIZ);
929 	    if (newsz <= bufsz)
930 		newsz = ROUNDUP(fs.st_size, BUFSIZ);
931 	    if (newsz <= bufsz)
932 		return x;		/* truncated */
933 	    if (DEBUG(META))
934 		fprintf(debug_file, "growing buffer %u -> %u\n",
935 			(unsigned)bufsz, (unsigned)newsz);
936 	    p = bmake_realloc(buf, newsz);
937 	    if (p) {
938 		*bufp = buf = p;
939 		*szp = bufsz = newsz;
940 		/* fetch the rest */
941 		if (!fgets(&buf[x], bufsz - x, fp))
942 		    return x;		/* truncated! */
943 		goto check_newline;
944 	    }
945 	}
946     }
947     return 0;
948 }
949 
950 /* Lst_ForEach wants 1 to stop search */
951 static int
952 prefix_match(void *p, void *q)
953 {
954     const char *prefix = p;
955     const char *path = q;
956     size_t n = strlen(prefix);
957 
958     return strncmp(path, prefix, n) == 0;
959 }
960 
961 /*
962  * looking for exact or prefix/ match to
963  * Lst_Find wants 0 to stop search
964  */
965 static int
966 path_match(const void *p, const void *q)
967 {
968     const char *prefix = q;
969     const char *path = p;
970     size_t n = strlen(prefix);
971     int rc;
972 
973     if ((rc = strncmp(path, prefix, n)) == 0) {
974 	switch (path[n]) {
975 	case '\0':
976 	case '/':
977 	    break;
978 	default:
979 	    rc = 1;
980 	    break;
981 	}
982     }
983     return rc;
984 }
985 
986 /* Lst_Find wants 0 to stop search */
987 static int
988 string_match(const void *p, const void *q)
989 {
990     const char *p1 = p;
991     const char *p2 = q;
992 
993     return strcmp(p1, p2);
994 }
995 
996 
997 static int
998 meta_ignore(GNode *gn, const char *p)
999 {
1000     char fname[MAXPATHLEN];
1001 
1002     if (p == NULL)
1003 	return TRUE;
1004 
1005     if (*p == '/') {
1006 	cached_realpath(p, fname); /* clean it up */
1007 	if (Lst_ForEach(metaIgnorePaths, prefix_match, fname)) {
1008 #ifdef DEBUG_META_MODE
1009 	    if (DEBUG(META))
1010 		fprintf(debug_file, "meta_oodate: ignoring path: %s\n",
1011 			p);
1012 #endif
1013 	    return TRUE;
1014 	}
1015     }
1016 
1017     if (metaIgnorePatterns) {
1018 	char *pm;
1019 
1020 	Var_Set(".p.", p, gn);
1021 	pm = Var_Subst(NULL,
1022 		       "${" MAKE_META_IGNORE_PATTERNS ":@m@${.p.:M$m}@}",
1023 		       gn, VARF_WANTRES);
1024 	if (*pm) {
1025 #ifdef DEBUG_META_MODE
1026 	    if (DEBUG(META))
1027 		fprintf(debug_file, "meta_oodate: ignoring pattern: %s\n",
1028 			p);
1029 #endif
1030 	    free(pm);
1031 	    return TRUE;
1032 	}
1033 	free(pm);
1034     }
1035 
1036     if (metaIgnoreFilter) {
1037 	char *fm;
1038 
1039 	/* skip if filter result is empty */
1040 	snprintf(fname, sizeof(fname),
1041 		 "${%s:L:${%s:ts:}}",
1042 		 p, MAKE_META_IGNORE_FILTER);
1043 	fm = Var_Subst(NULL, fname, gn, VARF_WANTRES);
1044 	if (*fm == '\0') {
1045 #ifdef DEBUG_META_MODE
1046 	    if (DEBUG(META))
1047 		fprintf(debug_file, "meta_oodate: ignoring filtered: %s\n",
1048 			p);
1049 #endif
1050 	    free(fm);
1051 	    return TRUE;
1052 	}
1053 	free(fm);
1054     }
1055     return FALSE;
1056 }
1057 
1058 /*
1059  * When running with 'meta' functionality, a target can be out-of-date
1060  * if any of the references in its meta data file is more recent.
1061  * We have to track the latestdir on a per-process basis.
1062  */
1063 #define LCWD_VNAME_FMT ".meta.%d.lcwd"
1064 #define LDIR_VNAME_FMT ".meta.%d.ldir"
1065 
1066 /*
1067  * It is possible that a .meta file is corrupted,
1068  * if we detect this we want to reproduce it.
1069  * Setting oodate TRUE will have that effect.
1070  */
1071 #define CHECK_VALID_META(p) if (!(p && *p)) { \
1072     warnx("%s: %d: malformed", fname, lineno); \
1073     oodate = TRUE; \
1074     continue; \
1075     }
1076 
1077 #define DEQUOTE(p) if (*p == '\'') {	\
1078     char *ep; \
1079     p++; \
1080     if ((ep = strchr(p, '\''))) \
1081 	*ep = '\0'; \
1082     }
1083 
1084 Boolean
1085 meta_oodate(GNode *gn, Boolean oodate)
1086 {
1087     static char *tmpdir = NULL;
1088     static char cwd[MAXPATHLEN];
1089     char lcwd_vname[64];
1090     char ldir_vname[64];
1091     char lcwd[MAXPATHLEN];
1092     char latestdir[MAXPATHLEN];
1093     char fname[MAXPATHLEN];
1094     char fname1[MAXPATHLEN];
1095     char fname2[MAXPATHLEN];
1096     char fname3[MAXPATHLEN];
1097     const char *dname;
1098     const char *tname;
1099     char *p;
1100     char *cp;
1101     char *link_src;
1102     char *move_target;
1103     static size_t cwdlen = 0;
1104     static size_t tmplen = 0;
1105     FILE *fp;
1106     Boolean needOODATE = FALSE;
1107     Lst missingFiles;
1108     char *pa[4];			/* >= possible uses */
1109     int i;
1110     int have_filemon = FALSE;
1111 
1112     if (oodate)
1113 	return oodate;		/* we're done */
1114 
1115     i = 0;
1116 
1117     dname = Var_Value(".OBJDIR", gn, &pa[i++]);
1118     tname = Var_Value(TARGET, gn, &pa[i++]);
1119 
1120     /* if this succeeds fname3 is realpath of dname */
1121     if (!meta_needed(gn, dname, fname3, FALSE))
1122 	goto oodate_out;
1123     dname = fname3;
1124 
1125     missingFiles = Lst_Init(FALSE);
1126 
1127     /*
1128      * We need to check if the target is out-of-date. This includes
1129      * checking if the expanded command has changed. This in turn
1130      * requires that all variables are set in the same way that they
1131      * would be if the target needs to be re-built.
1132      */
1133     Make_DoAllVar(gn);
1134 
1135     meta_name(fname, sizeof(fname), dname, tname, dname);
1136 
1137 #ifdef DEBUG_META_MODE
1138     if (DEBUG(META))
1139 	fprintf(debug_file, "meta_oodate: %s\n", fname);
1140 #endif
1141 
1142     if ((fp = fopen(fname, "r")) != NULL) {
1143 	static char *buf = NULL;
1144 	static size_t bufsz;
1145 	int lineno = 0;
1146 	int lastpid = 0;
1147 	int pid;
1148 	int x;
1149 	LstNode ln;
1150 	struct stat fs;
1151 
1152 	if (!buf) {
1153 	    bufsz = 8 * BUFSIZ;
1154 	    buf = bmake_malloc(bufsz);
1155 	}
1156 
1157 	if (!cwdlen) {
1158 	    if (getcwd(cwd, sizeof(cwd)) == NULL)
1159 		err(1, "Could not get current working directory");
1160 	    cwdlen = strlen(cwd);
1161 	}
1162 	strlcpy(lcwd, cwd, sizeof(lcwd));
1163 	strlcpy(latestdir, cwd, sizeof(latestdir));
1164 
1165 	if (!tmpdir) {
1166 	    tmpdir = getTmpdir();
1167 	    tmplen = strlen(tmpdir);
1168 	}
1169 
1170 	/* we want to track all the .meta we read */
1171 	Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL);
1172 
1173 	ln = Lst_First(gn->commands);
1174 	while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) {
1175 	    lineno++;
1176 	    if (buf[x - 1] == '\n')
1177 		buf[x - 1] = '\0';
1178 	    else {
1179 		warnx("%s: %d: line truncated at %u", fname, lineno, x);
1180 		oodate = TRUE;
1181 		break;
1182 	    }
1183 	    link_src = NULL;
1184 	    move_target = NULL;
1185 	    /* Find the start of the build monitor section. */
1186 	    if (!have_filemon) {
1187 		if (strncmp(buf, "-- filemon", 10) == 0) {
1188 		    have_filemon = TRUE;
1189 		    continue;
1190 		}
1191 		if (strncmp(buf, "# buildmon", 10) == 0) {
1192 		    have_filemon = TRUE;
1193 		    continue;
1194 		}
1195 	    }
1196 
1197 	    /* Delimit the record type. */
1198 	    p = buf;
1199 #ifdef DEBUG_META_MODE
1200 	    if (DEBUG(META))
1201 		fprintf(debug_file, "%s: %d: %s\n", fname, lineno, buf);
1202 #endif
1203 	    strsep(&p, " ");
1204 	    if (have_filemon) {
1205 		/*
1206 		 * We are in the 'filemon' output section.
1207 		 * Each record from filemon follows the general form:
1208 		 *
1209 		 * <key> <pid> <data>
1210 		 *
1211 		 * Where:
1212 		 * <key> is a single letter, denoting the syscall.
1213 		 * <pid> is the process that made the syscall.
1214 		 * <data> is the arguments (of interest).
1215 		 */
1216 		switch(buf[0]) {
1217 		case '#':		/* comment */
1218 		case 'V':		/* version */
1219 		    break;
1220 		default:
1221 		    /*
1222 		     * We need to track pathnames per-process.
1223 		     *
1224 		     * Each process run by make, starts off in the 'CWD'
1225 		     * recorded in the .meta file, if it chdirs ('C')
1226 		     * elsewhere we need to track that - but only for
1227 		     * that process.  If it forks ('F'), we initialize
1228 		     * the child to have the same cwd as its parent.
1229 		     *
1230 		     * We also need to track the 'latestdir' of
1231 		     * interest.  This is usually the same as cwd, but
1232 		     * not if a process is reading directories.
1233 		     *
1234 		     * Each time we spot a different process ('pid')
1235 		     * we save the current value of 'latestdir' in a
1236 		     * variable qualified by 'lastpid', and
1237 		     * re-initialize 'latestdir' to any pre-saved
1238 		     * value for the current 'pid' and 'CWD' if none.
1239 		     */
1240 		    CHECK_VALID_META(p);
1241 		    pid = atoi(p);
1242 		    if (pid > 0 && pid != lastpid) {
1243 			char *ldir;
1244 			char *tp;
1245 
1246 			if (lastpid > 0) {
1247 			    /* We need to remember these. */
1248 			    Var_Set(lcwd_vname, lcwd, VAR_GLOBAL);
1249 			    Var_Set(ldir_vname, latestdir, VAR_GLOBAL);
1250 			}
1251 			snprintf(lcwd_vname, sizeof(lcwd_vname), LCWD_VNAME_FMT, pid);
1252 			snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid);
1253 			lastpid = pid;
1254 			ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp);
1255 			if (ldir) {
1256 			    strlcpy(latestdir, ldir, sizeof(latestdir));
1257 			    free(tp);
1258 			}
1259 			ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp);
1260 			if (ldir) {
1261 			    strlcpy(lcwd, ldir, sizeof(lcwd));
1262 			    free(tp);
1263 			}
1264 		    }
1265 		    /* Skip past the pid. */
1266 		    if (strsep(&p, " ") == NULL)
1267 			continue;
1268 #ifdef DEBUG_META_MODE
1269 		    if (DEBUG(META))
1270 			    fprintf(debug_file, "%s: %d: %d: %c: cwd=%s lcwd=%s ldir=%s\n",
1271 				    fname, lineno,
1272 				    pid, buf[0], cwd, lcwd, latestdir);
1273 #endif
1274 		    break;
1275 		}
1276 
1277 		CHECK_VALID_META(p);
1278 
1279 		/* Process according to record type. */
1280 		switch (buf[0]) {
1281 		case 'X':		/* eXit */
1282 		    Var_Delete(lcwd_vname, VAR_GLOBAL);
1283 		    Var_Delete(ldir_vname, VAR_GLOBAL);
1284 		    lastpid = 0;	/* no need to save ldir_vname */
1285 		    break;
1286 
1287 		case 'F':		/* [v]Fork */
1288 		    {
1289 			char cldir[64];
1290 			int child;
1291 
1292 			child = atoi(p);
1293 			if (child > 0) {
1294 			    snprintf(cldir, sizeof(cldir), LCWD_VNAME_FMT, child);
1295 			    Var_Set(cldir, lcwd, VAR_GLOBAL);
1296 			    snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child);
1297 			    Var_Set(cldir, latestdir, VAR_GLOBAL);
1298 #ifdef DEBUG_META_MODE
1299 			    if (DEBUG(META))
1300 				    fprintf(debug_file, "%s: %d: %d: cwd=%s lcwd=%s ldir=%s\n",
1301 					    fname, lineno,
1302 					    child, cwd, lcwd, latestdir);
1303 #endif
1304 			}
1305 		    }
1306 		    break;
1307 
1308 		case 'C':		/* Chdir */
1309 		    /* Update lcwd and latest directory. */
1310 		    strlcpy(latestdir, p, sizeof(latestdir));
1311 		    strlcpy(lcwd, p, sizeof(lcwd));
1312 		    Var_Set(lcwd_vname, lcwd, VAR_GLOBAL);
1313 		    Var_Set(ldir_vname, lcwd, VAR_GLOBAL);
1314 #ifdef DEBUG_META_MODE
1315 		    if (DEBUG(META))
1316 			fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, lcwd);
1317 #endif
1318 		    break;
1319 
1320 		case 'M':		/* renaMe */
1321 		    /*
1322 		     * For 'M'oves we want to check
1323 		     * the src as for 'R'ead
1324 		     * and the target as for 'W'rite.
1325 		     */
1326 		    cp = p;		/* save this for a second */
1327 		    /* now get target */
1328 		    if (strsep(&p, " ") == NULL)
1329 			continue;
1330 		    CHECK_VALID_META(p);
1331 		    move_target = p;
1332 		    p = cp;
1333 		    /* 'L' and 'M' put single quotes around the args */
1334 		    DEQUOTE(p);
1335 		    DEQUOTE(move_target);
1336 		    /* FALLTHROUGH */
1337 		case 'D':		/* unlink */
1338 		    if (*p == '/' && !Lst_IsEmpty(missingFiles)) {
1339 			/* remove any missingFiles entries that match p */
1340 			if ((ln = Lst_Find(missingFiles, p,
1341 					   path_match)) != NULL) {
1342 			    LstNode nln;
1343 			    char *tp;
1344 
1345 			    do {
1346 				nln = Lst_FindFrom(missingFiles, Lst_Succ(ln),
1347 						   p, path_match);
1348 				tp = Lst_Datum(ln);
1349 				Lst_Remove(missingFiles, ln);
1350 				free(tp);
1351 			    } while ((ln = nln) != NULL);
1352 			}
1353 		    }
1354 		    if (buf[0] == 'M') {
1355 			/* the target of the mv is a file 'W'ritten */
1356 #ifdef DEBUG_META_MODE
1357 			if (DEBUG(META))
1358 			    fprintf(debug_file, "meta_oodate: M %s -> %s\n",
1359 				    p, move_target);
1360 #endif
1361 			p = move_target;
1362 			goto check_write;
1363 		    }
1364 		    break;
1365 		case 'L':		/* Link */
1366 		    /*
1367 		     * For 'L'inks check
1368 		     * the src as for 'R'ead
1369 		     * and the target as for 'W'rite.
1370 		     */
1371 		    link_src = p;
1372 		    /* now get target */
1373 		    if (strsep(&p, " ") == NULL)
1374 			continue;
1375 		    CHECK_VALID_META(p);
1376 		    /* 'L' and 'M' put single quotes around the args */
1377 		    DEQUOTE(p);
1378 		    DEQUOTE(link_src);
1379 #ifdef DEBUG_META_MODE
1380 		    if (DEBUG(META))
1381 			fprintf(debug_file, "meta_oodate: L %s -> %s\n",
1382 				link_src, p);
1383 #endif
1384 		    /* FALLTHROUGH */
1385 		case 'W':		/* Write */
1386 		check_write:
1387 		    /*
1388 		     * If a file we generated within our bailiwick
1389 		     * but outside of .OBJDIR is missing,
1390 		     * we need to do it again.
1391 		     */
1392 		    /* ignore non-absolute paths */
1393 		    if (*p != '/')
1394 			break;
1395 
1396 		    if (Lst_IsEmpty(metaBailiwick))
1397 			break;
1398 
1399 		    /* ignore cwd - normal dependencies handle those */
1400 		    if (strncmp(p, cwd, cwdlen) == 0)
1401 			break;
1402 
1403 		    if (!Lst_ForEach(metaBailiwick, prefix_match, p))
1404 			break;
1405 
1406 		    /* tmpdir might be within */
1407 		    if (tmplen > 0 && strncmp(p, tmpdir, tmplen) == 0)
1408 			break;
1409 
1410 		    /* ignore anything containing the string "tmp" */
1411 		    if ((strstr("tmp", p)))
1412 			break;
1413 
1414 		    if ((link_src != NULL && cached_lstat(p, &fs) < 0) ||
1415 			(link_src == NULL && cached_stat(p, &fs) < 0)) {
1416 			if (!meta_ignore(gn, p)) {
1417 			    if (Lst_Find(missingFiles, p, string_match) == NULL)
1418 				Lst_AtEnd(missingFiles, bmake_strdup(p));
1419 			}
1420 		    }
1421 		    break;
1422 		check_link_src:
1423 		    p = link_src;
1424 		    link_src = NULL;
1425 #ifdef DEBUG_META_MODE
1426 		    if (DEBUG(META))
1427 			fprintf(debug_file, "meta_oodate: L src %s\n", p);
1428 #endif
1429 		    /* FALLTHROUGH */
1430 		case 'R':		/* Read */
1431 		case 'E':		/* Exec */
1432 		    /*
1433 		     * Check for runtime files that can't
1434 		     * be part of the dependencies because
1435 		     * they are _expected_ to change.
1436 		     */
1437 		    if (meta_ignore(gn, p))
1438 			break;
1439 
1440 		    /*
1441 		     * The rest of the record is the file name.
1442 		     * Check if it's not an absolute path.
1443 		     */
1444 		    {
1445 			char *sdirs[4];
1446 			char **sdp;
1447 			int sdx = 0;
1448 			int found = 0;
1449 
1450 			if (*p == '/') {
1451 			    sdirs[sdx++] = p; /* done */
1452 			} else {
1453 			    if (strcmp(".", p) == 0)
1454 				continue;  /* no point */
1455 
1456 			    /* Check vs latestdir */
1457 			    snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p);
1458 			    sdirs[sdx++] = fname1;
1459 
1460 			    if (strcmp(latestdir, lcwd) != 0) {
1461 				/* Check vs lcwd */
1462 				snprintf(fname2, sizeof(fname2), "%s/%s", lcwd, p);
1463 				sdirs[sdx++] = fname2;
1464 			    }
1465 			    if (strcmp(lcwd, cwd) != 0) {
1466 				/* Check vs cwd */
1467 				snprintf(fname3, sizeof(fname3), "%s/%s", cwd, p);
1468 				sdirs[sdx++] = fname3;
1469 			    }
1470 			}
1471 			sdirs[sdx++] = NULL;
1472 
1473 			for (sdp = sdirs; *sdp && !found; sdp++) {
1474 #ifdef DEBUG_META_MODE
1475 			    if (DEBUG(META))
1476 				fprintf(debug_file, "%s: %d: looking for: %s\n", fname, lineno, *sdp);
1477 #endif
1478 			    if (cached_stat(*sdp, &fs) == 0) {
1479 				found = 1;
1480 				p = *sdp;
1481 			    }
1482 			}
1483 			if (found) {
1484 #ifdef DEBUG_META_MODE
1485 			    if (DEBUG(META))
1486 				fprintf(debug_file, "%s: %d: found: %s\n", fname, lineno, p);
1487 #endif
1488 			    if (!S_ISDIR(fs.st_mode) &&
1489 				fs.st_mtime > gn->mtime) {
1490 				if (DEBUG(META))
1491 				    fprintf(debug_file, "%s: %d: file '%s' is newer than the target...\n", fname, lineno, p);
1492 				oodate = TRUE;
1493 			    } else if (S_ISDIR(fs.st_mode)) {
1494 				/* Update the latest directory. */
1495 				cached_realpath(p, latestdir);
1496 			    }
1497 			} else if (errno == ENOENT && *p == '/' &&
1498 				   strncmp(p, cwd, cwdlen) != 0) {
1499 			    /*
1500 			     * A referenced file outside of CWD is missing.
1501 			     * We cannot catch every eventuality here...
1502 			     */
1503 			    if (Lst_Find(missingFiles, p, string_match) == NULL)
1504 				    Lst_AtEnd(missingFiles, bmake_strdup(p));
1505 			}
1506 		    }
1507 		    if (buf[0] == 'E') {
1508 			/* previous latestdir is no longer relevant */
1509 			strlcpy(latestdir, lcwd, sizeof(latestdir));
1510 		    }
1511 		    break;
1512 		default:
1513 		    break;
1514 		}
1515 		if (!oodate && buf[0] == 'L' && link_src != NULL)
1516 		    goto check_link_src;
1517 	    } else if (strcmp(buf, "CMD") == 0) {
1518 		/*
1519 		 * Compare the current command with the one in the
1520 		 * meta data file.
1521 		 */
1522 		if (ln == NULL) {
1523 		    if (DEBUG(META))
1524 			fprintf(debug_file, "%s: %d: there were more build commands in the meta data file than there are now...\n", fname, lineno);
1525 		    oodate = TRUE;
1526 		} else {
1527 		    char *cmd = (char *)Lst_Datum(ln);
1528 		    Boolean hasOODATE = FALSE;
1529 
1530 		    if (strstr(cmd, "$?"))
1531 			hasOODATE = TRUE;
1532 		    else if ((cp = strstr(cmd, ".OODATE"))) {
1533 			/* check for $[{(].OODATE[:)}] */
1534 			if (cp > cmd + 2 && cp[-2] == '$')
1535 			    hasOODATE = TRUE;
1536 		    }
1537 		    if (hasOODATE) {
1538 			needOODATE = TRUE;
1539 			if (DEBUG(META))
1540 			    fprintf(debug_file, "%s: %d: cannot compare command using .OODATE\n", fname, lineno);
1541 		    }
1542 		    cmd = Var_Subst(NULL, cmd, gn, VARF_WANTRES|VARF_UNDEFERR);
1543 
1544 		    if ((cp = strchr(cmd, '\n'))) {
1545 			int n;
1546 
1547 			/*
1548 			 * This command contains newlines, we need to
1549 			 * fetch more from the .meta file before we
1550 			 * attempt a comparison.
1551 			 */
1552 			/* first put the newline back at buf[x - 1] */
1553 			buf[x - 1] = '\n';
1554 			do {
1555 			    /* now fetch the next line */
1556 			    if ((n = fgetLine(&buf, &bufsz, x, fp)) <= 0)
1557 				break;
1558 			    x = n;
1559 			    lineno++;
1560 			    if (buf[x - 1] != '\n') {
1561 				warnx("%s: %d: line truncated at %u", fname, lineno, x);
1562 				break;
1563 			    }
1564 			    cp = strchr(++cp, '\n');
1565 			} while (cp);
1566 			if (buf[x - 1] == '\n')
1567 			    buf[x - 1] = '\0';
1568 		    }
1569 		    if (p &&
1570 			!hasOODATE &&
1571 			!(gn->type & OP_NOMETA_CMP) &&
1572 			strcmp(p, cmd) != 0) {
1573 			if (DEBUG(META))
1574 			    fprintf(debug_file, "%s: %d: a build command has changed\n%s\nvs\n%s\n", fname, lineno, p, cmd);
1575 			if (!metaIgnoreCMDs)
1576 			    oodate = TRUE;
1577 		    }
1578 		    free(cmd);
1579 		    ln = Lst_Succ(ln);
1580 		}
1581 	    } else if (strcmp(buf, "CWD") == 0) {
1582 		/*
1583 		 * Check if there are extra commands now
1584 		 * that weren't in the meta data file.
1585 		 */
1586 		if (!oodate && ln != NULL) {
1587 		    if (DEBUG(META))
1588 			fprintf(debug_file, "%s: %d: there are extra build commands now that weren't in the meta data file\n", fname, lineno);
1589 		    oodate = TRUE;
1590 		}
1591 		CHECK_VALID_META(p);
1592 		if (strcmp(p, cwd) != 0) {
1593 		    if (DEBUG(META))
1594 			fprintf(debug_file, "%s: %d: the current working directory has changed from '%s' to '%s'\n", fname, lineno, p, curdir);
1595 		    oodate = TRUE;
1596 		}
1597 	    }
1598 	}
1599 
1600 	fclose(fp);
1601 	if (!Lst_IsEmpty(missingFiles)) {
1602 	    if (DEBUG(META))
1603 		fprintf(debug_file, "%s: missing files: %s...\n",
1604 			fname, (char *)Lst_Datum(Lst_First(missingFiles)));
1605 	    oodate = TRUE;
1606 	}
1607 	if (!oodate && !have_filemon && filemonMissing) {
1608 	    if (DEBUG(META))
1609 		fprintf(debug_file, "%s: missing filemon data\n", fname);
1610 	    oodate = TRUE;
1611 	}
1612     } else {
1613 	if (writeMeta && (metaMissing || (gn->type & OP_META))) {
1614 	    cp = NULL;
1615 
1616 	    /* if target is in .CURDIR we do not need a meta file */
1617 	    if (gn->path && (cp = strrchr(gn->path, '/')) && cp > gn->path) {
1618 		if (strncmp(curdir, gn->path, (cp - gn->path)) != 0) {
1619 		    cp = NULL;		/* not in .CURDIR */
1620 		}
1621 	    }
1622 	    if (!cp) {
1623 		if (DEBUG(META))
1624 		    fprintf(debug_file, "%s: required but missing\n", fname);
1625 		oodate = TRUE;
1626 		needOODATE = TRUE;	/* assume the worst */
1627 	    }
1628 	}
1629     }
1630 
1631     Lst_Destroy(missingFiles, (FreeProc *)free);
1632 
1633     if (oodate && needOODATE) {
1634 	/*
1635 	 * Target uses .OODATE which is empty; or we wouldn't be here.
1636 	 * We have decided it is oodate, so .OODATE needs to be set.
1637 	 * All we can sanely do is set it to .ALLSRC.
1638 	 */
1639 	Var_Delete(OODATE, gn);
1640 	Var_Set(OODATE, Var_Value(ALLSRC, gn, &cp), gn);
1641 	free(cp);
1642     }
1643 
1644  oodate_out:
1645     for (i--; i >= 0; i--) {
1646 	free(pa[i]);
1647     }
1648     return oodate;
1649 }
1650 
1651 /* support for compat mode */
1652 
1653 static int childPipe[2];
1654 
1655 void
1656 meta_compat_start(void)
1657 {
1658 #ifdef USE_FILEMON_ONCE
1659     /*
1660      * We need to re-open filemon for each cmd.
1661      */
1662     BuildMon *pbm = &Mybm;
1663 
1664     if (pbm->mfp != NULL && useFilemon) {
1665 	meta_open_filemon(pbm);
1666     } else {
1667 	pbm->mon_fd = -1;
1668 	pbm->filemon = NULL;
1669     }
1670 #endif
1671     if (pipe(childPipe) < 0)
1672 	Punt("Cannot create pipe: %s", strerror(errno));
1673     /* Set close-on-exec flag for both */
1674     (void)fcntl(childPipe[0], F_SETFD, FD_CLOEXEC);
1675     (void)fcntl(childPipe[1], F_SETFD, FD_CLOEXEC);
1676 }
1677 
1678 void
1679 meta_compat_child(void)
1680 {
1681     meta_job_child(NULL);
1682     if (dup2(childPipe[1], 1) < 0 ||
1683 	dup2(1, 2) < 0) {
1684 	execError("dup2", "pipe");
1685 	_exit(1);
1686     }
1687 }
1688 
1689 void
1690 meta_compat_parent(pid_t child)
1691 {
1692     int outfd, metafd, maxfd, nfds;
1693     char buf[BUFSIZ+1];
1694     fd_set readfds;
1695 
1696     meta_job_parent(NULL, child);
1697     close(childPipe[1]);			/* child side */
1698     outfd = childPipe[0];
1699 #ifdef USE_FILEMON
1700     metafd = Mybm.filemon ? filemon_readfd(Mybm.filemon) : -1;
1701 #else
1702     metafd = -1;
1703 #endif
1704     maxfd = -1;
1705     if (outfd > maxfd)
1706 	    maxfd = outfd;
1707     if (metafd > maxfd)
1708 	    maxfd = metafd;
1709 
1710     while (outfd != -1 || metafd != -1) {
1711 	FD_ZERO(&readfds);
1712 	if (outfd != -1) {
1713 	    FD_SET(outfd, &readfds);
1714 	}
1715 	if (metafd != -1) {
1716 	    FD_SET(metafd, &readfds);
1717 	}
1718 	nfds = select(maxfd + 1, &readfds, NULL, NULL, NULL);
1719 	if (nfds == -1) {
1720 	    if (errno == EINTR)
1721 		continue;
1722 	    err(1, "select");
1723 	}
1724 
1725 	if (outfd != -1 && FD_ISSET(outfd, &readfds)) do {
1726 	    /* XXX this is not line-buffered */
1727 	    ssize_t nread = read(outfd, buf, sizeof(buf) - 1);
1728 	    if (nread == -1)
1729 		err(1, "read");
1730 	    if (nread == 0) {
1731 		close(outfd);
1732 		outfd = -1;
1733 		break;
1734 	    }
1735 	    fwrite(buf, 1, (size_t)nread, stdout);
1736 	    fflush(stdout);
1737 	    buf[nread] = '\0';
1738 	    meta_job_output(NULL, buf, "");
1739 	} while (0);
1740 	if (metafd != -1 && FD_ISSET(metafd, &readfds)) {
1741 	    if (meta_job_event(NULL) <= 0)
1742 		metafd = -1;
1743 	}
1744     }
1745 }
1746 
1747 #endif	/* USE_META */
1748