[reflection] Use coop handles for MonoMethod icalls (#4272)
[mono.git] / mono / io-layer / posix.c
1 /*
2  * posix.c:  Posix-specific support.
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  * Copyright (c) 2002-2009 Novell, Inc.
9  * Copyright 2011 Xamarin Inc
10  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11  */
12
13 #include <config.h>
14 #include <glib.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <errno.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <stdio.h>
22
23 #include <mono/io-layer/wapi.h>
24 #include <mono/io-layer/wapi-private.h>
25 #include <mono/io-layer/io-private.h>
26 #include <mono/io-layer/io-trace.h>
27 #include <mono/utils/mono-logger-internals.h>
28 #include <mono/metadata/w32handle.h>
29
30 static guint32
31 convert_from_flags(int flags)
32 {
33         guint32 fileaccess=0;
34         
35 #ifndef O_ACCMODE
36 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
37 #endif
38
39         if((flags & O_ACCMODE) == O_RDONLY) {
40                 fileaccess=GENERIC_READ;
41         } else if ((flags & O_ACCMODE) == O_WRONLY) {
42                 fileaccess=GENERIC_WRITE;
43         } else if ((flags & O_ACCMODE) == O_RDWR) {
44                 fileaccess=GENERIC_READ|GENERIC_WRITE;
45         } else {
46                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't figure out flags 0x%x", __func__, flags);
47         }
48
49         /* Maybe sort out create mode too */
50
51         return(fileaccess);
52 }
53
54
55 gpointer _wapi_stdhandle_create (int fd, const gchar *name)
56 {
57         struct _WapiHandle_file file_handle = {0};
58         gpointer handle;
59         int flags;
60         
61         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__,
62                   name, fd);
63
64 #if !defined(__native_client__) 
65         /* Check if fd is valid */
66         do {
67                 flags=fcntl(fd, F_GETFL);
68         } while (flags == -1 && errno == EINTR);
69
70         if(flags==-1) {
71                 /* Invalid fd.  Not really much point checking for EBADF
72                  * specifically
73                  */
74                 MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd,
75                           strerror(errno));
76
77                 SetLastError (_wapi_get_win32_file_error (errno));
78                 return(INVALID_HANDLE_VALUE);
79         }
80         file_handle.fileaccess=convert_from_flags(flags);
81 #else
82         /* 
83          * fcntl will return -1 in nacl, as there is no real file system API. 
84          * Yet, standard streams are available.
85          */
86         file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
87 #endif
88
89         file_handle.fd = fd;
90         file_handle.filename = g_strdup(name);
91         /* some default security attributes might be needed */
92         file_handle.security_attributes=0;
93
94         /* Apparently input handles can't be written to.  (I don't
95          * know if output or error handles can't be read from.)
96          */
97         if (fd == 0) {
98                 file_handle.fileaccess &= ~GENERIC_WRITE;
99         }
100         
101         file_handle.sharemode=0;
102         file_handle.attrs=0;
103
104         handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle);
105         if (handle == INVALID_HANDLE_VALUE) {
106                 g_warning ("%s: error creating file handle", __func__);
107                 SetLastError (ERROR_GEN_FAILURE);
108                 return(INVALID_HANDLE_VALUE);
109         }
110         
111         MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
112
113         return(handle);
114 }
115