~ubuntu-branches/debian/lenny/mono/lenny

« back to all changes in this revision

Viewing changes to mono/metadata/file-io.c

  • Committer: Bazaar Package Importer
  • Author(s): Debian Mono Group
  • Date: 2004-06-19 14:38:57 UTC
  • Revision ID: james.westby@ubuntu.com-20040619143857-pycck6oxgwd172zc
Tags: upstream-0.96
ImportĀ upstreamĀ versionĀ 0.96

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * file-io.c: File IO internal calls
 
3
 *
 
4
 * Author:
 
5
 *      Dick Porter (dick@ximian.com)
 
6
 *
 
7
 * (C) 2001 Ximian, Inc.
 
8
 */
 
9
 
 
10
#include <config.h>
 
11
#include <glib.h>
 
12
#include <string.h>
 
13
#include <errno.h>
 
14
#include <signal.h>
 
15
#include <unistd.h>
 
16
 
 
17
#ifndef PLATFORM_WIN32
 
18
#ifdef HAVE_AIO_H
 
19
#include <aio.h>
 
20
#define USE_AIO 1
 
21
#elif defined(HAVE_SYS_AIO_H)
 
22
#include <sys/aio.h>
 
23
#define USE_AIO 1
 
24
#else
 
25
#undef USE_AIO
 
26
#endif
 
27
#endif
 
28
 
 
29
#include <mono/metadata/object.h>
 
30
#include <mono/io-layer/io-layer.h>
 
31
#include <mono/metadata/file-io.h>
 
32
#include <mono/metadata/exception.h>
 
33
#include <mono/metadata/appdomain.h>
 
34
#include <mono/metadata/marshal.h>
 
35
 
 
36
#undef DEBUG
 
37
 
 
38
/* conversion functions */
 
39
 
 
40
static guint32 convert_mode(MonoFileMode mono_mode)
 
41
{
 
42
        guint32 mode;
 
43
 
 
44
        switch(mono_mode) {
 
45
        case FileMode_CreateNew:
 
46
                mode=CREATE_NEW;
 
47
                break;
 
48
        case FileMode_Create:
 
49
                mode=CREATE_ALWAYS;
 
50
                break;
 
51
        case FileMode_Open:
 
52
                mode=OPEN_EXISTING;
 
53
                break;
 
54
        case FileMode_OpenOrCreate:
 
55
                mode=OPEN_ALWAYS;
 
56
                break;
 
57
        case FileMode_Truncate:
 
58
                mode=TRUNCATE_EXISTING;
 
59
                break;
 
60
        case FileMode_Append:
 
61
                mode=OPEN_ALWAYS;
 
62
                break;
 
63
        default:
 
64
                g_warning("System.IO.FileMode has unknown value 0x%x",
 
65
                          mono_mode);
 
66
                /* Safe fallback */
 
67
                mode=OPEN_EXISTING;
 
68
        }
 
69
        
 
70
        return(mode);
 
71
}
 
72
 
 
73
static guint32 convert_access(MonoFileAccess mono_access)
 
74
{
 
75
        guint32 access;
 
76
        
 
77
        switch(mono_access) {
 
78
        case FileAccess_Read:
 
79
                access=GENERIC_READ;
 
80
                break;
 
81
        case FileAccess_Write:
 
82
                access=GENERIC_WRITE;
 
83
                break;
 
84
        case FileAccess_ReadWrite:
 
85
                access=GENERIC_READ|GENERIC_WRITE;
 
86
                break;
 
87
        default:
 
88
                g_warning("System.IO.FileAccess has unknown value 0x%x",
 
89
                          mono_access);
 
90
                /* Safe fallback */
 
91
                access=GENERIC_READ;
 
92
        }
 
93
        
 
94
        return(access);
 
95
}
 
96
 
 
97
static guint32 convert_share(MonoFileShare mono_share)
 
98
{
 
99
        guint32 share;
 
100
        
 
101
        switch(mono_share) {
 
102
        case FileShare_None:
 
103
                share=0;
 
104
                break;
 
105
        case FileShare_Read:
 
106
                share=FILE_SHARE_READ;
 
107
                break;
 
108
        case FileShare_Write:
 
109
                share=FILE_SHARE_WRITE;
 
110
                break;
 
111
        case FileShare_ReadWrite:
 
112
                share=FILE_SHARE_READ|FILE_SHARE_WRITE;
 
113
                break;
 
114
        default:
 
115
                g_warning("System.IO.FileShare has unknown value 0x%x",
 
116
                          mono_share);
 
117
                /* Safe fallback */
 
118
                share=0;
 
119
        }
 
120
        
 
121
        return(share);
 
122
}
 
