Module Name:    src
Committed By:   sjg
Date:           Sun Feb 13 21:22:41 UTC 2011

Modified Files:
        src/usr.bin/make: meta.c

Log Message:
When making a target that involves creating itermediate dirs,
realpath() will fail until after those dirs exist.
Try to ensure the same meta file name is used regardless.


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/make/meta.c

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/meta.c
diff -u src/usr.bin/make/meta.c:1.7 src/usr.bin/make/meta.c:1.8
--- src/usr.bin/make/meta.c:1.7	Tue Feb  8 05:29:13 2011
+++ src/usr.bin/make/meta.c	Sun Feb 13 21:22:41 2011
@@ -169,6 +169,49 @@
 }
 #endif
 
+/*
+ * when realpath() fails,
+ * we use this, to clean up ./ and ../
+ */
+static void
+eat_dots(char *buf, size_t bufsz, int dots)
+{
+    char *cp;
+    char *cp2;
+    const char *eat;
+    size_t eatlen;
+
+    switch (dots) {
+    case 1:
+	eat = "/./";
+	eatlen = 2;
+	break;
+    case 2:
+	eat = "/../";
+	eatlen = 3;
+	break;
+    default:
+	return;
+    }
+    
+    do {
+	cp = strstr(buf, eat);
+	if (cp) {
+	    cp2 = cp + eatlen;
+	    if (dots == 2 && cp > buf) {
+		do {
+		    cp--;
+		} while (cp > buf && *cp != '/');
+	    }
+	    if (*cp == '/') {
+		strlcpy(cp, cp2, bufsz - (cp - buf));
+	    } else {
+		return;			/* can't happen? */
+	    }
+	}
+    } while (cp);
+}
+
 static char *
 meta_name(struct GNode *gn, char *mname, size_t mnamelen,
 	  const char *dname,
@@ -188,6 +231,9 @@
     if (!tname)
 	tname = Var_Value(TARGET, gn, &p[i++]);
 
+    if (realpath(dname, cwd))
+	dname = cwd;
+
     /*
      * Weed out relative paths from the target file name.
      * We have to be careful though since if target is a
@@ -204,10 +250,23 @@
 		    strlcpy(rp, cp, sizeof(buf) - (rp - buf));
 	    }
 	    tname = buf;
+	} else {
+	    /*
+	     * We likely have a directory which is about to be made.
+	     * We pretend realpath() succeeded, to have a chance
+	     * of generating the same meta file name that we will
+	     * next time through.
+	     */
+	    if (tname[0] == '/') {
+		strlcpy(buf, tname, sizeof(buf));
+	    } else {
+		snprintf(buf, sizeof(buf), "%s/%s", cwd, tname);
+	    }
+	    eat_dots(buf, sizeof(buf), 1);	/* ./ */
+	    eat_dots(buf, sizeof(buf), 2);	/* ../ */
+	    tname = buf;
 	}
     }
-    if (realpath(dname, cwd))
-	dname = cwd;
     /* on some systems dirname may modify its arg */
     tp = bmake_strdup(tname);
     if (strcmp(dname, dirname(tp)) == 0)
@@ -425,6 +484,11 @@
     fname = meta_name(gn, pbm->meta_fname, sizeof(pbm->meta_fname),
 		      dname, tname);
 
+#ifdef DEBUG_META_MODE
+    if (DEBUG(META))
+	fprintf(debug_file, "meta_create: %s\n", fname);
+#endif
+
     if ((mf.fp = fopen(fname, "w")) == NULL)
 	err(1, "Could not open meta file '%s'", fname);
 
@@ -733,6 +797,11 @@
 
     meta_name(gn, fname, sizeof(fname), NULL, NULL);
 
+#ifdef DEBUG_META_MODE
+    if (DEBUG(META))
+	fprintf(debug_file, "meta_oodate: %s\n", fname);
+#endif
+
     if ((fp = fopen(fname, "r")) != NULL) {
 	static char *buf = NULL;
 	static size_t bufsz;

Reply via email to