/* run the real compiler and put the result in cache */
static void to_cache(ARGS *args)
{
- char *path_stdout, *path_status, *path_stderr;
+ char *path_stderr;
+ char *tmp_stdout, *tmp_stderr, *tmp_hashname;
struct stat st;
+ int status;
- x_asprintf(&path_status, "%s.status", hashname);
- x_asprintf(&path_stderr, "%s.stderr", hashname);
- x_asprintf(&path_stdout, "%s.stdout", hashname);
+ x_asprintf(&tmp_stdout, "%s/tmp.stdout.%d", cache_dir, getpid());
+ x_asprintf(&tmp_stderr, "%s/tmp.stderr.%d", cache_dir, getpid());
+ x_asprintf(&tmp_hashname, "%s/tmp.hash.%d", cache_dir, getpid());
args_add(args, "-o");
- args_add(args, hashname);
+ args_add(args, tmp_hashname);
+ status = execute(args->argv, tmp_stdout, tmp_stderr);
+ args->argc -= 2;
- execute(args->argv, path_stdout, path_stderr, path_status);
+ if (status != 0) {
+ cc_log("compile of %s gave status = %d\n", output_file, status);
+ unlink(tmp_stdout);
+ unlink(tmp_stderr);
+ unlink(tmp_hashname);
+ failed();
+ }
- args->argc -= 2;
+ if (stat(tmp_stdout, &st) != 0 || st.st_size != 0) {
+ cc_log("compiler produced stdout for %s\n", output_file);
+ unlink(tmp_stdout);
+ unlink(tmp_stderr);
+ unlink(tmp_hashname);
+ failed();
+ }
- if (stat(path_stdout, &st) != 0 || st.st_size != 0) {
- cc_log("compiler produced stdout!\n");
- unlink(path_stdout);
- unlink(path_stderr);
- unlink(path_status);
- unlink(hashname);
+ unlink(tmp_stdout);
+
+ x_asprintf(&path_stderr, "%s.stderr", hashname);
+
+ if (rename(tmp_hashname, hashname) != 0 ||
+ rename(tmp_stderr, path_stderr) != 0) {
+ cc_log("failed to rename tmp files\n");
failed();
}
- unlink(path_stdout);
cc_log("Placed %s into cache\n", output_file);
+
+ free(tmp_hashname);
+ free(tmp_stderr);
+ free(tmp_stdout);
+ free(path_stderr);
}
static void find_hash(ARGS *args)
{
int i;
- char *path_stdout, *path_stderr, *path_status;
+ char *path_stdout, *path_stderr;
char *hash_dir;
char *s;
struct stat st;
+ int status;
hash_start();
/* now the run */
x_asprintf(&path_stdout, "%s/tmp.stdout.%d", cache_dir, getpid());
x_asprintf(&path_stderr, "%s/tmp.stderr.%d", cache_dir, getpid());
- x_asprintf(&path_status, "%s/tmp.status.%d", cache_dir, getpid());
args_add(args, "-E");
- execute(args->argv, path_stdout, path_stderr, path_status);
+ status = execute(args->argv, path_stdout, path_stderr);
args->argc--;
+ if (status != 0) {
+ unlink(path_stdout);
+ unlink(path_stderr);
+ cc_log("the preprocessor gave %d\n", status);
+ failed();
+ }
+
/* if the compilation is with -g then we have to inlcude the whole of the
preprocessor output, which means we are sensitive to line number
information. Otherwise we can discard line number info, which makes
stabs_hash(path_stdout);
}
hash_file(path_stderr);
- hash_file(path_status);
unlink(path_stdout);
unlink(path_stderr);
- unlink(path_status);
free(path_stdout);
free(path_stderr);
- free(path_status);
/* we use a single level subdir for the cache path to reduce the impact
on filesystems which are slow for large directories
otherwise it returns */
static void from_cache(int first)
{
- int fd_status, fd_stderr;
+ int fd_stderr;
char *s;
- int ret, status;
-
- x_asprintf(&s, "%s.status", hashname);
- fd_status = open(s, O_RDONLY);
- free(s);
- if (fd_status == -1) {
- /* its not cached */
- return;
- }
- if (read(fd_status, &status, sizeof(status)) != sizeof(status)) {
- cc_log("status file is too short\n");
- close(fd_status);
- return;
- }
- close(fd_status);
+ int ret;
x_asprintf(&s, "%s.stderr", hashname);
fd_stderr = open(s, O_RDONLY);
free(s);
if (fd_stderr == -1) {
- cc_log("stderr file not found\n");
+ /* it isn't in cache ... */
return;
}
/* and exit with the right status code */
if (first) {
- cc_log("got cached result for %s with status = %d\n",
- output_file, status);
- }
-
- if (status != 0) {
- /* we delete cached entries with non-zero status as we use them,
- which basically means we do them non-cached. This is needed to cope
- with someone interrupting a compile
- Is there a better way?
- */
- x_asprintf(&s, "%s.status", hashname);
- unlink(s);
+ cc_log("got cached result for %s\n", output_file);
}
- exit(status);
+ exit(0);
}
/* find the real compiler. We just search the PATH to find a executable of the
execute a compiler backend, capturing all output to the given paths
the full path to the compiler to run is in argv[0]
*/
-void execute(char **argv,
- const char *path_stdout,
- const char *path_stderr,
- const char *path_status)
+int execute(char **argv,
+ const char *path_stdout,
+ const char *path_stderr)
{
pid_t pid;
- int fd;
- int s, status;
+ int status;
pid = fork();
if (pid == -1) fatal("Failed to fork");
if (pid == 0) {
+ int fd;
+
unlink(path_stdout);
fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
if (fd == -1) {
if (waitpid(pid, &status, 0) != pid) {
fatal("waitpid failed");
}
-
- fd = open(path_status, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
- if (fd == -1) {
- fatal("Failed to create status file");
- }
- s = WEXITSTATUS(status);
- if (write(fd, &s, sizeof(s)) != sizeof(s)) {
- fatal("failed to write status file");
- }
- close(fd);
+
+ return WEXITSTATUS(status);
}