2using System.Collections.Generic;
5using System.Reflection;
16 internal class VfsTable
23 public static VfsTable BuildDefaultTable(VfsContext context,
string ikvmHome)
25#if FIRST_PASS || IMPORTER || EXPORTER
26 throw new NotImplementedException();
29 throw new ArgumentNullException(nameof(context));
31 if (Directory.Exists(ikvmHome) ==
false)
32 throw new DirectoryNotFoundException(
"Could not locate ikvm.home when establishing VFS.");
34 var table =
new VfsTable(context);
35 table.AddMount(Path.Combine(ikvmHome,
"assembly"),
new VfsAssemblyDirectory(context));
40 readonly VfsContext context;
41 readonly LinkedList<VfsMount> mounts =
new LinkedList<VfsMount>();
48 public VfsTable(VfsContext context)
50 this.context = context ??
throw new ArgumentNullException(nameof(context));
56 public VfsContext Context => context;
61 public IReadOnlyCollection<VfsMount> Mounts => mounts;
69 public VfsMount AddMount(
string path, VfsEntry item)
71 return mounts.AddFirst(
new VfsMount(path, item)).Value;
78 public void RemoveMount(
string path)
80 var mount = mounts.FirstOrDefault(i => i.Path == path);
90 public VfsMount GetMount(
string path) => mounts.FirstOrDefault(i => i.IsPath(path));
97 public bool IsPath(
string path) => GetMount(path) is not
null;
104 public VfsEntry GetEntry(
string path) => GetMount(path) is VfsMount mount ? mount.GetEntry(path.Substring(mount.Path.Length)) :
null;
111 public string[] List(
string path) => GetEntry(path) is VfsDirectory directory ? directory.List() :
null;
122 public Stream Open(
string path, FileMode mode, FileAccess access)
125 if (mode != FileMode.Open || access != FileAccess.Read)
126 throw new UnauthorizedAccessException(
"Virtual file system is read-only.");
129 return GetEntry(path)
switch
131 VfsFile file => file.Open(mode, access),
132 VfsDirectory =>
throw new UnauthorizedAccessException($
"Access to '{path}' was denied."),
133 _ =>
throw new FileNotFoundException(
"File not found.", path)
142 public long GetLength(
string path)
144 return GetEntry(path) is VfsFile entry ? entry.Size : 0;
152 public int GetBooleanAttributes(
string path)
154 const int BA_EXISTS = 0x01;
155 const int BA_REGULAR = 0x02;
156 const int BA_DIRECTORY = 0x04;
158 return GetEntry(path)
switch
160 VfsDirectory => BA_EXISTS | BA_DIRECTORY,
161 VfsFile => BA_EXISTS | BA_REGULAR,
173 public static string GetAssemblyClassesPath(VfsContext context,
Assembly assembly,
string ikvmHome)
175#if FIRST_PASS || IMPORTER || EXPORTER
176 throw new NotImplementedException();
178 if (assembly is
null)
179 throw new ArgumentNullException(nameof(assembly));
181 if (Directory.Exists(ikvmHome) ==
false)
182 throw new DirectoryNotFoundException(
"Could not locate IkvmHome when finding VFS.");
195 public static string GetAssemblyResourcesPath(VfsContext context,
Assembly assembly,
string ikvmHome)
197#if FIRST_PASS || IMPORTER || EXPORTER
198 throw new NotImplementedException();
200 if (assembly is
null)
201 throw new ArgumentNullException(nameof(assembly));
203 if (Directory.Exists(ikvmHome) ==
false)
204 throw new DirectoryNotFoundException(
"Could not locate IkvmHome when finding VFS.");
216 static bool IsLoadableAssembly(VfsContext context,
Assembly assembly)
218 if (assembly.ReflectionOnly)
222 if (assembly.GlobalAssemblyCache)
226 if (assembly.IsDynamic || assembly.Location ==
"")
231 if (Path.GetDirectoryName(assembly.Location) == Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory))
236 if (context.GetAssembly(assembly.GetName()) !=
null)
247 public static string GetAssemblyDirectoryName(VfsContext context,
Assembly assembly)
250 if (IsLoadableAssembly(context, assembly) ==
false)
251 return assembly.ManifestModule.ModuleVersionId.ToString(
"N");
253 var name = assembly.GetName();
254 var simpleName = name.Name;
255 var path =
new ValueStringBuilder(simpleName.Length + 4);
256 for (var i = 0; i < simpleName.Length; i++)
258 if (simpleName[i] ==
'_')
261 path.Append(simpleName[i]);
264 var publicKeyToken = name.GetPublicKeyToken();
265 if (publicKeyToken !=
null && publicKeyToken.Length != 0)
267 var v = name.Version.ToString();
268 path.EnsureCapacity(2 + v.Length + 2 + publicKeyToken.Length * 2);
273 for (
int i = 0; i < publicKeyToken.Length; i++)
274 path.Append(
string.Format(
"{0:x2}", publicKeyToken[i]));
277 if (name.CultureInfo !=
null && !
string.IsNullOrEmpty(name.CultureInfo.Name))
279 var n = name.CultureInfo.Name;
280 path.EnsureCapacity(2 + n.Length);
282 path.Append(name.CultureInfo.Name);
285 return path.ToString();
IKVM.Reflection.Assembly Assembly
Various extension methods for working with paths.
static string EnsureEndingDirectorySeparator(string path)
Ensures the given path ends with a directory separator.