123
 
 
124
#if 0
 
125
static guint32 convert_stdhandle(guint32 fd)
 
126
{
 
127
        guint32 stdhandle;
 
128
        
 
129
        switch(fd) {
 
130
        case 0:
 
131
                stdhandle=STD_INPUT_HANDLE;
 
132
                break;
 
133
        case 1:
 
134
                stdhandle=STD_OUTPUT_HANDLE;
 
135
                break;
 
136
        case 2:
 
137
                stdhandle=STD_ERROR_HANDLE;
 
138
                break;
 
139
        default:
 
140
                g_warning("unknown standard file descriptor %d", fd);
 
141
                stdhandle=STD_INPUT_HANDLE;
 
142
        }
 
143
        
 
144
        return(stdhandle);
 
145
}
 
146
#endif
 
147
 
 
148
static guint32 convert_seekorigin(MonoSeekOrigin origin)
 
149
{
 
150
        guint32 w32origin;
 
151
        
 
152
        switch(origin) {
 
153
        case SeekOrigin_Begin:
 
154
                w32origin=FILE_BEGIN;
 
155
                break;
 
156
        case SeekOrigin_Current:
 
157
                w32origin=FILE_CURRENT;
 
158
                break;
 
159
        case SeekOrigin_End:
 
160
                w32origin=FILE_END;
 
161
                break;
 
162
        default:
 
163
                g_warning("System.IO.SeekOrigin has unknown value 0x%x",
 
164
                          origin);
 
165
                /* Safe fallback */
 
166
                w32origin=FILE_CURRENT;
 
167
        }
 
168
        
 
169
        return(w32origin);
 
170
}
 
171
 
 
172
static gint64 convert_filetime (const FILETIME *filetime)
 
173
{
 
174
        guint64 ticks = filetime->dwHighDateTime;
 
175
        ticks <<= 32;
 
176
        ticks += filetime->dwLowDateTime;
 
177
        return (gint64)ticks;
 
178
}
 
179
 
 
180
static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, const gunichar2 *name, MonoIOStat *stat)
 
181
{
 
182
        int len;
 
183
        
 
184
        stat->attributes = data->dwFileAttributes;
 
185
        stat->creation_time = convert_filetime (&data->ftCreationTime);
 
186
        stat->last_access_time = convert_filetime (&data->ftLastAccessTime);
 
187
        stat->last_write_time = convert_filetime (&data->ftLastWriteTime);
 
188
        stat->length = ((gint64)data->nFileSizeHigh << 32) | data->nFileSizeLow;
 
189
 
 
190
        len = 0;
 
191
        while (name [len])
 
192
                ++ len;
 
193
 
 
194
        stat->name = mono_string_new_utf16 (mono_domain_get (), name, len);
 
195
}
 
196
 
 
197
/* Managed file attributes have nearly but not quite the same values
 
198
 * as the w32 equivalents.
 
199
 */
 
200
static guint32 convert_attrs(MonoFileAttributes attrs)
 
201
{
 
202
        if(attrs & FileAttributes_Encrypted) {
 
203
                attrs |= FILE_ATTRIBUTE_ENCRYPTED;
 
204
        }
 
205
        
 
206
        return(attrs);
 
207
}
 
208
 
 
209
/* System.IO.MonoIO internal calls */
 
210
 
 
211
MonoBoolean
 
212
ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
 
213
{
 
214
        gboolean ret;
 
215
        
 
216
        MONO_ARCH_SAVE_REGS;
 
217
 
 
218
        *error=ERROR_SUCCESS;
 
219
        
 
220
        ret=CreateDirectory (mono_string_chars (path), NULL);
 
221
        if(ret==FALSE) {
 
222
                *error=GetLastError ();
 
223
        }
 
224
        
 
225
        return(ret);
 
226
}
 
227
 
 
228
MonoBoolean
 
229
ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
 
230
{
 
231
        gboolean ret;
 
232
        
 
233
        MONO_ARCH_SAVE_REGS;
 
234
 
 
235
        *error=ERROR_SUCCESS;
 
236
        
 
237
        ret=RemoveDirectory (mono_string_chars (path));
 
238
        if(ret==FALSE) {
 
239
                *error=GetLastError ();
 
240
        }
 
241
        
 
242
        return(ret);
 
243
}
 
