2007-12-13 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / Mono.Posix / Mono.Unix / UnixStream.cs
index 49a3218647759f08eb03030f0a8fa7f7304863f9..d5d16676b8deb45fae11a1b79b8cbd899c91e446 100644 (file)
@@ -4,7 +4,9 @@
 // Authors:
 //   Jonathan Pryor (jonpryor@vt.edu)
 //
-// (C) 2004 Jonathan Pryor
+// (C) 2004-2006 Jonathan Pryor
+// (C) 2007 Novell, Inc.
+//
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -52,13 +54,13 @@ namespace Mono.Unix {
                        this.fileDescriptor = fileDescriptor;
                        this.owner = ownsHandle;
                        
-                       long offset = Syscall.lseek (fileDescriptor, 0, SeekFlags.SEEK_CUR);
+                       long offset = Native.Syscall.lseek (fileDescriptor, 0, Native.SeekFlags.SEEK_CUR);
                        if (offset != -1)
                                canSeek = true;
-                       long read = Syscall.read (fileDescriptor, IntPtr.Zero, 0);
+                       long read = Native.Syscall.read (fileDescriptor, IntPtr.Zero, 0);
                        if (read != -1)
                                canRead = true;
-                       long write = Syscall.write (fileDescriptor, IntPtr.Zero, 0);
+                       long write = Native.Syscall.write (fileDescriptor, IntPtr.Zero, 0);
                        if (write != -1)
                                canWrite = true;  
                }
@@ -90,10 +92,8 @@ namespace Mono.Unix {
                                AssertNotDisposed ();
                                if (!CanSeek)
                                        throw new NotSupportedException ("File descriptor doesn't support seeking");
-                               Stat stat;
-                               int r = Syscall.fstat (fileDescriptor, out stat);
-                               UnixMarshal.ThrowExceptionForLastErrorIf (r);
-                               return (long) stat.st_size;
+                               RefreshStat ();
+                               return stat.st_size;
                        }
                }
 
