aboutsummaryrefslogtreecommitdiffstats
path: root/src/clone_data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/clone_data.c')
-rw-r--r--src/clone_data.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/clone_data.c b/src/clone_data.c
new file mode 100644
index 0000000..3083914
--- /dev/null
+++ b/src/clone_data.c
@@ -0,0 +1,84 @@
+#include "project.h"
+
+
+int clone_data (ext2_filsys src_fs, ext2_filsys dst_fs, ext2_ino_t i_num, struct ext2_inode *src_i, struct ext2_inode *dst_i, uint64_t offset, uint64_t len)
+{
+ int ret;
+ __u64 file_len;
+ unsigned got, written, fetch;
+ ext2_file_t src_f = NULL, dst_f = NULL;
+
+ do {
+
+ EXT2_MOAN_FAIL (ret, ext2fs_file_open2 (src_fs, i_num, src_i, 0, &src_f));
+
+ if (ret)
+ return -1;
+
+ EXT2_MOAN_FAIL (ret, ext2fs_file_open2 (dst_fs, i_num, dst_i, EXT2_FILE_WRITE, &dst_f));
+
+ if (ret)
+ return -1;
+
+
+
+ if (offset) {
+
+ EXT2_MOAN_FAIL (ret, ext2fs_file_lseek (src_f, offset, SEEK_SET, NULL));
+
+ if (ret)
+ return -1;
+
+ EXT2_MOAN_FAIL (ret, ext2fs_file_lseek (dst_f, offset, SEEK_SET, NULL));
+
+ if (ret)
+ return -1;
+ }
+
+ EXT2_MOAN_FAIL (ret, ext2fs_file_get_lsize (src_f, &file_len));
+
+ if (ret)
+ break;
+
+
+ file_len -= offset;
+
+
+ if (len > file_len)
+ len = file_len;
+
+ while (len) {
+
+ fetch = len > BUF_SZ ? BUF_SZ : len;
+
+ EXT2_MOAN_FAIL (ret, ext2fs_file_read (src_f, buf, fetch, &got));
+
+ if (ret)
+ break;
+
+ if (got) {
+ EXT2_MOAN_FAIL (ret, ext2fs_file_write (dst_f, buf, got, &written));
+
+ if (ret)
+ break;
+
+ if (written != got) {
+ fprintf (stderr, "Not all bytes written in inode %d\n", (int) i_num);
+ ret = 1;
+ break;
+ }
+ }
+
+ stats_bytes += written;
+ len -= written;
+ }
+
+ } while (0);
+
+ ext2fs_file_flush (dst_f);
+ ext2fs_file_close (dst_f);
+ ext2fs_file_close (src_f);
+ return ret;
+}
+
+