[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / corlib / System.Security.Permissions / FileIOPermission.cs
blobc08313b278fd1ee0bd9a4425621eb3014f573494
1 //
2 // System.Security.Permissions.FileIOPermission.cs
3 //
4 // Authors:
5 // Nick Drochak, ndrochak@gol.com
6 // Sebastien Pouliot <sebastien@ximian.com>
7 //
8 // Copyright (C) 2001 Nick Drochak, All Rights Reserved
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.IO;
33 using System.Text;
35 using System.Runtime.InteropServices;
36 using System.Security.AccessControl;
38 namespace System.Security.Permissions {
40 [ComVisible (true)]
41 [Serializable]
42 public sealed class FileIOPermission
43 : CodeAccessPermission, IBuiltInPermission, IUnrestrictedPermission {
45 private const int version = 1;
47 private static char[] BadPathNameCharacters;
48 private static char[] BadFileNameCharacters;
50 static FileIOPermission ()
52 // we keep a local (static) copies to avoid calls/allocations
53 BadPathNameCharacters = Path.GetInvalidPathChars ();
54 BadFileNameCharacters = Path.GetInvalidFileNameChars ();
57 private bool m_Unrestricted = false;
58 private FileIOPermissionAccess m_AllFilesAccess = FileIOPermissionAccess.NoAccess;
59 private FileIOPermissionAccess m_AllLocalFilesAccess = FileIOPermissionAccess.NoAccess;
60 private ArrayList readList;
61 private ArrayList writeList;
62 private ArrayList appendList;
63 private ArrayList pathList;
65 public FileIOPermission (PermissionState state)
67 if (CheckPermissionState (state, true) == PermissionState.Unrestricted) {
68 m_Unrestricted = true;
69 m_AllFilesAccess = FileIOPermissionAccess.AllAccess;
70 m_AllLocalFilesAccess = FileIOPermissionAccess.AllAccess;
72 CreateLists ();
75 public FileIOPermission (FileIOPermissionAccess access, string path)
77 if (path == null)
78 throw new ArgumentNullException ("path");
80 CreateLists ();
81 // access and path will be validated in AddPathList
82 AddPathList (access, path);
85 public FileIOPermission (FileIOPermissionAccess access, string[] pathList)
87 if (pathList == null)
88 throw new ArgumentNullException ("pathList");
90 CreateLists ();
91 // access and path will be validated in AddPathList
92 AddPathList (access, pathList);
95 internal void CreateLists ()
97 readList = new ArrayList ();
98 writeList = new ArrayList ();
99 appendList = new ArrayList ();
100 pathList = new ArrayList ();
103 [MonoTODO ("(2.0) Access Control isn't implemented")]
104 public FileIOPermission (FileIOPermissionAccess access, AccessControlActions control, string path)
106 throw new NotImplementedException ();
109 [MonoTODO ("(2.0) Access Control isn't implemented")]
110 public FileIOPermission (FileIOPermissionAccess access, AccessControlActions control, string[] pathList)
112 throw new NotImplementedException ();
115 internal FileIOPermission (FileIOPermissionAccess access, string[] pathList, bool checkForDuplicates, bool needFullPath)
119 public FileIOPermissionAccess AllFiles {
120 get { return m_AllFilesAccess; }
121 set {
122 // if we are already set to unrestricted, don't change this property
123 if (!m_Unrestricted){
124 m_AllFilesAccess = value;
129 public FileIOPermissionAccess AllLocalFiles {
130 get { return m_AllLocalFilesAccess; }
131 set {
132 // if we are already set to unrestricted, don't change this property
133 if (!m_Unrestricted){
134 m_AllLocalFilesAccess = value;
139 public void AddPathList (FileIOPermissionAccess access, string path)
141 if ((FileIOPermissionAccess.AllAccess & access) != access)
142 ThrowInvalidFlag (access, true);
143 ThrowIfInvalidPath (path);
144 AddPathInternal (access, path);
147 public void AddPathList (FileIOPermissionAccess access, string[] pathList)
149 if ((FileIOPermissionAccess.AllAccess & access) != access)
150 ThrowInvalidFlag (access, true);
151 ThrowIfInvalidPath (pathList);
152 foreach (string path in pathList) {
153 AddPathInternal (access, path);
157 // internal to avoid duplicate checks
158 internal void AddPathInternal (FileIOPermissionAccess access, string path)
160 // call InsecureGetFullPath (and not GetFullPath) to avoid recursion
161 path = Path.InsecureGetFullPath (path);
163 if ((access & FileIOPermissionAccess.Read) == FileIOPermissionAccess.Read)
164 readList.Add (path);
165 if ((access & FileIOPermissionAccess.Write) == FileIOPermissionAccess.Write)
166 writeList.Add (path);
167 if ((access & FileIOPermissionAccess.Append) == FileIOPermissionAccess.Append)
168 appendList.Add (path);
169 if ((access & FileIOPermissionAccess.PathDiscovery) == FileIOPermissionAccess.PathDiscovery)
170 pathList.Add (path);
173 public override IPermission Copy ()
175 if (m_Unrestricted)
176 return new FileIOPermission (PermissionState.Unrestricted);
178 FileIOPermission copy = new FileIOPermission (PermissionState.None);
179 copy.readList = (ArrayList) readList.Clone ();
180 copy.writeList = (ArrayList) writeList.Clone ();
181 copy.appendList = (ArrayList) appendList.Clone ();
182 copy.pathList = (ArrayList) pathList.Clone ();
183 copy.m_AllFilesAccess = m_AllFilesAccess;
184 copy.m_AllLocalFilesAccess = m_AllLocalFilesAccess;
185 return copy;
188 public override void FromXml (SecurityElement esd)
190 // General validation in CodeAccessPermission
191 CheckSecurityElement (esd, "esd", version, version);
192 // Note: we do not (yet) care about the return value
193 // as we only accept version 1 (min/max values)
195 if (IsUnrestricted (esd)) {
196 m_Unrestricted = true;
198 else{
199 m_Unrestricted = false;
200 string fileList = esd.Attribute ("Read");
201 string[] files;
202 if (fileList != null){
203 files = fileList.Split (';');
204 AddPathList (FileIOPermissionAccess.Read, files);
206 fileList = esd.Attribute ("Write");
207 if (fileList != null){
208 files = fileList.Split (';');
209 AddPathList (FileIOPermissionAccess.Write, files);
211 fileList = esd.Attribute ("Append");
212 if (fileList != null){
213 files = fileList.Split (';');
214 AddPathList (FileIOPermissionAccess.Append, files);
216 fileList = esd.Attribute ("PathDiscovery");
217 if (fileList != null){
218 files = fileList.Split (';');
219 AddPathList (FileIOPermissionAccess.PathDiscovery, files);
224 public string[] GetPathList (FileIOPermissionAccess access)
226 if ((FileIOPermissionAccess.AllAccess & access) != access)
227 ThrowInvalidFlag (access, true);
229 ArrayList result = new ArrayList ();
230 switch (access) {
231 case FileIOPermissionAccess.NoAccess:
232 break;
233 case FileIOPermissionAccess.Read:
234 result.AddRange (readList);
235 break;
236 case FileIOPermissionAccess.Write:
237 result.AddRange (writeList);
238 break;
239 case FileIOPermissionAccess.Append:
240 result.AddRange (appendList);
241 break;
242 case FileIOPermissionAccess.PathDiscovery:
243 result.AddRange (pathList);
244 break;
245 default:
246 ThrowInvalidFlag (access, false);
247 break;
249 return (result.Count > 0) ? (string[]) result.ToArray (typeof (string)) : null;
252 public override IPermission Intersect (IPermission target)
254 FileIOPermission fiop = Cast (target);
255 if (fiop == null)
256 return null;
258 if (IsUnrestricted ())
259 return fiop.Copy ();
260 if (fiop.IsUnrestricted ())
261 return Copy ();
263 FileIOPermission result = new FileIOPermission (PermissionState.None);
264 result.AllFiles = m_AllFilesAccess & fiop.AllFiles;
265 result.AllLocalFiles = m_AllLocalFilesAccess & fiop.AllLocalFiles;
267 IntersectKeys (readList, fiop.readList, result.readList);
268 IntersectKeys (writeList, fiop.writeList, result.writeList);
269 IntersectKeys (appendList, fiop.appendList, result.appendList);
270 IntersectKeys (pathList, fiop.pathList, result.pathList);
272 return (result.IsEmpty () ? null : result);
275 public override bool IsSubsetOf (IPermission target)
277 FileIOPermission fiop = Cast (target);
278 if (fiop == null)
279 return false;
280 if (fiop.IsEmpty ())
281 return IsEmpty ();
283 if (IsUnrestricted ())
284 return fiop.IsUnrestricted ();
285 else if (fiop.IsUnrestricted ())
286 return true;
288 if ((m_AllFilesAccess & fiop.AllFiles) != m_AllFilesAccess)
289 return false;
290 if ((m_AllLocalFilesAccess & fiop.AllLocalFiles) != m_AllLocalFilesAccess)
291 return false;
293 if (!KeyIsSubsetOf (appendList, fiop.appendList))
294 return false;
295 if (!KeyIsSubsetOf (readList, fiop.readList))
296 return false;
297 if (!KeyIsSubsetOf (writeList, fiop.writeList))
298 return false;
299 if (!KeyIsSubsetOf (pathList, fiop.pathList))
300 return false;
302 return true;
305 public bool IsUnrestricted ()
307 return m_Unrestricted;
310 public void SetPathList (FileIOPermissionAccess access, string path)
312 if ((FileIOPermissionAccess.AllAccess & access) != access)
313 ThrowInvalidFlag (access, true);
314 ThrowIfInvalidPath (path);
315 // note: throw before clearing the actual list
316 Clear (access);
317 AddPathInternal (access, path);
320 public void SetPathList (FileIOPermissionAccess access, string[] pathList)
322 if ((FileIOPermissionAccess.AllAccess & access) != access)
323 ThrowInvalidFlag (access, true);
324 ThrowIfInvalidPath (pathList);
325 // note: throw before clearing the actual list
326 Clear (access);
327 foreach (string path in pathList)
328 AddPathInternal (access, path);
331 public override SecurityElement ToXml ()
333 SecurityElement se = Element (1);
334 if (m_Unrestricted) {
335 se.AddAttribute ("Unrestricted", "true");
337 else {
338 string[] paths = GetPathList (FileIOPermissionAccess.Append);
339 if (null != paths && paths.Length > 0) {
340 se.AddAttribute ("Append", String.Join (";", paths));
342 paths = GetPathList (FileIOPermissionAccess.Read);
343 if (null != paths && paths.Length > 0) {
344 se.AddAttribute ("Read", String.Join (";", paths));
346 paths = GetPathList (FileIOPermissionAccess.Write);
347 if (null != paths && paths.Length > 0) {
348 se.AddAttribute ("Write", String.Join (";", paths));
350 paths = GetPathList (FileIOPermissionAccess.PathDiscovery);
351 if (null != paths && paths.Length > 0) {
352 se.AddAttribute ("PathDiscovery", String.Join (";", paths));
355 return se;
358 public override IPermission Union (IPermission other)
360 FileIOPermission fiop = Cast (other);
361 if (fiop == null)
362 return Copy ();
364 if (IsUnrestricted () || fiop.IsUnrestricted ())
365 return new FileIOPermission (PermissionState.Unrestricted);
367 if (IsEmpty () && fiop.IsEmpty ())
368 return null;
370 FileIOPermission result = (FileIOPermission) Copy ();
371 result.AllFiles |= fiop.AllFiles;
372 result.AllLocalFiles |= fiop.AllLocalFiles;
374 string[] paths = fiop.GetPathList (FileIOPermissionAccess.Read);
375 if (paths != null)
376 UnionKeys (result.readList, paths);
378 paths = fiop.GetPathList (FileIOPermissionAccess.Write);
379 if (paths != null)
380 UnionKeys (result.writeList, paths);
382 paths = fiop.GetPathList (FileIOPermissionAccess.Append);
383 if (paths != null)
384 UnionKeys (result.appendList, paths);
386 paths = fiop.GetPathList (FileIOPermissionAccess.PathDiscovery);
387 if (paths != null)
388 UnionKeys (result.pathList, paths);
390 return result;
393 [MonoTODO ("(2.0)")]
394 [ComVisible (false)]
395 public override bool Equals (object obj)
397 return false;
400 [MonoTODO ("(2.0)")]
401 [ComVisible (false)]
402 public override int GetHashCode ()
404 return base.GetHashCode ();
407 // IBuiltInPermission
408 int IBuiltInPermission.GetTokenIndex ()
410 return (int) BuiltInToken.FileIO;
413 // helpers
415 private bool IsEmpty ()
417 return ((!m_Unrestricted) && (appendList.Count == 0) && (readList.Count == 0)
418 && (writeList.Count == 0) && (pathList.Count == 0));
421 private static FileIOPermission Cast (IPermission target)
423 if (target == null)
424 return null;
426 FileIOPermission fiop = (target as FileIOPermission);
427 if (fiop == null) {
428 ThrowInvalidPermission (target, typeof (FileIOPermission));
431 return fiop;
434 internal static void ThrowInvalidFlag (FileIOPermissionAccess access, bool context)
436 string msg = null;
437 if (context)
438 msg = Locale.GetText ("Unknown flag '{0}'.");
439 else
440 msg = Locale.GetText ("Invalid flag '{0}' in this context.");
441 throw new ArgumentException (String.Format (msg, access), "access");
444 internal static void ThrowIfInvalidPath (string path)
446 string dir = Path.GetDirectoryName (path);
447 if ((dir != null) && (dir.LastIndexOfAny (BadPathNameCharacters) >= 0)) {
448 string msg = String.Format (Locale.GetText ("Invalid path characters in path: '{0}'"), path);
449 throw new ArgumentException (msg, "path");
452 string fname = Path.GetFileName (path);
453 if ((fname != null) && (fname.LastIndexOfAny (BadFileNameCharacters) >= 0)) {
454 string msg = String.Format (Locale.GetText ("Invalid filename characters in path: '{0}'"), path);
455 throw new ArgumentException (msg, "path");
457 // LAMESPEC: docs don't say it must be a rooted path, but the MS implementation enforces it, so we will too.
458 if (!Path.IsPathRooted (path)) {
459 string msg = Locale.GetText ("Absolute path information is required.");
460 throw new ArgumentException (msg, "path");
464 internal static void ThrowIfInvalidPath (string[] paths)
466 foreach (string path in paths)
467 ThrowIfInvalidPath (path);
470 // we known that access is valid at this point
471 internal void Clear (FileIOPermissionAccess access)
473 if ((access & FileIOPermissionAccess.Read) == FileIOPermissionAccess.Read)
474 readList.Clear ();
475 if ((access & FileIOPermissionAccess.Write) == FileIOPermissionAccess.Write)
476 writeList.Clear ();
477 if ((access & FileIOPermissionAccess.Append) == FileIOPermissionAccess.Append)
478 appendList.Clear ();
479 if ((access & FileIOPermissionAccess.PathDiscovery) == FileIOPermissionAccess.PathDiscovery)
480 pathList.Clear ();
483 // note: all path in IList are already "full paths"
484 internal static bool KeyIsSubsetOf (IList local, IList target)
486 bool result = false;
487 foreach (string l in local) {
488 foreach (string t in target) {
489 if (Path.IsPathSubsetOf (t, l)) {
490 result = true;
491 break;
494 if (!result)
495 return false;
497 return true;
500 internal static void UnionKeys (IList list, string[] paths)
502 foreach (string path in paths) {
503 int len = list.Count;
504 if (len == 0) {
505 list.Add (path);
507 else {
508 int i;
509 for (i=0; i < len; i++) {
510 string s = (string) list [i];
511 if (Path.IsPathSubsetOf (path, s)) {
512 // replace (with reduced version)
513 list [i] = path;
514 break;
516 else if (Path.IsPathSubsetOf (s, path)) {
517 // no need to add
518 break;
521 if (i == len) {
522 list.Add (path);
528 internal static void IntersectKeys (IList local, IList target, IList result)
530 foreach (string l in local) {
531 foreach (string t in target) {
532 if (t.Length > l.Length) {
533 if (Path.IsPathSubsetOf (l ,t))
534 result.Add (t);
536 else {
537 if (Path.IsPathSubsetOf (t, l))
538 result.Add (l);