1 //
2 // Copyright (c) 2010-2018 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using System.IO;
10 #if !PLATFORM_WINDOWS
11 using Mono.Unix.Native;
12 #endif
13 using System.Runtime.InteropServices;
14 using Antmicro.Renode.Exceptions;
15 using Antmicro.Renode.Core;
16 
17 namespace Antmicro.Renode.Utilities
18 {
19     public static class FileCopier
20     {
Copy(string src, string dst, bool overwrite = false)21         public static void Copy(string src, string dst, bool overwrite = false)
22         {
23             try
24             {
25 #if !PLATFORM_WINDOWS
26                 if (ConfigurationManager.Instance.Get("file-system", "use-cow", false))
27                 {
28                     int sfd = -1, dfd = -1;
29                     try
30                     {
31                         sfd = Syscall.open(src, OpenFlags.O_RDONLY);
32                         dfd = Syscall.open(dst, overwrite ? OpenFlags.O_CREAT | OpenFlags.O_TRUNC | OpenFlags.O_WRONLY : (OpenFlags.O_CREAT | OpenFlags.O_EXCL), FilePermissions.S_IRUSR | FilePermissions.S_IWUSR);
33 
34                         if(sfd != -1 && dfd != -1 && ioctl(dfd, 0x40049409, sfd) != -1)
35                         {
36                             return;
37                         }
38                     }
39                     finally
40                     {
41                         if(sfd != -1)
42                         {
43                             Syscall.close(sfd);
44                         }
45 
46                         if(dfd != -1)
47                         {
48                             Syscall.close(dfd);
49                         }
50                     }
51                 }
52 #endif
53 
54                 var lastTime = CustomDateTime.Now;
55                 using(var source = File.Open(src, FileMode.Open, FileAccess.Read))
56                 {
57                     using(var destination = File.Open(dst, overwrite ? FileMode.Create : FileMode.CreateNew))
58                     {
59                         var progressHandler = EmulationManager.Instance.ProgressMonitor.Start("Copying...", false, true);
60 
61                         var read = 0;
62                         var count = 0L;
63                         var sourceLength = source.Length;
64                         var buffer = new byte[64*1024];
65                         do
66                         {
67                             read = source.Read(buffer, 0, buffer.Length);
68                             destination.Write(buffer, 0, read);
69                             count += read;
70 
71                             var now = CustomDateTime.Now;
72                             if(now - lastTime > TimeSpan.FromSeconds(0.25))
73                             {
74                                 progressHandler.UpdateProgress((int)(100L*count/sourceLength));
75                                 lastTime = now;
76                             }
77                         }
78                         while(read > 0);
79                         progressHandler.Finish();
80                     }
81                 }
82             }
83             catch (IOException e)
84             {
85                 throw new RecoverableException(e);
86             }
87         }
88 
89 #if !PLATFORM_WINDOWS
90         [DllImport("libc")]
ioctl(int d, ulong request, int a)91         private extern static int ioctl(int d, ulong request, int a);
92 #endif
93     }
94 }
95 
96