aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/BinderFileManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/BinderFileManager.cs')
-rw-r--r--src/WixToolset.Core/BinderFileManager.cs371
1 files changed, 0 insertions, 371 deletions
diff --git a/src/WixToolset.Core/BinderFileManager.cs b/src/WixToolset.Core/BinderFileManager.cs
deleted file mode 100644
index dece3a20..00000000
--- a/src/WixToolset.Core/BinderFileManager.cs
+++ /dev/null
@@ -1,371 +0,0 @@
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
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Diagnostics.CodeAnalysis;
8 using System.IO;
9 using System.Linq;
10 using System.Runtime.InteropServices;
11 using WixToolset.Data;
12 using WixToolset.Extensibility;
13
14#if DEAD_CODE
15 /// <summary>
16 /// Base class for creating a binder file manager.
17 /// </summary>
18 public class BinderFileManager : IBinderFileManager
19 {
20 /// <summary>
21 /// Gets or sets the file manager core.
22 /// </summary>
23 public IBinderFileManagerCore Core { get; set; }
24
25 /// <summary>
26 /// Compares two files to determine if they are equivalent.
27 /// </summary>
28 /// <param name="targetFile">The target file.</param>
29 /// <param name="updatedFile">The updated file.</param>
30 /// <returns>true if the files are equal; false otherwise.</returns>
31 public virtual bool? CompareFiles(string targetFile, string updatedFile)
32 {
33 FileInfo targetFileInfo = new FileInfo(targetFile);
34 FileInfo updatedFileInfo = new FileInfo(updatedFile);
35
36 if (targetFileInfo.Length != updatedFileInfo.Length)
37 {
38 return false;
39 }
40
41 using (FileStream targetStream = File.OpenRead(targetFile))
42 {
43 using (FileStream updatedStream = File.OpenRead(updatedFile))
44 {
45 if (targetStream.Length != updatedStream.Length)
46 {
47 return false;
48 }
49
50 // Using a larger buffer than the default buffer of 4 * 1024 used by FileStream.ReadByte improves performance.
51 // The buffer size is based on user feedback. Based on performance results, a better buffer size may be determined.
52 byte[] targetBuffer = new byte[16 * 1024];
53 byte[] updatedBuffer = new byte[16 * 1024];
54 int targetReadLength;
55 int updatedReadLength;
56 do
57 {
58 targetReadLength = targetStream.Read(targetBuffer, 0, targetBuffer.Length);
59 updatedReadLength = updatedStream.Read(updatedBuffer, 0, updatedBuffer.Length);
60
61 if (targetReadLength != updatedReadLength)
62 {
63 return false;
64 }
65
66 for (int i = 0; i < targetReadLength; ++i)
67 {
68 if (targetBuffer[i] != updatedBuffer[i])
69 {
70 return false;
71 }
72 }
73
74 } while (0 < targetReadLength);
75 }
76 }
77
78 return true;
79 }
80
81 /// <summary>
82 /// Resolves the source path of a file.
83 /// </summary>
84 /// <param name="source">Original source value.</param>
85 /// <param name="type">Optional type of source file being resolved.</param>
86 /// <param name="sourceLineNumbers">Optional source line of source file being resolved.</param>
87 /// <param name="bindStage">The binding stage used to determine what collection of bind paths will be used</param>
88 /// <returns>Should return a valid path for the stream to be imported.</returns>
89 public virtual string ResolveFile(string source, string type, SourceLineNumber sourceLineNumbers, BindStage bindStage)
90 {
91 if (String.IsNullOrEmpty(source))
92 {
93 throw new ArgumentNullException("source");
94 }
95
96 if (BinderFileManager.CheckFileExists(source)) // if the file exists, we're good to go.
97 {
98 return source;
99 }
100 else if (Path.IsPathRooted(source)) // path is rooted so bindpaths won't help, bail since the file apparently doesn't exist.
101 {
102 return null;
103 }
104 else // not a rooted path so let's try applying all the different source resolution options.
105 {
106 const string bindPathOpenString = "!(bindpath.";
107
108 string bindName = String.Empty;
109 string path = source;
110 string pathWithoutSourceDir = null;
111
112 if (source.StartsWith(bindPathOpenString, StringComparison.Ordinal))
113 {
114 int closeParen = source.IndexOf(')', bindPathOpenString.Length);
115 if (-1 != closeParen)
116 {
117 bindName = source.Substring(bindPathOpenString.Length, closeParen - bindPathOpenString.Length);
118 path = source.Substring(bindPathOpenString.Length + bindName.Length + 1); // +1 for the closing brace.
119 path = path.TrimStart('\\'); // remove starting '\\' char so the path doesn't look rooted.
120 }
121 }
122 else if (source.StartsWith("SourceDir\\", StringComparison.Ordinal) || source.StartsWith("SourceDir/", StringComparison.Ordinal))
123 {
124 pathWithoutSourceDir = path.Substring(10);
125 }
126
127 var bindPaths = this.Core.GetBindPaths(bindStage, bindName);
128 foreach (string bindPath in bindPaths)
129 {
130 string filePath;
131 if (!String.IsNullOrEmpty(pathWithoutSourceDir))
132 {
133 filePath = Path.Combine(bindPath, pathWithoutSourceDir);
134 if (BinderFileManager.CheckFileExists(filePath))
135 {
136 return filePath;
137 }
138 }
139
140 filePath = Path.Combine(bindPath, path);
141 if (BinderFileManager.CheckFileExists(filePath))
142 {
143 return filePath;
144 }
145 }
146 }
147
148 // Didn't find the file.
149 return null;
150 }
151
152 /// <summary>
153 /// Resolves the source path of a file related to another file's source.
154 /// </summary>
155 /// <param name="source">Original source value.</param>
156 /// <param name="relatedSource">Source related to original source.</param>
157 /// <param name="type">Optional type of source file being resolved.</param>
158 /// <param name="sourceLineNumbers">Optional source line of source file being resolved.</param>
159 /// <param name="bindStage">The binding stage used to determine what collection of bind paths will be used</param>
160 /// <returns>Should return a valid path for the stream to be imported.</returns>
161 public virtual string ResolveRelatedFile(string source, string relatedSource, string type, SourceLineNumber sourceLineNumbers, BindStage bindStage)
162 {
163 string resolvedSource = this.ResolveFile(source, type, sourceLineNumbers, bindStage);
164 return Path.Combine(Path.GetDirectoryName(resolvedSource), relatedSource);
165 }
166
167 /// <summary>
168 /// Resolves the source path of a cabinet file.
169 /// </summary>
170 /// <param name="cabinetPath">Default path to cabinet to generate.</param>
171 /// <param name="filesWithPath">Collection of files in this cabinet.</param>
172 /// <returns>The CabinetBuildOption and path to build the . By default the cabinet is built and moved to its target location.</returns>
173 [SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
174 public virtual ResolvedCabinet ResolveCabinet(string cabinetPath, IEnumerable<BindFileWithPath> filesWithPath)
175 {
176 if (null == filesWithPath)
177 {
178 throw new ArgumentNullException("fileRows");
179 }
180
181 // By default cabinet should be built and moved to the suggested location.
182 ResolvedCabinet resolved = new ResolvedCabinet() { BuildOption = CabinetBuildOption.BuildAndMove, Path = cabinetPath };
183
184 // If a cabinet cache path was provided, change the location for the cabinet
185 // to be built to and check if there is a cabinet that can be reused.
186 if (!String.IsNullOrEmpty(this.Core.CabCachePath))
187 {
188 string cabinetName = Path.GetFileName(cabinetPath);
189 resolved.Path = Path.Combine(this.Core.CabCachePath, cabinetName);
190
191 if (BinderFileManager.CheckFileExists(resolved.Path))
192 {
193 // Assume that none of the following are true:
194 // 1. any files are added or removed
195 // 2. order of files changed or names changed
196 // 3. modified time changed
197 bool cabinetValid = true;
198
199 // Need to force garbage collection of WixEnumerateCab to ensure the handle
200 // associated with it is closed before it is reused.
201 using (Cab.WixEnumerateCab wixEnumerateCab = new Cab.WixEnumerateCab())
202 {
203 List<CabinetFileInfo> fileList = wixEnumerateCab.Enumerate(resolved.Path);
204
205 if (filesWithPath.Count() != fileList.Count)
206 {
207 cabinetValid = false;
208 }
209 else
210 {
211 int i = 0;
212 foreach (BindFileWithPath file in filesWithPath)
213 {
214 // First check that the file identifiers match because that is quick and easy.
215 CabinetFileInfo cabFileInfo = fileList[i];
216 cabinetValid = (cabFileInfo.FileId == file.Id);
217 if (cabinetValid)
218 {
219 // Still valid so ensure the file sizes are the same.
220 FileInfo fileInfo = new FileInfo(file.Path);
221 cabinetValid = (cabFileInfo.Size == fileInfo.Length);
222 if (cabinetValid)
223 {
224 // Still valid so ensure the source time stamp hasn't changed. Thus we need
225 // to convert the source file time stamp into a cabinet compatible data/time.
226 ushort sourceCabDate;
227 ushort sourceCabTime;
228
229 WixToolset.Core.Native.CabInterop.DateTimeToCabDateAndTime(fileInfo.LastWriteTime, out sourceCabDate, out sourceCabTime);
230 cabinetValid = (cabFileInfo.Date == sourceCabDate && cabFileInfo.Time == sourceCabTime);
231 }
232 }
233
234 if (!cabinetValid)
235 {
236 break;
237 }
238
239 i++;
240 }
241 }
242 }
243
244 resolved.BuildOption = cabinetValid ? CabinetBuildOption.Copy : CabinetBuildOption.BuildAndCopy;
245 }
246 }
247
248 return resolved;
249 }
250
251 /// <summary>
252 /// Resolve the layout path of a media.
253 /// </summary>
254 /// <param name="mediaRow">The media's row.</param>
255 /// <param name="mediaLayoutDirectory">The layout directory provided by the Media element.</param>
256 /// <param name="layoutDirectory">The layout directory for the setup image.</param>
257 /// <returns>The layout path for the media.</returns>
258 public virtual string ResolveMedia(MediaRow mediaRow, string mediaLayoutDirectory, string layoutDirectory)
259 {
260 return null;
261 }
262
263 /// <summary>
264 /// Resolves the URL to a file.
265 /// </summary>
266 /// <param name="url">URL that may be a format string for the id and fileName.</param>
267 /// <param name="packageId">Identity of the package (if payload is not part of a package) the URL points to. NULL if not part of a package.</param>
268 /// <param name="payloadId">Identity of the payload the URL points to.</param>
269 /// <param name="fileName">File name the URL points at.</param>
270 /// <param name="fallbackUrl">Optional URL to use if the URL provided is empty.</param>
271 /// <returns>An absolute URL or null if no URL is provided.</returns>
272 public virtual string ResolveUrl(string url, string fallbackUrl, string packageId, string payloadId, string fileName)
273 {
274 // If a URL was not specified but there is a fallback URL that has a format specifier in it
275 // then use the fallback URL formatter for this URL.
276 if (String.IsNullOrEmpty(url) && !String.IsNullOrEmpty(fallbackUrl))
277 {
278 string formattedFallbackUrl = String.Format(fallbackUrl, packageId, payloadId, fileName);
279 if (!String.Equals(fallbackUrl, formattedFallbackUrl, StringComparison.OrdinalIgnoreCase))
280 {
281 url = fallbackUrl;
282 }
283 }
284
285 if (!String.IsNullOrEmpty(url))
286 {
287 string formattedUrl = String.Format(url, packageId, payloadId, fileName);
288
289 Uri canonicalUri;
290 if (Uri.TryCreate(formattedUrl, UriKind.Absolute, out canonicalUri))
291 {
292 url = canonicalUri.AbsoluteUri;
293 }
294 else
295 {
296 url = null;
297 }
298 }
299
300 return url;
301 }
302
303 /// <summary>
304 /// Copies a file.
305 /// </summary>
306 /// <param name="source">The file to copy.</param>
307 /// <param name="destination">The destination file.</param>
308 /// <param name="overwrite">true if the destination file can be overwritten; otherwise, false.</param>
309 public virtual bool CopyFile(string source, string destination, bool overwrite)
310 {
311 if (overwrite && File.Exists(destination))
312 {
313 File.Delete(destination);
314 }
315
316 if (!CreateHardLink(destination, source, IntPtr.Zero))
317 {
318#if DEBUG
319 int er = Marshal.GetLastWin32Error();
320#endif
321
322 File.Copy(source, destination, overwrite);
323 }
324
325 return true;
326 }
327
328 /// <summary>
329 /// Moves a file.
330 /// </summary>
331 /// <param name="source">The file to move.</param>
332 /// <param name="destination">The destination file.</param>
333 public virtual bool MoveFile(string source, string destination, bool overwrite)
334 {
335 if (overwrite && File.Exists(destination))
336 {
337 File.Delete(destination);
338 }
339
340 var directory = Path.GetDirectoryName(destination);
341 if (!String.IsNullOrEmpty(directory))
342 {
343 Directory.CreateDirectory(directory);
344 }
345
346 File.Move(source, destination);
347 return true;
348 }
349
350 /// <summary>
351 /// Checks if a path exists, and throws a well known error for invalid paths.
352 /// </summary>
353 /// <param name="path">Path to check.</param>
354 /// <returns>True if path exists.</returns>
355 private static bool CheckFileExists(string path)
356 {
357 try
358 {
359 return File.Exists(path);
360 }
361 catch (ArgumentException)
362 {
363 throw new WixException(WixErrors.IllegalCharactersInPath(path));
364 }
365 }
366
367 [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
368 private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);
369 }
370#endif
371}