244
 
 
245
HANDLE 
 
246
ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path, MonoIOStat *stat,
 
247
                                          gint32 *error)
 
248
{
 
249
        WIN32_FIND_DATA data;
 
250
        HANDLE result;
 
251
        gboolean r = TRUE;
 
252
 
 
253
        MONO_ARCH_SAVE_REGS;
 
254
 
 
255
        *error=ERROR_SUCCESS;
 
256
 
 
257
        result = FindFirstFile (mono_string_chars (path), &data);
 
258
 
 
259
        /* note: WIN32_FIND_DATA is an extension of WIN32_FILE_ATTRIBUTE_DATA */
 
260
        while (result != INVALID_HANDLE_VALUE && r) {
 
261
                if ((data.cFileName [0] == '.' && data.cFileName [1] == 0) ||
 
262
                    (data.cFileName [0] == '.' && data.cFileName [1] == '.' && data.cFileName [2] == 0)) {
 
263
                        r = FindNextFile (result, &data);
 
264
                } else {
 
265
                        convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
 
266
                                                           &data.cFileName [0], stat);
 
267
                        break;
 
268
                } 
 
269
        }
 
270
        
 
271
        if (result == INVALID_HANDLE_VALUE) {
 
272
                *error=GetLastError ();
 
273
        }
 
274
        
 
275
        if (r == FALSE) {
 
276
                /* No more files were found, after we discarded . and .. */
 
277
                FindClose(result);
 
278
                result = INVALID_HANDLE_VALUE;
 
279
                *error = ERROR_NO_MORE_FILES;
 
280
        }
 
281
 
 
282
        return result;
 
283
}
 
284
 
 
285
MonoBoolean
 
286
ves_icall_System_IO_MonoIO_FindNextFile (HANDLE find, MonoIOStat *stat,
 
287
                                         gint32 *error)
 
288
{
 
289
        WIN32_FIND_DATA data;
 
290
        gboolean result;
 
291
 
 
292
        MONO_ARCH_SAVE_REGS;
 
293
 
 
294
        *error=ERROR_SUCCESS;
 
295
        
 
296
        result = FindNextFile (find, &data);
 
297
        while (result != FALSE) {
 
298
                if ((data.cFileName [0] == '.' && data.cFileName [1] == 0) ||
 
299
                    (data.cFileName [0] == '.' && data.cFileName [1] == '.' && data.cFileName [2] == 0)) {
 
300
                        result = FindNextFile (find, &data);
 
301
                } else {
 
302
                        convert_win32_file_attribute_data ((const WIN32_FILE_ATTRIBUTE_DATA *)&data,
 
303
                                                           &data.cFileName [0], stat);
 
304
                        break;
 
305
                } 
 
306
        }
 
307
        
 
308
        if (result == FALSE) {
 
309
                *error=GetLastError ();
 
310
        }
 
311
 
 
312
        return result;
 
313
}
 
314
 
 
315
MonoBoolean
 
316
ves_icall_System_IO_MonoIO_FindClose (HANDLE find, gint32 *error)
 
317
{
 
318
        gboolean ret;
 
319
        
 
320
        MONO_ARCH_SAVE_REGS;
 
321
 
 
322
        *error=ERROR_SUCCESS;
 
323
        
 
324
        ret=FindClose (find);
 
325
        if(ret==FALSE) {
 
326
                *error=GetLastError ();
 
327
        }
 
328
        
 
329
        return(ret);
 
330
}
 
331
 
 
332
MonoString *
 
333
ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error)
 
334
{
 
335
        MonoString *result;
 
336
        gunichar2 *buf;
 
337
        int len;
 
338
 
 
339
        MONO_ARCH_SAVE_REGS;
 
340
 
 
341
        len = MAX_PATH + 1;
 
342
        buf = g_new (gunichar2, len);
 
343
        
 
344
        *error=ERROR_SUCCESS;
 
345
        result = NULL;
 
346
 
 
347
        if (GetCurrentDirectory (len, buf) > 0) {
 
348
                len = 0;
 
349
                while (buf [len])
 
350
                        ++ len;
 
351
 
 
352
                result = mono_string_new_utf16 (mono_domain_get (), buf, len);
 
353
        } else {
 
354
                *error=GetLastError ();
 
355
        }
 
356
 
 
357
        g_free (buf);
 
358
        return result;
 
359
}
 
360
 
 
361
MonoBoolean
 
362
ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
 
363
                                                gint32 *error)
 
