aboutsummaryrefslogtreecommitdiffstats
path: root/src/clone_data.c
blob: 3083914cf9ffbb8c90f12f0bf572cdaf4088ee50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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;
}