4 * ----------------------------------------------------------------
7 * Copyright (C) 2003-2006 Mojave Group, Caltech
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation,
12 * version 2.1 of the License.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * Additional permission is given to link this library with the
24 * OpenSSL project's "OpenSSL" library, and with the OCaml runtime,
25 * and you may distribute the linked executables. See the file
26 * LICENSE.libmojave for more details.
28 * Author: Jason Hickey
29 * @email{jyh@cs.caltech.edu}
33 #include <caml/signals.h>
34 #include <caml/mlvalues.h>
35 #include <caml/alloc.h>
36 #include <caml/memory.h>
37 #include <caml/custom.h>
38 #include <caml/fail.h>
40 #if defined(WIN32) || defined(_WIN32)
41 /* Disable some of the warnings */
42 #pragma warning( disable : 4100 4201 4127 4189 4702 4996 )
54 #define FLOCK_LEN ((unsigned int) ~0 >> 2)
57 * Print the stack pointer for debugging.
59 value
lm_print_stack_pointer(value v_arg
)
63 fprintf(stderr
, "Stack pointer: 0x%08lx\n", (unsigned long) &sp
);
71 #include "lm_compat_win32.h"
76 value
int_of_fd(value fd
)
78 return Val_long((long) *(HANDLE
*)Data_custom_val(fd
));
82 * Home directory on Win32.
84 value
home_win32(value v_unit
)
89 if(SUCCEEDED(CompatSHGetFolderPath(NULL
, CSIDL_LOCAL_APPDATA
| CSIDL_FLAG_CREATE
, NULL
, 0, path
)))
90 CAMLreturn(copy_string(path
));
92 failwith("home_win32");
106 value
lockf_win32(value v_fd
, value v_kind
, value v_len
)
108 HANDLE fd
= *(HANDLE
*)Data_custom_val(v_fd
);
109 int kind
= Int_val(v_kind
);
110 int len
= Int_val(v_len
);
111 OVERLAPPED overlapped
;
113 DWORD pos
, error
= 0;
115 /* Get the current position in the file */
116 pos
= SetFilePointer(fd
, 0, 0, FILE_CURRENT
);
118 /* XXX: HACK: we should probably compute this correctly */
124 UnlockFile(fd
, pos
, 0, len
, 0);
126 /* Some kind of locking operation */
129 flags
= LOCKFILE_EXCLUSIVE_LOCK
;
132 flags
= LOCKFILE_EXCLUSIVE_LOCK
| LOCKFILE_FAIL_IMMEDIATELY
;
138 flags
= LOCKFILE_FAIL_IMMEDIATELY
;
141 invalid_argument("lockf_win32");
146 memset(&overlapped
, 0, sizeof(overlapped
));
147 overlapped
.Offset
= pos
;
149 /* Perform the lock */
150 enter_blocking_section();
151 code
= LockFileEx(fd
, flags
, 0, len
, 0, &overlapped
);
153 error
= GetLastError();
154 leave_blocking_section();
156 /* Fail if the lock was not successful */
162 case ERROR_LOCK_FAILED
:
163 case ERROR_LOCK_VIOLATION
:
165 * XXX: HACK: this exception is being caught
166 * Do not change the string w/o changing the wrapper code.
168 failwith("lockf_win32: already locked");
170 case ERROR_POSSIBLE_DEADLOCK
:
172 * XXX: HACK: this exception is being caught
173 * Do not change the string w/o changing the wrapper code.
175 failwith("lockf_win32: possible deadlock");
179 FORMAT_MESSAGE_ALLOCATE_BUFFER
|
180 FORMAT_MESSAGE_FROM_SYSTEM
,
183 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
187 sprintf(szBuf
, "lockf_win32 failed with error %d: %s", error
, lpMsgBuf
);
199 * Translate flock operators.
201 static int lockf_of_flock
[] = {
212 value
lm_flock(value v_fd
, value v_op
)
216 v_kind
= Val_int(lockf_of_flock
[Int_val(v_op
)]);
217 return lockf_win32(v_fd
, v_kind
, Val_int(FLOCK_LEN
));
221 * Truncate to the current position.
223 value
ftruncate_win32(value v_fd
)
225 HANDLE fd
= *(HANDLE
*)Data_custom_val(v_fd
);
230 /************************************************************************
235 * Get the value of a registry key.
237 value
caml_registry_find(value v_hkey
, value v_subkey
, value v_field
)
240 const char *subkey
, *field
;
245 /* Get the arguments */
246 switch(Int_val(v_hkey
)) {
248 hkey
= HKEY_CLASSES_ROOT
;
251 hkey
= HKEY_CURRENT_CONFIG
;
254 hkey
= HKEY_CURRENT_USER
;
257 hkey
= HKEY_LOCAL_MACHINE
;
263 caml_failwith("get_registry: unknown handle");
268 subkey
= String_val(v_subkey
);
269 field
= String_val(v_field
);
270 len
= sizeof(buffer
);
273 code
= RegGetValue(hkey
, subkey
, field
, RRF_RT_REG_SZ
, NULL
, (LPVOID
) buffer
, &len
);
274 if(code
!= ERROR_SUCCESS
)
275 caml_raise_not_found();
280 code
= RegOpenKeyEx(hkey
, subkey
, 0, KEY_QUERY_VALUE
, &hand
);
281 if(code
!= ERROR_SUCCESS
)
282 caml_raise_not_found();
284 code
= RegQueryValueEx(hand
, field
, NULL
, NULL
, (LPBYTE
) buffer
, &len
);
286 if(code
!= ERROR_SUCCESS
)
287 caml_raise_not_found();
292 return copy_string(buffer
);
298 #include <sys/file.h>
299 #include <sys/types.h>
302 value
int_of_fd(value fd
)
307 value
home_win32(value v_unit
)
309 caml_failwith("home_win32: not to be used except on Win32");
313 value
lockf_win32(value v_fd
, value v_kind
, value v_len
)
315 caml_failwith("lockf_win32: not to be used except on Win32");
319 value
ftruncate_win32(value v_fd
)
321 caml_failwith("ftruncate_current_win32: not to be used except on Win32");
325 value
caml_registry_find(value v_key
, value v_subkey
, value v_field
)
327 caml_raise_not_found();
334 #if defined(LOCK_UN) && defined(LOCK_SH) && defined(LOCK_EX)
335 #define FLOCK_ENABLED
336 static int flock_of_flock
[] = {
345 #if defined(F_RDLCK) && defined(F_WRLCK) && defined(F_UNLCK) && defined(F_SETLK) && defined(F_SETLKW) && defined(SEEK_SET)
346 #define FCNTL_ENABLED
347 static int fcntl_type_of_flock
[] = {
355 static int fcntl_of_flock
[] = {
364 #if defined(F_ULOCK) && defined(F_LOCK) && defined(F_TLOCK)
365 #define LOCKF_ENABLED
366 static int lockf_of_flock
[] = {
375 value
lm_flock(value v_fd
, value v_op
)
377 int fd
, op
, cmd
, code
;
381 #if defined(FLOCK_ENABLED)
382 cmd
= flock_of_flock
[op
];
383 enter_blocking_section();
384 code
= flock(fd
, cmd
);
385 leave_blocking_section();
386 #elif defined(FCNTL_ENABLED)
389 cmd
= fcntl_of_flock
[op
];
390 info
.l_type
= fcntl_type_of_flock
[op
];
391 info
.l_whence
= SEEK_SET
;
393 info
.l_len
= FLOCK_LEN
;
394 enter_blocking_section();
395 code
= fcntl(fd
, cmd
, &info
);
396 leave_blocking_section();
398 #elif defined(LOCKF_ENABLED)
399 cmd
= lockf_of_flock
[op
];
400 enter_blocking_section();
401 code
= lockf(fd
, cmd
, FLOCK_LEN
);
402 leave_blocking_section();
413 /************************************************************************
414 * Password file (only on Unix).
421 value
lm_getpwents(value v_unit
)
423 return Val_emptylist
;
429 * Scan the password file.
431 type passwd_entry = {
441 value
lm_getpwents(value v_unit
)
444 CAMLlocal3(users
, entry
, cons
);
445 struct passwd
*entryp
;
447 /* Create a list of users */
448 users
= Val_emptylist
;
450 /* Scan the password file */
452 while((entryp
= getpwent())) {
453 entry
= caml_alloc_tuple(7);
454 Store_field(entry
, 0, caml_copy_string(entryp
->pw_name
));
455 Store_field(entry
, 1, caml_copy_string(entryp
->pw_passwd
));
456 Store_field(entry
, 2, Val_int(entryp
->pw_uid
));
457 Store_field(entry
, 3, Val_int(entryp
->pw_gid
));
459 Store_field(entry
, 4, copy_string(""));
461 Store_field(entry
, 4, copy_string(entryp
->pw_gecos
));
463 Store_field(entry
, 5, copy_string(entryp
->pw_dir
));
464 Store_field(entry
, 6, copy_string(entryp
->pw_shell
));
465 cons
= caml_alloc_tuple(2);
466 Store_field(cons
, 0, entry
);
467 Store_field(cons
, 1, users
);