364
{
 
365
        gboolean ret;
 
366
        
 
367
        MONO_ARCH_SAVE_REGS;
 
368
 
 
369
        *error=ERROR_SUCCESS;
 
370
        
 
371
        ret=SetCurrentDirectory (mono_string_chars (path));
 
372
        if(ret==FALSE) {
 
373
                *error=GetLastError ();
 
374
        }
 
375
        
 
376
        return(ret);
 
377
}
 
378
 
 
379
MonoBoolean
 
380
ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
 
381
                                     gint32 *error)
 
382
{
 
383
        gboolean ret;
 
384
        
 
385
        MONO_ARCH_SAVE_REGS;
 
386
 
 
387
        *error=ERROR_SUCCESS;
 
388
        
 
389
        ret=MoveFile (mono_string_chars (path), mono_string_chars (dest));
 
390
        if(ret==FALSE) {
 
391
                *error=GetLastError ();
 
392
        }
 
393
        
 
394
        return(ret);
 
395
}
 
396
 
 
397
MonoBoolean
 
398
ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
 
399
                                     MonoBoolean overwrite, gint32 *error)
 
400
{
 
401
        gboolean ret;
 
402
        
 
403
        MONO_ARCH_SAVE_REGS;
 
404
 
 
405
        *error=ERROR_SUCCESS;
 
406
        
 
407
        ret=CopyFile (mono_string_chars (path), mono_string_chars (dest), !overwrite);
 
408
        if(ret==FALSE) {
 
409
                *error=GetLastError ();
 
410
        }
 
411
        
 
412
        return(ret);
 
413
}
 
414
 
 
415
MonoBoolean
 
416
ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
 
417
{
 
418
        gboolean ret;
 
419
        
 
420
        MONO_ARCH_SAVE_REGS;
 
421
 
 
422
        *error=ERROR_SUCCESS;
 
423
        
 
424
        ret=DeleteFile (mono_string_chars (path));
 
425
        if(ret==FALSE) {
 
426
                *error=GetLastError ();
 
427
        }
 
428
        
 
429
        return(ret);
 
430
}
 
431
 
 
432
gint32 
 
433
ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
 
434
{
 
435
        gint32 ret;
 
436
        
 
437
        MONO_ARCH_SAVE_REGS;
 
438
 
 
439
        *error=ERROR_SUCCESS;
 
440
        
 
441
        ret=GetFileAttributes (mono_string_chars (path));
 
442
 
 
443
        /* 
 
444
         * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
 
445
         * headers is wrong, hence this temporary workaround.
 
446
         * See
 
447
         * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
 
448
         */
 
449
        if (ret==-1) {
 
450
//      if(ret==INVALID_FILE_ATTRIBUTES) {
 
451
                *error=GetLastError ();
 
452
        }
 
453
        
 
454
        return(ret);
 
455
}
 
456
 
 
457
MonoBoolean
 
458
ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
 
459
                                              gint32 *error)
 
460
{
 
461
        gboolean ret;
 
462
        
 
463
        MONO_ARCH_SAVE_REGS;
 
464
 
 
465
        *error=ERROR_SUCCESS;
 
466
        
 
467
        ret=SetFileAttributes (mono_string_chars (path),
 
468
                               convert_attrs (attrs));
 
469
        if(ret==FALSE) {
 
470
                *error=GetLastError ();
 
471
        }
 
472
        
 
473
        return(ret);
 
474
}
 
475
 
 
476
gint32
 
477
ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
 
478
{
 
479
        gboolean ret;
 
480
        
 
481
        MONO_ARCH_SAVE_REGS;
 
482
 
 
483
        *error=ERROR_SUCCESS;
 
484
        
 
485
        ret=GetFileType (handle);
 
486
        if(ret==FILE_TYPE_UNKNOWN) {
 
487
                /* Not necessarily an error, but the caller will have
 
488
                 * to decide based on the error value.
 
489
                 */
 
490
                *error=GetLastError ();
 
491
        }
 
492
        
 
493
        return(ret);
 
494
}
 
495
 
 
496
MonoBoolean
 
497
ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
 
498
                                        gint32 *error)
 
