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