hc
2023-02-18 a08c8b75ee83d7f62c9aefc23bfb42082aa4076c
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
From 34ed66f2bc913b70cae217fd32cc3cba050069c4 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Sat, 29 Dec 2018 17:33:48 +0800
Subject: [PATCH] ntfscp: Support directory copy
 
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 ntfsprogs/ntfscp.c | 45 ++++++++++++++++++++++++++++++++-------------
 1 file changed, 32 insertions(+), 13 deletions(-)
 
diff --git a/ntfsprogs/ntfscp.c b/ntfsprogs/ntfscp.c
index 19303b6..6f9180a 100644
--- a/ntfsprogs/ntfscp.c
+++ b/ntfsprogs/ntfscp.c
@@ -798,19 +798,20 @@ static int preallocate(ntfs_attr *na, s64 new_size)
 }
 
 /**
- * Create a regular file under the given directory inode
+ * Create a file under the given directory inode
  *
  * It is a wrapper function to ntfs_create(...)
  *
  * Return:  the created file inode
  */
 static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni,
-              const char *filename)
+              const char *filename, mode_t typemode)
 {
     ntfschar *ufilename;
     /* inode to the file that is being created */
     ntfs_inode *ni;
     int ufilename_len;
+    mode_t type = typemode & ~07777;
 
     /* ntfs_mbstoucs(...) will allocate memory for ufilename if it's NULL */
     ufilename = NULL;
@@ -820,7 +821,7 @@ static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni,
                     filename);
         return NULL;
     }
-    ni = ntfs_create(dir_ni, const_cpu_to_le32(0), ufilename, ufilename_len, S_IFREG);
+    ni = ntfs_create(dir_ni, const_cpu_to_le32(0), ufilename, ufilename_len, type);
     free(ufilename);
     return ni;
 }
@@ -852,6 +853,8 @@ int main(int argc, char *argv[])
 #ifdef HAVE_WINDOWS_H
     char *unix_name;
 #endif
+    struct stat fst;
+    int created = 0;
 
     ntfs_log_set_handler(ntfs_log_handler_stderr);
 
@@ -892,14 +895,11 @@ int main(int argc, char *argv[])
         goto umount;
     }
 
-    {
-        struct stat fst;
-        if (stat(opts.src_file, &fst) == -1) {
-            ntfs_log_perror("ERROR: Couldn't stat source file");
-            goto umount;
-        }
-        new_size = fst.st_size;
+    if (stat(opts.src_file, &fst) == -1) {
+        ntfs_log_perror("ERROR: Couldn't stat source file");
+        goto umount;
     }
+    new_size = fst.st_size;
     ntfs_log_verbose("New file size: %lld\n", (long long)new_size);
 
     in = fopen(opts.src_file, "r");
@@ -960,6 +960,8 @@ int main(int argc, char *argv[])
             ntfs_log_verbose("Target path does not contain '/'. "
                     "Using root directory as parent.\n");
             dir_ni = ntfs_inode_open(vol, FILE_root);
+            free(parent_dirname);
+            dirname_last_whack = parent_dirname = strdup("/");
         }
         if (dir_ni) {
             if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
@@ -974,7 +976,7 @@ int main(int argc, char *argv[])
             }
             ntfs_log_verbose("Creating a new file '%s' under '%s'"
                      "\n", filename, parent_dirname);
-            ni = ntfs_new_file(dir_ni, filename);
+            ni = ntfs_new_file(dir_ni, filename, fst.st_mode);
             ntfs_inode_close(dir_ni);
             if (!ni) {
                 ntfs_log_perror("Failed to create '%s' under "
@@ -984,6 +986,7 @@ int main(int argc, char *argv[])
                 goto close_src;
             }
             out = ni;
+            created = 1;
         } else {
             ntfs_log_perror("ERROR: Couldn't open '%s'",
                     parent_dirname);
@@ -993,7 +996,8 @@ int main(int argc, char *argv[])
         free(parent_dirname);
     }
     /* The destination is a directory. */
-    if ((out->mrec->flags & MFT_RECORD_IS_DIRECTORY) && !opts.inode) {
+    if (!created && (out->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+       && !opts.inode) {
         char *filename;
         char *overwrite_filename;
         int overwrite_filename_len;
@@ -1027,6 +1031,16 @@ int main(int argc, char *argv[])
         ni = ntfs_pathname_to_inode(vol, dir_ni, overwrite_filename);
         /* Does a file with the same name exist in the dest dir? */
         if (ni) {
+            if (S_ISDIR(fst.st_mode)
+               || ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
+                ntfs_log_verbose("Destination path has a file"
+                        " with the same name\nCannot"
+                        " overwriting the file '%s'\n",
+                        overwrite_filename);
+                ntfs_inode_close(out);
+                free(overwrite_filename);
+                goto close_src;
+            }
             ntfs_log_verbose("Destination path has a file with "
                     "the same name\nOverwriting the file "
                     "'%s'\n", overwrite_filename);
@@ -1035,7 +1049,7 @@ int main(int argc, char *argv[])
         } else {
             ntfs_log_verbose("Creating a new file '%s' under "
                     "'%s'\n", filename, opts.dest_file);
-            ni = ntfs_new_file(dir_ni, filename);
+            ni = ntfs_new_file(dir_ni, filename, fst.st_mode);
             ntfs_inode_close(dir_ni);
             if (!ni) {
                 ntfs_log_perror("ERROR: Failed to create the "
@@ -1077,6 +1091,11 @@ int main(int argc, char *argv[])
         }
     }
 
+    if (S_ISDIR(fst.st_mode)) {
+        result = 0;
+        goto close_attr;
+    }
+
     ntfs_log_verbose("Old file size: %lld\n", (long long)na->data_size);
     if (opts.minfragments && NAttrCompressed(na)) {
         ntfs_log_info("Warning : Cannot avoid fragmentation"
-- 
2.20.1