499
{
 
500
        gboolean result;
 
501
        WIN32_FILE_ATTRIBUTE_DATA data;
 
502
 
 
503
        MONO_ARCH_SAVE_REGS;
 
504
 
 
505
        *error=ERROR_SUCCESS;
 
506
        
 
507
        result = GetFileAttributesEx (mono_string_chars (path), GetFileExInfoStandard, &data);
 
508
 
 
509
        if (result) {
 
510
                convert_win32_file_attribute_data (&data,
 
511
                                                   mono_string_chars (path),
 
512
                                                   stat);
 
513
        } else {
 
514
                *error=GetLastError ();
 
515
        }
 
516
 
 
517
        return result;
 
518
}
 
519
 
 
520
HANDLE 
 
521
ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
 
522
                                 gint32 access_mode, gint32 share,
 
523
                                 MonoBoolean async, gint32 *error)
 
524
{
 
525
        HANDLE ret;
 
526
        
 
527
        MONO_ARCH_SAVE_REGS;
 
528
 
 
529
        *error=ERROR_SUCCESS;
 
530
        
 
531
        ret=CreateFile (mono_string_chars (filename),
 
532
                        convert_access (access_mode), convert_share (share),
 
533
                        NULL, convert_mode (mode),
 
534
                        FILE_ATTRIBUTE_NORMAL | ((async) ? FILE_FLAG_OVERLAPPED : 0),
 
535
                        NULL);
 
536
        if(ret==INVALID_HANDLE_VALUE) {
 
537
                *error=GetLastError ();
 
538
        }
 
539
        
 
540
        return(ret);
 
541
}
 
542
 
 
543
MonoBoolean
 
544
ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
 
545
{
 
546
        gboolean ret;
 
547
        
 
548
        MONO_ARCH_SAVE_REGS;
 
549
 
 
550
        *error=ERROR_SUCCESS;
 
551
        
 
552
        ret=CloseHandle (handle);
 
553
        if(ret==FALSE) {
 
554
                *error=GetLastError ();
 
555
        }
 
556
        
 
557
        return(ret);
 
558
}
 
559
 
 
560
gint32 
 
561
ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
 
562
                                 gint32 dest_offset, gint32 count,
 
563
                                 gint32 *error)
 
564
{
 
565
        guchar *buffer;
 
566
        gboolean result;
 
567
        guint32 n;
 
568
 
 
569
        MONO_ARCH_SAVE_REGS;
 
570
 
 
571
        *error=ERROR_SUCCESS;
 
572
        
 
573
        if (dest_offset + count > mono_array_length (dest))
 
574
                return 0;
 
575
 
 
576
        buffer = mono_array_addr (dest, guchar, dest_offset);
 
577
        result = ReadFile (handle, buffer, count, &n, NULL);
 
578
 
 
579
        if (!result) {
 
580
                *error=GetLastError ();
 
581
                return -1;
 
582
        }
 
583
 
 
584
        return (gint32)n;
 
585
}
 
586
 
 
587
gint32 
 
588
ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
 
589
                                  gint32 src_offset, gint32 count,
 
590
                                  gint32 *error)
 
591
{
 
592
        guchar *buffer;
 
593
        gboolean result;
 
594
        guint32 n;
 
595
 
 
596
        MONO_ARCH_SAVE_REGS;
 
597
 
 
598
        *error=ERROR_SUCCESS;
 
599
        
 
600
        if (src_offset + count > mono_array_length (src))
 
601
                return 0;
 
602
        
 
603
        buffer = mono_array_addr (src, guchar, src_offset);
 
604
        result = WriteFile (handle, buffer, count, &n, NULL);
 
605
 
 
606
        if (!result) {
 
607
                *error=GetLastError ();
 
608
                return -1;
 
609
        }
 
610
 
 
611
        return (gint32)n;
 
612
}
 
613
 
 
614
gint64 
 
615
ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
 
616
                                 gint32 *error)
 
617
{
 
618
        guint32 offset_hi;
 
619
 
 
620
        MONO_ARCH_SAVE_REGS;
 
621
 
 
622
        *error=ERROR_SUCCESS;
 
623
        
 
624
        offset_hi = offset >> 32;
 
625
        offset = SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
 
626
                                 convert_seekorigin (origin));
 
627
 
 
628
        if(offset==INVALID_SET_FILE_POINTER) {
 
629
                *error=GetLastError ();
 
630
        }
 
631
        
 
632
        return offset | ((gint64)offset_hi << 32);
 
633
}
 
634
 
 
635
MonoBoolean
 
636
ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
 
637
{
 
638
        gboolean ret;
 
639
        
 
640
        MONO_ARCH_SAVE_REGS;
 
641
 
 
642
        *error=ERROR_SUCCESS;
 
643
        
 
644
        ret=FlushFileBuffers (handle);
 
645
        if(ret==FALSE) {
 
646
                *error=GetLastError ();
 
647
        }
 
648
        
 
649
        return(ret);
 
650
}
 
