Merge pull request #301 from directhex/master
[mono.git] / mono / io-layer / locking.c
1 /*
2  * io.c:  File, console and find handles
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  * Copyright (c) 2002-2009 Novell, Inc.
9  */
10 #include <config.h>
11 #include <stdio.h>
12 #include <glib.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 #include <mono/io-layer/wapi.h>
16 #include <mono/io-layer/wapi-private.h>
17 #include <mono/io-layer/handles-private.h>
18 #include <mono/io-layer/io-private.h>
19
20 #if 0
21 // #define DEBUG(...) g_message(__VA_ARGS__)
22 #else
23 #define DEBUG(...)
24 #endif
25
26 gboolean
27 _wapi_lock_file_region (int fd, off_t offset, off_t length)
28 {
29 #if defined(__native_client__)
30         printf("WARNING: locking.c: _wapi_lock_file_region(): fcntl() not available on Native Client!\n");
31         // behave as below -- locks are not available
32         return(TRUE);
33 #else
34         struct flock lock_data;
35         int ret;
36
37         lock_data.l_type = F_WRLCK;
38         lock_data.l_whence = SEEK_SET;
39         lock_data.l_start = offset;
40         lock_data.l_len = length;
41         
42         do {
43                 ret = fcntl (fd, F_SETLK, &lock_data);
44         } while(ret == -1 && errno == EINTR);
45         
46         DEBUG ("%s: fcntl returns %d", __func__, ret);
47
48         if (ret == -1) {
49                 /*
50                  * if locks are not available (NFS for example),
51                  * ignore the error
52                  */
53                 if (errno == ENOLCK
54 #ifdef EOPNOTSUPP
55                     || errno == EOPNOTSUPP
56 #endif
57 #ifdef ENOTSUP
58                     || errno == ENOTSUP
59 #endif
60                    ) {
61                         return (TRUE);
62                 }
63                 
64                 SetLastError (ERROR_LOCK_VIOLATION);
65                 return(FALSE);
66         }
67
68         return(TRUE);
69 #endif /* __native_client__ */
70 }
71
72 gboolean
73 _wapi_unlock_file_region (int fd, off_t offset, off_t length)
74 {
75 #if defined(__native_client__)
76         printf("WARNING: locking.c: _wapi_unlock_file_region(): fcntl() not available on Native Client!\n");
77         return (TRUE);
78 #else
79         struct flock lock_data;
80         int ret;
81
82         lock_data.l_type = F_UNLCK;
83         lock_data.l_whence = SEEK_SET;
84         lock_data.l_start = offset;
85         lock_data.l_len = length;
86         
87         do {
88                 ret = fcntl (fd, F_SETLK, &lock_data);
89         } while(ret == -1 && errno == EINTR);
90         
91         DEBUG ("%s: fcntl returns %d", __func__, ret);
92         
93         if (ret == -1) {
94                 /*
95                  * if locks are not available (NFS for example),
96                  * ignore the error
97                  */
98                 if (errno == ENOLCK
99 #ifdef EOPNOTSUPP
100                     || errno == EOPNOTSUPP
101 #endif
102 #ifdef ENOTSUP
103                     || errno == ENOTSUP
104 #endif
105                    ) {
106                         return (TRUE);
107                 }
108                 
109                 SetLastError (ERROR_LOCK_VIOLATION);
110                 return(FALSE);
111         }
112
113         return(TRUE);
114 #endif /* __native_client__ */
115 }
116
117 gboolean
118 LockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
119           guint32 length_low, guint32 length_high)
120 {
121         struct _WapiHandle_file *file_handle;
122         gboolean ok;
123         off_t offset, length;
124         int fd = GPOINTER_TO_UINT(handle);
125         
126         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
127                                   (gpointer *)&file_handle);
128         if (ok == FALSE) {
129                 g_warning ("%s: error looking up file handle %p", __func__,
130                            handle);
131                 SetLastError (ERROR_INVALID_HANDLE);
132                 return(FALSE);
133         }
134
135         if (!(file_handle->fileaccess & GENERIC_READ) &&
136             !(file_handle->fileaccess & GENERIC_WRITE) &&
137             !(file_handle->fileaccess & GENERIC_ALL)) {
138                 DEBUG ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
139                 SetLastError (ERROR_ACCESS_DENIED);
140                 return(FALSE);
141         }
142
143 #ifdef HAVE_LARGE_FILE_SUPPORT
144         offset = ((gint64)offset_high << 32) | offset_low;
145         length = ((gint64)length_high << 32) | length_low;
146
147         DEBUG ("%s: Locking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
148 #else
149         offset = offset_low;
150         length = length_low;
151
152         DEBUG ("%s: Locking handle %p, offset %ld, length %ld", __func__,
153                    handle, offset, length);
154 #endif
155
156         return(_wapi_lock_file_region (fd, offset, length));
157 }
158
159 gboolean
160 UnlockFile (gpointer handle, guint32 offset_low,
161             guint32 offset_high, guint32 length_low,
162             guint32 length_high)
163 {
164         struct _WapiHandle_file *file_handle;
165         gboolean ok;
166         off_t offset, length;
167         int fd = GPOINTER_TO_UINT(handle);
168         
169         ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
170                                   (gpointer *)&file_handle);
171         if (ok == FALSE) {
172                 g_warning ("%s: error looking up file handle %p", __func__,
173                            handle);
174                 SetLastError (ERROR_INVALID_HANDLE);
175                 return(FALSE);
176         }
177         
178         if (!(file_handle->fileaccess & GENERIC_READ) &&
179             !(file_handle->fileaccess & GENERIC_WRITE) &&
180             !(file_handle->fileaccess & GENERIC_ALL)) {
181                 DEBUG ("%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
182                 SetLastError (ERROR_ACCESS_DENIED);
183                 return(FALSE);
184         }
185
186 #ifdef HAVE_LARGE_FILE_SUPPORT
187         offset = ((gint64)offset_high << 32) | offset_low;
188         length = ((gint64)length_high << 32) | length_low;
189
190         DEBUG ("%s: Unlocking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
191 #else
192         offset = offset_low;
193         length = length_low;
194
195         DEBUG ("%s: Unlocking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
196 #endif
197
198         return(_wapi_unlock_file_region (fd, offset, length));
199 }