Print this page
Cleanup temp files without rm
Cleanup cw tempfiles properly
Revert "Revert most of "9899 cw(1onbld) should shadow more compilation""
This reverts commit 67deef8cbc83060db238a0f4ee252d1ba74641ef.

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/cw/cw.c
          +++ new/usr/src/tools/cw/cw.c
↓ open down ↓ 252 lines elided ↑ open up ↑
 253  253  
 254  254  #include <ctype.h>
 255  255  #include <err.h>
 256  256  #include <errno.h>
 257  257  #include <fcntl.h>
 258  258  #include <getopt.h>
 259  259  #include <stdio.h>
 260  260  #include <stdlib.h>
 261  261  #include <string.h>
 262  262  #include <unistd.h>
      263 +#include <dirent.h>
 263  264  
 264  265  #include <sys/param.h>
 265  266  #include <sys/stat.h>
 266  267  #include <sys/types.h>
 267  268  #include <sys/utsname.h>
 268  269  #include <sys/wait.h>
 269  270  
 270  271  #define CW_F_CXX        0x01
 271  272  #define CW_F_SHADOW     0x02
 272  273  #define CW_F_EXEC       0x04
↓ open down ↓ 28 lines elided ↑ open up ↑
 301  302  } cw_compiler_t;
 302  303  
 303  304  typedef struct cw_ictx {
 304  305          struct cw_ictx  *i_next;
 305  306          cw_compiler_t   *i_compiler;
 306  307          struct aelist   *i_ae;
 307  308          uint32_t        i_flags;
 308  309          int             i_oldargc;
 309  310          char            **i_oldargv;
 310  311          pid_t           i_pid;
 311      -        char            i_discard[MAXPATHLEN];
      312 +        char            *i_tmpdir;
 312  313          char            *i_stderr;
 313  314  } cw_ictx_t;
 314  315  
 315  316  /*
 316  317   * Status values to indicate which Studio compiler and associated
 317  318   * flags are being used.
 318  319   */
 319  320  #define M32             0x01    /* -m32 - only on Studio 12 */
 320  321  #define M64             0x02    /* -m64 - only on Studio 12 */
 321  322  #define SS11            0x100   /* Studio 11 */