651
 
 
652
gint64 
 
653
ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
 
654
{
 
655
        gint64 length;
 
656
        guint32 length_hi;
 
657
 
 
658
        MONO_ARCH_SAVE_REGS;
 
659
 
 
660
        *error=ERROR_SUCCESS;
 
661
        
 
662
        length = GetFileSize (handle, &length_hi);
 
663
        if(length==INVALID_FILE_SIZE) {
 
664
                *error=GetLastError ();
 
665
        }
 
666
        
 
667
        return length | ((gint64)length_hi << 32);
 
668
}
 
669
 
 
670
MonoBoolean
 
671
ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
 
672
                                      gint32 *error)
 
673
{
 
674
        gint64 offset, offset_set;
 
675
        gint32 offset_hi;
 
676
        gint32 length_hi;
 
677
        gboolean result;
 
678
 
 
679
        MONO_ARCH_SAVE_REGS;
 
680
 
 
681
        *error=ERROR_SUCCESS;
 
682
        
 
683
        /* save file pointer */
 
684
 
 
685
        offset_hi = 0;
 
686
        offset = SetFilePointer (handle, 0, &offset_hi, FILE_CURRENT);
 
687
        if(offset==INVALID_SET_FILE_POINTER) {
 
688
                *error=GetLastError ();
 
689
                return(FALSE);
 
690
        }
 
691
 
 
692
        /* extend or truncate */
 
693
 
 
694
        length_hi = length >> 32;
 
695
        offset_set=SetFilePointer (handle, length & 0xFFFFFFFF, &length_hi,
 
696
                                   FILE_BEGIN);
 
697
        if(offset_set==INVALID_SET_FILE_POINTER) {
 
698
                *error=GetLastError ();
 
699
                return(FALSE);
 
700
        }
 
701
 
 
702
        result = SetEndOfFile (handle);
 
703
        if(result==FALSE) {
 
704
                *error=GetLastError ();
 
705
                return(FALSE);
 
706
        }
 
707
 
 
708
        /* restore file pointer */
 
709
 
 
710
        offset_set=SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
 
711
                                   FILE_BEGIN);
 
712
        if(offset_set==INVALID_SET_FILE_POINTER) {
 
713
                *error=GetLastError ();
 
714
                return(FALSE);
 
715
        }
 
716
 
 
717
        return result;
 
718
}
 
719
 
 
720
MonoBoolean
 
721
ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
 
722
                                        gint64 last_access_time,
 
723
                                        gint64 last_write_time, gint32 *error)
 
724
{
 
725
        gboolean ret;
 
726
        const FILETIME *creation_filetime;
 
727
        const FILETIME *last_access_filetime;
 
728
        const FILETIME *last_write_filetime;
 
729
 
 
730
        MONO_ARCH_SAVE_REGS;
 
731
 
 
732
        *error=ERROR_SUCCESS;
 
733
        
 
734
        if (creation_time < 0)
 
735
                creation_filetime = NULL;
 
736
        else
 
737
                creation_filetime = (FILETIME *)&creation_time;
 
738
 
 
739
        if (last_access_time < 0)
 
740
                last_access_filetime = NULL;
 
741
        else
 
742
                last_access_filetime = (FILETIME *)&last_access_time;
 
743
 
 
744
        if (last_write_time < 0)
 
745
                last_write_filetime = NULL;
 
746
        else
 
747
                last_write_filetime = (FILETIME *)&last_write_time;
 
748
 
 
749
        ret=SetFileTime (handle, creation_filetime, last_access_filetime, last_write_filetime);
 
750
        if(ret==FALSE) {
 
751
                *error=GetLastError ();
 
752
        }
 
753
        
 
754
        return(ret);
 
755
}
 
756
 
 
757
HANDLE 
 
758
ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
 
759
{
 
760
        MONO_ARCH_SAVE_REGS;
 
761
 
 
762
        return GetStdHandle (STD_OUTPUT_HANDLE);
 
763
}
 
764
 
 
765
HANDLE 
 
766
ves_icall_System_IO_MonoIO_get_ConsoleInput ()
 
767
{
 
768
        MONO_ARCH_SAVE_REGS;
 
769
 
 
770
        return GetStdHandle (STD_INPUT_HANDLE);
 
771
}
 
772
 
 
773
HANDLE 
 