@@ -102,7 +102,7 @@ namespace Mono.Unix {
                                AssertNotDisposed ();
                                if (!CanSeek)
                                        throw new NotSupportedException ("The stream does not support seeking");
-                               long pos = Syscall.lseek (fileDescriptor, 0, SeekFlags.SEEK_CUR);
+                               long pos = Native.Syscall.lseek (fileDescriptor, 0, Native.SeekFlags.SEEK_CUR);
                                if (pos == -1)
                                        UnixMarshal.ThrowExceptionForLastError ();
                                return (long) pos;
@@ -113,84 +113,88 @@ namespace Mono.Unix {
                }
 
                [CLSCompliant (false)]
-               [Obsolete ("The type of this property will change in the next release.")]
-               public FilePermissions Permissions {
+               public Native.FilePermissions Protection {
                        get {
-                               Stat stat;
-                               int r = Syscall.fstat (fileDescriptor, out stat);
-                               UnixMarshal.ThrowExceptionForLastErrorIf (r);
+                               RefreshStat ();
                                return stat.st_mode;
                        }
                        set {
-                               int r = Syscall.fchmod (fileDescriptor, value);
+                               // we can't change file type with fchmod, so clear out that portion
+                               value &= ~Native.FilePermissions.S_IFMT;
+                               int r = Native.Syscall.fchmod (fileDescriptor, value);
                                UnixMarshal.ThrowExceptionForLastErrorIf (r);
                        }
                }
 
-               public void AdviseNormalAccess (long offset, long len)
-               {
-                       UnixFile.AdviseNormalAccess (fileDescriptor, offset, len);
-               }
-
-               public void AdviseNormalAccess ()
-               {
-                       UnixFile.AdviseNormalAccess (fileDescriptor);
-               }
-
-               public void AdviseSequentialAccess (long offset, long len)
-               {
-                       UnixFile.AdviseSequentialAccess (fileDescriptor, offset, len);
+               public FileTypes FileType {
+                       get {
+                               int type = (int) Protection;
+                               return (FileTypes) (type & (int) UnixFileSystemInfo.AllFileTypes);
+                       }
+                       // no set as fchmod(2) won't accept changing the file type.
                }
 
-               public void AdviseSequentialAccess ()
-               {
-                       UnixFile.AdviseSequentialAccess (fileDescriptor);
+               public FileAccessPermissions FileAccessPermissions {
+                       get {
+                               int perms = (int) Protection;
+                               return (FileAccessPermissions) (perms & (int) FileAccessPermissions.AllPermissions);
+                       }
+                       set {
+                               int perms = (int) Protection;
+                               perms &= (int) ~FileAccessPermissions.AllPermissions;
+                               perms |= (int) value;
+                               Protection = (Native.FilePermissions) perms;
+                       }
                }
 
-               public void AdviseRandomAccess (long offset, long len)
-               {
-                       UnixFile.AdviseRandomAccess (fileDescriptor, offset, len);
+               public FileSpecialAttributes FileSpecialAttributes {
+                       get {
+                               int attrs = (int) Protection;
+                               return (FileSpecialAttributes) (attrs & (int) UnixFileSystemInfo.AllSpecialAttributes);
+                       }
+                       set {
+                               int perms = (int) Protection;
+                               perms &= (int) ~UnixFileSystemInfo.AllSpecialAttributes;
+                               perms |= (int) value;
+                               Protection = (Native.FilePermissions) perms;
+                       }
                }
 
-               public void AdviseRandomAccess ()
-               {
-                       UnixFile.AdviseRandomAccess (fileDescriptor);
+               public UnixUserInfo OwnerUser {
+                       get {RefreshStat (); return new UnixUserInfo (stat.st_uid);}
                }
-
-               public void AdviseNeedAccess (long offset, long len)
-               {
-                       UnixFile.AdviseNeedAccess (fileDescriptor, offset, len);
+                                                                                                
+               public long OwnerUserId {
+                       get {RefreshStat (); return stat.st_uid;}
                }
-
-               public void AdviseNeedAccess ()
-               {
-                       UnixFile.AdviseNeedAccess (fileDescriptor);
+                                                                                                
+               public UnixGroupInfo OwnerGroup {
+                       get {RefreshStat (); return new UnixGroupInfo (stat.st_gid);}
                }
-
-               public void AdviseNoAccess (long offset, long len)
-               {
-                       UnixFile.AdviseNoAccess (fileDescriptor, offset, len);
+                                                                                                
+               public long OwnerGroupId {
+                       get {RefreshStat (); return stat.st_gid;}
                }
 
-               public void AdviseNoAccess ()
+               private void RefreshStat ()
                {
-                       UnixFile.AdviseNoAccess (fileDescriptor);
+                       AssertNotDisposed ();
+                       int r = Native.Syscall.fstat (fileDescriptor, out stat);
+                       UnixMarshal.ThrowExceptionForLastErrorIf (r);
                }
 
-               public void AdviseOnceAccess (long offset, long len)
+               public void AdviseFileAccessPattern (FileAccessPattern pattern, long offset, long len)
                {
-                       UnixFile.AdviseOnceAccess (fileDescriptor, offset, len);
+                       FileHandleOperations.AdviseFileAccessPattern (fileDescriptor, pattern, offset, len);
                }
 
-               public void AdviseOnceAccess ()
+               public void AdviseFileAccessPattern (FileAccessPattern pattern)
                {
-                       UnixFile.AdviseOnceAccess (fileDescriptor);
+                       AdviseFileAccessPattern (pattern, 0, 0);
                }
 
                public override void Flush ()
                {
-                       int r = Syscall.fsync (fileDescriptor);
-                       UnixMarshal.ThrowExceptionForLastErrorIf (r);
                }
 
                public override unsafe int Read ([In, Out] byte[] buffer, int offset, int count)
@@ -200,10 +204,13 @@ namespace Mono.Unix {
                        if (!CanRead)
                                throw new NotSupportedException ("Stream does not support reading");
                                 
+                       if (buffer.Length == 0)
+                               return 0;
+
                        long r = 0;
                        fixed (byte* buf = &buffer[offset]) {
                                do {
-                                       r = Syscall.read (fileDescriptor, buf, (ulong) count);
+                                       r = Native.Syscall.read (fileDescriptor, buf, (ulong) count);
                                } while (UnixMarshal.ShouldRetrySyscall ((int) r));
                        }
                        if (r == -1)
@@ -233,10 +240,13 @@ namespace Mono.Unix {
                        if (!CanRead)
                                throw new NotSupportedException ("Stream does not support reading");
                                 
+                       if (buffer.Length == 0)
+                               return 0;
+
                        long r = 0;
                        fixed (byte* buf = &buffer[offset]) {
                                do {
-                                       r = Syscall.pread (fileDescriptor, buf, (ulong) count, fileOffset);
+                                       r = Native.Syscall.pread (fileDescriptor, buf, (ulong) count, fileOffset);
                                } while (UnixMarshal.ShouldRetrySyscall ((int) r));
                        }
                        if (r == -1)
@@ -252,14 +262,14 @@ namespace Mono.Unix {
                        if (offset > int.MaxValue)
                                throw new ArgumentOutOfRangeException ("offset", "too large");
                                        
-                       SeekFlags sf = SeekFlags.SEEK_CUR;
+                       Native.SeekFlags sf = Native.SeekFlags.SEEK_CUR;
                        switch (origin) {
-                               case SeekOrigin.Begin:   sf = SeekFlags.SEEK_SET; break;
-                               case SeekOrigin.Current: sf = SeekFlags.SEEK_CUR; break;
-                               case SeekOrigin.End:     sf = SeekFlags.SEEK_END; break;
+                               case SeekOrigin.Begin:   sf = Native.SeekFlags.SEEK_SET; break;
+                               case SeekOrigin.Current: sf = Native.SeekFlags.SEEK_CUR; break;
+                               case SeekOrigin.End:     sf = Native.SeekFlags.SEEK_END; break;
                        }
 
-                       long pos = Syscall.lseek (fileDescriptor, offset, sf);
+                       long pos = Native.Syscall.lseek (fileDescriptor, offset, sf);
                        if (pos == -1)
                                UnixMarshal.ThrowExceptionForLastError ();
                        return (long) pos;
@@ -275,7 +285,7 @@ namespace Mono.Unix {
                        
                        int r;
                        do {
-                               r = Syscall.ftruncate (fileDescriptor, value);
+                               r = Native.Syscall.ftruncate (fileDescriptor, value);
                        } while (UnixMarshal.ShouldRetrySyscall (r));
                        UnixMarshal.ThrowExceptionForLastErrorIf (r);
                }
@@ -287,10 +297,13 @@ namespace Mono.Unix {
                        if (!CanWrite)
                                throw new NotSupportedException ("File Descriptor does not support writing");
 
+                       if (buffer.Length == 0)
+                               return;
+
                        long r = 0;
                        fixed (byte* buf = &buffer[offset]) {
                                do {
-                                       r = Syscall.write (fileDescriptor, buf, (ulong) count);
+                                       r = Native.Syscall.write (fileDescriptor, buf, (ulong) count);
                                } while (UnixMarshal.ShouldRetrySyscall ((int) r));
                        }
                        if (r == -1)
@@ -305,10 +318,13 @@ namespace Mono.Unix {
                        if (!CanWrite)
                                throw new NotSupportedException ("File Descriptor does not support writing");
 
+                       if (buffer.Length == 0)
+                               return;
+
                        long r = 0;
                        fixed (byte* buf = &buffer[offset]) {
                                do {
-                                       r = Syscall.pwrite (fileDescriptor, buf, (ulong) count, fileOffset);
+                                       r = Native.Syscall.pwrite (fileDescriptor, buf, (ulong) count, fileOffset);
                                } while (UnixMarshal.ShouldRetrySyscall ((int) r));
                        }
                        if (r == -1)
@@ -332,17 +348,17 @@ namespace Mono.Unix {
                        if (!CanWrite)
                                throw new NotSupportedException ("Unable to write to the current file descriptor");
                        long offset = Position;
-                       long r = Syscall.sendfile (out_fd, fileDescriptor, ref offset, count);
+                       long r = Native.Syscall.sendfile (out_fd, fileDescriptor, ref offset, count);
                        if (r == -1)
                                UnixMarshal.ThrowExceptionForLastError ();
                }
                
-               [CLSCompliant (false)]
-               public void SetOwner (uint user, uint group)
+               public void SetOwner (long user, long group)
                {
                        AssertNotDisposed ();
 
-                       int r = Syscall.fchown (fileDescriptor, user, group);
+                       int r = Native.Syscall.fchown (fileDescriptor, 
+                                       Convert.ToUInt32 (user), Convert.ToUInt32 (group));
                        UnixMarshal.ThrowExceptionForLastErrorIf (r);
                }
 
@@ -350,8 +366,8 @@ namespace Mono.Unix {
                {
                        AssertNotDisposed ();
 
-                       uint uid = UnixUser.GetUserId (user);
-                       uint gid = UnixGroup.GetGroupId (group);
+                       long uid = new UnixUserInfo (user).UserId;
+                       long gid = new UnixGroupInfo (group).GroupId;
                        SetOwner (uid, gid);
                }
 
@@ -359,21 +375,20 @@ namespace Mono.Unix {
                {
                        AssertNotDisposed ();
 
-                       Passwd pw = Syscall.getpwnam (user);
+                       Native.Passwd pw = Native.Syscall.getpwnam (user);
                        if (pw == null)
                                throw new ArgumentException (Locale.GetText ("invalid username"), "user");
-                       uint uid = pw.pw_uid;
-                       uint gid = pw.pw_gid;
+                       long uid = pw.pw_uid;
+                       long gid = pw.pw_gid;
                        SetOwner (uid, gid);
                }
 
                [CLSCompliant (false)]
-               public long GetConfigurationValue (PathConf name)
+               public long GetConfigurationValue (Native.PathconfName name)
                {
                        AssertNotDisposed ();
-                       Syscall.SetLastError ((Error) 0);
-                       long r = Syscall.fpathconf (fileDescriptor, name);
-                       if (r == -1 && Syscall.GetLastError() != (Error) 0)
+                       long r = Native.Syscall.fpathconf (fileDescriptor, name);
+                       if (r == -1 && Native.Syscall.GetLastError() != (Native.Errno) 0)
                                UnixMarshal.ThrowExceptionForLastError ();
                        return r;
                }
@@ -389,9 +404,13 @@ namespace Mono.Unix {
                                return;
                                
                        Flush ();
+
+                       if (!owner)
+                               return;
+
                        int r;
                        do {
-                               r = Syscall.close (fileDescriptor);
+                               r = Native.Syscall.close (fileDescriptor);
                        } while (UnixMarshal.ShouldRetrySyscall (r));
                        UnixMarshal.ThrowExceptionForLastErrorIf (r);
                        fileDescriptor = InvalidFileDescriptor;
@@ -412,6 +431,7 @@ namespace Mono.Unix {
                private bool canWrite = false;
                private bool owner = true;
                private int fileDescriptor = InvalidFileDescriptor;
+               private Native.Stat stat;
        }
 }