↓ open down ↓ 224 lines elided ↑ open up ↑
 546  547                  error(xarg);
 547  548  
 548  549          table++;
 549  550  
 550  551          while (*table != NULL) {
 551  552                  newae(h, *table);
 552  553                  table++;
 553  554          }
 554  555  }
 555  556  
      557 +/*
      558 + * The compiler wants the output file to end in appropriate extension.  If
      559 + * we're generating a name from whole cloth (path == NULL), we assume that
      560 + * extension to be .o, otherwise we match the extension of the caller.
      561 + */
      562 +static char *
      563 +discard_file_name(cw_ictx_t *ctx, const char *path)
      564 +{
      565 +        char *ret, *ext;
      566 +        char tmpl[] = "cwXXXXXX";
      567 +
      568 +        if (path == NULL) {
      569 +                ext = ".o";
      570 +        } else {
      571 +                ext = strrchr(path, '.');
      572 +        }
      573 +
      574 +        /*
      575 +         * We need absolute control over where the temporary file goes, since
      576 +         * we rely on it for cleanup so tempnam(3C) and tmpnam(3C) are
      577 +         * inappropriate (they use TMPDIR, preferentially).
      578 +         *
      579 +         * mkstemp(3C) doesn't actually help us, since the temporary file
      580 +         * isn't used by us, only its name.
      581 +         */
      582 +        if (mktemp(tmpl) == NULL)
      583 +                nomem();
      584 +
      585 +        (void) asprintf(&ret, "%s/%s%s", ctx->i_tmpdir, tmpl,
      586 +            (ext != NULL) ? ext : "");
      587 +
      588 +        if (ret == NULL)
      589 +                nomem();
      590 +
      591 +        return (ret);
      592 +}
      593 +
 556  594  static void
 557  595  do_gcc(cw_ictx_t *ctx)
 558  596  {
 559  597          int c;
 560  598          int nolibc = 0;
 561  599          int in_output = 0, seen_o = 0, c_files = 0;
 562  600          cw_op_t op = CW_O_LINK;
 563  601          char *model = NULL;
 564  602          char *nameflag;
 565      -        int     mflag = 0;
      603 +        int mflag = 0;
 566  604  
 567  605          if (ctx->i_flags & CW_F_PROG) {
 568  606                  newae(ctx->i_ae, "--version");
 569  607                  return;
 570  608          }
 571  609  
 572  610          newae(ctx->i_ae, "-fident");
 573  611          newae(ctx->i_ae, "-finline");
 574  612          newae(ctx->i_ae, "-fno-inline-functions");
 575  613          newae(ctx->i_ae, "-fno-builtin");
↓ open down ↓ 47 lines elided ↑ open up ↑
 623  661                              (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
 624  662                              arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
 625  663                                  c_files++;
 626  664  
 627  665                          /*
 628  666                           * Otherwise, filenames and partial arguments
 629  667                           * are passed through for gcc to chew on.  However,
 630  668                           * output is always discarded for the secondary
 631  669                           * compiler.
 632  670                           */
 633      -                        if ((ctx->i_flags & CW_F_SHADOW) && in_output)
 634      -                                newae(ctx->i_ae, ctx->i_discard);
 635      -                        else
      671 +                        if ((ctx->i_flags & CW_F_SHADOW) && in_output) {
      672 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
      673 +                        } else {
 636  674                                  newae(ctx->i_ae, arg);
      675 +                        }
 637  676                          in_output = 0;
 638  677                          continue;
 639  678                  }
 640  679  
 641  680                  if (ctx->i_flags & CW_F_CXX) {
 642  681                          if (strncmp(arg, "-_g++=", 6) == 0) {
 643  682                                  newae(ctx->i_ae, strchr(arg, '=') + 1);
 644  683                                  continue;
 645  684                          }
 646  685                          if (strncmp(arg, "-compat=", 8) == 0) {
↓ open down ↓ 95 lines elided ↑ open up ↑
 742  781                  case 'w':
 743  782                          newae(ctx->i_ae, arg);
 744  783                          break;
 745  784                  case 'o':
 746  785                          seen_o = 1;
 747  786                          if (arglen == 1) {
 748  787                                  in_output = 1;
 749  788                                  newae(ctx->i_ae, arg);
 750  789                          } else if (ctx->i_flags & CW_F_SHADOW) {
 751  790                                  newae(ctx->i_ae, "-o");
 752      -                                newae(ctx->i_ae, ctx->i_discard);
      791 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
 753  792                          } else {
 754  793                                  newae(ctx->i_ae, arg);
 755  794                          }
 756  795                          break;
 757  796                  case 'D':
 758  797                          newae(ctx->i_ae, arg);
 759  798                          /*
 760  799                           * XXX  Clearly a hack ... do we need _KADB too?
 761  800                           */
 762  801                          if (strcmp(arg, "-D_KERNEL") == 0 ||
↓ open down ↓ 417 lines elided ↑ open up ↑
1180 1219                           * We could map -Qy into -Wl,-Qy etc.
1181 1220                           */
1182 1221                  default:
1183 1222                          error(arg);
1184 1223                          break;
1185 1224                  }
1186 1225          }
1187 1226  
1188 1227          free(nameflag);
1189 1228  
1190      -        if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1191      -            op != CW_O_PREPROCESS) {
     1229 +        /*
     1230 +         * When compiling multiple source files in a single invocation some
     1231 +         * compilers output objects into the current directory with
     1232 +         * predictable and conventional names.
     1233 +         *
     1234 +         * We prevent any attempt to compile multiple files at once so that
     1235 +         * any such objects created by a shadow can't escape into a later
     1236 +         * link-edit.
     1237 +         */
     1238 +        if (c_files > 1 && op != CW_O_PREPROCESS) {
1192 1239                  errx(2, "multiple source files are "
1193 1240                      "allowed only with -E or -P");
1194 1241          }
1195 1242  
1196 1243          /*
1197 1244           * Make sure that we do not have any unintended interactions between
1198 1245           * the xarch options passed in and the version of the Studio compiler
1199 1246           * used.
1200 1247           */
1201 1248          if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
↓ open down ↓ 47 lines elided ↑ open up ↑
1249 1296  #endif
1250 1297                  break;
1251 1298          case (SS12|M64):
1252 1299                  break;
1253 1300          default:
1254 1301                  (void) fprintf(stderr,
1255 1302                      "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1256 1303                  exit(2);
1257 1304          }
1258 1305  
1259      -        if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1260      -            (ctx->i_flags & CW_F_SHADOW))
1261      -                exit(0);
     1306 +        if (ctx->i_flags & CW_F_SHADOW) {
     1307 +                if (op == CW_O_PREPROCESS)
     1308 +                        exit(0);
     1309 +                else if (op == CW_O_LINK && c_files == 0)
     1310 +                        exit(0);
     1311 +        }
1262 1312  
1263 1313          if (model != NULL)
1264 1314                  newae(ctx->i_ae, model);
1265 1315          if (!nolibc)
1266 1316                  newae(ctx->i_ae, "-lc");
1267 1317          if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1268 1318                  newae(ctx->i_ae, "-o");
1269      -                newae(ctx->i_ae, ctx->i_discard);
     1319 +                newae(ctx->i_ae, discard_file_name(ctx, NULL));
1270 1320          }
1271 1321  }
1272 1322  
1273 1323  static void
1274 1324  do_cc(cw_ictx_t *ctx)
1275 1325  {
1276      -        int in_output = 0, seen_o = 0;
     1326 +        int in_output = 0, seen_o = 0, c_files = 0;
1277 1327          cw_op_t op = CW_O_LINK;
1278 1328          char *nameflag;
1279 1329  
1280 1330          if (ctx->i_flags & CW_F_PROG) {
1281 1331                  newae(ctx->i_ae, "-V");
1282 1332                  return;
1283 1333          }
1284 1334  
1285 1335          if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1286 1336                  nomem();
1287 1337  
1288 1338          while (--ctx->i_oldargc > 0) {
1289 1339                  char *arg = *++ctx->i_oldargv;
     1340 +                size_t arglen = strlen(arg);
1290 1341  
1291 1342                  if (strncmp(arg, "-_CC=", 5) == 0) {
1292 1343                          newae(ctx->i_ae, strchr(arg, '=') + 1);
1293 1344                          continue;
1294 1345                  }
1295 1346  
1296 1347                  if (*arg != '-') {
     1348 +                        if (!in_output && arglen > 2 &&
     1349 +                            arg[arglen - 2] == '.' &&
     1350 +                            (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
     1351 +                            arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
     1352 +                                c_files++;
     1353 +
1297 1354                          if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1298 1355                                  newae(ctx->i_ae, arg);
1299 1356                          } else {
1300 1357                                  in_output = 0;
1301      -                                newae(ctx->i_ae, ctx->i_discard);
     1358 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
1302 1359                          }
1303 1360                          continue;
1304 1361                  }
1305 1362                  switch (*(arg + 1)) {
1306 1363                  case '_':
1307 1364                          if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
1308 1365                              (strncmp(arg, "-_cc=", 5) == 0) ||
1309 1366                              (strncmp(arg, "-_sun=", 6) == 0)) {
1310 1367                                  newae(ctx->i_ae, strchr(arg, '=') + 1);
1311 1368                          }
↓ open down ↓ 3 lines elided ↑ open up ↑
1315 1372                          ctx->i_flags &= ~CW_F_ECHO;
1316 1373                          newae(ctx->i_ae, arg);
1317 1374                          break;
1318 1375                  case 'o':
1319 1376                          seen_o = 1;
1320 1377                          if (strlen(arg) == 2) {
1321 1378                                  in_output = 1;
1322 1379                                  newae(ctx->i_ae, arg);
1323 1380                          } else if (ctx->i_flags & CW_F_SHADOW) {
1324 1381                                  newae(ctx->i_ae, "-o");
1325      -                                newae(ctx->i_ae, ctx->i_discard);
     1382 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
1326 1383                          } else {
1327 1384                                  newae(ctx->i_ae, arg);
1328 1385                          }
1329 1386                          break;
1330 1387                  case 'c':
1331 1388                  case 'S':
1332 1389                          if (strlen(arg) == 2)
1333 1390                                  op = CW_O_COMPILE;
1334 1391                          newae(ctx->i_ae, arg);
1335 1392                          break;
↓ open down ↓ 2 lines elided ↑ open up ↑
1338 1395                          if (strlen(arg) == 2)
1339 1396                                  op = CW_O_PREPROCESS;
1340 1397                  /*FALLTHROUGH*/
1341 1398                  default:
1342 1399                          newae(ctx->i_ae, arg);
1343 1400                  }
1344 1401          }
1345 1402  
1346 1403          free(nameflag);
1347 1404  
1348      -        if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1349      -            (ctx->i_flags & CW_F_SHADOW))
1350      -                exit(0);
     1405 +        /* See the comment on this same code in do_gcc() */
     1406 +        if (c_files > 1 && op != CW_O_PREPROCESS) {
     1407 +                errx(2, "multiple source files are "
     1408 +                    "allowed only with -E or -P");
     1409 +        }
     1410 +
     1411 +        if (ctx->i_flags & CW_F_SHADOW) {
     1412 +                if (op == CW_O_PREPROCESS)
     1413 +                        exit(0);
     1414 +                else if (op == CW_O_LINK && c_files == 0)
     1415 +                        exit(0);
     1416 +        }