774
ves_icall_System_IO_MonoIO_get_ConsoleError ()
 
775
{
 
776
        MONO_ARCH_SAVE_REGS;
 
777
 
 
778
        return GetStdHandle (STD_ERROR_HANDLE);
 
779
}
 
780
 
 
781
MonoBoolean
 
782
ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle,
 
783
                                       HANDLE *write_handle)
 
784
{
 
785
        SECURITY_ATTRIBUTES attr;
 
786
        gboolean ret;
 
787
        
 
788
        MONO_ARCH_SAVE_REGS;
 
789
 
 
790
        attr.nLength=sizeof(SECURITY_ATTRIBUTES);
 
791
        attr.bInheritHandle=TRUE;
 
792
        attr.lpSecurityDescriptor=NULL;
 
793
        
 
794
        ret=CreatePipe (read_handle, write_handle, &attr, 0);
 
795
        if(ret==FALSE) {
 
796
                /* FIXME: throw an exception? */
 
797
                return(FALSE);
 
798
        }
 
799
        
 
800
        return(TRUE);
 
801
}
 
802
 
 
803
gunichar2 
 
804
ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
 
805
{
 
806
        MONO_ARCH_SAVE_REGS;
 
807
 
 
808
#if defined (PLATFORM_WIN32)
 
809
        return (gunichar2) 0x003a;      /* colon */
 
810
#else
 
811
        return (gunichar2) 0x002f;      /* forward slash */
 
812
#endif
 
813
}
 
814
 
 
815
gunichar2 
 
816
ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
 
817
{
 
818
        MONO_ARCH_SAVE_REGS;
 
819
 
 
820
#if defined (PLATFORM_WIN32)
 
821
        return (gunichar2) 0x005c;      /* backslash */
 
822
#else
 
823
        return (gunichar2) 0x002f;      /* forward slash */
 
824
#endif
 
825
}
 
826
 
 
827
gunichar2 
 
828
ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
 
829
{
 
830
        MONO_ARCH_SAVE_REGS;
 
831
 
 
832
#if defined (PLATFORM_WIN32)
 
833
        return (gunichar2) 0x002f;      /* forward slash */
 
834
#else
 
835
        return (gunichar2) 0x005c;      /* backslash */
 
836
#endif
 
837
}
 
838
 
 
839
gunichar2 
 
840
ves_icall_System_IO_MonoIO_get_PathSeparator ()
 
841
{
 
842
        MONO_ARCH_SAVE_REGS;
 
843
 
 
844
#if defined (PLATFORM_WIN32)
 
845
        return (gunichar2) 0x003b;      /* semicolon */
 
846
#else
 
847
        return (gunichar2) 0x003a;      /* colon */
 
848
#endif
 
849
}
 
850
 
 
851
static gunichar2 invalid_path_chars [] = {
 
852
#if defined (PLATFORM_WIN32)
 
853
        0x0022,                         /* double quote, which seems allowed in MS.NET but should be rejected */
 
854
        0x003c,                         /* less than */
 
855
        0x003e,                         /* greater than */
 
856
        0x007c,                         /* pipe */
 
857
        0x0008,
 
858
        0x0010,
 
859
        0x0011,
 
860
        0x0012,
 
861
        0x0014,
 
862
        0x0015,
 
863
        0x0016,
 
864
        0x0017,
 
865
        0x0018,
 
866
        0x0019,
 
867
#endif
 
868
        0x0000                          /* null */
 
869
};
 
870
 
 
871
MonoArray *
 
872
ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
 
873
{
 
874
        MonoArray *chars;
 
875
        MonoDomain *domain;
 
876
        int i, n;
 
877
 
 
878
        MONO_ARCH_SAVE_REGS;
 
879
 
 
880
        domain = mono_domain_get ();
 
881
        chars = mono_array_new (domain, mono_defaults.char_class, 15);
 
882
 
 
883
        n = sizeof (invalid_path_chars) / sizeof (gunichar2);
 
884
 
 
885
        for (i = 0; i < n; ++ i)
 
886
                mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
 
887
        
 
888
        return chars;
 
889
}
 
890
 
 
891
gint32
 
892
ves_icall_System_IO_MonoIO_GetTempPath (MonoString **mono_name)
 
