added UnixWrapper, FileStream and Stream Class + various fixes
[mono.git] / mcs / class / corlib / System.IO / FileStream.cs
1 //
2 // System.IO/FileStream.cs
3 //
4 // Author:
5 //   Dietmar Maurer (dietmar@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 //
9 using System;
10 using System.Runtime.InteropServices;
11 using Unix;
12
13 // fixme: I do not know how to handle errno when calling PInvoke functions
14 // fixme: emit the correct exceptions everywhere
15
16 namespace System.IO
17 {
18
19         class FileStream : Stream
20         {
21                         
22                 private IntPtr fd;
23                 private FileAccess acc;
24                 private bool owner;
25                 
26                 private int getUnixFlags (FileMode mode, FileAccess access)
27                 {
28                         int flags = 0;
29
30                         switch (access) {
31                         case FileAccess.Read:
32                                 flags = Wrapper.O_RDONLY;
33                                 break;
34                         case FileAccess.Write:
35                                 flags = Wrapper.O_WRONLY;
36                                 break;
37                         case FileAccess.ReadWrite:
38                                 flags = Wrapper.O_RDWR;
39                                 break;
40                         }
41                         
42                         switch (mode) {
43                         case FileMode.Append:
44                                 flags |= Wrapper.O_APPEND;
45                                 break;
46                         case FileMode.Create:
47                                 flags |= Wrapper.O_CREAT;
48                                 break;
49                         case FileMode.CreateNew:
50                                 flags |= Wrapper.O_CREAT |  Wrapper.O_EXCL;
51                                 break;
52                         case FileMode.Open:
53                                 break;
54                         case FileMode.OpenOrCreate:
55                                 flags |= Wrapper.O_CREAT;                               
56                                 break;
57                         case FileMode.Truncate:
58                                 flags |= Wrapper.O_TRUNC;
59                                 break;
60                         }
61
62                         return flags;
63                 }
64                 
65                 public FileStream (IntPtr fd, FileAccess access)
66                         : this (fd, access, true, 0, false) {}
67
68                 public FileStream (IntPtr fd, FileAccess access, bool ownsHandle)
69                         : this (fd, access, ownsHandle, 0, false) {}
70                 
71                 public FileStream (IntPtr fd, FileAccess access, bool ownsHandle, int bufferSize)
72                         : this (fd, access, ownsHandle, bufferSize, false) {}
73                 
74                 public FileStream (IntPtr fd, FileAccess access, bool ownsHandle,
75                                    int bufferSize, bool isAsync)
76                 {
77                         fd = fd;
78                         acc = access;
79                         owner = ownsHandle;
80                 }
81                 
82                 public FileStream (string name, FileMode mode)
83                         : this (name, mode, FileAccess.ReadWrite, FileShare.ReadWrite, 0, false) {}
84
85                 public FileStream (string name, FileMode mode, FileAccess access)
86                         : this (name, mode, access, FileShare.ReadWrite, 0, false) {}
87
88                 public FileStream (string name, FileMode mode, FileAccess access, FileShare share)
89                         : this (name, mode, access, share, 0, false) {}
90                 
91                 public FileStream (string name, FileMode mode, FileAccess access,
92                                    FileShare share, int buferSize)
93                         : this (name, mode, access, share, 0, false) {}
94
95                 // fixme: implement all share, buffer, async
96                 public FileStream (string name, FileMode mode, FileAccess access, FileShare share,
97                                    int buferSize, bool useAsync)
98                 {
99                         int flags = getUnixFlags (mode, access);
100                         
101                         if ((int)(fd = Wrapper.open (name, flags, 0x1a4)) == -1)
102                                 throw new IOException();
103
104                         acc = access;
105                         owner = true;
106                 }
107                 
108                 public override bool CanRead
109                 {
110                         get {
111                                 switch (acc) {
112                                 case FileAccess.Read:
113                                 case FileAccess.ReadWrite:
114                                         return true;
115                                 case FileAccess.Write:
116                                 default:
117                                         return false;
118                                 }
119                         }
120                 }
121
122                 public override bool CanSeek
123                 {
124                         get {
125                                 // fixme: not alway true
126                                 return true;
127                         }
128                 }
129
130                 public override bool CanWrite
131                 {
132                         get {
133                                 switch (acc) {
134                                 case FileAccess.Write:
135                                 case FileAccess.ReadWrite:
136                                         return true;
137                                 default:
138                                         return false;
139                                 }
140                         }
141                 }
142
143                 unsafe public override long Length
144                 {
145                         get {
146                                 stat fs;
147
148                                 Wrapper.fstat (fd, &fs);
149                                 return fs.st_size;
150                         }
151                 }
152
153                 public override long Position
154                 {
155                         get {
156                                 return Wrapper.seek (fd, 0,  Wrapper.SEEK_CUR);
157                         }
158                         set {
159                                 Wrapper.seek (fd, value, Wrapper.SEEK_SET);
160                         }
161                 }
162
163                 public override void Flush ()
164                 {
165                 }
166
167                 public override void Close ()
168                 {
169                         if (owner && Wrapper.close (fd) != 0)
170                                 throw new IOException();
171                 }
172
173                 public unsafe override int Read (byte[] buffer,
174                                           int offset,
175                                           int count)
176                 {
177                         int res;
178
179                         fixed (void *p = &buffer [offset]) {
180                                 res = Wrapper.read (fd, p, count);
181                         }
182                         
183                         return res;
184                 }
185
186                 public unsafe override int ReadByte ()
187                 {
188                         byte val;
189                         
190                         if (Wrapper.read (fd, &val, 1) != 1)
191                                 throw new IOException();
192                         
193                         return val;
194                 }
195
196                 public override long Seek (long offset,
197                                            SeekOrigin origin)
198                 {
199                         int off = (int)offset;
200                         
201                         switch (origin) {
202                         case SeekOrigin.End:
203                                 return Wrapper.seek (fd, Wrapper.SEEK_END, off);
204                         case SeekOrigin.Current:
205                                 return Wrapper.seek (fd, Wrapper.SEEK_CUR, off);
206                         default:
207                                 return Wrapper.seek (fd, Wrapper.SEEK_SET, off);
208                         }
209                 }
210
211                 public override void SetLength (long value)
212                 {
213                         int res;
214
215                         if ((res = Wrapper.ftruncate (fd, value)) == -1)
216                                 throw new IOException();
217
218                         
219                 }
220
221                 public unsafe override void Write (byte[] buffer,
222                                                    int offset,
223                                                    int count)
224                 {
225                         int res;
226                         
227                         fixed (void *p = &buffer [offset]) {
228                                 res = Wrapper.write (fd, p, count);
229                         }
230                         
231                         if (res != count)
232                                 throw new IOException();
233                 }
234
235                 public unsafe override void WriteByte (byte value)
236                 {
237                         if (Wrapper.write (fd, &value, 1) != 1)
238                                 throw new IOException();
239                 }
240
241         }
242 }