1351 1417  
1352 1418          if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1353 1419                  newae(ctx->i_ae, "-o");
1354      -                newae(ctx->i_ae, ctx->i_discard);
     1420 +                newae(ctx->i_ae, discard_file_name(ctx, NULL));
1355 1421          }
1356 1422  }
1357 1423  
1358 1424  static void
1359 1425  prepctx(cw_ictx_t *ctx)
1360 1426  {
1361 1427          newae(ctx->i_ae, ctx->i_compiler->c_path);
1362 1428  
1363 1429          if (ctx->i_flags & CW_F_PROG) {
1364 1430                  (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
↓ open down ↓ 87 lines elided ↑ open up ↑
1452 1518                          if (WIFSIGNALED(status)) {
1453 1519                                  ret = -WTERMSIG(status);
1454 1520                                  break;
1455 1521                          } else if (WIFEXITED(status)) {
1456 1522                                  ret = WEXITSTATUS(status);
1457 1523                                  break;
1458 1524                          }
1459 1525                  }
1460 1526          } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1461 1527  
1462      -        (void) unlink(ctx->i_discard);
1463      -
1464 1528          if (stat(ctx->i_stderr, &s) < 0) {
1465 1529                  warn("stat failed on child cleanup");
1466 1530                  return (-1);
1467 1531          }
1468 1532          if (s.st_size != 0) {
1469 1533                  FILE *f;
1470 1534  
1471 1535                  if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1472 1536                          while (fgets(buf, sizeof (buf), f))
1473 1537                                  (void) fprintf(stderr, "%s", buf);
↓ open down ↓ 9 lines elided ↑ open up ↑
1483 1547           */
1484 1548          if (ctx->i_flags & CW_F_PROG)
1485 1549                  return (0);
1486 1550  
1487 1551          return (ret);
1488 1552  }
1489 1553  
1490 1554  static int
1491 1555  exec_ctx(cw_ictx_t *ctx, int block)
1492 1556  {
1493      -        char *file;
1494      -
1495      -        /*
1496      -         * To avoid offending cc's sensibilities, the name of its output
1497      -         * file must end in '.o'.
1498      -         */
1499      -        if ((file = tempnam(NULL, ".cw")) == NULL) {
1500      -                nomem();
1501      -                return (-1);
1502      -        }
1503      -        (void) strlcpy(ctx->i_discard, file, MAXPATHLEN);
1504      -        (void) strlcat(ctx->i_discard, ".o", MAXPATHLEN);
1505      -        free(file);
1506      -
1507      -        if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
     1557 +        if ((ctx->i_stderr = tempnam(ctx->i_tmpdir, "cw")) == NULL) {
1508 1558                  nomem();
1509 1559                  return (-1);
1510 1560          }
1511 1561  
1512 1562          if ((ctx->i_pid = fork()) == 0) {
1513 1563                  int fd;
1514 1564  
1515 1565                  (void) fclose(stderr);
1516 1566                  if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1517 1567                      0666)) < 0) {
↓ open down ↓ 47 lines elided ↑ open up ↑
1565 1615          else if ((strcasecmp(token, "sun") == 0) ||
1566 1616              (strcasecmp(token, "cc") == 0))
1567 1617                  compiler->c_style = SUN;
1568 1618          else
1569 1619                  errx(1, "unknown compiler style: %s", token);
1570 1620  
1571 1621          if (tspec != NULL)
1572 1622                  errx(1, "Excess tokens in compiler: %s", spec);
1573 1623  }
1574 1624  
     1625 +static void
     1626 +cleanup(cw_ictx_t *ctx)
     1627 +{
     1628 +        DIR *dirp;
     1629 +        struct dirent *dp;
     1630 +        char buf[MAXPATHLEN];
     1631 +
     1632 +        if ((dirp = opendir(ctx->i_tmpdir)) == NULL) {
     1633 +                if (errno != ENOENT) {
     1634 +                        err(1, "couldn't open temp directory: %s",
     1635 +                            ctx->i_tmpdir);
     1636 +                } else {
     1637 +                        return;
     1638 +                }
     1639 +        }
     1640 +
     1641 +        errno = 0;
     1642 +        while ((dp = readdir(dirp)) != NULL) {
     1643 +                (void) snprintf(buf, MAXPATHLEN, "%s/%s", ctx->i_tmpdir,
     1644 +                    dp->d_name);
     1645 +
     1646 +                if (strncmp(dp->d_name, ".", strlen(dp->d_name)) == 0 ||
     1647 +                    strncmp(dp->d_name, "..", strlen(dp->d_name)) == 0)
     1648 +                        continue;
     1649 +
     1650 +                if (unlink(buf) == -1)
     1651 +                        err(1, "failed to unlink temp file: %s", dp->d_name);
     1652 +                errno = 0;
     1653 +        }
     1654 +
     1655 +        if (errno != 0) {
     1656 +                err(1, "failed to read temporary directory: %s",
     1657 +                    ctx->i_tmpdir);
     1658 +        }
     1659 +
     1660 +        (void) closedir(dirp);
     1661 +        if (rmdir(ctx->i_tmpdir) != 0) {
     1662 +                err(1, "failed to unlink temporary directory: %s",
     1663 +                    ctx->i_tmpdir);
     1664 +        }
     1665 +}
     1666 +
