In .:
[mono.git] / mcs / class / Microsoft.VisualBasic / Microsoft.VisualBasic / FileSystem.cs
1 /*
2  * Copyright (c) 2002-2003 Mainsoft Corporation.
3  * Copyright (C) 2004 Novell, Inc (http://www.novell.com)
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  * 
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  * 
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23  
24
25 using System;
26 using System.IO;
27 using System.Text;
28 using System.Collections;
29 using System.Globalization;
30 using Microsoft.VisualBasic;
31 using System.Runtime.InteropServices;
32 using Microsoft.VisualBasic.CompilerServices;
33
34 #if ONLY_1_1
35 using DefaultParameterValueAttribute = Microsoft.VisualBasic.CompilerServices.__DefaultParameterValueAttribute;
36 #endif
37
38 /**
39  * CURRENT LIMITATIONS
40  * @limit TAB(int) - not supported.
41  * @limit not all file attributes are supported. supported are: Hidden, Directory, ReadOnly
42  * @limit ChDir(..) - not supported.
43  * @limit ChDrive - not supported.
44  * @limit CurDir(Char) - ignores the parameter.
45  */
46
47 namespace Microsoft.VisualBasic
48 {
49         [StandardModule]
50         sealed public class FileSystem
51         {
52                 private FileSystem () {}
53
54                 private static Hashtable _fileNameIdMap = new Hashtable();
55                 private static Hashtable _openFilesMap = new Hashtable();
56                 private static Hashtable _randomRecordLength = new Hashtable();
57
58                 static String _pattern;
59                 static int _fileAttrs;
60                 private static int _fileIndex;
61                 private static FileInfo[] _files;
62                 private static bool _isEndOfFiles = true;
63
64
65                 public static void Reset()
66                 {
67                         ICollection s = _openFilesMap.Keys;
68
69                         int [] iArr = new int[s.Count];
70                         s.CopyTo(iArr, 0);
71                         close(iArr);
72                 }
73
74                 public static void FileClose(params int[] fileNumbers)
75                 {
76                         int[] iArr = null;
77                         if (fileNumbers == null || fileNumbers.Length == 0)
78                         {
79                                 ICollection keySet = FileSystem._openFilesMap.Keys;
80                                 iArr = new int[keySet.Count];
81                                 keySet.CopyTo(iArr, 0);
82                         }
83                         else
84                         {
85                                 iArr = new int[fileNumbers.Length];
86                                 for (int i = 0; i < fileNumbers.Length; i++)
87                                         iArr[i] = fileNumbers[i];
88                         }
89                         close(iArr);
90                 }
91
92                 private static void close(int [] keys)
93                 {
94                         Object obj;
95
96                         for (int i = 0; i < keys.Length; i++)
97                         {
98                                 if (keys[i] < 0 || keys[i] > 255)
99                                 {
100                                         ExceptionUtils.VbMakeException(
101                                                                        VBErrors.IllegalFuncCall);
102                                         throw new ArgumentOutOfRangeException();
103                                 }
104                                 obj = _openFilesMap[keys[i]];
105
106                                 if (obj == null)
107                                 {
108                                         String message = VBUtils.GetResourceString(52);
109                                         throw (IOException)VBUtils.VBException(new IOException(message), 52);
110                                 }
111                                 String fileName = null;
112                                 if (obj is VBFile)
113                                 {
114                                         ((VBFile)obj).closeFile();
115                                         fileName = ((VBFile)obj).getFullPath();
116                                 }
117
118
119                                 _openFilesMap.Remove(keys[i]);
120                                 _fileNameIdMap.Remove(fileName);
121                         }
122                 }
123
124                 public static void FileOpen(
125                                             int fileNumber,
126                                             String fileName,
127                                             OpenMode mode,
128                                             [Optional, __DefaultParameterValue((int)(-1))] OpenAccess access, 
129                                             [Optional, __DefaultParameterValue((int)(-1))] OpenShare share, 
130                                             [Optional, DefaultParameterValue(-1)] int recordLength)
131
132                 {
133                         if (!isFileNumberFree(fileNumber))
134                                 throw ExceptionUtils.VbMakeException(VBErrors.FileAlreadyOpen);
135                         if (fileNumber < 0 || fileNumber > 255)
136                                 throw ExceptionUtils.VbMakeException(VBErrors.BadFileNameOrNumber);
137                         if (recordLength != -1 && recordLength <= 0)
138                                 throw ExceptionUtils.VbMakeException(VBErrors.IllegalFuncCall);
139                         if (share != OpenShare.Shared && _fileNameIdMap.ContainsKey(Path.GetFullPath(string.Intern(fileName))))
140                                 throw ExceptionUtils.VbMakeException(VBErrors.FileAlreadyOpen);
141                         if (mode == OpenMode.Input)
142                         {
143                                 VBFile vbFile = new InputVBFile(fileName, (FileAccess) access,(recordLength == -1)? 4096:recordLength);
144                                 _openFilesMap.Add(fileNumber, vbFile);
145                         }
146                         else if (mode == OpenMode.Output || mode == OpenMode.Append)
147                         {
148                                 VBFile vbFile = new OutPutVBFile(fileName,mode,access,recordLength);
149                                 _openFilesMap.Add(fileNumber, vbFile);
150                         }
151                         else if (mode == OpenMode.Random)
152                         {
153                                 VBFile vbFile = new RandomVBFile(fileName,mode,access,recordLength);
154                                 _openFilesMap.Add(fileNumber, vbFile);
155                         }
156                         else if (mode == OpenMode.Binary)
157                         {
158                                 VBFile vbFile = new BinaryVBFile(fileName,mode,access,recordLength);
159                                 _openFilesMap.Add(fileNumber, vbFile);
160                         }
161                         if (share != OpenShare.Shared && !_fileNameIdMap.ContainsKey(Path.GetFullPath(string.Intern(fileName))))
162                                 _fileNameIdMap.Add(Path.GetFullPath(string.Intern(fileName)),fileNumber);
163                 }
164
165                 public static void FilePut(int fileNumber,
166                                            bool value,
167                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
168                 {
169                         checkRecordNumber(recordNumber,false);
170                         VBFile vbFile = getVBFile(fileNumber);
171                         vbFile.put(value,recordNumber);
172                 }
173
174
175                 public static void FilePut(int fileNumber, 
176                                            byte value, 
177                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
178                 {
179                         checkRecordNumber(recordNumber,false);
180                         VBFile vbFile = getVBFile(fileNumber);
181                         vbFile.put(value,recordNumber);
182                 }
183
184                 public static void FilePut(int fileNumber, 
185                                            short value, 
186                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
187                 {
188                         checkRecordNumber(recordNumber,false);
189                         VBFile vbFile = getVBFile(fileNumber);
190                         vbFile.put(value,recordNumber);
191                 }
192
193
194                 public static void FilePut(int fileNumber, 
195                                            char value, 
196                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
197                 {
198                         checkRecordNumber(recordNumber,false);
199                         VBFile vbFile = getVBFile(fileNumber);
200                         vbFile.put(value,recordNumber);
201                 }
202
203                 public static void FilePut(int fileNumber, 
204                                            int value, 
205                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
206                 {
207                         checkRecordNumber(recordNumber,false);
208                         VBFile vbFile = getVBFile(fileNumber);
209                         vbFile.put(value,recordNumber);
210                 }
211
212                 public static void FilePut(int fileNumber, 
213                                            long value, 
214                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
215                 {
216                         checkRecordNumber(recordNumber,false);
217                         VBFile vbFile = getVBFile(fileNumber);
218                         vbFile.put(value,recordNumber);
219                 }
220
221
222                 public static void FilePut(int fileNumber, 
223                                            float value, 
224                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
225                 {
226                         checkRecordNumber(recordNumber,false);
227                         VBFile vbFile = getVBFile(fileNumber);
228                         vbFile.put(value,recordNumber);
229                 }
230
231                 public static void FilePut(int fileNumber, 
232                                            double value, 
233                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
234                 {
235                         checkRecordNumber(recordNumber,false);
236                         VBFile vbFile = getVBFile(fileNumber);
237                         vbFile.put(value,recordNumber);
238                 }
239
240                 public static void FilePut(int fileNumber,
241                                            String value,
242                                            [Optional, DefaultParameterValue((long)-1)] long recordNumber,
243                                            [Optional, DefaultParameterValue(false)] bool stringIsFixedLength)
244                 {
245                         checkRecordNumber(recordNumber,true);
246                         VBFile vbFile = getVBFile(fileNumber);
247                         vbFile.put(value,recordNumber,stringIsFixedLength);
248                 }
249
250                 public static void FilePut(int fileNumber,
251                                            DateTime value,
252                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
253                 {
254                         checkRecordNumber(recordNumber,false);
255                         VBFile vbFile = getVBFile(fileNumber);
256                         vbFile.put(value,recordNumber);
257                 }
258
259                 private static void checkRecordNumber(long recordNumber,bool throwArgExc)
260                 {
261                         if ((recordNumber < 1) && (recordNumber != -1))
262                         {
263                                 if (!throwArgExc)
264                                         throw (IOException) ExceptionUtils.VbMakeException(
265                                                                                            new ArgumentException(
266                                                                                                                  Utils.GetResourceString(
267                                                                                                                                          "Argument_InvalidValue1",
268                                                                                                                                          "RecordNumber")),
269                                                                                            VBErrors.BadRecordNum);
270                                 else
271                                 {
272                                         ExceptionUtils.VbMakeException(VBErrors.BadRecordNum);
273                                         throw new ArgumentException(
274                                                                     Utils.GetResourceString(
275                                                                                             "Argument_InvalidValue1",
276                                                                                             "RecordNumber"));
277                                 }
278
279                         }
280                 }
281
282                 private static VBFile getVBFile(int fileNumber)
283                 {
284                         if ((fileNumber < 1) || (fileNumber > 255))
285                                 throw (IOException) ExceptionUtils.VbMakeException(
286                                                                                    VBErrors.BadFileNameOrNumber);
287                         Object obj = _openFilesMap[fileNumber];
288                         if (obj == null)
289                                 throw (IOException) ExceptionUtils.VbMakeException(
290                                                                                    VBErrors.BadFileNameOrNumber);
291                         return (VBFile)obj;
292                 }
293
294                 private static VBFile getVBFile(String pathName)
295                 {
296                         object o = _fileNameIdMap[pathName];
297                         int fileNumber = o == null ? 0 : (int) o ;
298                         if (fileNumber == 0)
299                                 throw (IOException) ExceptionUtils.VbMakeException(
300                                                                                    VBErrors.BadFileNameOrNumber);
301                         Object obj = _openFilesMap[fileNumber];
302                         if (obj == null)
303                                 throw (IOException) ExceptionUtils.VbMakeException(
304                                                                                    VBErrors.BadFileNameOrNumber);
305                         return (VBFile)obj;
306                 }
307
308                 public static void FileGet(
309                                 int fileNumber,
310                                 ref byte value,
311                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
312
313                 {
314                         checkRecordNumber(recordNumber,false);
315                         VBFile vbFile = getVBFile(fileNumber);
316                         vbFile.get(out value,recordNumber);
317                 }
318
319                 public static void FileGet(
320                                 int fileNumber,
321                                 ref bool value,
322                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
323
324                 {
325                         checkRecordNumber(recordNumber,false);
326                         VBFile vbFile = getVBFile(fileNumber);
327                         vbFile.get(out value,recordNumber);
328                 }
329
330                 public static void FileGet(
331                                 int fileNumber,
332                                 ref short value,
333                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
334
335                 {
336                         checkRecordNumber(recordNumber,false);
337                         VBFile vbFile = getVBFile(fileNumber);
338                         vbFile.get(out value,recordNumber);
339                 }
340
341                 public static void FileGet(
342                                 int fileNumber,
343                                 ref char value,
344                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
345
346
347                 {
348                         checkRecordNumber(recordNumber,false);
349                         VBFile vbFile = getVBFile(fileNumber);
350                         vbFile.get(out value,recordNumber);
351                 }
352
353
354                 public static void FileGet(
355                                 int fileNumber, 
356                                 ref int value,
357                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
358                 {
359                         checkRecordNumber(recordNumber,false);
360                         VBFile vbFile = getVBFile(fileNumber);
361                         vbFile.get(out value,recordNumber);
362                 }
363
364                 public static void FileGet(
365                                 int fileNumber, 
366                                 ref long value, 
367                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
368                 {
369                         checkRecordNumber(recordNumber,false);
370                         VBFile vbFile = getVBFile(fileNumber);
371                         vbFile.get(out value,recordNumber);
372                 }
373
374                 public static void FileGet(
375                                 int fileNumber,
376                                 ref float value,
377                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
378                 {
379                         checkRecordNumber(recordNumber,false);
380                         VBFile vbFile = getVBFile(fileNumber);
381                         vbFile.get(out value,recordNumber);
382                 }
383
384                 public static void FileGet(
385                                 int fileNumber,
386                                 ref double value,
387                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
388                                            
389                 {
390                         checkRecordNumber(recordNumber,false);
391                         VBFile vbFile = getVBFile(fileNumber);
392                         vbFile.get(out value,recordNumber);
393                 }
394
395                 public static void FileGet(
396                                 int fileNumber,
397                                 ref Decimal value,
398                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
399                                            
400                 {
401                         checkRecordNumber(recordNumber,false);
402                         VBFile vbFile = getVBFile(fileNumber);
403                         vbFile.get(out value,recordNumber);
404                 }
405
406                 public static void FileGet(
407                                 int fileNumber,
408                                 ref string value,
409                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber,
410                                 [Optional, DefaultParameterValue(false)] bool stringIsFixedLength)
411                 {
412                         checkRecordNumber(recordNumber,true);
413                         VBFile vbFile = getVBFile(fileNumber);
414                         vbFile.get(ref value,recordNumber,stringIsFixedLength);
415                 }
416
417                 public static void FileGet(
418                                 int fileNumber,
419                                 ref DateTime value,
420                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber)
421
422                 {
423                         checkRecordNumber(recordNumber,true);
424                         VBFile vbFile = getVBFile(fileNumber);
425                         vbFile.get(out value,recordNumber);
426                 }
427
428                 [MonoTODO]
429                 public static void FileGet(
430                                 int fileNumber, 
431                                 ref ValueType value, 
432                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
433                 {
434                         throw new NotImplementedException();
435                 }
436
437                 public static void FileGet(
438                                 int fileNumber,
439                                 ref Array value,
440                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber, 
441                                 [Optional, DefaultParameterValue(false)] bool arrayIsDynamic, 
442                                 [Optional, DefaultParameterValue(false)] bool stringIsFixedLength) 
443                 {
444                         checkRecordNumber(recordNumber,true);
445                         VBFile vbFile = getVBFile(fileNumber);
446                         vbFile.get(ref value,recordNumber,arrayIsDynamic,stringIsFixedLength);
447                 }
448
449                 public static long Seek(int fileNumber)
450                 {
451                         VBFile vbFile = getVBFile(fileNumber);
452                         return vbFile.seek();
453                 }
454
455                 public static void Seek(int fileNumber, long position)
456                 {
457                         VBFile vbFile = getVBFile(fileNumber);
458                         vbFile.seek(position);
459
460                 }
461
462                 public static long Loc(int fileNumber)
463                 {
464                         VBFile vbFile = getVBFile(fileNumber);
465                         return vbFile.getPosition();
466                 }
467
468                 public static long LOF(int fileNumber)
469                 {
470                         VBFile vbFile = getVBFile(fileNumber);
471                         return vbFile.getLength();
472                 }
473
474                 public static void Input(int fileNumber, ref Object value)
475                 {
476                         VBFile vbFile = getVBFile(fileNumber);
477                         if (value != null)
478                         {
479                                 if (value is bool) {
480                                         bool tmp;
481                                         vbFile.Input(out tmp);
482                                         value = tmp;
483                                 }
484                                 else if (value is byte) {
485                                         byte tmp;
486                                         vbFile.Input(out tmp);
487                                         value = tmp;
488                                 }
489                                 else if (value is char) {
490                                         char tmp;
491                                         vbFile.Input(out tmp);
492                                         value = tmp;
493                                 }
494                                 else if (value is double) {
495                                         double tmp;
496                                         vbFile.Input(out tmp);
497                                         value = tmp;
498                                 }
499                                 else if (value is short) {
500                                         short tmp;
501                                         vbFile.Input(out tmp);
502                                         value = tmp;
503                                 }
504                                 else if (value is int) {
505                                         int tmp;
506                                         vbFile.Input(out tmp);
507                                         value = tmp;
508                                 }
509                                 else if (value is long) {
510                                         long tmp;
511                                         vbFile.Input(out tmp);
512                                         value = tmp;
513                                 }
514                                 else if (value is float) {
515                                         float tmp;
516                                         vbFile.Input(out tmp);
517                                         value = tmp;
518                                 }
519                                 else if (value is Decimal) {
520                                         Decimal tmp;
521                                         vbFile.Input(out tmp);
522                                         value = tmp;
523                                 }
524                                 else if (value is string)
525                                         vbFile.Input((string)value);
526                                 // Come back to it later
527                                 //                      else if (type.get_IsByRef())
528                                 //                              vbFile.Input((ObjectRefWrapper)value[i],false);
529
530                         }
531                 }
532
533                 public static String InputString(int fileNumber, int count)
534                 {
535                         if (count < 0)
536                                 throw (ArgumentException)ExceptionUtils.VbMakeException(VBErrors.IllegalFuncCall);
537                         VBFile vbFile = getVBFile(fileNumber);
538                         if (vbFile.getLength()- vbFile.getPosition() < count)
539                                 throw (EndOfStreamException)ExceptionUtils.VbMakeException(VBErrors.EndOfFile);
540                         return vbFile.InputString(count);
541                 }
542
543                 public static String LineInput(int fileNumber)
544                 {
545                         VBFile vbFile = getVBFile(fileNumber);
546
547                         if (EOF(fileNumber))
548                                 throw new EndOfStreamException("Input past end of file.");
549
550                         return vbFile.readLine();
551                 }
552
553                 public static void Print(int fileNumber, params Object[] output)
554                 {
555                         VBFile vbFile = getVBFile(fileNumber);
556                         vbFile.print(output);
557                 }
558
559 // Seems not to exist in MS's 1.1 implementation as told by class status pages
560 //              public static void PrintLine(int fileNumber)
561 //              {
562 //                      VBFile vbFile = getVBFile(fileNumber);
563 //                      vbFile.printLine(null);
564 //              }
565
566                 public static void PrintLine(int fileNumber, params Object[] output)
567                 {
568                         VBFile vbFile = getVBFile(fileNumber);
569                         vbFile.printLine(output);
570                 }
571
572                 public static void Write(int fileNumber, params Object[] output)
573                 {
574                         VBFile vbFile = getVBFile(fileNumber);
575                         vbFile.write(output);
576                 }
577
578                 public static void WriteLine(int fileNumber, params Object[] output)
579                 {
580                         VBFile vbFile = getVBFile(fileNumber);
581                         vbFile.writeLine(output);
582                 }
583
584                 public static void Rename(String oldPath, String newPath)
585                 {
586                         FileInfo file = new FileInfo(newPath);
587                         if (file.Exists)
588                                 throw (IOException) ExceptionUtils.VbMakeException(
589                                                                                    VBErrors.FileAlreadyExists);
590                         try
591                         {
592                                 File.Move(oldPath, newPath);
593                         }catch (Exception e){
594                                 throw (ArgumentException)ExceptionUtils.VbMakeException(VBErrors.IllegalFuncCall);
595                         }
596                 }
597
598                 public static void FileCopy(String source, String destination)
599                 {
600                         DirectoryInfo dir;
601
602                         if ((source == null) || (source.Length == 0))
603                         {
604                                 ExceptionUtils.VbMakeException(VBErrors.BadFileNameOrNumber);
605                                 throw new ArgumentException(
606                                                             Utils.GetResourceString("Argument_PathNullOrEmpty"));
607                         }
608
609
610                         if ((destination == null) || (destination.Length == 0))
611                         {
612                                 ExceptionUtils.VbMakeException(VBErrors.BadFileNameOrNumber);
613                                 throw new ArgumentException(
614                                                             Utils.GetResourceString("Argument_PathNullOrEmpty"));
615                         }
616
617                         FileInfo f = new FileInfo(source);
618                         if (!f.Exists)
619                                 throw (FileNotFoundException) ExceptionUtils.VbMakeException(
620                                                                                              VBErrors.FileNotFound);
621                         if (_fileNameIdMap[source] != null)
622                                 throw (IOException) ExceptionUtils.VbMakeException(
623                                                                                    VBErrors.FileAlreadyOpen);
624                         int lastIndex = destination.LastIndexOf('/');
625
626                         if(lastIndex == -1)
627                                 dir = new DirectoryInfo(".");
628                         else
629                                 dir = new DirectoryInfo(destination.Substring(0,lastIndex));
630
631                         if (!dir.Exists)
632                         {
633                                 ExceptionUtils.VbMakeException(VBErrors.FileAlreadyOpen);
634                                 throw new DirectoryNotFoundException();
635                         }
636
637                         // the file name length is 0
638                         if (destination.Length == lastIndex +1)
639                         {
640                                 throw (IOException)ExceptionUtils.VbMakeException(VBErrors.FileAlreadyOpen);
641
642                         }
643
644 /*
645                         f = new FileInfo(destination);
646                         if (f.Exists)
647                                 throw (IOException) ExceptionUtils.VbMakeException(
648                                                                                    VBErrors.FileAlreadyExists);
649 */
650
651                         File.Copy(source, destination, true);
652                 }
653
654                 public static void MkDir(String path)
655                 {
656                         if ((path == null) || (path.Length == 0))
657                         {
658                                 ExceptionUtils.VbMakeException(VBErrors.BadFileNameOrNumber);
659                                 throw new ArgumentException(
660                                                             Utils.GetResourceString("Argument_PathNullOrEmpty"));
661                         }
662                         if (Directory.Exists(path))
663                                 throw (IOException) ExceptionUtils.VbMakeException(
664                                                                                    VBErrors.PathFileAccess);
665
666                         Directory.CreateDirectory(path);
667                 }
668
669                 public static void Kill(String pathName)
670                 {
671                         if (_fileNameIdMap[pathName] != null)
672                                 throw (IOException) ExceptionUtils.VbMakeException(
673                                                                                    VBErrors.FileAlreadyOpen);
674                         if (!File.Exists(pathName))
675                                 throw (IOException) ExceptionUtils.VbMakeException(
676                                                                                    VBErrors.FileNotFound);
677                         File.Delete(pathName);
678                 }
679
680                 public static void RmDir(String pathName)
681                 {
682                         if (pathName == null || pathName.Length == 0 )
683                         {
684                                 ExceptionUtils.VbMakeException(VBErrors.BadFileNameOrNumber);
685                                 throw new ArgumentException(pathName);
686                         }
687                         DirectoryInfo dir = new DirectoryInfo(pathName);
688                         if (!dir.Exists)
689                         {
690                                 ExceptionUtils.VbMakeException(VBErrors.PathNotFound);
691                                 throw new DirectoryNotFoundException();
692                         }
693                         if (dir.GetFiles().Length != 0)
694                                 throw (IOException) ExceptionUtils.VbMakeException(
695                                                                                    VBErrors.PathFileAccess);
696                         Directory.Delete(pathName);
697                 }
698
699                 public static FileAttribute  GetAttr(String pathName)
700                 {
701                         if (pathName == null || pathName.Length == 0 ||
702                             pathName.IndexOf('*') != -1 || pathName.IndexOf('?') != -1)
703                         {
704                                 throw (IOException)ExceptionUtils.VbMakeException(VBErrors.BadFileNameOrNumber);
705                         }
706                         //              File f = new File(pathName);
707                         //              if (!f.exists())
708                         //                      throw (FileNotFoundException)
709                         //                              ExceptionUtils.VbMakeException(VBErrors.FileNotFound);
710                         return (FileAttribute) File.GetAttributes(pathName);
711                 }
712
713                 public static void SetAttr(String pathName, FileAttribute fileAttr)
714                 {
715                         if (pathName == null || pathName.Length == 0 ||
716                             pathName.IndexOf('*') != -1 || pathName.IndexOf('?') != -1)
717                         {
718                                 throw (ArgumentException)ExceptionUtils.VbMakeException(VBErrors.IllegalFuncCall);
719                         }
720                         FileInfo f = new FileInfo(pathName);
721                         if (!f.Directory.Exists)
722                         {
723                                 ExceptionUtils.VbMakeException(VBErrors.PathNotFound);
724                                 throw new DirectoryNotFoundException();
725                         }
726                         if (!f.Exists)
727                         {
728                                 throw (FileNotFoundException)
729                                         ExceptionUtils.VbMakeException(VBErrors.FileNotFound);
730                         }
731
732                         try
733                         {
734                                 File.SetAttributes(pathName, (FileAttributes)fileAttr);
735                         }
736                         catch (ArgumentException e)
737                         {
738                                 throw (ArgumentException) ExceptionUtils.VbMakeException(
739                                                                                          VBErrors.IllegalFuncCall);
740                         }
741                         catch (DirectoryNotFoundException ex)
742                         {
743                                 ExceptionUtils.VbMakeException(VBErrors.PathNotFound);
744                                 throw ex;
745                         }
746                         catch (FileNotFoundException ex)
747                         {
748                                 throw (FileNotFoundException)
749                                         ExceptionUtils.VbMakeException(VBErrors.FileNotFound);
750                         }
751
752                 }
753
754
755                 public static /*synchronized*/ String Dir(String pathName, 
756                                                           [Optional, __DefaultParameterValue((int)0)] 
757                                                           FileAttribute fileAttribute)
758                 {
759                         _fileIndex = 0;
760                         _files = null;
761                         _pattern = null;
762
763                         _fileAttrs = (int)fileAttribute;
764
765                         if (pathName == null || pathName.Equals(""))
766                         {
767                                 return "";
768                         }
769
770                         if (FileAttribute.Volume == fileAttribute)
771                                 return "";
772
773
774                         int lastBabkSlashInx = pathName.LastIndexOf('\\');
775                         int lastSlashInx = pathName.LastIndexOf('/');
776                         int maxIndex = (lastSlashInx>lastBabkSlashInx)?lastSlashInx:lastBabkSlashInx; 
777                         String dir = pathName.Substring(0, maxIndex + 1);
778                         String fileName = pathName.Substring(1 + maxIndex);
779                         if (fileName == null || fileName.Length == 0)
780                                 fileName = "*";
781
782                         //        int astricsInx = fileName.indexOf('*');
783                         //        int questionInx = fileName.indexOf('?');
784
785                         //        String pattern;
786                         DirectoryInfo directory = new DirectoryInfo(dir);
787                         //      java.io.File directory = new java.io.File(dir);
788                         //              java.io.File file;
789                         if (!directory.Exists)
790                         {
791                                 // path not found - return empty string
792                                 return "";
793                         }
794
795                         //        if (astricsInx == -1 && questionInx == -1)
796                         //        {
797                         //            pattern = fileName;
798                         //        }
799                         //        else
800                         //        {
801                         //            pattern = Strings.Replace(fileName, ".", "\\.", 1, -1, CompareMethod.Binary);
802                         //            pattern = Strings.Replace(pattern, "*", ".*", 1, -1, CompareMethod.Binary);
803                         //            pattern = Strings.Replace(pattern, "?", ".?", 1, -1, CompareMethod.Binary);
804                         //        }
805
806                         _pattern = fileName;
807                         //        _pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
808
809                         _files = directory.GetFiles(_pattern);
810                         String answer;
811                         if (_files == null || _files.Length == 0)
812                         {
813                                 DirectoryInfo[] dirs = directory.GetDirectories(_pattern);
814                                 if (dirs == null || dirs.Length == 0)
815                                 {
816                                         return "";
817                                 }
818                                 answer = dirs[0].Name;            
819                         }
820                         else
821                         {   
822                                 answer = _files[0].Name;
823                         }   
824
825                         _fileIndex++;
826                         _isEndOfFiles = false;
827
828
829                         return answer;
830
831                 }
832
833                 public static /*synchronized*/ String Dir()
834                 {
835                         String name;
836                         if (_files == null || _isEndOfFiles)
837                                 throw new /*Illegal*/ArgumentException("no path has been initiated");
838
839                         if (_fileIndex < _files.Length)
840                         {
841                                 name = _files[_fileIndex].Name;
842                                 _fileIndex++;
843                         }
844                         else
845                         {
846                                 _isEndOfFiles = true;
847                                 name = "";
848                         }
849
850                         return name;
851                 }
852
853                 public static DateTime FileDateTime(String pathName)
854                 {
855                         if (pathName == null || pathName.Length == 0 ||
856                             pathName.IndexOf('*') != -1 || pathName.IndexOf('?') != -1)
857                         {
858                                 ExceptionUtils.VbMakeException(VBErrors.BadFileNameOrNumber);
859                                 throw new ArgumentException(
860                                                             VBUtils.GetResourceString(
861                                                                                       "Argument_InvalidValue1",
862                                                                                       "PathName"));
863                         }
864                         FileInfo f = new FileInfo(pathName);
865                         if (!f.Exists)
866                         {
867                                 DirectoryInfo d = new DirectoryInfo(pathName);
868                                 if (!d.Exists)  
869                                         throw (FileNotFoundException)
870                                                 ExceptionUtils.VbMakeException(VBErrors.FileNotFound);
871                                 return d.LastWriteTime;
872                         }
873                         return f.LastWriteTime;
874                 }
875
876                 public static long FileLen(String pathName)
877                 {
878                         FileInfo f = new FileInfo(pathName);
879                         if (!f.Exists)
880                                 throw new FileNotFoundException(
881                                                                 "file not exists: " + pathName);
882
883                         return f.Length;
884                 }
885
886
887                 internal static String SPC(int count)
888                 {
889                         StringBuilder sb = new StringBuilder(count);
890                         for (int i = 0; i < count; i++)
891                                 sb.Append(' ');
892
893                         return sb.ToString();
894                 }
895
896                 public static int FreeFile()
897                 {
898                         ICollection s = _openFilesMap.Keys;
899
900                         if (s.Count == 0)
901                                 return 1;
902
903                         int [] keyArr = new int[s.Count];
904
905                         s.CopyTo(keyArr, 0);
906
907                         Array.Sort(keyArr);
908                         int i = 0;
909                         for (; i < keyArr.Length - 1; i++)
910                         {
911                                 if ((keyArr[i]+ 1) < keyArr[i + 1])
912                                         break;
913                         }
914
915                         int retVal = keyArr[i]+ 1;
916
917                         if (retVal > 255)
918                         {
919                                 String message = VBUtils.GetResourceString(67);
920                                 throw (IOException)VBUtils.VBException(
921                                                                        new IOException(message),
922                                                                        67);
923                         }
924
925                         return retVal;
926
927                 }
928
929                 public static bool EOF(int fileNumber)
930                 {
931                         VBFile vbFile = getVBFile(fileNumber);
932                         return vbFile.isEndOfFile();
933                 }
934
935                 // check if a specific number is free
936                 private static bool isFileNumberFree(int fileNumber)
937                 {
938                         return !_openFilesMap.ContainsKey(fileNumber);
939                 }
940
941                 [MonoTODO("If path is another drive, it should change the default folder for that drive, but not switch to it.")]
942                 public static void ChDir (string Path) 
943                 {
944                         if ((Path=="") || (Path==null))
945                                 throw new ArgumentException (Utils.GetResourceString ("Argument_PathNullOrEmpty")); 
946                         try {
947                                 Environment.CurrentDirectory = Path;
948                         }
949                         catch { 
950                                 throw new FileNotFoundException (Utils.GetResourceString ("FileSystem_PathNotFound1", Path));
951                         }
952                 }
953
954
955                 public static void ChDrive(char Drive)
956                 {
957 #if NET_2_0
958                         if (Environment.OSVersion.Platform == PlatformID.Unix)
959 #else
960                         if (Environment.OSVersion.Platform == (PlatformID) 128)
961 #endif
962                                 throw new InvalidOperationException("ChDrive function is not supported on this platform !");
963                         Drive = char.ToUpper(Drive, CultureInfo.InvariantCulture);
964                         if ((Drive < 65) || (Drive > 90))
965                         {
966                                 throw new ArgumentException(
967                                                             Utils.GetResourceString("Argument_InvalidValue1", "Drive"));
968                         }
969                         Directory.SetCurrentDirectory(String.Concat(StringType.FromChar(Drive), StringType.FromChar(Path.VolumeSeparatorChar)));
970                 }
971
972                 public static void ChDrive(String Drive)
973                 {
974                         if (Drive != null && Drive.Length != 0)
975                                 FileSystem.ChDrive(Drive[0]);
976                 }
977
978                 public static String CurDir()
979                 {
980                         return Environment.CurrentDirectory;
981                 }
982
983                 public static String CurDir(char Drive)
984                 {
985                         return Directory.GetCurrentDirectory();
986                 }
987
988                 [MonoTODO("How to deal with Array types?")]
989                 public static void FileGetObject(
990                                 int fileNumber,
991                                 ref object value,
992                                 [Optional, DefaultParameterValue((long)-1)] long recordNumber) 
993                 {
994                         checkRecordNumber(recordNumber,true);
995                         VBFile vbFile = getVBFile(fileNumber);
996
997                         Type type = value.GetType();
998
999                         if (type == null || value is string) {
1000                                 string tmp = null;
1001                                 vbFile.get(ref tmp, recordNumber, false);
1002                                 value = tmp;
1003                         }
1004                         else if ( value is bool) {
1005                                 bool tmp;
1006                                 vbFile.get(out tmp,recordNumber);
1007                                 value = tmp;
1008                         }
1009                         else if ( value is char) {
1010                                 char tmp;
1011                                 vbFile.get(out tmp,recordNumber);
1012                                 value = tmp;
1013                         }
1014                         else if ( value is byte) {
1015                                 byte tmp;
1016                                 vbFile.get(out tmp,recordNumber);
1017                                 value = tmp;
1018                         }
1019                         else if ( value is short) {
1020                                 short tmp;
1021                                 vbFile.get(out tmp,recordNumber);
1022                                 value = tmp;
1023                         }
1024                         else if ( value is int) {
1025                                 int tmp;
1026                                 vbFile.get(out tmp,recordNumber);
1027                                 value = tmp;
1028                         }
1029                         else if ( value is long) {
1030                                 long tmp;
1031                                 vbFile.get(out tmp,recordNumber);
1032                                 value = tmp;
1033                         }
1034                         else if ( value is float) {
1035                                 float tmp;
1036                                 vbFile.get(out tmp,recordNumber);
1037                                 value = tmp;
1038                         }
1039                         else if ( value is double) {
1040                                 double tmp;
1041                                 vbFile.get(out tmp,recordNumber);
1042                                 value = tmp;
1043                         }
1044                         else if ( value is Decimal) {
1045                                 Decimal tmp;
1046                                 vbFile.get(out tmp,recordNumber);
1047                                 value = tmp;
1048                         }
1049                         else if ( value is DateTime) {
1050                                 DateTime tmp;
1051                                 vbFile.get(out tmp,recordNumber);
1052                                 value = tmp;
1053                         }
1054                         else if (type.IsArray) {
1055                                 // need to figure out how to convert from Object& to Array&
1056                                 // vbFile.get(out value, recordNumber,true,false);
1057                                 // value = tmp;
1058                                 throw new NotImplementedException();
1059                         }
1060                         else
1061                                 throw new NotSupportedException();
1062                 }
1063
1064                 public static void FilePutObject(int fileNumber,
1065                                                  Object value,
1066                                                  [Optional, DefaultParameterValue((long)-1)] long recordNumber)
1067
1068                 {
1069                         checkRecordNumber(recordNumber,true);
1070                         VBFile vbFile = getVBFile(fileNumber);
1071                         Type type = value.GetType();
1072                         if(value is string || value == null)
1073                                 vbFile.put((String)value,recordNumber,false);
1074                         else if( value is bool) {
1075                                 vbFile.put((bool)value, recordNumber);
1076                         }
1077                         else if( value is char) {
1078                                 vbFile.put((char)value,recordNumber);
1079                         }
1080                         else if( value is byte) {
1081                                 vbFile.put((byte)value, recordNumber);
1082                         }
1083                         else if( value is short) {
1084                                 vbFile.put((short)value, recordNumber);
1085                         }
1086                         else if( value is int) {
1087                                 vbFile.put((int)value, recordNumber);
1088                         }
1089                         else if( value is long) {
1090                                 vbFile.put((long)value, recordNumber);
1091                         }
1092                         else if( value is float) {
1093                                 vbFile.put((float)value, recordNumber);
1094                         }
1095                         else if( value is double) {
1096                                 vbFile.put((double)value, recordNumber);
1097                         }
1098                         else if( value is Decimal) {
1099                                 vbFile.put((Decimal)value,recordNumber);
1100                         }
1101                         else if( value is DateTime) {
1102                                 vbFile.put((DateTime)value, recordNumber);
1103                         }
1104                         else if(type.IsArray) {
1105                                 vbFile.put(value,recordNumber,true,false);
1106                         }
1107                         else {
1108                                 throw new NotSupportedException();
1109                         }
1110
1111                 }
1112
1113                 private const string obsoleteMsg1 = "Use FilePutObject to write Object types, or";
1114                 private const string obsoleteMsg2 = "coerce FileNumber and RecordNumber to Integer for writing non-Object types";
1115                 private const string obsoleteMsg = obsoleteMsg1 + obsoleteMsg2; 
1116
1117                 [System.ObsoleteAttribute(obsoleteMsg, false)] 
1118                 public static void FilePut(Object FileNumber,
1119                                            Object Value,
1120                                            [Optional, DefaultParameterValue(-1)] System.Object RecordNumber)
1121                 {
1122                         throw new ArgumentException(Utils.GetResourceString("UseFilePutObject"));
1123                 }
1124
1125                 [MonoTODO]
1126                 public static void FilePut(int FileNumber,
1127                                            ValueType Value,
1128                                            [Optional, DefaultParameterValue((long)-1)] System.Int64 RecordNumber)
1129
1130                 {
1131                         throw new NotImplementedException();
1132                 }
1133
1134                 public static void FilePut(int fileNumber,
1135                                            Array value,
1136                                            [Optional, DefaultParameterValue((long)-1)] long recordNumber,
1137                                            [Optional, DefaultParameterValue(false)] bool arrayIsDynamic,
1138                                            [Optional, DefaultParameterValue(false)] bool stringIsFixedLength)
1139                 {
1140                         checkRecordNumber(recordNumber,true);
1141                         VBFile vbFile = getVBFile(fileNumber);
1142                         vbFile.put(value,recordNumber,arrayIsDynamic,stringIsFixedLength);
1143                 }
1144
1145                 public static void FilePut(int fileNumber,
1146                                            Decimal value,
1147                                            [Optional, DefaultParameterValue((long)-1)] long  recordNumber)
1148                 {
1149                         checkRecordNumber(recordNumber,true);
1150                         VBFile vbFile = getVBFile(fileNumber);
1151                         vbFile.put(value,recordNumber);
1152                 }
1153
1154                 public static void Input(int fileNumber, ref bool Value)
1155                 {
1156
1157                         VBFile vbFile = getVBFile(fileNumber);
1158                         vbFile.Input(out Value);
1159                 }
1160
1161                 public static void Input(int fileNumber, ref byte Value)
1162                 {
1163                         VBFile vbFile = getVBFile(fileNumber);
1164                         vbFile.Input(out Value);
1165                 }
1166
1167                 public static void Input(int fileNumber, ref short Value)
1168                 {
1169                         VBFile vbFile = getVBFile(fileNumber);
1170                         vbFile.Input(out Value);
1171                 }
1172
1173                 public static void Input(int fileNumber, ref int Value)
1174                 {
1175                         VBFile vbFile = getVBFile(fileNumber);
1176                         vbFile.Input(out Value);
1177                 }
1178
1179                 public static void Input(int fileNumber, ref long Value)
1180                 {
1181                         VBFile vbFile = getVBFile(fileNumber);
1182                         vbFile.Input(out Value);
1183                 }
1184
1185                 public static void Input(int fileNumber, ref char Value)
1186                 {
1187                         VBFile vbFile = getVBFile(fileNumber);
1188                         vbFile.Input(out Value);
1189                 }
1190
1191                 public static void Input(int fileNumber, ref float Value)
1192                 {
1193                         VBFile vbFile = getVBFile(fileNumber);
1194                         vbFile.Input(out Value);
1195                 }
1196
1197                 public static void Input(int fileNumber, ref double Value)
1198                 {
1199                         VBFile vbFile = getVBFile(fileNumber);
1200                         vbFile.Input(out Value);
1201                 }
1202
1203                 public static void Input(int fileNumber, ref Decimal Value)
1204                 {
1205                         VBFile vbFile = getVBFile(fileNumber);
1206                         vbFile.Input(out Value);
1207                 }
1208
1209                 public static void Input(int fileNumber, ref DateTime Value)
1210                 {
1211                         VBFile vbFile = getVBFile(fileNumber);
1212                         vbFile.Input(out Value);
1213                 }
1214
1215                 public static void Input(int fileNumber, ref string Value)
1216                 {
1217                         VBFile vbFile = getVBFile(fileNumber);
1218                         vbFile.Input(out Value);
1219                 }
1220
1221
1222                 //      public static void Input$V$FileSystem$ILSystem_Object$$$(int fileNumber, ObjectRefWrapper Value)
1223                 //      {
1224                 //              VBFile vbFile = getVBFile(fileNumber);
1225                 //              vbFile.Input(Value,false);
1226                 //      }
1227
1228                 [MonoTODO]
1229                 public static void Lock(int fileNumber) 
1230                 {
1231                         throw new NotImplementedException("The method Lock in class FileSystem is not supported");
1232                 }
1233
1234                 [MonoTODO]
1235                 public static void Lock(int FileNumber, long Record) 
1236                 {
1237                         throw new NotImplementedException("The method Lock in class FileSystem is not supported");
1238                 }
1239
1240                 [MonoTODO]
1241                 public static void Lock(int FileNumber, long FromRecord, long ToRecord) 
1242                 {
1243                         throw new NotImplementedException("The method Lock in class FileSystem is not supported");
1244                 }
1245
1246                 [MonoTODO]
1247                 public static void Unlock(int FileNumber) 
1248                 {
1249                         throw new NotImplementedException("The method Unlock in class FileSystem is not supported");
1250                 }
1251
1252                 [MonoTODO]
1253                 public static void Unlock(int FileNumber, long Record) 
1254                 {
1255                         throw new NotImplementedException("The method Unlock in class FileSystem is not supported");
1256                 }
1257
1258                 [MonoTODO]
1259                 public static void Unlock(int FileNumber, long FromRecord, long ToRecord) 
1260                 {
1261                         throw new NotImplementedException("The method Unlock in class FileSystem is not supported");
1262                 }
1263
1264                 public static void FileWidth(int fileNumber, int RecordWidth)
1265                 {
1266                         VBFile vbFile = getVBFile(fileNumber);
1267                         vbFile.width(fileNumber,RecordWidth);
1268                 }
1269
1270                 public static TabInfo TAB()
1271                 {
1272                         return new TabInfo((short) - 1);
1273                 }
1274
1275                 public static TabInfo TAB(short Column)
1276                 {
1277                         return new TabInfo(Column);
1278                 }
1279
1280                 public static SpcInfo SPC(short Count)
1281                 {
1282                         return new SpcInfo(Count);
1283                 }
1284
1285                 public static OpenMode FileAttr(int fileNumber)
1286                 {
1287                         VBFile vbFile = getVBFile(fileNumber);
1288                         return (OpenMode) vbFile.getMode();
1289                 }
1290         }
1291
1292         class VBStreamWriter : StreamWriter
1293         {
1294                 int _currentColumn;
1295                 int _width;
1296
1297                 public VBStreamWriter(string fileName):base(fileName)
1298                 {
1299                 }
1300
1301                 public VBStreamWriter(string fileName, bool append):base(fileName, append)
1302                 {
1303                 }
1304         }
1305
1306         //TODO: FileFilters from Mainsoft code
1307
1308 }