* BinaryReader.cs: Fixed line endings.
[mono.git] / mcs / class / corlib / System.IO / MonoIO.cs
1 // System.IO.MonoIO.cs: static interface to native filesystem.
2 //
3 // Author:
4 //   Dan Lewis (dihlewis@yahoo.co.uk)
5 //   Dick Porter (dick@ximian.com)
6 //
7 // (C) 2002
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
36 using System.Threading;
37
38 namespace System.IO
39 {
40         unsafe internal sealed class MonoIO {
41                 public static readonly FileAttributes
42                         InvalidFileAttributes = (FileAttributes)(-1);
43
44                 public static readonly IntPtr
45                         InvalidHandle = (IntPtr)(-1L);
46
47                 // error methods
48                 public static Exception GetException (MonoIOError error)
49                 {
50                         /* This overload is currently only called from
51                          * File.MoveFile(), Directory.Move() and
52                          * Directory.GetCurrentDirectory() -
53                          * everywhere else supplies a path to format
54                          * with the error text.
55                          */
56                         switch(error) {
57                         case MonoIOError.ERROR_ACCESS_DENIED:
58                                 return new UnauthorizedAccessException ("Access to the path is denied.");
59                         default:
60                                 /* Add more mappings here if other
61                                  * errors trigger the named but empty
62                                  * path bug (see bug 82141.) For
63                                  * everything else, fall through to
64                                  * the other overload
65                                  */
66                                 return GetException (String.Empty, error);
67                         }
68                 }
69
70                 public static Exception GetException (string path,
71                                                       MonoIOError error)
72                 {
73                         string message;
74
75                         switch (error) {
76                         // FIXME: add more exception mappings here
77                         case MonoIOError.ERROR_FILE_NOT_FOUND:
78                                 message = String.Format ("Could not find file \"{0}\"", path);
79                                 return new FileNotFoundException (message,
80                                                                   path);
81
82                         case MonoIOError.ERROR_TOO_MANY_OPEN_FILES:
83                                 return new IOException ("Too many open files", unchecked((int)0x80070000) | (int)error);
84                                 
85                         case MonoIOError.ERROR_PATH_NOT_FOUND:
86                                 message = String.Format ("Could not find a part of the path \"{0}\"", path);
87                                 return new DirectoryNotFoundException (message);
88
89                         case MonoIOError.ERROR_ACCESS_DENIED:
90                                 message = String.Format ("Access to the path \"{0}\" is denied.", path);
91                                 return new UnauthorizedAccessException (message);
92
93                         case MonoIOError.ERROR_INVALID_HANDLE:
94                                 message = String.Format ("Invalid handle to path \"{0}\"", path);
95                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
96                         case MonoIOError.ERROR_INVALID_DRIVE:
97                                 message = String.Format ("Could not find the drive  '{0}'. The drive might not be ready or might not be mapped.", path);
98 #if NET_2_0
99                                 return new DriveNotFoundException (message);
100 #else
101                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
102 #endif
103                         case MonoIOError.ERROR_FILE_EXISTS:
104                                 message = String.Format ("Could not create file \"{0}\". File already exists.", path);
105                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
106
107                         case MonoIOError.ERROR_FILENAME_EXCED_RANGE:
108                                 message = String.Format ("Path is too long. Path: {0}", path); 
109                                 return new PathTooLongException (message);
110
111                         case MonoIOError.ERROR_INVALID_PARAMETER:
112                                 message = String.Format ("Invalid parameter");
113                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
114
115                         case MonoIOError.ERROR_WRITE_FAULT:
116                                 message = String.Format ("Write fault on path {0}", path);
117                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
118
119                         case MonoIOError.ERROR_SHARING_VIOLATION:
120                                 message = String.Format ("Sharing violation on path {0}", path);
121                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
122                                 
123                         case MonoIOError.ERROR_LOCK_VIOLATION:
124                                 message = String.Format ("Lock violation on path {0}", path);
125                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
126                         
127                         case MonoIOError.ERROR_HANDLE_DISK_FULL:
128                                 message = String.Format ("Disk full. Path {0}", path);
129                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
130                         
131                         case MonoIOError.ERROR_DIR_NOT_EMPTY:
132                                 message = String.Format ("Directory {0} is not empty", path);
133                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
134
135                         case MonoIOError.ERROR_ENCRYPTION_FAILED:
136                                 return new IOException ("Encryption failed", unchecked((int)0x80070000) | (int)error);
137
138                         case MonoIOError.ERROR_CANNOT_MAKE:
139                                 message = String.Format ("Path {0} is a directory", path);
140                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
141                                 
142                         default:
143                                 message = String.Format ("Win32 IO returned {0}. Path: {1}", error, path);
144                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
145                         }
146                 }
147
148                 // directory methods
149
150                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
151                 public extern static bool CreateDirectory (string path, out MonoIOError error);
152
153                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
154                 public extern static bool RemoveDirectory (string path, out MonoIOError error);
155
156                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
157                 public extern static string [] GetFileSystemEntries (string path, string path_with_pattern, int attrs, int mask, out MonoIOError error);
158
159                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
160                 public extern static string GetCurrentDirectory (out MonoIOError error);
161
162                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
163                 public extern static bool SetCurrentDirectory (string path, out MonoIOError error);
164
165                 // file methods
166
167                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
168                 public extern static bool MoveFile (string path, string dest,
169                                                     out MonoIOError error);
170
171                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
172                 public extern static bool CopyFile (string path, string dest,
173                                                     bool overwrite,
174                                                     out MonoIOError error);
175
176                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
177                 public extern static bool DeleteFile (string path,
178                                                       out MonoIOError error);
179
180                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
181                 public extern static bool ReplaceFile (string sourceFileName, 
182                                                        string destinationFileName, 
183                                                        string destinationBackupFileName, 
184                                                        bool ignoreMetadataErrors,
185                                                        out MonoIOError error);
186
187                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
188                 public extern static FileAttributes GetFileAttributes (string path, out MonoIOError error);
189
190                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
191                 public extern static bool SetFileAttributes (string path, FileAttributes attrs, out MonoIOError error);
192
193                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
194                 public extern static MonoFileType GetFileType (IntPtr handle, out MonoIOError error);
195
196                 public static bool Exists (string path, out MonoIOError error)
197                 {
198                         FileAttributes attrs = GetFileAttributes (path,
199                                                                   out error);
200                         if (attrs == InvalidFileAttributes)
201                                 return false;
202
203                         return true;
204                 }
205
206                 public static bool ExistsFile (string path,
207                                                out MonoIOError error)
208                 {
209                         FileAttributes attrs = GetFileAttributes (path,
210                                                                   out error);
211                         if (attrs == InvalidFileAttributes)
212                                 return false;
213
214                         if ((attrs & FileAttributes.Directory) != 0)
215                                 return false;
216
217                         return true;
218                 }
219
220                 public static bool ExistsDirectory (string path,
221                                                     out MonoIOError error)
222                 {
223                         FileAttributes attrs = GetFileAttributes (path,
224                                                                   out error);
225                                                                   
226                         // Actually, we are looking for a directory, not a file
227                         if (error == MonoIOError.ERROR_FILE_NOT_FOUND)
228                                 error = MonoIOError.ERROR_PATH_NOT_FOUND;
229                                 
230                         if (attrs == InvalidFileAttributes)
231                                 return false;
232
233                         if ((attrs & FileAttributes.Directory) == 0)
234                                 return false;
235
236                         return true;
237                 }
238
239                 public static bool ExistsSymlink (string path,
240                                                   out MonoIOError error)
241                 {
242                         FileAttributes attrs = GetFileAttributes (path,
243                                                                   out error);
244                         if (attrs == InvalidFileAttributes)
245                                 return false;
246                         
247                         if ((attrs & FileAttributes.ReparsePoint) == 0)
248                                 return false;
249
250                         return true;
251                 }
252
253                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
254                 public extern static bool GetFileStat (string path,
255                                                        out MonoIOStat stat,
256                                                        out MonoIOError error);
257
258                 // handle methods
259
260                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
261                 public extern static IntPtr Open (string filename,
262                                                   FileMode mode,
263                                                   FileAccess access,
264                                                   FileShare share,
265                                                   FileOptions options,
266                                                   out MonoIOError error);
267                 
268                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
269                 public extern static bool Close (IntPtr handle,
270                                                  out MonoIOError error);
271                 
272                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
273                 public extern static int Read (IntPtr handle, byte [] dest,
274                                                int dest_offset, int count,
275                                                out MonoIOError error);
276                 
277                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
278                 public extern static int Write (IntPtr handle, [In] byte [] src,
279                                                 int src_offset, int count,
280                                                 out MonoIOError error);
281                 
282                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
283                 public extern static long Seek (IntPtr handle, long offset,
284                                                 SeekOrigin origin,
285                                                 out MonoIOError error);
286                 
287                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
288                 public extern static bool Flush (IntPtr handle,
289                                                  out MonoIOError error);
290
291                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
292                 public extern static long GetLength (IntPtr handle,
293                                                      out MonoIOError error);
294
295                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
296                 public extern static bool SetLength (IntPtr handle,
297                                                      long length,
298                                                      out MonoIOError error);
299
300                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
301                 public extern static bool SetFileTime (IntPtr handle,
302                                                        long creation_time,
303                                                        long last_access_time,
304                                                        long last_write_time,
305                                                        out MonoIOError error);
306
307                 public static bool SetFileTime (string path,
308                                                 long creation_time,
309                                                 long last_access_time,
310                                                 long last_write_time,
311                                                 out MonoIOError error)
312                 {
313                         return SetFileTime (path,
314                                 0,
315                                 creation_time,
316                                 last_access_time,
317                                 last_write_time,
318                                 DateTime.MinValue,
319                                 out error);
320                 }
321
322                 public static bool SetCreationTime (string path,
323                                                 DateTime dateTime,
324                                                 out MonoIOError error)
325                 {
326                         return SetFileTime (path, 1, -1, -1, -1, dateTime, out error);
327                 }
328
329                 public static bool SetLastAccessTime (string path,
330                                                 DateTime dateTime,
331                                                 out MonoIOError error)
332                 {
333                         return SetFileTime (path, 2, -1, -1, -1, dateTime, out error);
334                 }
335
336                 public static bool SetLastWriteTime (string path,
337                                                 DateTime dateTime,
338                                                 out MonoIOError error)
339                 {
340                         return SetFileTime (path, 3, -1, -1, -1, dateTime, out error);
341                 }
342
343                 public static bool SetFileTime (string path,
344                                                 int type,
345                                                 long creation_time,
346                                                 long last_access_time,
347                                                 long last_write_time,
348                                                 DateTime dateTime,
349                                                 out MonoIOError error)
350                 {
351                         IntPtr handle;
352                         bool result;
353
354                         handle = Open (path, FileMode.Open,
355                                        FileAccess.ReadWrite,
356                                        FileShare.ReadWrite, FileOptions.None, out error);
357                         if (handle == MonoIO.InvalidHandle)
358                                 return false;
359
360                         switch (type) {
361                         case 1:
362                                 creation_time = dateTime.ToFileTime ();
363                                 break;
364                         case 2:
365                                 last_access_time = dateTime.ToFileTime ();
366                                 break;
367                         case 3:
368                                 last_write_time = dateTime.ToFileTime ();
369                                 break;
370                         }
371
372                         result = SetFileTime (handle, creation_time,
373                                               last_access_time,
374                                               last_write_time, out error);
375
376                         MonoIOError ignore_error;
377                         Close (handle, out ignore_error);
378                         
379                         return result;
380                 }
381
382                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
383                 public extern static void Lock (IntPtr handle,
384                                                 long position, long length,
385                                                 out MonoIOError error);
386
387                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
388                 public extern static void Unlock (IntPtr handle,
389                                                   long position, long length,
390                                                   out MonoIOError error);
391
392                 // console handles
393
394                 public extern static IntPtr ConsoleOutput {
395                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
396                         get;
397                 }
398
399                 public extern static IntPtr ConsoleInput {
400                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
401                         get;
402                 }
403
404                 public extern static IntPtr ConsoleError {
405                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
406                         get;
407                 }
408
409                 // pipe handles
410
411                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
412                 public extern static bool CreatePipe (out IntPtr read_handle, out IntPtr write_handle);
413
414                 // path characters
415
416                 public extern static char VolumeSeparatorChar {
417                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
418                         get;
419                 }
420
421                 public extern static char DirectorySeparatorChar {
422                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
423                         get;
424                 }
425
426                 public extern static char AltDirectorySeparatorChar {
427                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
428                         get;
429                 }
430
431                 public extern static char PathSeparator {
432                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
433                         get;
434                 }
435
436                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
437                 public extern static int GetTempPath(out string path);
438         }
439 }
440