Add an 'fd' field to WapiHandle_file, to make it easier to break the fd==handle depen...
[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  */
10
11 #include <config.h>
12 #include <glib.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <stdio.h>
20
21 #include <mono/io-layer/wapi.h>
22 #include <mono/io-layer/wapi-private.h>
23 #include <mono/io-layer/handles-private.h>
24 #include <mono/io-layer/io-private.h>
25
26 #if 0
27 #define DEBUG(...) g_message(__VA_ARGS__)
28 #else
29 #define DEBUG(...)
30 #endif
31
32 static guint32
33 convert_from_flags(int flags)
34 {
35         guint32 fileaccess=0;
36         
37 #ifndef O_ACCMODE
38 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
39 #endif
40
41         if((flags & O_ACCMODE) == O_RDONLY) {
42                 fileaccess=GENERIC_READ;
43         } else if ((flags & O_ACCMODE) == O_WRONLY) {
44                 fileaccess=GENERIC_WRITE;
45         } else if ((flags & O_ACCMODE) == O_RDWR) {
46                 fileaccess=GENERIC_READ|GENERIC_WRITE;
47         } else {
48                 DEBUG("%s: Can't figure out flags 0x%x", __func__, flags);
49         }
50
51         /* Maybe sort out create mode too */
52
53         return(fileaccess);
54 }
55
56
57 gpointer _wapi_stdhandle_create (int fd, const gchar *name)
58 {
59         struct _WapiHandle_file file_handle = {0};
60         gpointer handle;
61         int flags;
62         
63         DEBUG("%s: creating standard handle type %s, fd %d", __func__,
64                   name, fd);
65
66 #if !defined(__native_client__) 
67         /* Check if fd is valid */
68         do {
69                 flags=fcntl(fd, F_GETFL);
70         } while (flags == -1 && errno == EINTR);
71
72         if(flags==-1) {
73                 /* Invalid fd.  Not really much point checking for EBADF
74                  * specifically
75                  */
76                 DEBUG("%s: fcntl error on fd %d: %s", __func__, fd,
77                           strerror(errno));
78
79                 SetLastError (_wapi_get_win32_file_error (errno));
80                 return(INVALID_HANDLE_VALUE);
81         }
82         file_handle.fileaccess=convert_from_flags(flags);
83 #else
84         /* 
85          * fcntl will return -1 in nacl, as there is no real file system API. 
86          * Yet, standard streams are available.
87          */
88         file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
89 #endif
90
91         file_handle.fd = fd;
92         file_handle.filename = g_strdup(name);
93         /* some default security attributes might be needed */
94         file_handle.security_attributes=0;
95
96         /* Apparently input handles can't be written to.  (I don't
97          * know if output or error handles can't be read from.)
98          */
99         if (fd == 0) {
100                 file_handle.fileaccess &= ~GENERIC_WRITE;
101         }
102         
103         file_handle.sharemode=0;
104         file_handle.attrs=0;
105
106         handle = _wapi_handle_new_fd (WAPI_HANDLE_CONSOLE, fd, &file_handle);
107         if (handle == _WAPI_HANDLE_INVALID) {
108                 g_warning ("%s: error creating file handle", __func__);
109                 SetLastError (ERROR_GEN_FAILURE);
110                 return(INVALID_HANDLE_VALUE);
111         }
112         
113         DEBUG("%s: returning handle %p", __func__, handle);
114
115         return(handle);
116 }
117