893
{
 
894
        gunichar2 *name;
 
895
        int ret;
 
896
 
 
897
        name=g_new0 (gunichar2, 256);
 
898
        
 
899
        ret=GetTempPath (256, name);
 
900
        if(ret>255) {
 
901
                /* Buffer was too short. Try again... */
 
902
                g_free (name);
 
903
                name=g_new0 (gunichar2, ret+2); /* include the terminator */
 
904
                ret=GetTempPath (ret, name);
 
905
        }
 
906
        
 
907
        if(ret>0) {
 
908
#ifdef DEBUG
 
909
                g_message (G_GNUC_PRETTY_FUNCTION
 
910
                           ": Temp path is [%s] (len %d)", name, ret);
 
911
#endif
 
912
 
 
913
                *mono_name=mono_string_new_utf16 (mono_domain_get (), name,
 
914
                                                  ret);
 
915
        }
 
916
 
 
917
        g_free (name);
 
918
        
 
919
        return(ret);
 
920
}
 
921
 
 
922
/*
 
923
 * Asynchronous IO
 
924
 */
 
925
MonoBoolean
 
926
ves_icall_System_IO_MonoIO_GetSupportsAsync (void)
 
927
{
 
928
        MONO_ARCH_SAVE_REGS;
 
929
 
 
930
#ifdef PLATFORM_WIN32
 
931
        /* Seems like BindIoCompletionCallback is not found when compiling...
 
932
         * Disabling AIO support on win. Any one wants to fix this?
 
933
         */
 
934
        return FALSE;   
 
935
        /* return (g_getenv ("MONO_DISABLE_AIO") == NULL && WINVER >= 0x500); */
 
936
#elif defined(USE_AIO)
 
937
        if (aio_cancel (-1, NULL) == -1 && errno == ENOSYS)
 
938
                return FALSE;
 
939
 
 
940
        return (g_getenv ("MONO_DISABLE_AIO") == NULL);
 
941
#else
 
942
        return FALSE;
 
943
#endif
 
944
}
 
945
 
 
946
static WapiOverlapped *
 
947
get_overlapped_from_fsa (MonoFSAsyncResult *ares)
 
948
{
 
949
        WapiOverlapped *ovl;
 
950
 
 
951
        ovl = g_new0 (WapiOverlapped, 1);
 
952
        ovl->Offset = ares->offset;
 
953
        ovl->hEvent = ares->wait_handle;
 
954
 
 
955
        return ovl;
 
956
}
 
957
 
 
958
MonoBoolean
 
959
ves_icall_System_IO_MonoIO_BeginRead (HANDLE handle, MonoFSAsyncResult *ares)
 
960
{
 
961
        guint32 bytesread;
 
962
        WapiOverlapped *ovl;
 
963
 
 
964
        MONO_ARCH_SAVE_REGS;
 
965
 
 
966
        ovl = get_overlapped_from_fsa (ares);
 
967
        ovl->handle1 = ares;
 
968
        return ReadFile (handle, mono_array_addr (ares->buffer, gchar, ares->offset), ares->count, &bytesread, ovl);
 
969
}
 
970
 
 
971
MonoBoolean
 
972
ves_icall_System_IO_MonoIO_BeginWrite (HANDLE handle, MonoFSAsyncResult *ares)
 
973
{
 
974
        guint32 byteswritten;
 
975
        WapiOverlapped *ovl;
 
976
 
 
977
        MONO_ARCH_SAVE_REGS;
 
978
 
 
979
        ovl = get_overlapped_from_fsa (ares);
 
980
        ovl->handle1 = ares;
 
981
        return WriteFile (handle, mono_array_addr (ares->buffer, gchar, ares->offset), ares->count, &byteswritten, ovl);
 
982
}
 
983
 
 
984
void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
 
985
                                      gint64 length, gint32 *error)
 
986
{
 
987
        gboolean ret;
 
988
        
 
989
        *error=ERROR_SUCCESS;
 
990
        
 
991
        ret=LockFile (handle, position & 0xFFFFFFFF, position >> 32,
 
992
                      length & 0xFFFFFFFF, length >> 32);
 
993
        if (ret == FALSE) {
 
994
                *error = GetLastError ();
 
995
        }
 
996
}
 
997
 
 
998
void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
 
999
                                        gint64 length, gint32 *error)
 
1000
{
 
1001
        gboolean ret;
 
1002
        
 
1003
        *error=ERROR_SUCCESS;
 
1004
        
 
1005
        ret=UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
 
1006
                        length & 0xFFFFFFFF, length >> 32);
 
1007
        if (ret == FALSE) {
 
1008
                *error = GetLastError ();
 
1009
        }
 
1010
}
 
1011