[Mono.Posix] Add Syscall.getgrouplist().
[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 #if MOONLIGHT
89                                 return new IsolatedStorageException (message);
90 #else
91                                 return new FileNotFoundException (message, path);
92 #endif
93
94                         case MonoIOError.ERROR_TOO_MANY_OPEN_FILES:
95                                 return new IOException ("Too many open files", unchecked((int)0x80070000) | (int)error);
96                                 
97                         case MonoIOError.ERROR_PATH_NOT_FOUND:
98                                 message = String.Format ("Could not find a part of the path \"{0}\"", path);
99 #if MOONLIGHT
100                                 return new IsolatedStorageException (message);
101 #else
102                                 return new DirectoryNotFoundException (message);
103 #endif
104
105                         case MonoIOError.ERROR_ACCESS_DENIED:
106                                 message = String.Format ("Access to the path \"{0}\" is denied.", path);
107                                 return new UnauthorizedAccessException (message);
108
109                         case MonoIOError.ERROR_INVALID_HANDLE:
110                                 message = String.Format ("Invalid handle to path \"{0}\"", path);
111                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
112                         case MonoIOError.ERROR_INVALID_DRIVE:
113                                 message = String.Format ("Could not find the drive  '{0}'. The drive might not be ready or might not be mapped.", path);
114 #if !NET_2_1
115                                 return new DriveNotFoundException (message);
116 #else
117                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
118 #endif
119                         case MonoIOError.ERROR_FILE_EXISTS:
120                                 message = String.Format ("Could not create file \"{0}\". File already exists.", path);
121                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
122
123                         case MonoIOError.ERROR_FILENAME_EXCED_RANGE:
124                                 message = String.Format ("Path is too long. Path: {0}", path); 
125                                 return new PathTooLongException (message);
126
127                         case MonoIOError.ERROR_INVALID_PARAMETER:
128                                 message = String.Format ("Invalid parameter");
129                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
130
131                         case MonoIOError.ERROR_WRITE_FAULT:
132                                 message = String.Format ("Write fault on path {0}", path);
133                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
134
135                         case MonoIOError.ERROR_SHARING_VIOLATION:
136                                 message = String.Format ("Sharing violation on path {0}", path);
137                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
138                                 
139                         case MonoIOError.ERROR_LOCK_VIOLATION:
140                                 message = String.Format ("Lock violation on path {0}", path);
141                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
142                         
143                         case MonoIOError.ERROR_HANDLE_DISK_FULL:
144                                 message = String.Format ("Disk full. Path {0}", path);
145                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
146                         
147                         case MonoIOError.ERROR_DIR_NOT_EMPTY:
148                                 message = String.Format ("Directory {0} is not empty", path);
149                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
150
151                         case MonoIOError.ERROR_ENCRYPTION_FAILED:
152                                 return new IOException ("Encryption failed", unchecked((int)0x80070000) | (int)error);
153
154                         case MonoIOError.ERROR_CANNOT_MAKE:
155                                 message = String.Format ("Path {0} is a directory", path);
156                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
157                                 
158                         case MonoIOError.ERROR_NOT_SAME_DEVICE:
159                                 message = "Source and destination are not on the same device";
160                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
161                                 
162                         default:
163                                 message = String.Format ("Win32 IO returned {0}. Path: {1}", error, path);
164                                 return new IOException (message, unchecked((int)0x80070000) | (int)error);
165                         }
166                 }
167
168                 // directory methods
169
170                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
171                 public extern static bool CreateDirectory (string path, out MonoIOError error);
172
173                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
174                 public extern static bool RemoveDirectory (string path, out MonoIOError error);
175
176                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
177                 public extern static string [] GetFileSystemEntries (string path, string path_with_pattern, int attrs, int mask, out MonoIOError error);
178
179                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
180                 public extern static string GetCurrentDirectory (out MonoIOError error);
181
182                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
183                 public extern static bool SetCurrentDirectory (string path, out MonoIOError error);
184
185                 // file methods
186
187                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
188                 public extern static bool MoveFile (string path, string dest,
189                                                     out MonoIOError error);
190
191                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
192                 public extern static bool CopyFile (string path, string dest,
193                                                     bool overwrite,
194                                                     out MonoIOError error);
195
196                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
197                 public extern static bool DeleteFile (string path,
198                                                       out MonoIOError error);
199
200                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
201                 public extern static bool ReplaceFile (string sourceFileName, 
202                                                        string destinationFileName, 
203                                                        string destinationBackupFileName, 
204                                                        bool ignoreMetadataErrors,
205                                                        out MonoIOError error);
206
207                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
208                 public extern static FileAttributes GetFileAttributes (string path, out MonoIOError error);
209
210                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
211                 public extern static bool SetFileAttributes (string path, FileAttributes attrs, out MonoIOError error);
212
213                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
214                 public extern static MonoFileType GetFileType (IntPtr handle, out MonoIOError error);
215
216                 //
217                 // Find file methods
218                 //
219                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
220                 public extern static string FindFirst (string path, string pattern, out FileAttributes result_attr, out MonoIOError error, out IntPtr handle);
221                 
222                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
223                 public extern static string FindNext (IntPtr handle, out FileAttributes result_attr, out MonoIOError error);
224                 
225                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
226                 public extern static int FindClose (IntPtr handle);
227                 
228                 public static bool Exists (string path, out MonoIOError error)
229                 {
230                         FileAttributes attrs = GetFileAttributes (path,
231                                                                   out error);
232                         if (attrs == InvalidFileAttributes)
233                                 return false;
234
235                         return true;
236                 }
237
238                 public static bool ExistsFile (string path,
239                                                out MonoIOError error)
240                 {
241                         FileAttributes attrs = GetFileAttributes (path,
242                                                                   out error);
243                         if (attrs == InvalidFileAttributes)
244                                 return false;
245
246                         if ((attrs & FileAttributes.Directory) != 0)
247                                 return false;
248
249                         return true;
250                 }
251
252                 public static bool ExistsDirectory (string path,
253                                                     out MonoIOError error)
254                 {
255                         FileAttributes attrs = GetFileAttributes (path,
256                                                                   out error);
257                                                                   
258                         // Actually, we are looking for a directory, not a file
259                         if (error == MonoIOError.ERROR_FILE_NOT_FOUND)
260                                 error = MonoIOError.ERROR_PATH_NOT_FOUND;
261                                 
262                         if (attrs == InvalidFileAttributes)
263                                 return false;
264
265                         if ((attrs & FileAttributes.Directory) == 0)
266                                 return false;
267
268                         return true;
269                 }
270
271                 public static bool ExistsSymlink (string path,
272                                                   out MonoIOError error)
273                 {
274                         FileAttributes attrs = GetFileAttributes (path,
275                                                                   out error);
276                         if (attrs == InvalidFileAttributes)
277                                 return false;
278                         
279                         if ((attrs & FileAttributes.ReparsePoint) == 0)
280                                 return false;
281
282                         return true;
283                 }
284
285                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
286                 public extern static bool GetFileStat (string path,
287                                                        out MonoIOStat stat,
288                                                        out MonoIOError error);
289
290                 // handle methods
291
292                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
293                 public extern static IntPtr Open (string filename,
294                                                   FileMode mode,
295                                                   FileAccess access,
296                                                   FileShare share,
297                                                   FileOptions options,
298                                                   out MonoIOError error);
299                 
300                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
301                 public extern static bool Close (IntPtr handle,
302                                                  out MonoIOError error);
303                 
304                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
305                 public extern static int Read (IntPtr handle, byte [] dest,
306                                                int dest_offset, int count,
307                                                out MonoIOError error);
308                 
309                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
310                 public extern static int Write (IntPtr handle, [In] byte [] src,
311                                                 int src_offset, int count,
312                                                 out MonoIOError error);
313                 
314                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
315                 public extern static long Seek (IntPtr handle, long offset,
316                                                 SeekOrigin origin,
317                                                 out MonoIOError error);
318                 
319                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
320                 public extern static bool Flush (IntPtr handle,
321                                                  out MonoIOError error);
322
323                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
324                 public extern static long GetLength (IntPtr handle,
325                                                      out MonoIOError error);
326
327                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
328                 public extern static bool SetLength (IntPtr handle,
329                                                      long length,
330                                                      out MonoIOError error);
331
332                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
333                 public extern static bool SetFileTime (IntPtr handle,
334                                                        long creation_time,
335                                                        long last_access_time,
336                                                        long last_write_time,
337                                                        out MonoIOError error);
338
339                 public static bool SetFileTime (string path,
340                                                 long creation_time,
341                                                 long last_access_time,
342                                                 long last_write_time,
343                                                 out MonoIOError error)
344                 {
345                         return SetFileTime (path,
346                                 0,
347                                 creation_time,
348                                 last_access_time,
349                                 last_write_time,
350                                 DateTime.MinValue,
351                                 out error);
352                 }
353
354                 public static bool SetCreationTime (string path,
355                                                 DateTime dateTime,
356                                                 out MonoIOError error)
357                 {
358                         return SetFileTime (path, 1, -1, -1, -1, dateTime, out error);
359                 }
360
361                 public static bool SetLastAccessTime (string path,
362                                                 DateTime dateTime,
363                                                 out MonoIOError error)
364                 {
365                         return SetFileTime (path, 2, -1, -1, -1, dateTime, out error);
366                 }
367
368                 public static bool SetLastWriteTime (string path,
369                                                 DateTime dateTime,
370                                                 out MonoIOError error)
371                 {
372                         return SetFileTime (path, 3, -1, -1, -1, dateTime, out error);
373                 }
374
375                 public static bool SetFileTime (string path,
376                                                 int type,
377                                                 long creation_time,
378                                                 long last_access_time,
379                                                 long last_write_time,
380                                                 DateTime dateTime,
381                                                 out MonoIOError error)
382                 {
383                         IntPtr handle;
384                         bool result;
385
386                         handle = Open (path, FileMode.Open,
387                                        FileAccess.ReadWrite,
388                                        FileShare.ReadWrite, FileOptions.None, out error);
389                         if (handle == MonoIO.InvalidHandle)
390                                 return false;
391
392                         switch (type) {
393                         case 1:
394                                 creation_time = dateTime.ToFileTime ();
395                                 break;
396                         case 2:
397                                 last_access_time = dateTime.ToFileTime ();
398                                 break;
399                         case 3:
400                                 last_write_time = dateTime.ToFileTime ();
401                                 break;
402                         }
403
404                         result = SetFileTime (handle, creation_time,
405                                               last_access_time,
406                                               last_write_time, out error);
407
408                         MonoIOError ignore_error;
409                         Close (handle, out ignore_error);
410                         
411                         return result;
412                 }
413
414                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
415                 public extern static void Lock (IntPtr handle,
416                                                 long position, long length,
417                                                 out MonoIOError error);
418
419                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
420                 public extern static void Unlock (IntPtr handle,
421                                                   long position, long length,
422                                                   out MonoIOError error);
423
424                 // console handles
425
426                 public extern static IntPtr ConsoleOutput {
427                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
428                         get;
429                 }
430
431                 public extern static IntPtr ConsoleInput {
432                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
433                         get;
434                 }
435
436                 public extern static IntPtr ConsoleError {
437                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
438                         get;
439                 }
440
441                 // pipe handles
442
443                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
444                 public extern static bool CreatePipe (out IntPtr read_handle, out IntPtr write_handle);
445
446                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
447                 public extern static bool DuplicateHandle (IntPtr source_process_handle, IntPtr source_handle,
448                         IntPtr target_process_handle, out IntPtr target_handle, int access, int inherit, int options);
449
450                 // path characters
451
452                 public extern static char VolumeSeparatorChar {
453                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
454                         get;
455                 }
456
457                 public extern static char DirectorySeparatorChar {
458                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
459                         get;
460                 }
461
462                 public extern static char AltDirectorySeparatorChar {
463                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
464                         get;
465                 }
466
467                 public extern static char PathSeparator {
468                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
469                         get;
470                 }
471
472                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
473                 public extern static int GetTempPath(out string path);
474         }
475 }
476