1575 1667  int
1576 1668  main(int argc, char **argv)
1577 1669  {
1578 1670          int ch;
1579 1671          cw_compiler_t primary = { NULL, NULL, 0 };
1580 1672          cw_compiler_t shadows[10];
1581 1673          int nshadows = 0;
1582 1674          int ret = 0;
1583 1675          boolean_t do_serial = B_FALSE;
1584 1676          boolean_t do_exec = B_FALSE;
1585 1677          boolean_t vflg = B_FALSE;
1586 1678          boolean_t Cflg = B_FALSE;
1587 1679          boolean_t cflg = B_FALSE;
1588 1680          boolean_t nflg = B_FALSE;
     1681 +        char *tmpdir;
1589 1682  
1590 1683          cw_ictx_t *main_ctx;
1591 1684  
1592 1685          static struct option longopts[] = {
1593 1686                  { "compiler", no_argument, NULL, 'c' },
1594 1687                  { "noecho", no_argument, NULL, 'n' },
1595 1688                  { "primary", required_argument, NULL, 'p' },
1596 1689                  { "shadow", required_argument, NULL, 's' },
1597 1690                  { "versions", no_argument, NULL, 'v' },
1598 1691                  { NULL, 0, NULL, 0 },
↓ open down ↓ 67 lines elided ↑ open up ↑
1666 1759          }
1667 1760  
1668 1761          if (vflg) {
1669 1762                  (void) printf("cw version %s\n", CW_VERSION);
1670 1763                  (void) fflush(stdout);
1671 1764                  main_ctx->i_flags &= ~CW_F_ECHO;
1672 1765                  main_ctx->i_flags |= CW_F_PROG | CW_F_EXEC;
1673 1766                  do_serial = 1;
1674 1767          }
1675 1768  
     1769 +        tmpdir = getenv("TMPDIR");
     1770 +        if (tmpdir == NULL)
     1771 +                tmpdir = "/tmp";
     1772 +
     1773 +        if (asprintf(&main_ctx->i_tmpdir, "%s/cw.XXXXXX", tmpdir) == -1)
     1774 +                nomem();
     1775 +
     1776 +        if ((main_ctx->i_tmpdir = mkdtemp(main_ctx->i_tmpdir)) == NULL)
     1777 +                errx(1, "failed to create temporary directory");
     1778 +
1676 1779          ret |= exec_ctx(main_ctx, do_serial);
1677 1780  
1678 1781          for (int i = 0; i < nshadows; i++) {
1679 1782                  int r;
1680 1783                  cw_ictx_t *shadow_ctx;
1681 1784  
1682 1785                  if ((shadow_ctx = newictx()) == NULL)
1683 1786                          nomem();
1684 1787  
1685      -                memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
     1788 +                (void) memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
1686 1789  
1687 1790                  shadow_ctx->i_flags |= CW_F_SHADOW;
1688 1791                  shadow_ctx->i_compiler = &shadows[i];
1689 1792  
1690 1793                  r = exec_ctx(shadow_ctx, do_serial);
1691 1794                  if (r == 0) {
1692 1795                          shadow_ctx->i_next = main_ctx->i_next;
1693 1796                          main_ctx->i_next = shadow_ctx;
1694 1797                  }
1695 1798                  ret |= r;
↓ open down ↓ 1 lines elided ↑ open up ↑
1697 1800  
1698 1801          if (!do_serial) {
1699 1802                  cw_ictx_t *next = main_ctx;
1700 1803                  while (next != NULL) {
1701 1804                          cw_ictx_t *toreap = next;
1702 1805                          next = next->i_next;
1703 1806                          ret |= reap(toreap);
1704 1807                  }
1705 1808          }
1706 1809  
     1810 +        cleanup(main_ctx);
1707 1811          return (ret);
1708 1812  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX