int proc_flushstdio(void) { size_t len; int errors = 0; /* * flush any pending IO */ if (!initialized) return (-1); (void) fflush(stdout); (void) fflush(stderr); if ((len = ftell(stdout)) > 0) errors += copy_fd(cached_stdout_fd, stdout, len); if ((len = ftell(stderr)) > 0) errors += copy_fd(cached_stderr_fd, stderr, len); return (errors?-1:0); }
int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on_error) { int fd, orig_fd; fd = lock_file(lk, path); if (fd < 0) { if (die_on_error) die("unable to create '%s.lock': %s", path, strerror(errno)); return fd; } orig_fd = open(path, O_RDONLY); if (orig_fd < 0) { if (errno != ENOENT) { if (die_on_error) die("cannot open '%s' for copying", path); close(fd); return error("cannot open '%s' for copying", path); } } else if (copy_fd(orig_fd, fd)) { if (die_on_error) exit(128); close(fd); return -1; } return fd; }
/* * Write fdin to a new temp file in maildir/tmp, return full path to * the file, or NULL on errors. */ static char * maildir_write_tmp (const void *ctx, int fdin, const char *maildir) { char *path; int fdout; fdout = maildir_mktemp (ctx, maildir, &path); if (fdout < 0) return NULL; if (! copy_fd (fdout, fdin)) goto FAIL; if (fsync (fdout)) { fprintf (stderr, "Error: fsync '%s': %s\n", path, strerror (errno)); goto FAIL; } close (fdout); return path; FAIL: close (fdout); unlink (path); return NULL; }
int copy_file(const char *dst, const char *src, int mode) { int fdi, fdo, status; mode = (mode & 0111) ? 0777 : 0666; if ((fdi = open(src, O_RDONLY)) < 0) return fdi; if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { close(fdi); return fdo; } status = copy_fd(fdi, fdo); switch (status) { case COPY_READ_ERROR: error("copy-fd: read returned %s", strerror(errno)); break; case COPY_WRITE_ERROR: error("copy-fd: write returned %s", strerror(errno)); break; } close(fdi); if (close(fdo) != 0) return error("%s: close error: %s", dst, strerror(errno)); if (!status && adjust_shared_perm(dst)) return -1; return status; }
int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags) { int fd, orig_fd; fd = lock_file(lk, path, flags); if (fd < 0) { if (flags & LOCK_DIE_ON_ERROR) unable_to_lock_index_die(path, errno); return fd; } orig_fd = open(path, O_RDONLY); if (orig_fd < 0) { if (errno != ENOENT) { if (flags & LOCK_DIE_ON_ERROR) die("cannot open '%s' for copying", path); close(fd); return error("cannot open '%s' for copying", path); } } else if (copy_fd(orig_fd, fd)) { if (flags & LOCK_DIE_ON_ERROR) exit(128); close(fd); return -1; } return fd; }
void createOutput() { int ifd, ofd = -1; if ( verbose ) { #if defined(HOST_TOOLCHAIN_MSC) printf("\tcopy /b %s+%s %s\n", out, pltmp, out); #else printf("\tcat %s >> %s\n", pltmp, out); #endif } if ( !fake ) { if ( (ofd = open(out, O_WRONLY|O_BINARY, 0666)) < 0 ) { fprintf(stderr, "Could not open %s: %s\n", out, oserror()); error(1); } if ( lseek(ofd, 0, SEEK_END) == (off_t)-1 ) { fprintf(stderr, "Could not seek to end of %s: %s\n", out, oserror()); error(1); } if ( (ifd = open(pltmp, O_RDONLY|O_BINARY)) < 0 ) { close(ofd); remove(out); fprintf(stderr, "Could not open %s: %s\n", pltmp, oserror()); error(1); } copy_fd(ifd, ofd); close(ifd); } #ifdef HAVE_CHMOD { int mask = umask(0777); umask(mask); if ( verbose ) printf("\tchmod %03o %s\n", 0777 & ~mask, out); if ( !fake ) { #ifdef HAVE_FCHMOD if ( fchmod(ofd, 0777 & ~mask) != 0 ) #else if ( chmod(out, 0777 & ~mask) != 0 ) #endif { fprintf(stderr, "Could not make %s executable: %s\n", out, oserror()); error(1); } } } #endif if ( !fake ) close(ofd); }
static int copy_file(const char *source, char *dest, const char *hex, int warn_if_not_exists) { safe_create_leading_directories(dest); if (use_link) { if (!link(source, dest)) { pull_say("link %s\n", hex); return 0; } /* If we got ENOENT there is no point continuing. */ if (errno == ENOENT) { if (warn_if_not_exists) fprintf(stderr, "does not exist %s\n", source); return -1; } } if (use_symlink) { struct stat st; if (stat(source, &st)) { if (!warn_if_not_exists && errno == ENOENT) return -1; fprintf(stderr, "cannot stat %s: %s\n", source, strerror(errno)); return -1; } if (!symlink(source, dest)) { pull_say("symlink %s\n", hex); return 0; } } if (use_filecopy) { int ifd, ofd, status = 0; ifd = open(source, O_RDONLY); if (ifd < 0) { if (!warn_if_not_exists && errno == ENOENT) return -1; fprintf(stderr, "cannot open %s\n", source); return -1; } ofd = open(dest, O_WRONLY | O_CREAT | O_EXCL, 0666); if (ofd < 0) { fprintf(stderr, "cannot open %s\n", dest); close(ifd); return -1; } status = copy_fd(ifd, ofd); close(ofd); if (status) fprintf(stderr, "cannot write %s\n", dest); else pull_say("copy %s\n", hex); return status; } fprintf(stderr, "failed to copy %s with given copy methods.\n", hex); return -1; }
static int copy_file(const char *dst, const char *src, int mode) { int fdi, fdo, status; mode = (mode & 0111) ? 0777 : 0666; if ((fdi = open(src, O_RDONLY)) < 0) return fdi; if ((fdo = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) { close(fdi); return fdo; } status = copy_fd(fdi, fdo); close(fdo); return status; }
int copy_file (const char *dst, const char *src, int mode) { int fdi, fdo, status; if ((fdi = g_open (src, O_RDONLY | O_BINARY, 0)) < 0) return fdi; fdo = g_open (dst, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, mode); if (fdo < 0 && errno == EEXIST) { close (fdi); return 0; } else if (fdo < 0){ close (fdi); return -1; } status = copy_fd (fdi, fdo); if (close (fdo) != 0) return -1; return status; }
int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags) { int fd, orig_fd; fd = lock_file(lk, path, flags); if (fd < 0) { if (flags & LOCK_DIE_ON_ERROR) unable_to_lock_die(path, errno); return fd; } orig_fd = open(path, O_RDONLY); if (orig_fd < 0) { if (errno != ENOENT) { int save_errno = errno; if (flags & LOCK_DIE_ON_ERROR) die("cannot open '%s' for copying", path); rollback_lock_file(lk); error("cannot open '%s' for copying", path); errno = save_errno; return -1; } } else if (copy_fd(orig_fd, fd)) { int save_errno = errno; if (flags & LOCK_DIE_ON_ERROR) die("failed to prepare '%s' for appending", path); close(orig_fd); rollback_lock_file(lk); errno = save_errno; return -1; } else { close(orig_fd); } return fd; }
/* try to return the compile result from cache. If we can return from cache then this function exits with the correct status code, otherwise it returns */ static void from_cache(int first) { int fd_stderr, fd_cpp_stderr; char *stderr_file; int ret; struct stat st; x_asprintf(&stderr_file, "%s.stderr", hashname); fd_stderr = open(stderr_file, O_RDONLY | O_BINARY); if (fd_stderr == -1) { /* it isn't in cache ... */ free(stderr_file); return; } /* make sure the output is there too */ if (stat(hashname, &st) != 0) { close(fd_stderr); unlink(stderr_file); free(stderr_file); return; } /* the user might be disabling cache hits */ if (first && getenv("CCACHE_RECACHE")) { close(fd_stderr); unlink(stderr_file); free(stderr_file); return; } utime(stderr_file, NULL); if (strcmp(output_file, "/dev/null") == 0) { ret = 0; } else { unlink(output_file); if (getenv("CCACHE_HARDLINK")) { ret = link(hashname, output_file); } else { ret = copy_file(hashname, output_file); } } /* the hash file might have been deleted by some external process */ if (ret == -1 && errno == ENOENT) { cc_log("hashfile missing for %s\n", output_file); stats_update(STATS_MISSING); close(fd_stderr); unlink(stderr_file); return; } free(stderr_file); if (ret == -1) { ret = copy_file(hashname, output_file); if (ret == -1) { cc_log("failed to copy %s -> %s (%s)\n", hashname, output_file, strerror(errno)); stats_update(STATS_ERROR); failed(); } } if (ret == 0) { /* update the mtime on the file so that make doesn't get confused */ utime(output_file, NULL); } /* get rid of the intermediate preprocessor file */ if (i_tmpfile) { if (!direct_i_file) { unlink(i_tmpfile); } free(i_tmpfile); i_tmpfile = NULL; } /* send the cpp stderr, if applicable */ fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY); if (fd_cpp_stderr != -1) { copy_fd(fd_cpp_stderr, 2); close(fd_cpp_stderr); unlink(cpp_stderr); free(cpp_stderr); cpp_stderr = NULL; } /* send the stderr */ copy_fd(fd_stderr, 2); close(fd_stderr); /* and exit with the right status code */ if (first) { cc_log("got cached result for %s\n", output_file); stats_update(STATS_CACHED); } exit(0); }
/* run the real compiler and put the result in cache */ static void to_cache(ARGS *args) { char *path_stderr; char *tmp_stdout, *tmp_stderr, *tmp_hashname; struct stat st1, st2; int status; x_asprintf(&tmp_stdout, "%s/tmp.stdout.%s", temp_dir, tmp_string()); x_asprintf(&tmp_stderr, "%s/tmp.stderr.%s", temp_dir, tmp_string()); x_asprintf(&tmp_hashname, "%s/tmp.hash.%s.o", temp_dir, tmp_string()); args_add(args, "-o"); args_add(args, tmp_hashname); /* Turn off DEPENDENCIES_OUTPUT when running cc1, because * otherwise it will emit a line like * * tmp.stdout.vexed.732.o: /home/mbp/.ccache/tmp.stdout.vexed.732.i * * unsetenv() is on BSD and Linux but not portable. */ putenv("DEPENDENCIES_OUTPUT"); if (getenv("CCACHE_CPP2")) { args_add(args, input_file); } else { args_add(args, i_tmpfile); } status = execute(args->argv, tmp_stdout, tmp_stderr); args_pop(args, 3); if (stat(tmp_stdout, &st1) != 0 || st1.st_size != 0) { cc_log("compiler produced stdout for %s\n", output_file); stats_update(STATS_STDOUT); unlink(tmp_stdout); unlink(tmp_stderr); unlink(tmp_hashname); failed(); } unlink(tmp_stdout); if (status != 0) { int fd; cc_log("compile of %s gave status = %d\n", output_file, status); stats_update(STATS_STATUS); fd = open(tmp_stderr, O_RDONLY | O_BINARY); if (fd != -1) { if (strcmp(output_file, "/dev/null") == 0 || rename(tmp_hashname, output_file) == 0 || errno == ENOENT) { if (cpp_stderr) { /* we might have some stderr from cpp */ int fd2 = open(cpp_stderr, O_RDONLY | O_BINARY); if (fd2 != -1) { copy_fd(fd2, 2); close(fd2); unlink(cpp_stderr); cpp_stderr = NULL; } } /* we can use a quick method of getting the failed output */ copy_fd(fd, 2); close(fd); unlink(tmp_stderr); if (i_tmpfile && !direct_i_file) { unlink(i_tmpfile); } exit(status); } } unlink(tmp_stderr); unlink(tmp_hashname); failed(); } x_asprintf(&path_stderr, "%s.stderr", hashname); if (stat(tmp_stderr, &st1) != 0 || stat(tmp_hashname, &st2) != 0 || rename(tmp_hashname, hashname) != 0 || rename(tmp_stderr, path_stderr) != 0) { cc_log("failed to rename tmp files - %s\n", strerror(errno)); stats_update(STATS_ERROR); failed(); } cc_log("Placed %s into cache\n", output_file); stats_tocache(file_size(&st1) + file_size(&st2)); free(tmp_hashname); free(tmp_stderr); free(tmp_stdout); free(path_stderr); }
/* try to return the compile result from cache. If we can return from cache then this function exits with the correct status code, otherwise it returns */ static void from_cache(int first) { int fd_stderr, fd_cpp_stderr; char *stderr_file; struct stat st; x_asprintf(&stderr_file, "%s.stderr", hashname); fd_stderr = open(stderr_file, O_RDONLY | O_BINARY); if (fd_stderr == -1) { /* it isn't in cache ... */ free(stderr_file); return; } /* make sure the output is there too */ if (stat(hashname, &st) != 0) { close(fd_stderr); unlink(stderr_file); free(stderr_file); return; } /* the user might be disabling cache hits */ #ifndef ENABLE_ZLIB /* if the cache file is compressed we must recache */ if ((first && getenv("CCACHE_RECACHE")) || test_if_compressed(hashname) == 1) #else if (first && getenv("CCACHE_RECACHE")) #endif { close(fd_stderr); unlink(stderr_file); free(stderr_file); return; } if (first) { int hardlink; int passfail = -1; /* update timestamps for LRU cleanup also gives output_file a sensible mtime when hard-linking (for make) */ x_utimes(stderr_file); hardlink = (getenv("CCACHE_HARDLINK") != 0); if (swig) { /* read the list of generated files and copy each of them out of the cache */ FILE *file; char *outfiles; x_asprintf(&outfiles, "%s.outfiles", hashname); file = fopen(outfiles, "r"); if (file) { char out_filename[FILENAME_MAX + 1]; char out_filename_cache[FILENAME_MAX + 1]; int retrieved_files_count = 0; x_utimes(outfiles); while (fgets(out_filename, FILENAME_MAX, file)) { char *linefeed = strchr(out_filename, '\n'); if (linefeed) { char *potential_cr = linefeed - 1; if (potential_cr >= out_filename && *potential_cr == '\r') *potential_cr = 0; *linefeed = 0; if (retrieved_files_count == 0) { strcpy(out_filename_cache, hashname); } else { sprintf(out_filename_cache, "%s.%d", hashname, retrieved_files_count); } passfail = retrieve_from_cache(out_filename_cache, out_filename, hardlink); if (passfail == -1) { break; } retrieved_files_count++; } else { cc_log("failed to copy output files from cache - internal error\n"); stats_update(STATS_ERROR); passfail = -1; break; } } if (retrieved_files_count == 0) { cc_log("failed to copy output files from cache - internal error\n"); stats_update(STATS_ERROR); passfail = -1; } fclose(file); } else { cc_log("failed to open cached outfiles file - %s\n", strerror(errno)); stats_update(STATS_ERROR); } } else { passfail = retrieve_from_cache(hashname, output_file, hardlink); } if (passfail == -1) { close(fd_stderr); unlink(stderr_file); free(stderr_file); return; } free(stderr_file); } /* get rid of the intermediate preprocessor file */ if (i_tmpfile) { if (!direct_i_file) { unlink(i_tmpfile); } free(i_tmpfile); i_tmpfile = NULL; } /* send the cpp stderr, if applicable */ fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY); if (fd_cpp_stderr != -1) { copy_fd(fd_cpp_stderr, 2); close(fd_cpp_stderr); unlink(cpp_stderr); free(cpp_stderr); cpp_stderr = NULL; } /* send the stderr */ copy_fd(fd_stderr, 2); close(fd_stderr); /* and exit with the right status code */ if (first) { cc_log("got cached result for %s\n", input_file); stats_update(STATS_CACHED); } exit(0); }
/* run the real compiler and put the result in cache */ static void to_cache(ARGS *args) { char *path_stderr; char *tmp_stdout, *tmp_stderr, *tmp_outfiles; struct stat st1; int status; int cached_files_count = 0; int files_size = 0; x_asprintf(&tmp_stdout, "%s/tmp.stdout.%s", temp_dir, tmp_string()); x_asprintf(&tmp_stderr, "%s/tmp.stderr.%s", temp_dir, tmp_string()); x_asprintf(&tmp_outfiles, "%s/tmp.outfiles.%s", temp_dir, tmp_string()); if (strip_c_option && !swig) { args_add(stripped_args, "-c"); } if (output_file) { args_add(args, "-o"); args_add(args, output_file); } /* Turn off DEPENDENCIES_OUTPUT when running cc1, because * otherwise it will emit a line like * * tmp.stdout.vexed.732.o: /home/mbp/.ccache/tmp.stdout.vexed.732.i * * unsetenv() is on BSD and Linux but not portable. */ putenv("DEPENDENCIES_OUTPUT"); /* Give SWIG a filename for it to create and populate with a list of files that it generates */ if (swig) { char *ccache_outfiles; x_asprintf(&ccache_outfiles, "CCACHE_OUTFILES=%s", tmp_outfiles); unlink(tmp_outfiles); if (getenv("CCACHE_OUTFILES") || putenv(ccache_outfiles) == -1) { cc_log("CCACHE_OUTFILES env variable already set or could not be set\n"); stats_update(STATS_ERROR); failed(); } } if (getenv("CCACHE_CPP2")) { args_add(args, input_file); } else { if (swig) { args_add(args, "-nopreprocess"); } args_add(args, i_tmpfile); } status = execute(args->argv, tmp_stdout, tmp_stderr); args_pop(args, 3); if (stat(tmp_stdout, &st1) != 0 || st1.st_size != 0) { cc_log("compiler produced stdout for %s\n", input_file); stats_update(STATS_STDOUT); unlink(tmp_stdout); unlink(tmp_stderr); unlink(tmp_outfiles); if (!swig) unlink(output_file); failed(); } unlink(tmp_stdout); if (status != 0) { int fd; cc_log("compile of %s gave status = %d\n", input_file, status); stats_update(STATS_STATUS); fd = open(tmp_stderr, O_RDONLY | O_BINARY); if (fd != -1) { if (cpp_stderr) { /* we might have some stderr from cpp */ int fd2 = open(cpp_stderr, O_RDONLY | O_BINARY); if (fd2 != -1) { copy_fd(fd2, 2); close(fd2); unlink(cpp_stderr); cpp_stderr = NULL; } } /* we can use a quick method of getting the failed output */ copy_fd(fd, 2); close(fd); unlink(tmp_stderr); if (i_tmpfile && !direct_i_file) { unlink(i_tmpfile); } exit(status); } unlink(tmp_stderr); unlink(tmp_outfiles); if (!swig) unlink(output_file); failed(); } else { int hardlink = (getenv("CCACHE_NOCOMPRESS") != 0) && (getenv("CCACHE_HARDLINK") != 0); if (swig) { /* read the list of generated files and copy each of them into the cache */ FILE *file; file = fopen(tmp_outfiles, "r"); if (file) { char out_filename[FILENAME_MAX + 1]; char out_filename_cache[FILENAME_MAX + 1]; while (fgets(out_filename, FILENAME_MAX, file)) { char *linefeed = strchr(out_filename, '\n'); if (linefeed) { char *potential_cr = linefeed - 1; if (potential_cr >= out_filename && *potential_cr == '\r') *potential_cr = 0; *linefeed = 0; if (cached_files_count == 0) { strcpy(out_filename_cache, hashname); } else { sprintf(out_filename_cache, "%s.%d", hashname, cached_files_count); } if (commit_to_cache(out_filename, out_filename_cache, hardlink) != 0) { fclose(file); unlink(tmp_outfiles); failed(); } to_cache_stats_helper(&st1, out_filename_cache, tmp_outfiles, &files_size, &cached_files_count); } else { cached_files_count = 0; break; } } fclose(file); if (cached_files_count == 0) { cc_log("failed to copy output files to cache - internal error\n"); stats_update(STATS_ERROR); unlink(tmp_outfiles); failed(); } /* also copy the (uncompressed) file containing the list of generated files into the cache */ sprintf(out_filename_cache, "%s.outfiles", hashname); if (stat(tmp_outfiles, &st1) != 0 || safe_rename(tmp_outfiles, out_filename_cache) != 0) { cc_log("failed to copy outfiles file to cache - %s\n", strerror(errno)); stats_update(STATS_ERROR); unlink(tmp_outfiles); failed(); } to_cache_stats_helper(&st1, out_filename_cache, tmp_outfiles, &files_size, &cached_files_count); unlink(tmp_outfiles); } else { cc_log("failed to open temp outfiles file - %s\n", strerror(errno)); stats_update(STATS_ERROR); failed(); } } else { if (commit_to_cache(output_file, hashname, hardlink) != 0) { failed(); } to_cache_stats_helper(&st1, hashname, 0, &files_size, &cached_files_count); } } x_asprintf(&path_stderr, "%s.stderr", hashname); if (stat(tmp_stderr, &st1) != 0 || move_file(tmp_stderr, path_stderr) != 0) { cc_log("failed to rename tmp files - %s\n", strerror(errno)); stats_update(STATS_ERROR); failed(); } to_cache_stats_helper(&st1, path_stderr, 0, &files_size, &cached_files_count); cc_log("Placed %d files for %s into cache\n", cached_files_count, input_file); stats_tocache(files_size, cached_files_count); free(tmp_stderr); free(tmp_stdout); free(tmp_outfiles); free(path_stderr); }