aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Bind/TransferFilesCommand.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Bind/TransferFilesCommand.cs')
-rw-r--r--src/WixToolset.Core/Bind/TransferFilesCommand.cs214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/WixToolset.Core/Bind/TransferFilesCommand.cs b/src/WixToolset.Core/Bind/TransferFilesCommand.cs
new file mode 100644
index 00000000..719b8b20
--- /dev/null
+++ b/src/WixToolset.Core/Bind/TransferFilesCommand.cs
@@ -0,0 +1,214 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Bind
4{
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Security.AccessControl;
9 using WixToolset.Data;
10 using WixToolset.Extensibility;
11
12 internal class TransferFilesCommand : ICommand
13 {
14 public IEnumerable<IBinderFileManager> FileManagers { private get; set; }
15
16 public IEnumerable<FileTransfer> FileTransfers { private get; set; }
17
18 public bool SuppressAclReset { private get; set; }
19
20 public void Execute()
21 {
22 List<string> destinationFiles = new List<string>();
23
24 foreach (FileTransfer fileTransfer in this.FileTransfers)
25 {
26 string fileSource = this.ResolveFile(fileTransfer.Source, fileTransfer.Type, fileTransfer.SourceLineNumbers, BindStage.Normal);
27
28 // If the source and destination are identical, then there's nothing to do here
29 if (0 == String.Compare(fileSource, fileTransfer.Destination, StringComparison.OrdinalIgnoreCase))
30 {
31 fileTransfer.Redundant = true;
32 continue;
33 }
34
35 bool retry = false;
36 do
37 {
38 try
39 {
40 if (fileTransfer.Move)
41 {
42 Messaging.Instance.OnMessage(WixVerboses.MoveFile(fileSource, fileTransfer.Destination));
43 this.TransferFile(true, fileSource, fileTransfer.Destination);
44 }
45 else
46 {
47 Messaging.Instance.OnMessage(WixVerboses.CopyFile(fileSource, fileTransfer.Destination));
48 this.TransferFile(false, fileSource, fileTransfer.Destination);
49 }
50
51 retry = false;
52 destinationFiles.Add(fileTransfer.Destination);
53 }
54 catch (FileNotFoundException e)
55 {
56 throw new WixFileNotFoundException(e.FileName);
57 }
58 catch (DirectoryNotFoundException)
59 {
60 // if we already retried, give up
61 if (retry)
62 {
63 throw;
64 }
65
66 string directory = Path.GetDirectoryName(fileTransfer.Destination);
67 Messaging.Instance.OnMessage(WixVerboses.CreateDirectory(directory));
68 Directory.CreateDirectory(directory);
69 retry = true;
70 }
71 catch (UnauthorizedAccessException)
72 {
73 // if we already retried, give up
74 if (retry)
75 {
76 throw;
77 }
78
79 if (File.Exists(fileTransfer.Destination))
80 {
81 Messaging.Instance.OnMessage(WixVerboses.RemoveDestinationFile(fileTransfer.Destination));
82
83 // try to ensure the file is not read-only
84 FileAttributes attributes = File.GetAttributes(fileTransfer.Destination);
85 try
86 {
87 File.SetAttributes(fileTransfer.Destination, attributes & ~FileAttributes.ReadOnly);
88 }
89 catch (ArgumentException) // thrown for unauthorized access errors
90 {
91 throw new WixException(WixErrors.UnauthorizedAccess(fileTransfer.Destination));
92 }
93
94 // try to delete the file
95 try
96 {
97 File.Delete(fileTransfer.Destination);
98 }
99 catch (IOException)
100 {
101 throw new WixException(WixErrors.FileInUse(null, fileTransfer.Destination));
102 }
103
104 retry = true;
105 }
106 else // no idea what just happened, bail
107 {
108 throw;
109 }
110 }
111 catch (IOException)
112 {
113 // if we already retried, give up
114 if (retry)
115 {
116 throw;
117 }
118
119 if (File.Exists(fileTransfer.Destination))
120 {
121 Messaging.Instance.OnMessage(WixVerboses.RemoveDestinationFile(fileTransfer.Destination));
122
123 // ensure the file is not read-only, then delete it
124 FileAttributes attributes = File.GetAttributes(fileTransfer.Destination);
125 File.SetAttributes(fileTransfer.Destination, attributes & ~FileAttributes.ReadOnly);
126 try
127 {
128 File.Delete(fileTransfer.Destination);
129 }
130 catch (IOException)
131 {
132 throw new WixException(WixErrors.FileInUse(null, fileTransfer.Destination));
133 }
134
135 retry = true;
136 }
137 else // no idea what just happened, bail
138 {
139 throw;
140 }
141 }
142 } while (retry);
143 }
144
145 // Finally, if there were any files remove the ACL that may have been added to
146 // during the file transfer process.
147 if (0 < destinationFiles.Count && !this.SuppressAclReset)
148 {
149 var aclReset = new FileSecurity();
150 aclReset.SetAccessRuleProtection(false, false);
151
152 try
153 {
154 //WixToolset.Core.Native.NativeMethods.ResetAcls(destinationFiles.ToArray(), (uint)destinationFiles.Count);
155
156 foreach (var file in destinationFiles)
157 {
158 new FileInfo(file).SetAccessControl(aclReset);
159 }
160 }
161 catch
162 {
163 Messaging.Instance.OnMessage(WixWarnings.UnableToResetAcls());
164 }
165 }
166 }
167
168 private string ResolveFile(string source, string type, SourceLineNumber sourceLineNumbers, BindStage bindStage)
169 {
170 string path = null;
171 foreach (IBinderFileManager fileManager in this.FileManagers)
172 {
173 path = fileManager.ResolveFile(source, type, sourceLineNumbers, bindStage);
174 if (null != path)
175 {
176 break;
177 }
178 }
179
180 if (null == path)
181 {
182 throw new WixFileNotFoundException(sourceLineNumbers, source, type);
183 }
184
185 return path;
186 }
187
188 private void TransferFile(bool move, string source, string destination)
189 {
190 bool complete = false;
191 foreach (IBinderFileManager fileManager in this.FileManagers)
192 {
193 if (move)
194 {
195 complete = fileManager.MoveFile(source, destination, true);
196 }
197 else
198 {
199 complete = fileManager.CopyFile(source, destination, true);
200 }
201
202 if (complete)
203 {
204 break;
205 }
206 }
207
208 if (!complete)
209 {
210 throw new InvalidOperationException(); // TODO: something needs to be said here that none of the binder file managers returned a result.
211 }
212 }
213 }
214}