-
-
Notifications
You must be signed in to change notification settings - Fork 726
/
FileExtensions.cs
158 lines (143 loc) · 5.64 KB
/
FileExtensions.cs
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
151
152
153
154
155
156
157
158
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
namespace Cake.Core.IO
{
/// <summary>
/// Contains extension methods for <see cref="IFile"/>.
/// </summary>
public static class FileExtensions
{
/// <summary>
/// Opens the file using the specified options.
/// </summary>
/// <param name="file">The file.</param>
/// <param name="mode">The mode.</param>
/// <returns>A <see cref="Stream"/> to the file.</returns>
public static Stream Open(this IFile file, FileMode mode)
{
if (file == null)
{
throw new ArgumentNullException(nameof(file));
}
return file.Open(mode,
mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite,
FileShare.None);
}
/// <summary>
/// Opens the file using the specified options.
/// </summary>
/// <param name="file">The file.</param>
/// <param name="mode">The mode.</param>
/// <param name="access">The access.</param>
/// <returns>A <see cref="Stream"/> to the file.</returns>
public static Stream Open(this IFile file, FileMode mode, FileAccess access)
{
if (file == null)
{
throw new ArgumentNullException(nameof(file));
}
return file.Open(mode, access, FileShare.None);
}
/// <summary>
/// Opens the file for reading.
/// </summary>
/// <param name="file">The file.</param>
/// <returns>A <see cref="Stream"/> to the file.</returns>
public static Stream OpenRead(this IFile file)
{
if (file == null)
{
throw new ArgumentNullException(nameof(file));
}
return file.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
}
/// <summary>
/// Opens the file for writing.
/// If the file already exists, it will be overwritten.
/// </summary>
/// <param name="file">The file to be opened.</param>
/// <returns>A <see cref="Stream"/> to the file.</returns>
public static Stream OpenWrite(this IFile file)
{
if (file == null)
{
throw new ArgumentNullException(nameof(file));
}
return file.Open(FileMode.Create, FileAccess.Write, FileShare.None);
}
/// <summary>
/// Enumerates line in file.
/// </summary>
/// <param name="file">The file to be read from.</param>
/// <param name="encoding">The encoding that is applied to the content of the file.</param>
/// <returns>A <see cref="IEnumerable{T}"/> of file line content.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static IEnumerable<string> ReadLines(this IFile file, System.Text.Encoding encoding)
{
if (file == null)
{
throw new ArgumentNullException(nameof(file));
}
using (var stream = file.OpenRead())
using (var reader = new StreamReader(stream, encoding))
{
var result = new List<string>();
string line;
while ((line = reader.ReadLine()) != null)
{
result.Add(line);
}
return result;
}
}
/// <summary>
/// Checks if file has CLR PE Header.
/// </summary>
/// <param name="file">The file to be read from.</param>
/// <returns><c>true</c> if file is CLR assembly; otherwise, <c>false</c>.</returns>
/// <remarks>
/// See <a href="https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format">https://docs.microsoft.com/en-us/windows/desktop/Debug/pe-format</a> for more information.
/// </remarks>
public static bool IsClrAssembly(this IFile file)
{
if (!file.Exists || file.Length < 365)
{
return false;
}
using (var fs = file.OpenRead())
{
using (var reader = new System.IO.BinaryReader(fs))
{
const uint MagicOffset = 0x18;
const uint Magic32Bit = 0x10b;
const int Offset32Bit = 0x5e;
const int Offset64Bit = 0x6e;
const int OffsetDictionary = 0x70;
// PE Header Start
fs.Position = 0x3C;
// Go to Magic header
long offset = reader.ReadUInt32() + MagicOffset;
if (offset + sizeof(UInt16) > fs.Length)
{
return false;
}
fs.Position = offset;
// Check magic to get 32 / 64 bit offset
var is32Bit = reader.ReadUInt16() == Magic32Bit;
offset = fs.Position + (is32Bit ? Offset32Bit : Offset64Bit) + OffsetDictionary;
if (offset + 4 > fs.Length)
{
return false;
}
// Go to dictionary start
fs.Position = offset;
return reader.ReadUInt32() > 0;
}
}
}
}
}