1*4882a593SmuzhiyunFrom 34ed66f2bc913b70cae217fd32cc3cba050069c4 Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Jeffy Chen <jeffy.chen@rock-chips.com> 3*4882a593SmuzhiyunDate: Sat, 29 Dec 2018 17:33:48 +0800 4*4882a593SmuzhiyunSubject: [PATCH] ntfscp: Support directory copy 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunSigned-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 7*4882a593Smuzhiyun--- 8*4882a593Smuzhiyun ntfsprogs/ntfscp.c | 45 ++++++++++++++++++++++++++++++++------------- 9*4882a593Smuzhiyun 1 file changed, 32 insertions(+), 13 deletions(-) 10*4882a593Smuzhiyun 11*4882a593Smuzhiyundiff --git a/ntfsprogs/ntfscp.c b/ntfsprogs/ntfscp.c 12*4882a593Smuzhiyunindex 19303b6..6f9180a 100644 13*4882a593Smuzhiyun--- a/ntfsprogs/ntfscp.c 14*4882a593Smuzhiyun+++ b/ntfsprogs/ntfscp.c 15*4882a593Smuzhiyun@@ -798,19 +798,20 @@ static int preallocate(ntfs_attr *na, s64 new_size) 16*4882a593Smuzhiyun } 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun /** 19*4882a593Smuzhiyun- * Create a regular file under the given directory inode 20*4882a593Smuzhiyun+ * Create a file under the given directory inode 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * It is a wrapper function to ntfs_create(...) 23*4882a593Smuzhiyun * 24*4882a593Smuzhiyun * Return: the created file inode 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni, 27*4882a593Smuzhiyun- const char *filename) 28*4882a593Smuzhiyun+ const char *filename, mode_t typemode) 29*4882a593Smuzhiyun { 30*4882a593Smuzhiyun ntfschar *ufilename; 31*4882a593Smuzhiyun /* inode to the file that is being created */ 32*4882a593Smuzhiyun ntfs_inode *ni; 33*4882a593Smuzhiyun int ufilename_len; 34*4882a593Smuzhiyun+ mode_t type = typemode & ~07777; 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun /* ntfs_mbstoucs(...) will allocate memory for ufilename if it's NULL */ 37*4882a593Smuzhiyun ufilename = NULL; 38*4882a593Smuzhiyun@@ -820,7 +821,7 @@ static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni, 39*4882a593Smuzhiyun filename); 40*4882a593Smuzhiyun return NULL; 41*4882a593Smuzhiyun } 42*4882a593Smuzhiyun- ni = ntfs_create(dir_ni, const_cpu_to_le32(0), ufilename, ufilename_len, S_IFREG); 43*4882a593Smuzhiyun+ ni = ntfs_create(dir_ni, const_cpu_to_le32(0), ufilename, ufilename_len, type); 44*4882a593Smuzhiyun free(ufilename); 45*4882a593Smuzhiyun return ni; 46*4882a593Smuzhiyun } 47*4882a593Smuzhiyun@@ -852,6 +853,8 @@ int main(int argc, char *argv[]) 48*4882a593Smuzhiyun #ifdef HAVE_WINDOWS_H 49*4882a593Smuzhiyun char *unix_name; 50*4882a593Smuzhiyun #endif 51*4882a593Smuzhiyun+ struct stat fst; 52*4882a593Smuzhiyun+ int created = 0; 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun ntfs_log_set_handler(ntfs_log_handler_stderr); 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun@@ -892,14 +895,11 @@ int main(int argc, char *argv[]) 57*4882a593Smuzhiyun goto umount; 58*4882a593Smuzhiyun } 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun- { 61*4882a593Smuzhiyun- struct stat fst; 62*4882a593Smuzhiyun- if (stat(opts.src_file, &fst) == -1) { 63*4882a593Smuzhiyun- ntfs_log_perror("ERROR: Couldn't stat source file"); 64*4882a593Smuzhiyun- goto umount; 65*4882a593Smuzhiyun- } 66*4882a593Smuzhiyun- new_size = fst.st_size; 67*4882a593Smuzhiyun+ if (stat(opts.src_file, &fst) == -1) { 68*4882a593Smuzhiyun+ ntfs_log_perror("ERROR: Couldn't stat source file"); 69*4882a593Smuzhiyun+ goto umount; 70*4882a593Smuzhiyun } 71*4882a593Smuzhiyun+ new_size = fst.st_size; 72*4882a593Smuzhiyun ntfs_log_verbose("New file size: %lld\n", (long long)new_size); 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun in = fopen(opts.src_file, "r"); 75*4882a593Smuzhiyun@@ -960,6 +960,8 @@ int main(int argc, char *argv[]) 76*4882a593Smuzhiyun ntfs_log_verbose("Target path does not contain '/'. " 77*4882a593Smuzhiyun "Using root directory as parent.\n"); 78*4882a593Smuzhiyun dir_ni = ntfs_inode_open(vol, FILE_root); 79*4882a593Smuzhiyun+ free(parent_dirname); 80*4882a593Smuzhiyun+ dirname_last_whack = parent_dirname = strdup("/"); 81*4882a593Smuzhiyun } 82*4882a593Smuzhiyun if (dir_ni) { 83*4882a593Smuzhiyun if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { 84*4882a593Smuzhiyun@@ -974,7 +976,7 @@ int main(int argc, char *argv[]) 85*4882a593Smuzhiyun } 86*4882a593Smuzhiyun ntfs_log_verbose("Creating a new file '%s' under '%s'" 87*4882a593Smuzhiyun "\n", filename, parent_dirname); 88*4882a593Smuzhiyun- ni = ntfs_new_file(dir_ni, filename); 89*4882a593Smuzhiyun+ ni = ntfs_new_file(dir_ni, filename, fst.st_mode); 90*4882a593Smuzhiyun ntfs_inode_close(dir_ni); 91*4882a593Smuzhiyun if (!ni) { 92*4882a593Smuzhiyun ntfs_log_perror("Failed to create '%s' under " 93*4882a593Smuzhiyun@@ -984,6 +986,7 @@ int main(int argc, char *argv[]) 94*4882a593Smuzhiyun goto close_src; 95*4882a593Smuzhiyun } 96*4882a593Smuzhiyun out = ni; 97*4882a593Smuzhiyun+ created = 1; 98*4882a593Smuzhiyun } else { 99*4882a593Smuzhiyun ntfs_log_perror("ERROR: Couldn't open '%s'", 100*4882a593Smuzhiyun parent_dirname); 101*4882a593Smuzhiyun@@ -993,7 +996,8 @@ int main(int argc, char *argv[]) 102*4882a593Smuzhiyun free(parent_dirname); 103*4882a593Smuzhiyun } 104*4882a593Smuzhiyun /* The destination is a directory. */ 105*4882a593Smuzhiyun- if ((out->mrec->flags & MFT_RECORD_IS_DIRECTORY) && !opts.inode) { 106*4882a593Smuzhiyun+ if (!created && (out->mrec->flags & MFT_RECORD_IS_DIRECTORY) 107*4882a593Smuzhiyun+ && !opts.inode) { 108*4882a593Smuzhiyun char *filename; 109*4882a593Smuzhiyun char *overwrite_filename; 110*4882a593Smuzhiyun int overwrite_filename_len; 111*4882a593Smuzhiyun@@ -1027,6 +1031,16 @@ int main(int argc, char *argv[]) 112*4882a593Smuzhiyun ni = ntfs_pathname_to_inode(vol, dir_ni, overwrite_filename); 113*4882a593Smuzhiyun /* Does a file with the same name exist in the dest dir? */ 114*4882a593Smuzhiyun if (ni) { 115*4882a593Smuzhiyun+ if (S_ISDIR(fst.st_mode) 116*4882a593Smuzhiyun+ || ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { 117*4882a593Smuzhiyun+ ntfs_log_verbose("Destination path has a file" 118*4882a593Smuzhiyun+ " with the same name\nCannot" 119*4882a593Smuzhiyun+ " overwriting the file '%s'\n", 120*4882a593Smuzhiyun+ overwrite_filename); 121*4882a593Smuzhiyun+ ntfs_inode_close(out); 122*4882a593Smuzhiyun+ free(overwrite_filename); 123*4882a593Smuzhiyun+ goto close_src; 124*4882a593Smuzhiyun+ } 125*4882a593Smuzhiyun ntfs_log_verbose("Destination path has a file with " 126*4882a593Smuzhiyun "the same name\nOverwriting the file " 127*4882a593Smuzhiyun "'%s'\n", overwrite_filename); 128*4882a593Smuzhiyun@@ -1035,7 +1049,7 @@ int main(int argc, char *argv[]) 129*4882a593Smuzhiyun } else { 130*4882a593Smuzhiyun ntfs_log_verbose("Creating a new file '%s' under " 131*4882a593Smuzhiyun "'%s'\n", filename, opts.dest_file); 132*4882a593Smuzhiyun- ni = ntfs_new_file(dir_ni, filename); 133*4882a593Smuzhiyun+ ni = ntfs_new_file(dir_ni, filename, fst.st_mode); 134*4882a593Smuzhiyun ntfs_inode_close(dir_ni); 135*4882a593Smuzhiyun if (!ni) { 136*4882a593Smuzhiyun ntfs_log_perror("ERROR: Failed to create the " 137*4882a593Smuzhiyun@@ -1077,6 +1091,11 @@ int main(int argc, char *argv[]) 138*4882a593Smuzhiyun } 139*4882a593Smuzhiyun } 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun+ if (S_ISDIR(fst.st_mode)) { 142*4882a593Smuzhiyun+ result = 0; 143*4882a593Smuzhiyun+ goto close_attr; 144*4882a593Smuzhiyun+ } 145*4882a593Smuzhiyun+ 146*4882a593Smuzhiyun ntfs_log_verbose("Old file size: %lld\n", (long long)na->data_size); 147*4882a593Smuzhiyun if (opts.minfragments && NAttrCompressed(na)) { 148*4882a593Smuzhiyun ntfs_log_info("Warning : Cannot avoid fragmentation" 149*4882a593Smuzhiyun-- 150*4882a593Smuzhiyun2.20.1 151*4882a593Smuzhiyun 152