summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--futility/cmd_gscvd.c3
-rw-r--r--futility/cmd_load_fmap.c7
-rw-r--r--futility/cmd_sign.c3
-rw-r--r--futility/futility.h4
-rw-r--r--futility/misc.c74
5 files changed, 39 insertions, 52 deletions
diff --git a/futility/cmd_gscvd.c b/futility/cmd_gscvd.c
index e68faf9c..e9f49679 100644
--- a/futility/cmd_gscvd.c
+++ b/futility/cmd_gscvd.c
@@ -1293,7 +1293,8 @@ static int do_gscvd(int argc, char *argv[])
}
if (outfile) {
- futil_copy_file_or_die(infile, outfile);
+ if (futil_copy_file(infile, outfile) < 0)
+ exit(1);
work_file = outfile;
} else {
work_file = infile;
diff --git a/futility/cmd_load_fmap.c b/futility/cmd_load_fmap.c
index 474ff56e..220070a2 100644
--- a/futility/cmd_load_fmap.c
+++ b/futility/cmd_load_fmap.c
@@ -144,10 +144,11 @@ static int do_load_fmap(int argc, char *argv[])
infile = argv[optind++];
/* okay, let's do it ... */
- if (outfile)
- futil_copy_file_or_die(infile, outfile);
- else
+ if (!outfile)
outfile = infile;
+ else
+ if (futil_copy_file(infile, outfile) < 0)
+ exit(1);
errorcnt |= futil_open_and_map_file(outfile, &fd, FILE_RW, &buf, &len);
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index 383d39d7..4126717d 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -1139,7 +1139,8 @@ static int do_sign(int argc, char *argv[])
if (!sign_option.create_new_outfile) {
/* We'll read-modify-write the output file */
if (sign_option.inout_file_count > 1)
- futil_copy_file_or_die(infile, sign_option.outfile);
+ if (futil_copy_file(infile, sign_option.outfile) < 0)
+ goto done;
infile = sign_option.outfile;
}
diff --git a/futility/futility.h b/futility/futility.h
index 221590c8..3a276996 100644
--- a/futility/futility.h
+++ b/futility/futility.h
@@ -113,8 +113,8 @@ void update_hwid_digest(struct vb2_gbb_header *gbb);
int print_hwid_digest(struct vb2_gbb_header *gbb,
const char *banner, const char *footer);
-/* Copies a file or dies with an error message */
-void futil_copy_file_or_die(const char *infile, const char *outfile);
+/* Copies a file. */
+int futil_copy_file(const char *infile, const char *outfile);
/* Possible file operation errors */
enum futil_file_err {
diff --git a/futility/misc.c b/futility/misc.c
index bcbc61ca..3f3fb656 100644
--- a/futility/misc.c
+++ b/futility/misc.c
@@ -8,6 +8,9 @@
#include <fcntl.h>
#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
#include <linux/fs.h> /* For BLKGETSIZE64 */
+#include <sys/sendfile.h>
+#else
+#include <copyfile.h>
#endif
#include <stdarg.h>
#include <stdint.h>
@@ -210,58 +213,39 @@ int futil_set_gbb_hwid(struct vb2_gbb_header *gbb, const char *hwid)
return VB2_SUCCESS;
}
-/*
- * TODO: All sorts of race conditions likely here, and everywhere this is used.
- * Do we care? If so, fix it.
- */
-void futil_copy_file_or_die(const char *infile, const char *outfile)
+int futil_copy_file(const char *infile, const char *outfile)
{
- pid_t pid;
- int status;
-
VB2_DEBUG("%s -> %s\n", infile, outfile);
- pid = fork();
-
- if (pid < 0) {
- fprintf(stderr, "Couldn't fork /bin/cp process: %s\n",
- strerror(errno));
- exit(1);
- }
-
- /* child */
- if (!pid) {
- execl("/bin/cp", "/bin/cp", infile, outfile, NULL);
- fprintf(stderr, "Child couldn't exec /bin/cp: %s\n",
- strerror(errno));
- exit(1);
+ int ifd, ofd;
+ if ((ifd = open(infile, O_RDONLY)) == -1) {
+ ERROR("Cannot open '%s', %s.\n", infile, strerror(errno));
+ return -1;
}
-
- /* parent - wait for child to finish */
- if (wait(&status) == -1) {
- fprintf(stderr,
- "Couldn't wait for /bin/cp process to exit: %s\n",
- strerror(errno));
- exit(1);
+ if ((ofd = creat(outfile, 0660)) == -1) {
+ ERROR("Cannot open '%s', %s.\n", outfile, strerror(errno));
+ close(ifd);
+ return -1;
}
-
- if (WIFEXITED(status)) {
- status = WEXITSTATUS(status);
- /* zero is normal exit */
- if (!status)
- return;
- fprintf(stderr, "/bin/cp exited with status %d\n", status);
- exit(1);
+ struct stat finfo = {0};
+ if (fstat(ifd, &finfo) < 0) {
+ ERROR("Cannot fstat '%s' as %s.\n", infile, strerror(errno));
+ close (ifd);
+ close (ofd);
+ return -1;
}
-
- if (WIFSIGNALED(status)) {
- status = WTERMSIG(status);
- fprintf(stderr, "/bin/cp was killed with signal %d\n", status);
- exit(1);
+#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
+ ssize_t ret = sendfile(ofd, ifd, NULL, finfo.st_size);
+#else
+ ssize_t ret = fcopyfile(ifd, ofd, 0, COPYFILE_ALL);
+#endif
+ close(ifd);
+ close(ofd);
+ if (ret == -1) {
+ ERROR("Cannot copy '%s'->'%s', %s.\n", infile,
+ outfile, strerror(errno));
}
-
- fprintf(stderr, "I have no idea what just happened\n");
- exit(1);
+ return ret;
}
enum futil_file_err futil_open_file(const char *infile, int *fd,