Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Pryor <jpryor@novell.com>2004-12-28 22:54:39 +0300
committerJonathan Pryor <jpryor@novell.com>2004-12-28 22:54:39 +0300
commitc05ab5c33336c3cbb7783b1a48fb1176748bf7e4 (patch)
tree8530173b7734e6ee245ed94824a166b0cd8d9bd1 /mcs/class/Mono.Posix
parent03398ebee4c91fef05643933c96fdd1b2a57675b (diff)
* Mono.Posix.dll.sources: Add UnixDriveInfo and UnixPath.
* CdeclFunctions.cs: Correct the comments for AMD64 * UnixDirectoryInfo.cs: override Name; add Parent & Root properties; Correct Path usage (s/Path/FullPath/g). * UnixDriveInfo.cs: Added. Based on .NET 2.0 System.IO.DriveInfo docs, provides statvfs(2) and getfsfile(3) information about a mounted volume. GetDrives() wraps getfsent(3), thus parsing /etc/fstab. * UnixFile.cs: Use UnixConver.ToOpenFlags, deleting the local version. * UnixFileInfo.cs: Use UnixConver.ToOpenFlags, deleting the local version; override Name; add DirectoryName and Directory properties; * UnixFileSystemInfo.cs: Make more .NET-like, using FullPath and OriginalPath protected members, abstract Name property; Add CreateSymbolicLink; Remove ReadLink (it's now UnixSymbolicLinkInfo.Contents); Use lstat(2) for Create(string), so we properly detect Symbolic Links. * UnixPath.cs: Added; Path manipulation utility functions. * UnixSymbolicLinkInfo.cs: - Seal the class; - override new abstract member Name; - rename ReadLink to ContentsPath (and Contents) properties (why "Contents"? Because readlink(2) says "readlink places the contents of the symbolic link in the buffer...") - Add CreateSymbolicLinkTo(), which creates a symlink to the specified "normal" file svn path=/trunk/mcs/; revision=38140
Diffstat (limited to 'mcs/class/Mono.Posix')
-rw-r--r--mcs/class/Mono.Posix/ChangeLog4
-rw-r--r--mcs/class/Mono.Posix/Mono.Posix.dll.sources4
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/CdeclFunction.cs18
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/ChangeLog26
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixDirectoryInfo.cs37
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixDriveInfo.cs169
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixFile.cs54
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixFileInfo.cs83
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs77
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs204
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs63
11 files changed, 576 insertions, 163 deletions
diff --git a/mcs/class/Mono.Posix/ChangeLog b/mcs/class/Mono.Posix/ChangeLog
index dd5a6b95479..27eb5dc598a 100644
--- a/mcs/class/Mono.Posix/ChangeLog
+++ b/mcs/class/Mono.Posix/ChangeLog
@@ -1,3 +1,7 @@
+2004-12-28 Jonathan Pryor <jonpryor@vt.edu>
+
+ * Mono.Posix.dll.sources: Add UnixDriveInfo and UnixPath.
+
2004-11-22 Raja R Harinath <rharinath@novell.com>
* Makefile (CLEAN_FILES): Clean up make-map.exe and the duplicated
diff --git a/mcs/class/Mono.Posix/Mono.Posix.dll.sources b/mcs/class/Mono.Posix/Mono.Posix.dll.sources
index a1cac12b721..17996c0a75a 100644
--- a/mcs/class/Mono.Posix/Mono.Posix.dll.sources
+++ b/mcs/class/Mono.Posix/Mono.Posix.dll.sources
@@ -10,7 +10,9 @@
./Mono.Unix/UnixConvert.cs
./Mono.Unix/UnixDirectory.cs
./Mono.Unix/UnixDirectoryInfo.cs
+./Mono.Unix/UnixDriveInfo.cs
./Mono.Unix/UnixEnvironment.cs
+./Mono.Unix/UnixEndPoint.cs
./Mono.Unix/UnixFile.cs
./Mono.Unix/UnixFileInfo.cs
./Mono.Unix/UnixFileSystemInfo.cs
@@ -18,12 +20,12 @@
./Mono.Unix/UnixGroupInfo.cs
./Mono.Unix/UnixIOException.cs
./Mono.Unix/UnixMarshal.cs
+./Mono.Unix/UnixPath.cs
./Mono.Unix/UnixProcess.cs
./Mono.Unix/UnixStream.cs
./Mono.Unix/UnixSymbolicLinkInfo.cs
./Mono.Unix/UnixUser.cs
./Mono.Unix/UnixUserInfo.cs
-./Mono.Unix/UnixEndPoint.cs
./Mono.Posix/Catalog.cs
./Mono.Posix/PeerCred.cs
./Mono.Posix/Syscall.cs
diff --git a/mcs/class/Mono.Posix/Mono.Unix/CdeclFunction.cs b/mcs/class/Mono.Posix/Mono.Unix/CdeclFunction.cs
index 04c7227f5fd..39d2d3a28e7 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/CdeclFunction.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/CdeclFunction.cs
@@ -46,7 +46,7 @@ namespace Mono.Unix {
//
// Then call the Invoke method with the appropriate number of arguments:
//
- // printf.Invoke (new object[]{"hello, %s\n", "world!"});
+ // printf.Invoke (new object[]{"hello, %s\n", "world!"});
//
// In the background a P/Invoke definition for the method with the
// requested argument types will be generated and invoked, invoking the
@@ -54,15 +54,19 @@ namespace Mono.Unix {
// calls with the same argument list do not generate new code, speeding up
// the call sequence.
//
- // Invoking Cdecl functions is not portable across all platforms. In
- // particular, AMD64 requires that the caller set EAX to the number of
- // floating point arguments passed in the SSE registers. This is only
- // required for variable argument/stdarg functions; consequently, Mono's JIT
- // doesn't set EAX properly which can lead to failures. See:
+ // Invoking Cdecl functions is not guaranteed to be portable across all
+ // platforms. For example, AMD64 requires that the caller set EAX to the
+ // number of floating point arguments passed in the SSE registers. This
+ // is only required for variable argument/cdecl functions; consequently,
+ // the overload technique used by this class wouldn't normally work.
+ // Mono's AMD64 JIT works around this by always setting EAX on P/Invoke
+ // invocations, allowing CdeclFunction to work properly, but it will not
+ // necessarily always work. See also:
//
// http://lwn.net/Articles/5201/?format=printable
//
- // Consequently, Cdecl functions should be avoided on most platforms.
+ // Due to potential portability issues, cdecl functions should be avoided
+ // on most platforms.
//
// This class is intended to be thread-safe.
public sealed class CdeclFunction
diff --git a/mcs/class/Mono.Posix/Mono.Unix/ChangeLog b/mcs/class/Mono.Posix/Mono.Unix/ChangeLog
index c99b833f455..b56c783caf0 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/ChangeLog
+++ b/mcs/class/Mono.Posix/Mono.Unix/ChangeLog
@@ -1,5 +1,31 @@
2004-12-28 Jonathan Pryor <jonpryor@vt.edu>
+ * CdeclFunctions.cs: Correct the comments for AMD64
+ * UnixDirectoryInfo.cs: override Name; add Parent & Root properties;
+ Correct Path usage (s/Path/FullPath/g).
+ * UnixDriveInfo.cs: Added. Based on .NET 2.0 System.IO.DriveInfo docs,
+ provides statvfs(2) and getfsfile(3) information about a mounted volume.
+ GetDrives() wraps getfsent(3), thus parsing /etc/fstab.
+ * UnixFile.cs: Use UnixConver.ToOpenFlags, deleting the local version.
+ * UnixFileInfo.cs: Use UnixConver.ToOpenFlags, deleting the local version;
+ override Name; add DirectoryName and Directory properties;
+ * UnixFileSystemInfo.cs: Make more .NET-like, using FullPath and
+ OriginalPath protected members, abstract Name property; Add
+ CreateSymbolicLink; Remove ReadLink (it's now
+ UnixSymbolicLinkInfo.Contents); Use lstat(2) for Create(string), so we
+ properly detect Symbolic Links.
+ * UnixPath.cs: Added; Path manipulation utility functions.
+ * UnixSymbolicLinkInfo.cs:
+ - Seal the class;
+ - override new abstract member Name;
+ - rename ReadLink to ContentsPath (and Contents) properties
+ (why "Contents"? Because readlink(2) says "readlink places the
+ contents of the symbolic link in the buffer...")
+ - Add CreateSymbolicLinkTo(), which creates a symlink to the specified
+ "normal" file
+
+2004-12-28 Jonathan Pryor <jonpryor@vt.edu>
+
* Stdlib.cs: Add syslog(3) to XPrintfFunctions; Add additional printf(3)
and fprintf(3) overload which properly escape the format string
(by using "%s" as the format for the user-supplied message).
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixDirectoryInfo.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixDirectoryInfo.cs
index ae97037cdcb..29c533a42bd 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/UnixDirectoryInfo.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixDirectoryInfo.cs
@@ -35,7 +35,7 @@ using Mono.Unix;
namespace Mono.Unix {
- public class UnixDirectoryInfo : UnixFileSystemInfo
+ public sealed class UnixDirectoryInfo : UnixFileSystemInfo
{
public UnixDirectoryInfo (string path)
: base (path)
@@ -47,9 +47,36 @@ namespace Mono.Unix {
{
}
+ public override string Name {
+ get {
+ string r = UnixPath.GetFileName (FullPath);
+ if (r == null || r == "")
+ return FullPath;
+ return r;
+ }
+ }
+
+ public UnixDirectoryInfo Parent {
+ get {
+ string dirname = UnixPath.GetDirectoryName (FullPath);
+ if (dirname == null)
+ return null;
+ return new UnixDirectoryInfo (dirname);
+ }
+ }
+
+ public UnixDirectoryInfo Root {
+ get {
+ string root = UnixPath.GetPathRoot (FullPath);
+ if (root == null)
+ return null;
+ return new UnixDirectoryInfo (root);
+ }
+ }
+
public void Create (FilePermissions mode)
{
- int r = Syscall.mkdir (Path, mode);
+ int r = Syscall.mkdir (FullPath, mode);
UnixMarshal.ThrowExceptionForLastErrorIf (r);
base.Refresh ();
}
@@ -76,14 +103,14 @@ namespace Mono.Unix {
e.Delete ();
}
}
- int r = Syscall.rmdir (Path);
+ int r = Syscall.rmdir (FullPath);
UnixMarshal.ThrowExceptionForLastErrorIf (r);
base.Refresh ();
}
public Dirent[] GetEntries ()
{
- IntPtr dirp = Syscall.opendir (Path);
+ IntPtr dirp = Syscall.opendir (FullPath);
if (dirp == IntPtr.Zero)
UnixMarshal.ThrowExceptionForLastError ();
@@ -123,7 +150,7 @@ namespace Mono.Unix {
public Dirent[] GetEntries (Regex regex)
{
- IntPtr dirp = Syscall.opendir (Path);
+ IntPtr dirp = Syscall.opendir (FullPath);
if (dirp == IntPtr.Zero)
UnixMarshal.ThrowExceptionForLastError ();
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixDriveInfo.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixDriveInfo.cs
new file mode 100644
index 00000000000..8eacd5cf879
--- /dev/null
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixDriveInfo.cs
@@ -0,0 +1,169 @@
+//
+// Mono.Unix/UnixDriveInfo.cs
+//
+// Authors:
+// Jonathan Pryor (jonpryor@vt.edu)
+//
+// (C) 2004 Jonathan Pryor
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.IO;
+using Mono.Unix;
+
+namespace Mono.Unix {
+
+ public enum UnixDriveType {
+ Unknown,
+ NoRootDirectory,
+ Removable,
+ Fixed,
+ Network,
+ CDRom,
+ Ram
+ }
+
+ // All methods & properties can throw IOException
+ public sealed class UnixDriveInfo
+ {
+ private Statvfs stat;
+ private Fstab fstab;
+
+ public UnixDriveInfo (string mountPoint)
+ {
+ if (mountPoint == null)
+ throw new ArgumentNullException ("mountPoint");
+ fstab = Syscall.getfsfile (mountPoint);
+ if (fstab == null)
+ throw new ArgumentException ("mountPoint isn't valid: " + mountPoint);
+ // throws ArgumentException if driveName isn't valid
+ // though .NET also has a DriveNotFoundException class, so maybe that's
+ // more appropriate?
+ }
+
+ public static UnixDriveInfo GetForSpecialFile (string specialFile)
+ {
+ if (specialFile == null)
+ throw new ArgumentNullException ("specialFile");
+ Fstab f = Syscall.getfsspec (specialFile);
+ if (f == null)
+ throw new ArgumentException ("specialFile isn't valid: " + specialFile);
+ return new UnixDriveInfo (f);
+ }
+
+ private UnixDriveInfo (Fstab fstab)
+ {
+ this.fstab = fstab;
+ }
+
+ public long AvailableFreeSpace {
+ get {Refresh (); return (long) (stat.f_bavail * stat.f_bsize);}
+ }
+
+ public string DriveFormat {
+ get {return fstab.fs_vfstype;}
+ }
+
+ public UnixDriveType DriveType {
+ get {return UnixDriveType.Unknown;}
+ }
+
+ // this throws no exceptions
+ public bool IsReady {
+ get {return Refresh (false);}
+ }
+
+ public string Name {
+ get {return fstab.fs_file;}
+ }
+
+ public UnixDirectoryInfo RootDirectory {
+ get {return new UnixDirectoryInfo (fstab.fs_file);}
+ }
+
+ public long TotalFreeSpace {
+ get {Refresh (); return (long) (stat.f_bfree * stat.f_bsize);}
+ }
+
+ public long TotalSize {
+ get {Refresh (); return (long) (stat.f_frsize * stat.f_blocks);}
+ }
+
+ // also throws SecurityException if caller lacks perms
+ public string VolumeLabel {
+ get {return fstab.fs_spec;}
+ // set {}
+ }
+
+ public ulong MaximumFilenameLength {
+ get {Refresh (); return stat.f_namemax;}
+ }
+
+ public static UnixDriveInfo[] GetDrives ()
+ {
+ // throws IOException, UnauthorizedAccessException (no permission)
+ Syscall.SetLastError ((Error) 0);
+ int r = Syscall.setfsent ();
+ if (r != 1)
+ throw new IOException ("Error calling setfsent(3)");
+ ArrayList entries = new ArrayList ();
+ try {
+ Fstab fs;
+ while ((fs = Syscall.getfsent()) != null) {
+ // avoid virtual entries, such as "swap"
+ if (fs.fs_file.StartsWith ("/"))
+ entries.Add (new UnixDriveInfo (fs));
+ }
+ }
+ finally {
+ Syscall.endfsent ();
+ }
+ return (UnixDriveInfo[]) entries.ToArray (typeof(UnixDriveInfo));
+ }
+
+ public override string ToString ()
+ {
+ return VolumeLabel;
+ }
+
+ private void Refresh ()
+ {
+ Refresh (true);
+ }
+
+ private bool Refresh (bool throwException)
+ {
+ int r = Syscall.statvfs (fstab.fs_file, out stat);
+ if (r == -1 && throwException) {
+ Error e = Syscall.GetLastError ();
+ throw new IOException (UnixMarshal.GetErrorDescription (e),
+ UnixMarshal.CreateExceptionForError (e));
+ }
+ else if (r == -1)
+ return false;
+ return true;
+ }
+ }
+}
+
+// vim: noexpandtab
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixFile.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixFile.cs
index f2d65af295f..0b1fdee4cf4 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/UnixFile.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixFile.cs
@@ -173,7 +173,7 @@ namespace Mono.Unix {
public static UnixStream Open (string path, FileMode mode)
{
- OpenFlags flags = ToOpenFlags (mode, FileAccess.ReadWrite);
+ OpenFlags flags = UnixConvert.ToOpenFlags (mode, FileAccess.ReadWrite);
int fd = Syscall.open (path, flags);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
@@ -182,7 +182,7 @@ namespace Mono.Unix {
public static UnixStream Open (string path, FileMode mode, FileAccess access)
{
- OpenFlags flags = ToOpenFlags (mode, access);
+ OpenFlags flags = UnixConvert.ToOpenFlags (mode, access);
int fd = Syscall.open (path, flags);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
@@ -191,7 +191,7 @@ namespace Mono.Unix {
public static UnixStream Open (string path, FileMode mode, FileAccess access, FilePermissions perms)
{
- OpenFlags flags = ToOpenFlags (mode, access);
+ OpenFlags flags = UnixConvert.ToOpenFlags (mode, access);
int fd = Syscall.open (path, flags, perms);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
@@ -256,54 +256,6 @@ namespace Mono.Unix {
SetLinkOwner (path, uid, gid);
}
- public static OpenFlags ToOpenFlags (FileMode mode, FileAccess access)
- {
- OpenFlags flags = 0;
- switch (mode) {
- case FileMode.CreateNew:
- flags = OpenFlags.O_CREAT | OpenFlags.O_EXCL;
- break;
- case FileMode.Create:
- flags = OpenFlags.O_CREAT | OpenFlags.O_TRUNC;
- break;
- case FileMode.Open:
- // do nothing
- break;
- case FileMode.OpenOrCreate:
- flags = OpenFlags.O_CREAT;
- break;
- case FileMode.Truncate:
- flags = OpenFlags.O_TRUNC;
- break;
- case FileMode.Append:
- flags = OpenFlags.O_APPEND;
- break;
- default:
- throw new ArgumentException (Locale.GetText ("Unsupported mode value"), "mode");
- }
-
- // Is O_LARGEFILE supported?
- int _v;
- if (UnixConvert.TryFromOpenFlags (OpenFlags.O_LARGEFILE, out _v))
- flags |= OpenFlags.O_LARGEFILE;
-
- switch (access) {
- case FileAccess.Read:
- flags |= OpenFlags.O_RDONLY;
- break;
- case FileAccess.Write:
- flags |= OpenFlags.O_WRONLY;
- break;
- case FileAccess.ReadWrite:
- flags |= OpenFlags.O_RDWR;
- break;
- default:
- throw new ArgumentException (Locale.GetText ("Unsupported access value"), "access");
- }
-
- return flags;
- }
-
public static void AdviseNormalAccess (int fd, long offset, long len)
{
int r = Syscall.posix_fadvise (fd, offset, len,
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixFileInfo.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixFileInfo.cs
index 09a1666ad92..5a12445768f 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/UnixFileInfo.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixFileInfo.cs
@@ -33,7 +33,7 @@ using Mono.Unix;
namespace Mono.Unix {
- public class UnixFileInfo : UnixFileSystemInfo
+ public sealed class UnixFileInfo : UnixFileSystemInfo
{
public UnixFileInfo (string path)
: base (path)
@@ -45,9 +45,21 @@ namespace Mono.Unix {
{
}
+ public override string Name {
+ get {return UnixPath.GetFileName (FullPath);}
+ }
+
+ public string DirectoryName {
+ get {return UnixPath.GetDirectoryName (FullPath);}
+ }
+
+ public UnixDirectoryInfo Directory {
+ get {return new UnixDirectoryInfo (DirectoryName);}
+ }
+
public override void Delete ()
{
- int r = Syscall.unlink (Path);
+ int r = Syscall.unlink (FullPath);
UnixMarshal.ThrowExceptionForLastErrorIf (r);
base.Refresh ();
}
@@ -62,7 +74,7 @@ namespace Mono.Unix {
public UnixStream Create (FilePermissions mode)
{
- int fd = Syscall.creat (Path, mode);
+ int fd = Syscall.creat (FullPath, mode);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
base.Refresh ();
@@ -71,7 +83,7 @@ namespace Mono.Unix {
public UnixStream Open (OpenFlags flags)
{
- int fd = Syscall.open (Path, flags);
+ int fd = Syscall.open (FullPath, flags);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
return new UnixStream (fd);
@@ -79,7 +91,7 @@ namespace Mono.Unix {
public UnixStream Open (OpenFlags flags, FilePermissions mode)
{
- int fd = Syscall.open (Path, flags, mode);
+ int fd = Syscall.open (FullPath, flags, mode);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
return new UnixStream (fd);
@@ -87,8 +99,8 @@ namespace Mono.Unix {
public UnixStream Open (FileMode mode)
{
- OpenFlags flags = ToOpenFlags (mode, FileAccess.ReadWrite);
- int fd = Syscall.open (Path, flags);
+ OpenFlags flags = UnixConvert.ToOpenFlags (mode, FileAccess.ReadWrite);
+ int fd = Syscall.open (FullPath, flags);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
return new UnixStream (fd);
@@ -96,8 +108,8 @@ namespace Mono.Unix {
public UnixStream Open (FileMode mode, FileAccess access)
{
- OpenFlags flags = ToOpenFlags (mode, access);
- int fd = Syscall.open (Path, flags);
+ OpenFlags flags = UnixConvert.ToOpenFlags (mode, access);
+ int fd = Syscall.open (FullPath, flags);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
return new UnixStream (fd);
@@ -105,8 +117,8 @@ namespace Mono.Unix {
public UnixStream Open (FileMode mode, FileAccess access, FilePermissions perms)
{
- OpenFlags flags = ToOpenFlags (mode, access);
- int fd = Syscall.open (Path, flags, perms);
+ OpenFlags flags = UnixConvert.ToOpenFlags (mode, access);
+ int fd = Syscall.open (FullPath, flags, perms);
if (fd < 0)
UnixMarshal.ThrowExceptionForLastError ();
return new UnixStream (fd);
@@ -121,55 +133,6 @@ namespace Mono.Unix {
{
return Open (FileMode.OpenOrCreate, FileAccess.Write);
}
-
- public static OpenFlags ToOpenFlags (FileMode mode, FileAccess access)
- {
- OpenFlags flags = 0;
- switch (mode) {
- case FileMode.CreateNew:
- flags = OpenFlags.O_CREAT | OpenFlags.O_EXCL;
- break;
- case FileMode.Create:
- flags = OpenFlags.O_CREAT | OpenFlags.O_TRUNC;
- break;
- case FileMode.Open:
- // do nothing
- break;
- case FileMode.OpenOrCreate:
- flags = OpenFlags.O_CREAT;
- break;
- case FileMode.Truncate:
- flags = OpenFlags.O_TRUNC;
- break;
- case FileMode.Append:
- flags = OpenFlags.O_APPEND;
- break;
- default:
- throw new ArgumentOutOfRangeException ("mode", mode,
- Locale.GetText ("Unsupported mode value"));
- }
-
- int _ignored;
- if (UnixConvert.TryFromOpenFlags (OpenFlags.O_LARGEFILE, out _ignored))
- flags |= OpenFlags.O_LARGEFILE;
-
- switch (access) {
- case FileAccess.Read:
- flags |= OpenFlags.O_RDONLY;
- break;
- case FileAccess.Write:
- flags |= OpenFlags.O_WRONLY;
- break;
- case FileAccess.ReadWrite:
- flags |= OpenFlags.O_RDWR;
- break;
- default:
- throw new ArgumentOutOfRangeException ("access", access,
- Locale.GetText ("Unsupported access value"));
- }
-
- return flags;
- }
}
}
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs
index 5b0b3ca1819..8b173c1bb46 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixFileSystemInfo.cs
@@ -36,25 +36,34 @@ namespace Mono.Unix {
public abstract class UnixFileSystemInfo
{
private Stat stat;
- private string path;
+ private string fullPath;
+ private string originalPath;
private bool valid = false;
protected UnixFileSystemInfo (string path)
{
- this.path = path;
+ UnixPath.CheckPath (path);
+ this.originalPath = path;
+ this.fullPath = UnixPath.GetFullPath (path);
Refresh (true);
}
internal UnixFileSystemInfo (String path, Stat stat)
{
- this.path = path;
+ this.originalPath = path;
+ this.fullPath = UnixPath.GetFullPath (path);
this.stat = stat;
this.valid = true;
}
- protected string Path {
- get {return path;}
- set {path = value;}
+ protected string FullPath {
+ get {return fullPath;}
+ set {fullPath = value;}
+ }
+
+ protected string OriginalPath {
+ get {return originalPath;}
+ set {originalPath = value;}
}
private void AssertValid ()
@@ -64,9 +73,15 @@ namespace Mono.Unix {
throw new InvalidOperationException ("Path doesn't exist!");
}
+ public virtual string FullName {
+ get {return FullPath;}
+ }
+
+ public abstract string Name {get;}
+
public bool Exists {
get {
- int r = Syscall.access (path, AccessMode.F_OK);
+ int r = Syscall.access (FullPath, AccessMode.F_OK);
if (r == 0)
return true;
return false;
@@ -192,42 +207,29 @@ namespace Mono.Unix {
public bool CanAccess (AccessMode mode)
{
- int r = Syscall.access (path, mode);
+ int r = Syscall.access (FullPath, mode);
return r == 0;
}
+ public UnixSymbolicLinkInfo CreateSymbolicLink (string path)
+ {
+ int r = Syscall.symlink (FullName, path);
+ UnixMarshal.ThrowExceptionForLastErrorIf (r);
+ return new UnixSymbolicLinkInfo (path);
+ }
+
public abstract void Delete ();
public long GetConfigurationValue (PathConf name)
{
Syscall.SetLastError ((Error) 0);
- long r = Syscall.pathconf (Path, name);
+ long r = Syscall.pathconf (FullPath, name);
if (r == -1 && Syscall.GetLastError() != (Error) 0)
UnixMarshal.ThrowExceptionForLastError ();
return r;
}
- // TODO: Should ReadLink be in UnixSymbolicLinkInfo?
- public string ReadLink ()
- {
- string r = TryReadLink ();
- if (r == null)
- UnixMarshal.ThrowExceptionForLastError ();
- return r;
- }
-
- public string TryReadLink ()
- {
- // Who came up with readlink(2)? There doesn't seem to be a way to
- // properly handle it.
- StringBuilder sb = new StringBuilder (512);
- int r = Syscall.readlink (path, sb);
- if (r == -1)
- return null;
- return sb.ToString().Substring (0, r);
- }
-
- public new void Refresh ()
+ public void Refresh ()
{
Refresh (true);
}
@@ -236,7 +238,7 @@ namespace Mono.Unix {
{
if (valid && !force)
return;
- int r = Syscall.stat (path, out this.stat);
+ int r = Syscall.lstat (FullPath, out this.stat);
valid = r == 0;
}
@@ -244,20 +246,20 @@ namespace Mono.Unix {
{
int r;
do {
- r = Syscall.truncate (path, length);
+ r = Syscall.truncate (FullPath, length);
} while (UnixMarshal.ShouldRetrySyscall (r));
UnixMarshal.ThrowExceptionForLastErrorIf (r);
}
public void SetPermissions (FilePermissions perms)
{
- int r = Syscall.chmod (path, perms);
+ int r = Syscall.chmod (FullPath, perms);
UnixMarshal.ThrowExceptionForLastErrorIf (r);
}
public virtual void SetOwner (uint owner, uint group)
{
- int r = Syscall.chown (path, owner, group);
+ int r = Syscall.chown (FullPath, owner, group);
UnixMarshal.ThrowExceptionForLastErrorIf (r);
}
@@ -281,12 +283,15 @@ namespace Mono.Unix {
public override string ToString ()
{
- return path;
+ return FullPath;
}
internal static UnixFileSystemInfo Create (string path)
{
- Stat stat = UnixFile.GetFileStatus (path);
+ Stat stat;
+ int r = Syscall.lstat (path, out stat);
+ UnixMarshal.ThrowExceptionForLastErrorIf (r);
+
if (IsType (stat.st_mode, FilePermissions.S_IFDIR))
return new UnixDirectoryInfo (path, stat);
else if (IsType (stat.st_mode, FilePermissions.S_IFLNK))
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs
new file mode 100644
index 00000000000..679c2c1405a
--- /dev/null
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixPath.cs
@@ -0,0 +1,204 @@
+//
+// Mono.Unix/UnixPath.cs
+//
+// Authors:
+// Jonathan Pryor (jonpryor@vt.edu)
+//
+// (C) 2004 Jonathan Pryor
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Text;
+using Mono.Unix;
+
+namespace Mono.Unix {
+
+ public sealed class UnixPath
+ {
+ private UnixPath () {}
+
+ public static readonly char DirectorySeparatorChar = '/';
+ public static readonly char AltDirectorySeparatorChar = '/';
+ public static readonly char[] InvalidPathChars = new char[]{'\0'};
+ public static readonly char PathSeparator = ':';
+ public static readonly char VolumeSeparatorChar = '/';
+
+ public static string Combine (string path1, params string[] paths)
+ {
+ if (path1 == null)
+ throw new ArgumentNullException ("path1");
+ if (paths == null)
+ throw new ArgumentNullException ("paths");
+ if (path1.IndexOfAny (InvalidPathChars) != -1)
+ throw new ArgumentException ("Illegal characters in path", "path1");
+
+ int len = path1.Length + 1;
+ for (int i = 0; i < paths.Length; ++i) {
+ if (paths [i] == null)
+ throw new ArgumentNullException ("paths");
+ len += paths [i].Length + 1;
+ }
+
+ StringBuilder sb = new StringBuilder (len);
+ sb.Append (path1);
+ for (int i = 0; i < paths.Length; ++i)
+ Combine (sb, paths [i]);
+ return sb.ToString ();
+ }
+
+ private static void Combine (StringBuilder path, string part)
+ {
+ if (part.IndexOfAny (InvalidPathChars) != -1)
+ throw new ArgumentException ("Illegal characters in path", "path1");
+ char end = path [path.Length-1];
+ if (end != DirectorySeparatorChar &&
+ end != AltDirectorySeparatorChar &&
+ end != VolumeSeparatorChar)
+ path.Append (DirectorySeparatorChar);
+ path.Append (part);
+ }
+
+ public static string GetDirectoryName (string path)
+ {
+ CheckPath (path);
+
+ int lastDir = path.LastIndexOf (DirectorySeparatorChar);
+ if (lastDir > 0)
+ return path.Substring (0, lastDir);
+ return "";
+ }
+
+ public static string GetFileName (string path)
+ {
+ if (path == null || path.Length == 0)
+ return path;
+
+ int lastDir = path.LastIndexOf (DirectorySeparatorChar);
+ if (lastDir >= 0)
+ return path.Substring (lastDir+1);
+
+ return path;
+ }
+
+ public static string GetFullPath (string path)
+ {
+ path = _GetFullPath (path);
+ string [] dirs;
+ int lastIndex;
+ GetPathComponents (path, out dirs, out lastIndex);
+ return string.Join ("/", dirs, 0, lastIndex);
+ }
+
+ private static string _GetFullPath (string path)
+ {
+ if (path == null)
+ throw new ArgumentNullException ("path");
+ if (!IsPathRooted (path))
+ path = UnixDirectory.GetCurrentDirectory() + DirectorySeparatorChar + path;
+
+ return path;
+ }
+
+ private static void GetPathComponents (string path,
+ out string[] components, out int lastIndex)
+ {
+ string [] dirs = path.Split (DirectorySeparatorChar);
+ int target = 0;
+ for (int i = 0; i < dirs.Length; ++i) {
+ if (dirs [i] == "." || (i != 0 && dirs [i] == string.Empty)) continue;
+ else if (dirs [i] == "..") {
+ if (target != 0) --target;
+ }
+ else
+ dirs [target++] = dirs [i];
+ }
+ components = dirs;
+ lastIndex = target;
+ }
+
+ public static string GetPathRoot (string path)
+ {
+ if (path == null)
+ return null;
+ if (!IsPathRooted (path))
+ return "";
+ return "/";
+ }
+
+ public static string GetRealPath (string path)
+ {
+ path = _GetFullPath (path);
+ string [] dirs;
+ int lastIndex;
+ GetPathComponents (path, out dirs, out lastIndex);
+ StringBuilder realPath = new StringBuilder ();
+ for (int i = 0; i < dirs.Length; ++i) {
+ realPath.Append ("/").Append (dirs [i]);
+ string p = _GetRealPath (realPath.ToString());
+ realPath.Remove (0, realPath.Length);
+ realPath.Append (p);
+ }
+ return realPath.ToString ();
+ }
+
+ private static string _GetRealPath (string path)
+ {
+ StringBuilder buf = new StringBuilder (1024);
+ int r;
+ do {
+ r = Syscall.readlink (path, buf);
+ if (r == -1) {
+ Error e;
+ switch (e = Syscall.GetLastError()) {
+ case Error.EINVAL:
+ // path isn't a symbolic link
+ return path;
+ default:
+ UnixMarshal.ThrowExceptionForError (e);
+ break;
+ }
+ }
+ path = buf.ToString ();
+ } while (r == 0);
+
+ return path;
+ }
+
+ public static bool IsPathRooted (string path)
+ {
+ if (path == null || path.Length == 0)
+ return false;
+ return path [0] == DirectorySeparatorChar;
+ }
+
+ internal static void CheckPath (string path)
+ {
+ if (path == null)
+ throw new ArgumentNullException ();
+ if (path.IndexOfAny (UnixPath.InvalidPathChars) != -1)
+ throw new ArgumentException ("Invalid characters in path.");
+ }
+ }
+}
+
+// vim: noexpandtab
diff --git a/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs b/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs
index 322f7069f4c..ea0336da154 100644
--- a/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix/UnixSymbolicLinkInfo.cs
@@ -33,7 +33,7 @@ using Mono.Unix;
namespace Mono.Unix {
- public class UnixSymbolicLinkInfo : UnixFileSystemInfo
+ public sealed class UnixSymbolicLinkInfo : UnixFileSystemInfo
{
public UnixSymbolicLinkInfo (string path)
: base (path)
@@ -45,18 +45,75 @@ namespace Mono.Unix {
{
}
+ public override string Name {
+ get {return UnixPath.GetFileName (FullPath);}
+ }
+
+ // maximum number of bytes read from the symbolic link
+ public static readonly int ContentsLength = 1024;
+
+ public UnixFileSystemInfo Contents {
+ get {
+ return UnixFileSystemInfo.Create (ContentsPath);
+ }
+ }
+
+ public string ContentsPath {
+ get {
+ return ReadLink ();
+ }
+ }
+
+ public bool HasContents {
+ get {
+ return TryReadLink () != null;
+ }
+ }
+
+ public void CreateSymbolicLinkTo (string path)
+ {
+ int r = Syscall.symlink (path, OriginalPath);
+ UnixMarshal.ThrowExceptionForLastErrorIf (r);
+ }
+
+ public void CreateSymbolicLinkTo (UnixFileSystemInfo path)
+ {
+ int r = Syscall.symlink (path.FullName, OriginalPath);
+ UnixMarshal.ThrowExceptionForLastErrorIf (r);
+ }
+
public override void Delete ()
{
- int r = Syscall.unlink (Path);
+ int r = Syscall.unlink (FullPath);
UnixMarshal.ThrowExceptionForLastErrorIf (r);
base.Refresh ();
}
public override void SetOwner (uint owner, uint group)
{
- int r = Syscall.lchown (Path, owner, group);
+ int r = Syscall.lchown (FullPath, owner, group);
UnixMarshal.ThrowExceptionForLastErrorIf (r);
}
+
+ // TODO: Should ReadLink be in UnixSymbolicLinkInfo?
+ private string ReadLink ()
+ {
+ string r = TryReadLink ();
+ if (r == null)
+ UnixMarshal.ThrowExceptionForLastError ();
+ return r;
+ }
+
+ private string TryReadLink ()
+ {
+ // Who came up with readlink(2)? There doesn't seem to be a way to
+ // properly handle it.
+ StringBuilder sb = new StringBuilder (ContentsLength+1);
+ int r = Syscall.readlink (FullPath, sb, (ulong) ContentsLength);
+ if (r == -1)
+ return null;
+ return sb.ToString().Substring (0, r);
+ }
}
}