append2simg: write to temporary file

append2simg causes libsparse to write mmapped data from a file
back to that same file.  On btrfs, this sometimes causes a page
of zeroes to be written instead of the file data.  Work around
the issue by writing the output to a temporary file and then
renaming it over the original file.

Change-Id: Ia194b6ba0ddb8548747b63292b523756f544706a
This commit is contained in:
Colin Cross 2014-04-25 14:28:54 -07:00
parent 9fdc8156ca
commit 0e3f47e482
2 changed files with 32 additions and 1 deletions

View File

@ -81,6 +81,8 @@ LOCAL_STATIC_LIBRARIES := \
include $(BUILD_EXECUTABLE)
ifneq ($(HOST_OS),windows)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := append2simg.c
LOCAL_MODULE := append2simg
@ -89,6 +91,7 @@ LOCAL_STATIC_LIBRARIES := \
libz
include $(BUILD_HOST_EXECUTABLE)
endif
include $(CLEAR_VARS)
LOCAL_MODULE := simg_dump.py

View File

@ -16,6 +16,7 @@
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE 1
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
@ -56,6 +57,11 @@ int main(int argc, char *argv[])
char *input_path;
off64_t input_len;
int tmp_fd;
char *tmp_path;
int ret;
if (argc == 3) {
output_path = argv[1];
input_path = argv[2];
@ -64,6 +70,12 @@ int main(int argc, char *argv[])
exit(-1);
}
ret = asprintf(&tmp_path, "%s.append2simg", output_path);
if (ret < 0) {
fprintf(stderr, "Couldn't allocate filename\n");
exit(-1);
}
output = open(output_path, O_RDWR | O_BINARY);
if (output < 0) {
fprintf(stderr, "Couldn't open output file (%s)\n", strerror(errno));
@ -99,14 +111,30 @@ int main(int argc, char *argv[])
}
sparse_output->len += input_len;
tmp_fd = open(tmp_path, O_WRONLY | O_CREAT | O_BINARY, 0664);
if (tmp_fd < 0) {
fprintf(stderr, "Couldn't open temporary file (%s)\n", strerror(errno));
exit(-1);
}
lseek64(output, 0, SEEK_SET);
if (sparse_file_write(sparse_output, output, false, true, false) < 0) {
if (sparse_file_write(sparse_output, tmp_fd, false, true, false) < 0) {
fprintf(stderr, "Failed to write sparse file\n");
exit(-1);
}
sparse_file_destroy(sparse_output);
close(tmp_fd);
close(output);
close(input);
ret = rename(tmp_path, output_path);
if (ret < 0) {
fprintf(stderr, "Failed to rename temporary file (%s)\n", strerror(errno));
exit(-1);
}
free(tmp_path);
exit(0);
}