| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: meta.c,v 1.37 2015/04/01 01:03:55 sjg Exp $ */ | | 1 | /* $NetBSD: meta.c,v 1.38 2015/04/11 05:24:30 sjg Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Implement 'meta' mode. | | 4 | * Implement 'meta' mode. |
5 | * Adapted from John Birrell's patches to FreeBSD make. | | 5 | * Adapted from John Birrell's patches to FreeBSD make. |
6 | * --sjg | | 6 | * --sjg |
7 | */ | | 7 | */ |
8 | /* | | 8 | /* |
9 | * Copyright (c) 2009-2010, Juniper Networks, Inc. | | 9 | * Copyright (c) 2009-2010, Juniper Networks, Inc. |
10 | * Portions Copyright (c) 2009, John Birrell. | | 10 | * Portions Copyright (c) 2009, John Birrell. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -838,56 +838,60 @@ string_match(const void *p, const void * | | | @@ -838,56 +838,60 @@ string_match(const void *p, const void * |
838 | { | | 838 | { |
839 | const char *p1 = p; | | 839 | const char *p1 = p; |
840 | const char *p2 = q; | | 840 | const char *p2 = q; |
841 | | | 841 | |
842 | return strcmp(p1, p2); | | 842 | return strcmp(p1, p2); |
843 | } | | 843 | } |
844 | | | 844 | |
845 | | | 845 | |
846 | /* | | 846 | /* |
847 | * When running with 'meta' functionality, a target can be out-of-date | | 847 | * When running with 'meta' functionality, a target can be out-of-date |
848 | * if any of the references in its meta data file is more recent. | | 848 | * if any of the references in its meta data file is more recent. |
849 | * We have to track the latestdir on a per-process basis. | | 849 | * We have to track the latestdir on a per-process basis. |
850 | */ | | 850 | */ |
| | | 851 | #define LCWD_VNAME_FMT ".meta.%d.lcwd" |
851 | #define LDIR_VNAME_FMT ".meta.%d.ldir" | | 852 | #define LDIR_VNAME_FMT ".meta.%d.ldir" |
852 | | | 853 | |
853 | /* | | 854 | /* |
854 | * It is possible that a .meta file is corrupted, | | 855 | * It is possible that a .meta file is corrupted, |
855 | * if we detect this we want to reproduce it. | | 856 | * if we detect this we want to reproduce it. |
856 | * Setting oodate TRUE will have that effect. | | 857 | * Setting oodate TRUE will have that effect. |
857 | */ | | 858 | */ |
858 | #define CHECK_VALID_META(p) if (!(p && *p)) { \ | | 859 | #define CHECK_VALID_META(p) if (!(p && *p)) { \ |
859 | warnx("%s: %d: malformed", fname, lineno); \ | | 860 | warnx("%s: %d: malformed", fname, lineno); \ |
860 | oodate = TRUE; \ | | 861 | oodate = TRUE; \ |
861 | continue; \ | | 862 | continue; \ |
862 | } | | 863 | } |
863 | | | 864 | |
864 | #define DEQUOTE(p) if (*p == '\'') { \ | | 865 | #define DEQUOTE(p) if (*p == '\'') { \ |
865 | char *ep; \ | | 866 | char *ep; \ |
866 | p++; \ | | 867 | p++; \ |
867 | if ((ep = strchr(p, '\''))) \ | | 868 | if ((ep = strchr(p, '\''))) \ |
868 | *ep = '\0'; \ | | 869 | *ep = '\0'; \ |
869 | } | | 870 | } |
870 | | | 871 | |
871 | Boolean | | 872 | Boolean |
872 | meta_oodate(GNode *gn, Boolean oodate) | | 873 | meta_oodate(GNode *gn, Boolean oodate) |
873 | { | | 874 | { |
874 | static char *tmpdir = NULL; | | 875 | static char *tmpdir = NULL; |
875 | static char cwd[MAXPATHLEN]; | | 876 | static char cwd[MAXPATHLEN]; |
| | | 877 | char lcwd_vname[64]; |
876 | char ldir_vname[64]; | | 878 | char ldir_vname[64]; |
| | | 879 | char lcwd[MAXPATHLEN]; |
877 | char latestdir[MAXPATHLEN]; | | 880 | char latestdir[MAXPATHLEN]; |
878 | char fname[MAXPATHLEN]; | | 881 | char fname[MAXPATHLEN]; |
879 | char fname1[MAXPATHLEN]; | | 882 | char fname1[MAXPATHLEN]; |
880 | char fname2[MAXPATHLEN]; | | 883 | char fname2[MAXPATHLEN]; |
| | | 884 | char fname3[MAXPATHLEN]; |
881 | char *p; | | 885 | char *p; |
882 | char *cp; | | 886 | char *cp; |
883 | char *link_src; | | 887 | char *link_src; |
884 | char *move_target; | | 888 | char *move_target; |
885 | static size_t cwdlen = 0; | | 889 | static size_t cwdlen = 0; |
886 | static size_t tmplen = 0; | | 890 | static size_t tmplen = 0; |
887 | FILE *fp; | | 891 | FILE *fp; |
888 | Boolean needOODATE = FALSE; | | 892 | Boolean needOODATE = FALSE; |
889 | Lst missingFiles; | | 893 | Lst missingFiles; |
890 | | | 894 | |
891 | if (oodate) | | 895 | if (oodate) |
892 | return oodate; /* we're done */ | | 896 | return oodate; /* we're done */ |
893 | | | 897 | |
| @@ -919,26 +923,28 @@ meta_oodate(GNode *gn, Boolean oodate) | | | @@ -919,26 +923,28 @@ meta_oodate(GNode *gn, Boolean oodate) |
919 | LstNode ln; | | 923 | LstNode ln; |
920 | struct stat fs; | | 924 | struct stat fs; |
921 | | | 925 | |
922 | if (!buf) { | | 926 | if (!buf) { |
923 | bufsz = 8 * BUFSIZ; | | 927 | bufsz = 8 * BUFSIZ; |
924 | buf = bmake_malloc(bufsz); | | 928 | buf = bmake_malloc(bufsz); |
925 | } | | 929 | } |
926 | | | 930 | |
927 | if (!cwdlen) { | | 931 | if (!cwdlen) { |
928 | if (getcwd(cwd, sizeof(cwd)) == NULL) | | 932 | if (getcwd(cwd, sizeof(cwd)) == NULL) |
929 | err(1, "Could not get current working directory"); | | 933 | err(1, "Could not get current working directory"); |
930 | cwdlen = strlen(cwd); | | 934 | cwdlen = strlen(cwd); |
931 | } | | 935 | } |
| | | 936 | strlcpy(lcwd, cwd, sizeof(lcwd)); |
| | | 937 | strlcpy(latestdir, cwd, sizeof(latestdir)); |
932 | | | 938 | |
933 | if (!tmpdir) { | | 939 | if (!tmpdir) { |
934 | tmpdir = getTmpdir(); | | 940 | tmpdir = getTmpdir(); |
935 | tmplen = strlen(tmpdir); | | 941 | tmplen = strlen(tmpdir); |
936 | } | | 942 | } |
937 | | | 943 | |
938 | /* we want to track all the .meta we read */ | | 944 | /* we want to track all the .meta we read */ |
939 | Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL); | | 945 | Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL); |
940 | | | 946 | |
941 | ln = Lst_First(gn->commands); | | 947 | ln = Lst_First(gn->commands); |
942 | while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) { | | 948 | while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) { |
943 | lineno++; | | 949 | lineno++; |
944 | if (buf[x - 1] == '\n') | | 950 | if (buf[x - 1] == '\n') |
| @@ -1002,74 +1008,99 @@ meta_oodate(GNode *gn, Boolean oodate) | | | @@ -1002,74 +1008,99 @@ meta_oodate(GNode *gn, Boolean oodate) |
1002 | * Each time we spot a different process ('pid') | | 1008 | * Each time we spot a different process ('pid') |
1003 | * we save the current value of 'latestdir' in a | | 1009 | * we save the current value of 'latestdir' in a |
1004 | * variable qualified by 'lastpid', and | | 1010 | * variable qualified by 'lastpid', and |
1005 | * re-initialize 'latestdir' to any pre-saved | | 1011 | * re-initialize 'latestdir' to any pre-saved |
1006 | * value for the current 'pid' and 'CWD' if none. | | 1012 | * value for the current 'pid' and 'CWD' if none. |
1007 | */ | | 1013 | */ |
1008 | CHECK_VALID_META(p); | | 1014 | CHECK_VALID_META(p); |
1009 | pid = atoi(p); | | 1015 | pid = atoi(p); |
1010 | if (pid > 0 && pid != lastpid) { | | 1016 | if (pid > 0 && pid != lastpid) { |
1011 | char *ldir; | | 1017 | char *ldir; |
1012 | char *tp; | | 1018 | char *tp; |
1013 | | | 1019 | |
1014 | if (lastpid > 0) { | | 1020 | if (lastpid > 0) { |
1015 | /* We need to remember this. */ | | 1021 | /* We need to remember these. */ |
| | | 1022 | Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0); |
1016 | Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0); | | 1023 | Var_Set(ldir_vname, latestdir, VAR_GLOBAL, 0); |
1017 | } | | 1024 | } |
| | | 1025 | snprintf(lcwd_vname, sizeof(lcwd_vname), LCWD_VNAME_FMT, pid); |
1018 | snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid); | | 1026 | snprintf(ldir_vname, sizeof(ldir_vname), LDIR_VNAME_FMT, pid); |
1019 | lastpid = pid; | | 1027 | lastpid = pid; |
1020 | ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp); | | 1028 | ldir = Var_Value(ldir_vname, VAR_GLOBAL, &tp); |
1021 | if (ldir) { | | 1029 | if (ldir) { |
1022 | strlcpy(latestdir, ldir, sizeof(latestdir)); | | 1030 | strlcpy(latestdir, ldir, sizeof(latestdir)); |
1023 | if (tp) | | 1031 | if (tp) |
1024 | free(tp); | | 1032 | free(tp); |
1025 | } else | | 1033 | } |
1026 | strlcpy(latestdir, cwd, sizeof(latestdir)); | | 1034 | ldir = Var_Value(lcwd_vname, VAR_GLOBAL, &tp); |
| | | 1035 | if (ldir) { |
| | | 1036 | strlcpy(lcwd, ldir, sizeof(lcwd)); |
| | | 1037 | if (tp) |
| | | 1038 | free(tp); |
| | | 1039 | } |
1027 | } | | 1040 | } |
1028 | /* Skip past the pid. */ | | 1041 | /* Skip past the pid. */ |
1029 | if (strsep(&p, " ") == NULL) | | 1042 | if (strsep(&p, " ") == NULL) |
1030 | continue; | | 1043 | continue; |
1031 | #ifdef DEBUG_META_MODE | | 1044 | #ifdef DEBUG_META_MODE |
1032 | if (DEBUG(META)) | | 1045 | if (DEBUG(META)) |
1033 | fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, latestdir); | | 1046 | fprintf(debug_file, "%s: %d: %d: %c: cwd=%s lcwd=%s ldir=%s\n", |
| | | 1047 | fname, lineno, |
| | | 1048 | pid, buf[0], cwd, lcwd, latestdir); |
1034 | #endif | | 1049 | #endif |
1035 | break; | | 1050 | break; |
1036 | } | | 1051 | } |
1037 | | | 1052 | |
1038 | CHECK_VALID_META(p); | | 1053 | CHECK_VALID_META(p); |
1039 | | | 1054 | |
1040 | /* Process according to record type. */ | | 1055 | /* Process according to record type. */ |
1041 | switch (buf[0]) { | | 1056 | switch (buf[0]) { |
1042 | case 'X': /* eXit */ | | 1057 | case 'X': /* eXit */ |
| | | 1058 | Var_Delete(lcwd_vname, VAR_GLOBAL); |
1043 | Var_Delete(ldir_vname, VAR_GLOBAL); | | 1059 | Var_Delete(ldir_vname, VAR_GLOBAL); |
1044 | lastpid = 0; /* no need to save ldir_vname */ | | 1060 | lastpid = 0; /* no need to save ldir_vname */ |
1045 | break; | | 1061 | break; |
1046 | | | 1062 | |
1047 | case 'F': /* [v]Fork */ | | 1063 | case 'F': /* [v]Fork */ |
1048 | { | | 1064 | { |
1049 | char cldir[64]; | | 1065 | char cldir[64]; |
1050 | int child; | | 1066 | int child; |
1051 | | | 1067 | |
1052 | child = atoi(p); | | 1068 | child = atoi(p); |
1053 | if (child > 0) { | | 1069 | if (child > 0) { |
| | | 1070 | snprintf(cldir, sizeof(cldir), LCWD_VNAME_FMT, child); |
| | | 1071 | Var_Set(cldir, lcwd, VAR_GLOBAL, 0); |
1054 | snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child); | | 1072 | snprintf(cldir, sizeof(cldir), LDIR_VNAME_FMT, child); |
1055 | Var_Set(cldir, latestdir, VAR_GLOBAL, 0); | | 1073 | Var_Set(cldir, latestdir, VAR_GLOBAL, 0); |
| | | 1074 | #ifdef DEBUG_META_MODE |
| | | 1075 | if (DEBUG(META)) |
| | | 1076 | fprintf(debug_file, "%s: %d: %d: cwd=%s lcwd=%s ldir=%s\n", |
| | | 1077 | fname, lineno, |
| | | 1078 | child, cwd, lcwd, latestdir); |
| | | 1079 | #endif |
1056 | } | | 1080 | } |
1057 | } | | 1081 | } |
1058 | break; | | 1082 | break; |
1059 | | | 1083 | |
1060 | case 'C': /* Chdir */ | | 1084 | case 'C': /* Chdir */ |
1061 | /* Update the latest directory. */ | | 1085 | /* Update lcwd and latest directory. */ |
1062 | strlcpy(latestdir, p, sizeof(latestdir)); | | 1086 | strlcpy(latestdir, p, sizeof(latestdir)); |
| | | 1087 | strlcpy(lcwd, p, sizeof(lcwd)); |
| | | 1088 | Var_Set(lcwd_vname, lcwd, VAR_GLOBAL, 0); |
| | | 1089 | Var_Set(ldir_vname, lcwd, VAR_GLOBAL, 0); |
| | | 1090 | #ifdef DEBUG_META_MODE |
| | | 1091 | if (DEBUG(META)) |
| | | 1092 | fprintf(debug_file, "%s: %d: cwd=%s ldir=%s\n", fname, lineno, cwd, lcwd); |
| | | 1093 | #endif |
1063 | break; | | 1094 | break; |
1064 | | | 1095 | |
1065 | case 'M': /* renaMe */ | | 1096 | case 'M': /* renaMe */ |
1066 | /* | | 1097 | /* |
1067 | * For 'M'oves we want to check | | 1098 | * For 'M'oves we want to check |
1068 | * the src as for 'R'ead | | 1099 | * the src as for 'R'ead |
1069 | * and the target as for 'W'rite. | | 1100 | * and the target as for 'W'rite. |
1070 | */ | | 1101 | */ |
1071 | cp = p; /* save this for a second */ | | 1102 | cp = p; /* save this for a second */ |
1072 | /* now get target */ | | 1103 | /* now get target */ |
1073 | if (strsep(&p, " ") == NULL) | | 1104 | if (strsep(&p, " ") == NULL) |
1074 | continue; | | 1105 | continue; |
1075 | CHECK_VALID_META(p); | | 1106 | CHECK_VALID_META(p); |
| @@ -1198,31 +1229,36 @@ meta_oodate(GNode *gn, Boolean oodate) | | | @@ -1198,31 +1229,36 @@ meta_oodate(GNode *gn, Boolean oodate) |
1198 | int sdx = 0; | | 1229 | int sdx = 0; |
1199 | int found = 0; | | 1230 | int found = 0; |
1200 | | | 1231 | |
1201 | if (*p == '/') { | | 1232 | if (*p == '/') { |
1202 | sdirs[sdx++] = p; /* done */ | | 1233 | sdirs[sdx++] = p; /* done */ |
1203 | } else { | | 1234 | } else { |
1204 | if (strcmp(".", p) == 0) | | 1235 | if (strcmp(".", p) == 0) |
1205 | continue; /* no point */ | | 1236 | continue; /* no point */ |
1206 | | | 1237 | |
1207 | /* Check vs latestdir */ | | 1238 | /* Check vs latestdir */ |
1208 | snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p); | | 1239 | snprintf(fname1, sizeof(fname1), "%s/%s", latestdir, p); |
1209 | sdirs[sdx++] = fname1; | | 1240 | sdirs[sdx++] = fname1; |
1210 | | | 1241 | |
1211 | if (strcmp(latestdir, cwd) != 0) { | | 1242 | if (strcmp(latestdir, lcwd) != 0) { |
1212 | /* Check vs cwd */ | | 1243 | /* Check vs lcwd */ |
1213 | snprintf(fname2, sizeof(fname2), "%s/%s", cwd, p); | | 1244 | snprintf(fname2, sizeof(fname2), "%s/%s", lcwd, p); |
1214 | sdirs[sdx++] = fname2; | | 1245 | sdirs[sdx++] = fname2; |
1215 | } | | 1246 | } |
| | | 1247 | if (strcmp(lcwd, cwd) != 0) { |
| | | 1248 | /* Check vs cwd */ |
| | | 1249 | snprintf(fname3, sizeof(fname3), "%s/%s", cwd, p); |
| | | 1250 | sdirs[sdx++] = fname3; |
| | | 1251 | } |
1216 | } | | 1252 | } |
1217 | sdirs[sdx++] = NULL; | | 1253 | sdirs[sdx++] = NULL; |
1218 | | | 1254 | |
1219 | for (sdp = sdirs; *sdp && !found; sdp++) { | | 1255 | for (sdp = sdirs; *sdp && !found; sdp++) { |
1220 | #ifdef DEBUG_META_MODE | | 1256 | #ifdef DEBUG_META_MODE |
1221 | if (DEBUG(META)) | | 1257 | if (DEBUG(META)) |
1222 | fprintf(debug_file, "%s: %d: looking for: %s\n", fname, lineno, *sdp); | | 1258 | fprintf(debug_file, "%s: %d: looking for: %s\n", fname, lineno, *sdp); |
1223 | #endif | | 1259 | #endif |
1224 | if (stat(*sdp, &fs) == 0) { | | 1260 | if (stat(*sdp, &fs) == 0) { |
1225 | found = 1; | | 1261 | found = 1; |
1226 | p = *sdp; | | 1262 | p = *sdp; |
1227 | } | | 1263 | } |
1228 | } | | 1264 | } |
| @@ -1241,26 +1277,30 @@ meta_oodate(GNode *gn, Boolean oodate) | | | @@ -1241,26 +1277,30 @@ meta_oodate(GNode *gn, Boolean oodate) |
1241 | realpath(p, latestdir); | | 1277 | realpath(p, latestdir); |
1242 | } | | 1278 | } |
1243 | } else if (errno == ENOENT && *p == '/' && | | 1279 | } else if (errno == ENOENT && *p == '/' && |
1244 | strncmp(p, cwd, cwdlen) != 0) { | | 1280 | strncmp(p, cwd, cwdlen) != 0) { |
1245 | /* | | 1281 | /* |
1246 | * A referenced file outside of CWD is missing. | | 1282 | * A referenced file outside of CWD is missing. |
1247 | * We cannot catch every eventuality here... | | 1283 | * We cannot catch every eventuality here... |
1248 | */ | | 1284 | */ |
1249 | if (DEBUG(META)) | | 1285 | if (DEBUG(META)) |
1250 | fprintf(debug_file, "%s: %d: file '%s' may have moved?...\n", fname, lineno, p); | | 1286 | fprintf(debug_file, "%s: %d: file '%s' may have moved?...\n", fname, lineno, p); |
1251 | oodate = TRUE; | | 1287 | oodate = TRUE; |
1252 | } | | 1288 | } |
1253 | } | | 1289 | } |
| | | 1290 | if (buf[0] == 'E') { |
| | | 1291 | /* previous latestdir is no longer relevant */ |
| | | 1292 | strlcpy(latestdir, lcwd, sizeof(latestdir)); |
| | | 1293 | } |
1254 | break; | | 1294 | break; |
1255 | default: | | 1295 | default: |
1256 | break; | | 1296 | break; |
1257 | } | | 1297 | } |
1258 | if (!oodate && buf[0] == 'L' && link_src != NULL) | | 1298 | if (!oodate && buf[0] == 'L' && link_src != NULL) |
1259 | goto check_link_src; | | 1299 | goto check_link_src; |
1260 | } else if (strcmp(buf, "CMD") == 0) { | | 1300 | } else if (strcmp(buf, "CMD") == 0) { |
1261 | /* | | 1301 | /* |
1262 | * Compare the current command with the one in the | | 1302 | * Compare the current command with the one in the |
1263 | * meta data file. | | 1303 | * meta data file. |
1264 | */ | | 1304 | */ |
1265 | if (ln == NULL) { | | 1305 | if (ln == NULL) { |
1266 | if (DEBUG(META)) | | 1306 | if (DEBUG(META)) |