BadScript 2
Loading...
Searching...
No Matches
BadLayeredFileSystem.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using BadScript2.IO;
8
10{
11
13 {
15
17 {
18 List<BadLayeredFileSystemInfo> fileSystems = new List<BadLayeredFileSystemInfo>();
19 Dictionary<string,BadLayeredFileSystemFileInfo> files = new Dictionary<string,BadLayeredFileSystemFileInfo>();
20 foreach (var layer in m_Layers)
21 {
22 var fs = layer.FileSystem;
23 fileSystems.Add(new BadLayeredFileSystemInfo() { Writable = fs == GetWritable(), Name = layer.Name, MetaData = layer.MetaData });
24 foreach (var file in fs.GetFiles("/", "", true))
25 {
26 if (!files.TryGetValue(file, out var info))
27 {
29 {
30 Path = file,
31 PresentIn = new List<string>()
32 };
33 files[file] = info;
34 }
35
36 info.PresentIn.Add(layer.Name);
37 }
38 }
39
40 return new BadLayeredFileSystemStackInfo() { FileSystems = fileSystems.ToArray(), Files = files.Values.ToArray() };
41 }
43 {
44 m_Layers = layers;
45 }
46
47 private bool ContentEquals(Stream s1, Stream s2)
48 {
49 if (s1.Length != s2.Length) return false;
50 int b1, b2;
51 do
52 {
53 b1 = s1.ReadByte();
54 b2 = s2.ReadByte();
55 if (b1 != b2) return false;
56 } while (b1 != -1);
57 return true;
58 }
59 public void Optimize()
60 {
61 //Ensure that the writable layer does not have a file that already exists in a read-only layer and has the same content
62 var writable = GetWritable();
63 foreach (var file in writable.GetFiles("/", "", true).ToArray())
64 {
65 foreach (var layer in m_Layers.SkipLast(1))
66 {
67 if (layer.FileSystem.Exists(file) && layer.FileSystem.IsFile(file))
68 {
69 bool equals;
70 using (var wStream = writable.OpenRead(file))
71 {
72 using var rStream = layer.FileSystem.OpenRead(file);
73 equals = ContentEquals(wStream, rStream);
74 }
75 if (equals)
76 {
77 writable.DeleteFile(file);
78 break;
79 }
80 }
81 }
82 }
83 }
84 public bool Restore(string path)
85 {
86 var writable = GetWritable();
87 if (writable.Exists(path))
88 {
89 if (writable.IsFile(path))
90 {
91 writable.DeleteFile(path);
92 }
93 else
94 {
95 writable.DeleteDirectory(path, true);
96 }
97 return true;
98 }
99 return false;
100 }
101 public string GetStartupDirectory()
102 {
104 }
105
106 public bool Exists(string path)
107 {
108 return m_Layers.Any(x => x.FileSystem.Exists(path));
109 }
110
111 public bool IsFile(string path)
112 {
113 return m_Layers.Any(x => x.FileSystem.IsFile(path));
114 }
115
116 public bool IsDirectory(string path)
117 {
118 return m_Layers.Any(x => x.FileSystem.IsDirectory(path));
119 }
120
121 public IEnumerable<string> GetFiles(string path, string extension, bool recursive)
122 {
123 return m_Layers.SelectMany(x =>
124 x.FileSystem.Exists(path) &&
125 x.FileSystem.IsDirectory(path) ?
126 x.FileSystem.GetFiles(path, extension, recursive) :
127 Enumerable.Empty<string>()).Distinct();
128 }
129
130 public IEnumerable<string> GetDirectories(string path, bool recursive)
131 {
132 return m_Layers.SelectMany(x =>
133 x.FileSystem.Exists(path) &&
134 x.FileSystem.IsDirectory(path) ?
135 x.FileSystem.GetDirectories(path, recursive) :
136 Enumerable.Empty<string>()).Distinct();
137 }
138
139 public void CreateDirectory(string path, bool recursive = false)
140 {
141 GetWritable().CreateDirectory(path, recursive);
142 }
143
144 public void DeleteDirectory(string path, bool recursive)
145 {
146 if (!GetWritable().IsDirectory(path)) throw new Exception("Is Readonly");
147 GetWritable().DeleteDirectory(path, recursive);
148 }
149
150 public void DeleteFile(string path)
151 {
152 if (!GetWritable().IsFile(path)) throw new Exception("Is Readonly");
153 GetWritable().DeleteFile(path);
154 }
155
156 public string GetFullPath(string path)
157 {
158 return GetWritable().GetFullPath(path);
159 }
160
161 public Stream OpenRead(string path)
162 {
163 var fs = m_Layers.Last(x => x.FileSystem.IsFile(path))?.FileSystem ?? GetWritable();
164 return fs.OpenRead(path);
165 }
166
167 public Stream OpenWrite(string path, BadWriteMode mode)
168 {
169 var writable = GetWritable();
170 var dir = Path.GetDirectoryName(path);
171 if (dir != null && IsDirectory(dir) && !writable.IsDirectory(dir))
172 {
173 //Create the directory if it does not exist(it exists in some other layer, we need to create it in the writable layer)
174 writable.CreateDirectory(dir, true);
175 }
176 //In order to properly work with Append mode, we need to copy the file to the writable file system if it does not exist
177 if (mode == BadWriteMode.Append && !writable.IsFile(path))
178 {
179 using var src = OpenRead(path);
180 using var dst = writable.OpenWrite(path, BadWriteMode.CreateNew);
181 src.CopyTo(dst);
182 }
183 return writable.OpenWrite(path, mode);
184 }
185
186 public string GetCurrentDirectory()
187 {
189 }
190
191 public void SetCurrentDirectory(string path)
192 {
193 foreach (var fs in m_Layers) fs.FileSystem.SetCurrentDirectory(path);
194 }
195
196 public void Copy(string src, string dst, bool overwrite = true)
197 {
198 if (IsDirectory(src))
199 {
200 if (IsSubfolderOf(src, dst)) throw new IOException("Cannot copy a directory to a subfolder of itself.");
201
202 if (!overwrite && IsDirectory(src)) throw new IOException("Directory already exists.");
203
204 CopyDirectoryToDirectory(src, dst);
205 }
206 else if (IsFile(src))
207 {
208 if (!overwrite && IsFile(src)) throw new IOException("File already exists.");
209
210 CopyFileToFile(src, dst);
211 }
212 else
213 {
214 throw new IOException("Source path is not a file or directory");
215 }
216 }
217
218 public void Move(string src, string dst, bool overwrite = true)
219 {
220 Copy(src, dst, overwrite);
221
222 if (IsDirectory(src))
223 DeleteDirectory(src, true);
224 else
225 DeleteFile(src);
226 }
227
229 {
230 return m_Layers.Last().FileSystem;
231 }
232
233 private bool IsSubfolderOf(string root, string sub)
234 {
235 return GetFullPath(sub).StartsWith(GetFullPath(root));
236 }
237
238 private void CopyDirectoryToDirectory(string src, string dst)
239 {
240 foreach (var directory in GetDirectories(src, true)) CreateDirectory(directory);
241
242 foreach (var file in GetFiles(src, "*", true)) CopyFileToFile(file, file.Replace(src, dst));
243 }
244
245 private void CopyFileToFile(string src, string dst)
246 {
247 using var s = OpenRead(src);
248 using var d = OpenWrite(dst, BadWriteMode.CreateNew);
249 s.CopyTo(d);
250 }
251 }
252}
Stream OpenWrite(string path, BadWriteMode mode)
Opens a file for writing.
void DeleteDirectory(string path, bool recursive)
Deletes a directory.
string GetFullPath(string path)
Returns the full path of the given path.
BadLayeredFileSystem(params BadLayeredFileSystemLayer[] layers)
void Copy(string src, string dst, bool overwrite=true)
Copies a file or directory to a new location.
readonly BadLayeredFileSystemLayer[] m_Layers
void CopyDirectoryToDirectory(string src, string dst)
bool IsFile(string path)
Returns true if the given path is a file.
void CreateDirectory(string path, bool recursive=false)
Creates a new directory.
bool Exists(string path)
Returns true if the given path is a file or directory.
BadLayeredFileSystemStackInfo GetInfo()
void Move(string src, string dst, bool overwrite=true)
Moves a file or directory to a new location.
string GetStartupDirectory()
The Startup Directory of the Application.
bool IsDirectory(string path)
Returns true if the given path is a directory.
Stream OpenRead(string path)
Opens a file for reading.
IEnumerable< string > GetFiles(string path, string extension, bool recursive)
Returns all files in the given directory that match the specified extension.
void SetCurrentDirectory(string path)
Sets the current Directory.
IEnumerable< string > GetDirectories(string path, bool recursive)
Returns all directories in the given directory.
void DeleteFile(string path)
Deletes a file.
string GetCurrentDirectory()
Returns the Current Directory.
Virtual File System Implementation for the BadScript Engine.
string GetCurrentDirectory()
Returns the Current Directory.
string GetStartupDirectory()
The Startup Directory of the Application.
void DeleteDirectory(string path, bool recursive)
Deletes a directory.
string GetFullPath(string path)
Returns the full path of the given path.
void DeleteFile(string path)
Deletes a file.
void CreateDirectory(string path, bool recursive=false)
Creates a new directory.
Contains the Implementation of the BadScript Virtual File System.
Contains IO Implementation for the BadScript2 Runtime.
BadWriteMode
The Write Modes of the File System Abstraction.
Contains Utility Functions and Classes.
Definition BadEnum.cs:5