PageRenderTime 132ms CodeModel.GetById 47ms RepoModel.GetById 10ms app.codeStats 1ms

/external/ocamllwt/src/unix/lwt_unix_unix.c

http://github.com/aryx/fork-ocsigen
C | 2293 lines | 1785 code | 345 blank | 163 comment | 126 complexity | 2a2ffa669eea87e64db275cf4ab250dd MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.0, LGPL-2.1, MIT, WTFPL

Large files files are truncated, but you can click here to view the full file

  1. /* Lightweight thread library for Objective Caml
  2. * http://www.ocsigen.org/lwt
  3. * Module Lwt_unix_unix
  4. * Copyright (C) 2009-2010 J?Šr?Šmie Dimino
  5. * 2009 Mauricio Fernandez
  6. * 2010 Pierre Chambart
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License as
  10. * published by the Free Software Foundation, with linking exceptions;
  11. * either version 2.1 of the License, or (at your option) any later
  12. * version. See COPYING file for details.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * 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.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  22. * 02111-1307, USA.
  23. */
  24. /* Unix (non windows) version of stubs. */
  25. /* +-----------------------------------------------------------------+
  26. | Test for readability/writability |
  27. +-----------------------------------------------------------------+ */
  28. #include <poll.h>
  29. CAMLprim value lwt_unix_readable(value fd)
  30. {
  31. struct pollfd pollfd;
  32. pollfd.fd = Int_val(fd);
  33. pollfd.events = POLLIN;
  34. pollfd.revents = 0;
  35. if (poll(&pollfd, 1, 0) < 0)
  36. uerror("readable", Nothing);
  37. return (Val_bool(pollfd.revents & POLLIN));
  38. }
  39. CAMLprim value lwt_unix_writable(value fd)
  40. {
  41. struct pollfd pollfd;
  42. pollfd.fd = Int_val(fd);
  43. pollfd.events = POLLOUT;
  44. pollfd.revents = 0;
  45. if (poll(&pollfd, 1, 0) < 0)
  46. uerror("readable", Nothing);
  47. return (Val_bool(pollfd.revents & POLLOUT));
  48. }
  49. /* +-----------------------------------------------------------------+
  50. | Memory mapped files |
  51. +-----------------------------------------------------------------+ */
  52. static int advise_table[] = {
  53. MADV_NORMAL,
  54. MADV_RANDOM,
  55. MADV_SEQUENTIAL,
  56. MADV_WILLNEED,
  57. MADV_DONTNEED,
  58. };
  59. CAMLprim value lwt_unix_madvise (value val_buffer, value val_offset, value val_length, value val_advice)
  60. {
  61. int ret = madvise((char*)Caml_ba_data_val(val_buffer) + Long_val(val_offset),
  62. Long_val(val_length),
  63. advise_table[Int_val(val_advice)]);
  64. if (ret == -1) uerror("madvise", Nothing);
  65. return Val_unit;
  66. }
  67. CAMLprim value lwt_unix_get_page_size()
  68. {
  69. long page_size = sysconf(_SC_PAGESIZE);
  70. if (page_size < 0) page_size = 4096;
  71. return Val_long(page_size);
  72. }
  73. CAMLprim value lwt_unix_mincore(value val_buffer, value val_offset, value val_length, value val_states)
  74. {
  75. long len = Wosize_val(val_states);
  76. unsigned char vec[len];
  77. mincore((char*)Caml_ba_data_val(val_buffer) + Long_val(val_offset), Long_val(val_length), vec);
  78. long i;
  79. for (i = 0; i < len; i++)
  80. Field(val_states, i) = Val_bool(vec[i] & 1);
  81. return Val_unit;
  82. }
  83. /* +-----------------------------------------------------------------+
  84. | read/write |
  85. +-----------------------------------------------------------------+ */
  86. CAMLprim value lwt_unix_read(value val_fd, value val_buf, value val_ofs, value val_len)
  87. {
  88. int ret;
  89. ret = read(Int_val(val_fd), &Byte(String_val(val_buf), Long_val(val_ofs)), Long_val(val_len));
  90. if (ret == -1) uerror("read", Nothing);
  91. return Val_int(ret);
  92. }
  93. CAMLprim value lwt_unix_bytes_read(value val_fd, value val_buf, value val_ofs, value val_len)
  94. {
  95. int ret;
  96. ret = read(Int_val(val_fd), (char*)Caml_ba_array_val(val_buf)->data + Long_val(val_ofs), Long_val(val_len));
  97. if (ret == -1) uerror("read", Nothing);
  98. return Val_int(ret);
  99. }
  100. CAMLprim value lwt_unix_write(value val_fd, value val_buf, value val_ofs, value val_len)
  101. {
  102. int ret;
  103. ret = write(Int_val(val_fd), &Byte(String_val(val_buf), Long_val(val_ofs)), Long_val(val_len));
  104. if (ret == -1) uerror("write", Nothing);
  105. return Val_int(ret);
  106. }
  107. CAMLprim value lwt_unix_bytes_write(value val_fd, value val_buf, value val_ofs, value val_len)
  108. {
  109. int ret;
  110. ret = write(Int_val(val_fd), (char*)Caml_ba_array_val(val_buf)->data + Long_val(val_ofs), Long_val(val_len));
  111. if (ret == -1) uerror("write", Nothing);
  112. return Val_int(ret);
  113. }
  114. /* +-----------------------------------------------------------------+
  115. | recv/send |
  116. +-----------------------------------------------------------------+ */
  117. static int msg_flag_table[] = {
  118. MSG_OOB, MSG_DONTROUTE, MSG_PEEK
  119. };
  120. value lwt_unix_recv(value fd, value buf, value ofs, value len, value flags)
  121. {
  122. int ret;
  123. ret = recv(Int_val(fd), &Byte(String_val(buf), Long_val(ofs)), Long_val(len),
  124. convert_flag_list(flags, msg_flag_table));
  125. if (ret == -1) uerror("recv", Nothing);
  126. return Val_int(ret);
  127. }
  128. value lwt_unix_bytes_recv(value fd, value buf, value ofs, value len, value flags)
  129. {
  130. int ret;
  131. ret = recv(Int_val(fd), (char*)Caml_ba_array_val(buf)->data + Long_val(ofs), Long_val(len),
  132. convert_flag_list(flags, msg_flag_table));
  133. if (ret == -1) uerror("recv", Nothing);
  134. return Val_int(ret);
  135. }
  136. value lwt_unix_send(value fd, value buf, value ofs, value len, value flags)
  137. {
  138. int ret;
  139. ret = send(Int_val(fd), &Byte(String_val(buf), Long_val(ofs)), Long_val(len),
  140. convert_flag_list(flags, msg_flag_table));
  141. if (ret == -1) uerror("send", Nothing);
  142. return Val_int(ret);
  143. }
  144. value lwt_unix_bytes_send(value fd, value buf, value ofs, value len, value flags)
  145. {
  146. int ret;
  147. ret = send(Int_val(fd), (char*)Caml_ba_array_val(buf)->data + Long_val(ofs), Long_val(len),
  148. convert_flag_list(flags, msg_flag_table));
  149. if (ret == -1) uerror("send", Nothing);
  150. return Val_int(ret);
  151. }
  152. /* +-----------------------------------------------------------------+
  153. | recvfrom/sendto |
  154. +-----------------------------------------------------------------+ */
  155. extern int socket_domain_table[];
  156. extern int socket_type_table[];
  157. union sock_addr_union {
  158. struct sockaddr s_gen;
  159. struct sockaddr_un s_unix;
  160. struct sockaddr_in s_inet;
  161. struct sockaddr_in6 s_inet6;
  162. };
  163. CAMLexport value alloc_sockaddr (union sock_addr_union * addr /*in*/,
  164. socklen_t addr_len, int close_on_error);
  165. value lwt_unix_recvfrom(value fd, value buf, value ofs, value len, value flags)
  166. {
  167. CAMLparam5(fd, buf, ofs, len, flags);
  168. CAMLlocal2(result, address);
  169. int ret;
  170. union sock_addr_union addr;
  171. socklen_t addr_len;
  172. addr_len = sizeof(addr);
  173. ret = recvfrom(Int_val(fd), &Byte(String_val(buf), Long_val(ofs)), Long_val(len),
  174. convert_flag_list(flags, msg_flag_table),
  175. &addr.s_gen, &addr_len);
  176. if (ret == -1) uerror("recvfrom", Nothing);
  177. address = alloc_sockaddr(&addr, addr_len, -1);
  178. result = caml_alloc_tuple(2);
  179. Field(result, 0) = Val_int(ret);
  180. Field(result, 1) = address;
  181. CAMLreturn(result);
  182. }
  183. value lwt_unix_bytes_recvfrom(value fd, value buf, value ofs, value len, value flags)
  184. {
  185. CAMLparam5(fd, buf, ofs, len, flags);
  186. CAMLlocal2(result, address);
  187. int ret;
  188. union sock_addr_union addr;
  189. socklen_t addr_len;
  190. addr_len = sizeof(addr);
  191. ret = recvfrom(Int_val(fd), (char*)Caml_ba_data_val(buf) + Long_val(ofs), Long_val(len),
  192. convert_flag_list(flags, msg_flag_table),
  193. &addr.s_gen, &addr_len);
  194. if (ret == -1) uerror("recvfrom", Nothing);
  195. address = alloc_sockaddr(&addr, addr_len, -1);
  196. result = caml_alloc_tuple(2);
  197. Field(result, 0) = Val_int(ret);
  198. Field(result, 1) = address;
  199. CAMLreturn(result);
  200. }
  201. extern void get_sockaddr (value mladdr,
  202. union sock_addr_union * addr /*out*/,
  203. socklen_t * addr_len /*out*/);
  204. value lwt_unix_sendto(value fd, value buf, value ofs, value len, value flags, value dest)
  205. {
  206. union sock_addr_union addr;
  207. socklen_t addr_len;
  208. int ret;
  209. get_sockaddr(dest, &addr, &addr_len);
  210. ret = sendto(Int_val(fd), &Byte(String_val(buf), Long_val(ofs)), Long_val(len),
  211. convert_flag_list(flags, msg_flag_table),
  212. &addr.s_gen, addr_len);
  213. if (ret == -1) uerror("send", Nothing);
  214. return Val_int(ret);
  215. }
  216. CAMLprim value lwt_unix_sendto_byte(value *argv, int argc)
  217. {
  218. return lwt_unix_sendto(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
  219. }
  220. value lwt_unix_bytes_sendto(value fd, value buf, value ofs, value len, value flags, value dest)
  221. {
  222. union sock_addr_union addr;
  223. socklen_t addr_len;
  224. int ret;
  225. get_sockaddr(dest, &addr, &addr_len);
  226. ret = sendto(Int_val(fd), (char*)Caml_ba_data_val(buf) + Long_val(ofs), Long_val(len),
  227. convert_flag_list(flags, msg_flag_table),
  228. &addr.s_gen, addr_len);
  229. if (ret == -1) uerror("send", Nothing);
  230. return Val_int(ret);
  231. }
  232. CAMLprim value lwt_unix_bytes_sendto_byte(value *argv, int argc)
  233. {
  234. return lwt_unix_bytes_sendto(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
  235. }
  236. /* +-----------------------------------------------------------------+
  237. | {recv/send}_msg |
  238. +-----------------------------------------------------------------+ */
  239. /* Convert a caml list of io-vectors into a C array io io-vector
  240. structures */
  241. static void store_iovs(struct iovec *iovs, value iovs_val)
  242. {
  243. CAMLparam0();
  244. CAMLlocal2(list, x);
  245. for(list = iovs_val; Is_block(list); list = Field(list, 1), iovs++) {
  246. x = Field(list, 0);
  247. iovs->iov_base = &Byte(String_val(Field(x, 0)), Long_val(Field(x, 1)));
  248. iovs->iov_len = Long_val(Field(x, 2));
  249. }
  250. CAMLreturn0;
  251. }
  252. static void bytes_store_iovs(struct iovec *iovs, value iovs_val)
  253. {
  254. CAMLparam0();
  255. CAMLlocal2(list, x);
  256. for(list = iovs_val; Is_block(list); list = Field(list, 1), iovs++) {
  257. x = Field(list, 0);
  258. iovs->iov_base = (char*)Caml_ba_data_val(Field(x, 0)) + Long_val(Field(x, 1));
  259. iovs->iov_len = Long_val(Field(x, 2));
  260. }
  261. CAMLreturn0;
  262. }
  263. static value wrapper_recv_msg(int fd, int n_iovs, struct iovec *iovs)
  264. {
  265. CAMLparam0();
  266. CAMLlocal3(list, result, x);
  267. struct msghdr msg;
  268. memset(&msg, 0, sizeof(msg));
  269. msg.msg_iov = iovs;
  270. msg.msg_iovlen = n_iovs;
  271. #if defined(HAVE_FD_PASSING)
  272. msg.msg_controllen = CMSG_SPACE(256 * sizeof(int));
  273. msg.msg_control = alloca(msg.msg_controllen);
  274. memset(msg.msg_control, 0, msg.msg_controllen);
  275. #endif
  276. int ret = recvmsg(fd, &msg, 0);
  277. if (ret == -1) uerror("recv_msg", Nothing);
  278. list = Val_int(0);
  279. #if defined(HAVE_FD_PASSING)
  280. struct cmsghdr *cm;
  281. for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm))
  282. if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) {
  283. int *fds = (int*)CMSG_DATA(cm);
  284. int nfds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
  285. int i;
  286. for(i = nfds - 1; i >= 0; i--) {
  287. x = caml_alloc_tuple(2);
  288. Store_field(x, 0, Val_int(fds[i]));
  289. Store_field(x, 1, list);
  290. list = x;
  291. };
  292. break;
  293. };
  294. #endif
  295. result = caml_alloc_tuple(2);
  296. Store_field(result, 0, Val_int(ret));
  297. Store_field(result, 1, list);
  298. CAMLreturn(result);
  299. }
  300. CAMLprim value lwt_unix_recv_msg(value val_fd, value val_n_iovs, value val_iovs)
  301. {
  302. int n_iovs = Int_val(val_n_iovs);
  303. struct iovec iovs[n_iovs];
  304. store_iovs(iovs, val_iovs);
  305. return wrapper_recv_msg(Int_val(val_fd), n_iovs, iovs);
  306. }
  307. CAMLprim value lwt_unix_bytes_recv_msg(value val_fd, value val_n_iovs, value val_iovs)
  308. {
  309. int n_iovs = Int_val(val_n_iovs);
  310. struct iovec iovs[n_iovs];
  311. bytes_store_iovs(iovs, val_iovs);
  312. return wrapper_recv_msg(Int_val(val_fd), n_iovs, iovs);
  313. }
  314. static value wrapper_send_msg(int fd, int n_iovs, struct iovec *iovs, value val_n_fds, value val_fds)
  315. {
  316. CAMLparam2(val_n_fds, val_fds);
  317. struct msghdr msg;
  318. memset(&msg, 0, sizeof(msg));
  319. msg.msg_iov = iovs;
  320. msg.msg_iovlen = n_iovs;
  321. #if defined(HAVE_FD_PASSING)
  322. int n_fds = Int_val(val_n_fds);
  323. if (n_fds > 0) {
  324. msg.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
  325. msg.msg_control = alloca(msg.msg_controllen);
  326. memset(msg.msg_control, 0, msg.msg_controllen);
  327. struct cmsghdr *cm;
  328. cm = CMSG_FIRSTHDR(&msg);
  329. cm->cmsg_level = SOL_SOCKET;
  330. cm->cmsg_type = SCM_RIGHTS;
  331. cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
  332. int *fds = (int*)CMSG_DATA(cm);
  333. for(; Is_block(val_fds); val_fds = Field(val_fds, 1), fds++)
  334. *fds = Int_val(Field(val_fds, 0));
  335. };
  336. #else
  337. if (n_fds > 0) lwt_unix_not_available("fd_passing");
  338. #endif
  339. int ret = sendmsg(fd, &msg, 0);
  340. if (ret == -1) uerror("send_msg", Nothing);
  341. CAMLreturn(Val_int(ret));
  342. }
  343. CAMLprim value lwt_unix_send_msg(value val_fd, value val_n_iovs, value val_iovs, value val_n_fds, value val_fds)
  344. {
  345. int n_iovs = Int_val(val_n_iovs);
  346. struct iovec iovs[n_iovs];
  347. store_iovs(iovs, val_iovs);
  348. return wrapper_send_msg(Int_val(val_fd), n_iovs, iovs, val_n_fds, val_fds);
  349. }
  350. CAMLprim value lwt_unix_bytes_send_msg(value val_fd, value val_n_iovs, value val_iovs, value val_n_fds, value val_fds)
  351. {
  352. int n_iovs = Int_val(val_n_iovs);
  353. struct iovec iovs[n_iovs];
  354. bytes_store_iovs(iovs, val_iovs);
  355. return wrapper_send_msg(Int_val(val_fd), n_iovs, iovs, val_n_fds, val_fds);
  356. }
  357. /* +-----------------------------------------------------------------+
  358. | Credentials |
  359. +-----------------------------------------------------------------+ */
  360. #if defined(HAVE_GET_CREDENTIALS)
  361. #include <sys/un.h>
  362. CAMLprim value lwt_unix_get_credentials(value fd)
  363. {
  364. CAMLparam1(fd);
  365. CAMLlocal1(res);
  366. struct ucred cred;
  367. socklen_t cred_len = sizeof(cred);
  368. if (getsockopt(Int_val(fd), SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) == -1)
  369. uerror("get_credentials", Nothing);
  370. res = caml_alloc_tuple(3);
  371. Store_field(res, 0, Val_int(cred.pid));
  372. Store_field(res, 1, Val_int(cred.uid));
  373. Store_field(res, 2, Val_int(cred.gid));
  374. CAMLreturn(res);
  375. }
  376. #endif
  377. /* +-----------------------------------------------------------------+
  378. | wait4 |
  379. +-----------------------------------------------------------------+ */
  380. /* Some code duplicated from OCaml's otherlibs/unix/wait.c */
  381. #include <sys/time.h>
  382. #include <sys/resource.h>
  383. #include <sys/wait.h>
  384. CAMLextern int caml_convert_signal_number (int);
  385. CAMLextern int caml_rev_convert_signal_number (int);
  386. #if !(defined(WIFEXITED) && defined(WEXITSTATUS) && defined(WIFSTOPPED) && \
  387. defined(WSTOPSIG) && defined(WTERMSIG))
  388. /* Assume old-style V7 status word */
  389. #define WIFEXITED(status) (((status) & 0xFF) == 0)
  390. #define WEXITSTATUS(status) (((status) >> 8) & 0xFF)
  391. #define WIFSTOPPED(status) (((status) & 0xFF) == 0xFF)
  392. #define WSTOPSIG(status) (((status) >> 8) & 0xFF)
  393. #define WTERMSIG(status) ((status) & 0x3F)
  394. #endif
  395. #define TAG_WEXITED 0
  396. #define TAG_WSIGNALED 1
  397. #define TAG_WSTOPPED 2
  398. static value alloc_process_status(int status)
  399. {
  400. value st;
  401. if (WIFEXITED(status)) {
  402. st = alloc_small(1, TAG_WEXITED);
  403. Field(st, 0) = Val_int(WEXITSTATUS(status));
  404. }
  405. else if (WIFSTOPPED(status)) {
  406. st = alloc_small(1, TAG_WSTOPPED);
  407. Field(st, 0) = Val_int(caml_rev_convert_signal_number(WSTOPSIG(status)));
  408. }
  409. else {
  410. st = alloc_small(1, TAG_WSIGNALED);
  411. Field(st, 0) = Val_int(caml_rev_convert_signal_number(WTERMSIG(status)));
  412. }
  413. return st;
  414. }
  415. static int wait_flag_table[] = {
  416. WNOHANG, WUNTRACED
  417. };
  418. value lwt_unix_wait4(value flags, value pid_req)
  419. {
  420. CAMLparam1(flags);
  421. CAMLlocal2(times, res);
  422. int pid, status, cv_flags;
  423. cv_flags = caml_convert_flag_list(flags, wait_flag_table);
  424. struct rusage ru;
  425. caml_enter_blocking_section();
  426. pid = wait4(Int_val(pid_req), &status, cv_flags, &ru);
  427. caml_leave_blocking_section();
  428. if (pid == -1) uerror("wait4", Nothing);
  429. times = alloc_small(2 * Double_wosize, Double_array_tag);
  430. Store_double_field(times, 0, ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6);
  431. Store_double_field(times, 1, ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6);
  432. res = caml_alloc_tuple(3);
  433. Store_field(res, 0, Val_int(pid));
  434. Store_field(res, 1, alloc_process_status(status));
  435. Store_field(res, 2, times);
  436. CAMLreturn(res);
  437. }
  438. value lwt_unix_has_wait4(value unit)
  439. {
  440. return Val_int(1);
  441. }
  442. /* +-----------------------------------------------------------------+
  443. | CPUs |
  444. +-----------------------------------------------------------------+ */
  445. #if defined(HAVE_GETCPU)
  446. CAMLprim value lwt_unix_get_cpu()
  447. {
  448. int cpu = sched_getcpu();
  449. if (cpu < 0) uerror("sched_getcpu", Nothing);
  450. return Val_int(cpu);
  451. }
  452. #endif
  453. #if defined(HAVE_AFFINITY)
  454. CAMLprim value lwt_unix_get_affinity(value val_pid)
  455. {
  456. CAMLparam1(val_pid);
  457. CAMLlocal2(list, node);
  458. cpu_set_t cpus;
  459. if (sched_getaffinity(Int_val(val_pid), sizeof(cpu_set_t), &cpus) < 0)
  460. uerror("sched_getaffinity", Nothing);
  461. int i;
  462. list = Val_int(0);
  463. for (i = sizeof(cpu_set_t) * 8 - 1; i >= 0; i--) {
  464. if (CPU_ISSET(i, &cpus)) {
  465. node = caml_alloc_tuple(2);
  466. Field(node, 0) = Val_int(i);
  467. Field(node, 1) = list;
  468. list = node;
  469. }
  470. }
  471. CAMLreturn(list);
  472. }
  473. CAMLprim value lwt_unix_set_affinity(value val_pid, value val_cpus)
  474. {
  475. cpu_set_t cpus;
  476. CPU_ZERO(&cpus);
  477. for (; Is_block(val_cpus); val_cpus = Field(val_cpus, 1))
  478. CPU_SET(Int_val(Field(val_cpus, 0)), &cpus);
  479. if (sched_setaffinity(Int_val(val_pid), sizeof(cpu_set_t), &cpus) < 0)
  480. uerror("sched_setaffinity", Nothing);
  481. return Val_unit;
  482. }
  483. #endif
  484. /* +-----------------------------------------------------------------+
  485. | JOB: guess_blocking |
  486. +-----------------------------------------------------------------+ */
  487. struct job_guess_blocking {
  488. struct lwt_unix_job job;
  489. int fd;
  490. int result;
  491. };
  492. #define Job_guess_blocking_val(v) *(struct job_guess_blocking**)Data_custom_val(v)
  493. static void worker_guess_blocking(struct job_guess_blocking *job)
  494. {
  495. struct stat stat;
  496. if (fstat(job->fd, &stat) == 0)
  497. job->result = !(S_ISFIFO(stat.st_mode) || S_ISSOCK(stat.st_mode));
  498. else
  499. job->result = 1;
  500. }
  501. CAMLprim value lwt_unix_guess_blocking_job(value val_fd)
  502. {
  503. struct job_guess_blocking *job = lwt_unix_new(struct job_guess_blocking);
  504. job->job.worker = (lwt_unix_job_worker)worker_guess_blocking;
  505. job->fd = Int_val(val_fd);
  506. return lwt_unix_alloc_job(&(job->job));
  507. }
  508. CAMLprim value lwt_unix_guess_blocking_result(value val_job)
  509. {
  510. struct job_guess_blocking *job = Job_guess_blocking_val(val_job);
  511. return Bool_val(job->result);
  512. }
  513. CAMLprim value lwt_unix_guess_blocking_free(value val_job)
  514. {
  515. struct job_guess_blocking *job = Job_guess_blocking_val(val_job);
  516. lwt_unix_free_job(&job->job);
  517. return Val_unit;
  518. }
  519. /* +-----------------------------------------------------------------+
  520. | JOB: wait_mincore |
  521. +-----------------------------------------------------------------+ */
  522. struct job_wait_mincore {
  523. struct lwt_unix_job job;
  524. char *ptr;
  525. };
  526. #define Job_wait_mincore_val(v) *(struct job_wait_mincore**)Data_custom_val(v)
  527. static void worker_wait_mincore(struct job_wait_mincore *job)
  528. {
  529. /* Read the byte to force the kernel to fetch the page: */
  530. char dummy = *(job->ptr);
  531. /* Make the compiler happy: */
  532. dummy = 0;
  533. }
  534. CAMLprim value lwt_unix_wait_mincore_job(value val_buffer, value val_offset)
  535. {
  536. struct job_wait_mincore *job = lwt_unix_new(struct job_wait_mincore);
  537. job->job.worker = (lwt_unix_job_worker)worker_wait_mincore;
  538. job->ptr = (char*)Caml_ba_data_val(val_buffer) + Long_val(val_offset);
  539. return lwt_unix_alloc_job(&(job->job));
  540. }
  541. CAMLprim value lwt_unix_wait_mincore_free(value val_job)
  542. {
  543. struct job_wait_mincore *job = Job_wait_mincore_val(val_job);
  544. lwt_unix_free_job(&job->job);
  545. return Val_unit;
  546. }
  547. /* +-----------------------------------------------------------------+
  548. | JOB: open |
  549. +-----------------------------------------------------------------+ */
  550. #ifndef O_NONBLOCK
  551. #define O_NONBLOCK O_NDELAY
  552. #endif
  553. #ifndef O_DSYNC
  554. #define O_DSYNC 0
  555. #endif
  556. #ifndef O_SYNC
  557. #define O_SYNC 0
  558. #endif
  559. #ifndef O_RSYNC
  560. #define O_RSYNC 0
  561. #endif
  562. static int open_flag_table[] = {
  563. O_RDONLY,
  564. O_WRONLY,
  565. O_RDWR,
  566. O_NONBLOCK,
  567. O_APPEND,
  568. O_CREAT,
  569. O_TRUNC,
  570. O_EXCL,
  571. O_NOCTTY,
  572. O_DSYNC,
  573. O_SYNC,
  574. O_RSYNC
  575. };
  576. struct job_open {
  577. struct lwt_unix_job job;
  578. char *path;
  579. int flags;
  580. int perms;
  581. int fd;
  582. int blocking;
  583. int error_code;
  584. };
  585. #define Job_open_val(v) *(struct job_open**)Data_custom_val(v)
  586. static void worker_open(struct job_open *job)
  587. {
  588. int fd;
  589. fd = open(job->path, job->flags, job->perms);
  590. job->fd = fd;
  591. job->error_code = errno;
  592. if (fd >= 0) {
  593. struct stat stat;
  594. if (fstat(fd, &stat) < 0)
  595. job->blocking = 1;
  596. else
  597. job->blocking = !(S_ISFIFO(stat.st_mode) || S_ISSOCK(stat.st_mode));
  598. }
  599. }
  600. CAMLprim value lwt_unix_open_job(value val_path, value val_flags, value val_perms)
  601. {
  602. struct job_open *job = lwt_unix_new(struct job_open);
  603. job->job.worker = (lwt_unix_job_worker)worker_open;
  604. job->path = lwt_unix_strdup(String_val(val_path));
  605. job->flags = convert_flag_list(val_flags, open_flag_table);
  606. job->perms = Int_val(val_perms);
  607. return lwt_unix_alloc_job(&(job->job));
  608. }
  609. CAMLprim value lwt_unix_open_result(value val_job)
  610. {
  611. struct job_open *job = Job_open_val(val_job);
  612. int fd = job->fd;
  613. if (fd < 0) unix_error(job->error_code, "open", Nothing);
  614. value result = caml_alloc_tuple(2);
  615. Field(result, 0) = Val_int(fd);
  616. Field(result, 1) = Val_bool(job->blocking);
  617. return result;
  618. }
  619. CAMLprim value lwt_unix_open_free(value val_job)
  620. {
  621. struct job_open *job = Job_open_val(val_job);
  622. free(job->path);
  623. lwt_unix_free_job(&job->job);
  624. return Val_unit;
  625. }
  626. /* +-----------------------------------------------------------------+
  627. | JOB: close |
  628. +-----------------------------------------------------------------+ */
  629. struct job_close {
  630. struct lwt_unix_job job;
  631. int fd;
  632. int result;
  633. int error_code;
  634. };
  635. #define Job_close_val(v) *(struct job_close**)Data_custom_val(v)
  636. static void worker_close(struct job_close *job)
  637. {
  638. job->result = close(job->fd);
  639. job->error_code = errno;
  640. }
  641. CAMLprim value lwt_unix_close_job(value val_fd)
  642. {
  643. struct job_close *job = lwt_unix_new(struct job_close);
  644. job->job.worker = (lwt_unix_job_worker)worker_close;
  645. job->fd = Int_val(val_fd);
  646. return lwt_unix_alloc_job(&(job->job));
  647. }
  648. CAMLprim value lwt_unix_close_result(value val_job)
  649. {
  650. struct job_close *job = Job_close_val(val_job);
  651. if (job->result < 0) unix_error(job->error_code, "close", Nothing);
  652. return Val_unit;
  653. }
  654. CAMLprim value lwt_unix_close_free(value val_job)
  655. {
  656. lwt_unix_free_job(&(Job_close_val(val_job))->job);
  657. return Val_unit;
  658. }
  659. /* +-----------------------------------------------------------------+
  660. | JOB: read |
  661. +-----------------------------------------------------------------+ */
  662. struct job_read {
  663. struct lwt_unix_job job;
  664. int fd;
  665. char *buffer;
  666. int length;
  667. int result;
  668. int error_code;
  669. };
  670. #define Job_read_val(v) *(struct job_read**)Data_custom_val(v)
  671. static void worker_read(struct job_read *job)
  672. {
  673. job->result = read(job->fd, job->buffer, job->length);
  674. job->error_code = errno;
  675. }
  676. CAMLprim value lwt_unix_read_job(value val_fd, value val_length)
  677. {
  678. struct job_read *job = lwt_unix_new(struct job_read);
  679. long length = Long_val(val_length);
  680. job->job.worker = (lwt_unix_job_worker)worker_read;
  681. job->fd = Int_val(val_fd);
  682. job->buffer = (char*)lwt_unix_malloc(length);
  683. job->length = length;
  684. return lwt_unix_alloc_job(&(job->job));
  685. }
  686. CAMLprim value lwt_unix_read_result(value val_job, value val_string, value val_offset)
  687. {
  688. struct job_read *job = Job_read_val(val_job);
  689. int result = job->result;
  690. if (result < 0) unix_error(job->error_code, "read", Nothing);
  691. memcpy(String_val(val_string) + Long_val(val_offset), job->buffer, result);
  692. return Val_long(result);
  693. }
  694. CAMLprim value lwt_unix_read_free(value val_job)
  695. {
  696. struct job_read *job = Job_read_val(val_job);
  697. free(job->buffer);
  698. lwt_unix_free_job(&job->job);
  699. return Val_unit;
  700. }
  701. /* +-----------------------------------------------------------------+
  702. | JOB: bytes_read |
  703. +-----------------------------------------------------------------+ */
  704. struct job_bytes_read {
  705. struct lwt_unix_job job;
  706. int fd;
  707. char *buffer;
  708. int length;
  709. int result;
  710. int error_code;
  711. };
  712. #define Job_bytes_read_val(v) *(struct job_bytes_read**)Data_custom_val(v)
  713. static void worker_bytes_read(struct job_bytes_read *job)
  714. {
  715. job->result = read(job->fd, job->buffer, job->length);
  716. job->error_code = errno;
  717. }
  718. CAMLprim value lwt_unix_bytes_read_job(value val_fd, value val_buf, value val_ofs, value val_len)
  719. {
  720. struct job_bytes_read *job = lwt_unix_new(struct job_bytes_read);
  721. job->job.worker = (lwt_unix_job_worker)worker_bytes_read;
  722. job->fd = Int_val(val_fd);
  723. job->buffer = (char*)Caml_ba_data_val(val_buf) + Long_val(val_ofs);
  724. job->length = Long_val(val_len);
  725. return lwt_unix_alloc_job(&(job->job));
  726. }
  727. CAMLprim value lwt_unix_bytes_read_result(value val_job)
  728. {
  729. struct job_bytes_read *job = Job_bytes_read_val(val_job);
  730. int result = job->result;
  731. if (result < 0) unix_error(job->error_code, "read", Nothing);
  732. return Val_long(result);
  733. }
  734. CAMLprim value lwt_unix_bytes_read_free(value val_job)
  735. {
  736. struct job_bytes_read *job = Job_bytes_read_val(val_job);
  737. lwt_unix_free_job(&job->job);
  738. return Val_unit;
  739. }
  740. /* +-----------------------------------------------------------------+
  741. | JOB: write |
  742. +-----------------------------------------------------------------+ */
  743. struct job_write {
  744. struct lwt_unix_job job;
  745. int fd;
  746. char *buffer;
  747. int length;
  748. int result;
  749. int error_code;
  750. };
  751. #define Job_write_val(v) *(struct job_write**)Data_custom_val(v)
  752. static void worker_write(struct job_write *job)
  753. {
  754. job->result = write(job->fd, job->buffer, job->length);
  755. job->error_code = errno;
  756. }
  757. CAMLprim value lwt_unix_write_job(value val_fd, value val_string, value val_offset, value val_length)
  758. {
  759. struct job_write *job = lwt_unix_new(struct job_write);
  760. long length = Long_val(val_length);
  761. job->job.worker = (lwt_unix_job_worker)worker_write;
  762. job->fd = Int_val(val_fd);
  763. job->buffer = (char*)lwt_unix_malloc(length);
  764. memcpy(job->buffer, String_val(val_string) + Long_val(val_offset), length);
  765. job->length = length;
  766. return lwt_unix_alloc_job(&(job->job));
  767. }
  768. CAMLprim value lwt_unix_write_result(value val_job)
  769. {
  770. struct job_write *job = Job_write_val(val_job);
  771. int result = job->result;
  772. if (result < 0) unix_error(job->error_code, "write", Nothing);
  773. return Val_long(result);
  774. }
  775. CAMLprim value lwt_unix_write_free(value val_job)
  776. {
  777. struct job_write *job = Job_write_val(val_job);
  778. free(job->buffer);
  779. lwt_unix_free_job(&job->job);
  780. return Val_unit;
  781. }
  782. /* +-----------------------------------------------------------------+
  783. | JOB: bytes_write |
  784. +-----------------------------------------------------------------+ */
  785. struct job_bytes_write {
  786. struct lwt_unix_job job;
  787. int fd;
  788. char *buffer;
  789. int length;
  790. int result;
  791. int error_code;
  792. };
  793. #define Job_bytes_write_val(v) *(struct job_bytes_write**)Data_custom_val(v)
  794. static void worker_bytes_write(struct job_bytes_write *job)
  795. {
  796. job->result = write(job->fd, job->buffer, job->length);
  797. job->error_code = errno;
  798. }
  799. CAMLprim value lwt_unix_bytes_write_job(value val_fd, value val_buffer, value val_offset, value val_length)
  800. {
  801. struct job_bytes_write *job = lwt_unix_new(struct job_bytes_write);
  802. job->job.worker = (lwt_unix_job_worker)worker_bytes_write;
  803. job->fd = Int_val(val_fd);
  804. job->buffer = (char*)Caml_ba_data_val(val_buffer) + Long_val(val_offset);
  805. job->length = Long_val(val_length);
  806. return lwt_unix_alloc_job(&(job->job));
  807. }
  808. CAMLprim value lwt_unix_bytes_write_result(value val_job)
  809. {
  810. struct job_bytes_write *job = Job_bytes_write_val(val_job);
  811. int result = job->result;
  812. if (result < 0) unix_error(job->error_code, "write", Nothing);
  813. return Val_long(result);
  814. }
  815. CAMLprim value lwt_unix_bytes_write_free(value val_job)
  816. {
  817. struct job_bytes_write *job = Job_bytes_write_val(val_job);
  818. lwt_unix_free_job(&job->job);
  819. return Val_unit;
  820. }
  821. /* +-----------------------------------------------------------------+
  822. | JOB: lseek |
  823. +-----------------------------------------------------------------+ */
  824. struct job_lseek {
  825. struct lwt_unix_job job;
  826. int fd;
  827. off_t offset;
  828. int command;
  829. off_t result;
  830. int error_code;
  831. };
  832. #define Job_lseek_val(v) *(struct job_lseek**)Data_custom_val(v)
  833. static int seek_command_table[] = {
  834. SEEK_SET, SEEK_CUR, SEEK_END
  835. };
  836. static void worker_lseek(struct job_lseek *job)
  837. {
  838. job->result = lseek(job->fd, job->offset, job->command);
  839. job->error_code = errno;
  840. }
  841. CAMLprim value lwt_unix_lseek_job(value val_fd, value val_offset, value val_command)
  842. {
  843. struct job_lseek *job = lwt_unix_new(struct job_lseek);
  844. job->job.worker = (lwt_unix_job_worker)worker_lseek;
  845. job->fd = Int_val(val_fd);
  846. job->offset = Long_val(val_offset);
  847. job->command = seek_command_table[Int_val(val_command)];
  848. return lwt_unix_alloc_job(&(job->job));
  849. }
  850. CAMLprim value lwt_unix_lseek_result(value val_job)
  851. {
  852. struct job_lseek *job = Job_lseek_val(val_job);
  853. off_t result = job->result;
  854. if (result < 0) unix_error(job->error_code, "lseek", Nothing);
  855. return Val_long(result);
  856. }
  857. CAMLprim value lwt_unix_lseek_free(value val_job)
  858. {
  859. struct job_lseek *job = Job_lseek_val(val_job);
  860. lwt_unix_free_job(&job->job);
  861. return Val_unit;
  862. }
  863. CAMLprim value lwt_unix_lseek_64_job(value val_fd, value val_offset, value val_command)
  864. {
  865. struct job_lseek *job = lwt_unix_new(struct job_lseek);
  866. job->job.worker = (lwt_unix_job_worker)worker_lseek;
  867. job->fd = Int_val(val_fd);
  868. job->offset = Int64_val(val_offset);
  869. job->command = seek_command_table[Int_val(val_command)];
  870. return lwt_unix_alloc_job(&(job->job));
  871. }
  872. CAMLprim value lwt_unix_lseek_64_result(value val_job)
  873. {
  874. struct job_lseek *job = Job_lseek_val(val_job);
  875. off_t result = job->result;
  876. if (result < 0) unix_error(job->error_code, "lseek", Nothing);
  877. return caml_copy_int64(result);
  878. }
  879. CAMLprim value lwt_unix_lseek_64_free(value val_job)
  880. {
  881. struct job_lseek *job = Job_lseek_val(val_job);
  882. lwt_unix_free_job(&job->job);
  883. return Val_unit;
  884. }
  885. /* +-----------------------------------------------------------------+
  886. | JOB: truncate |
  887. +-----------------------------------------------------------------+ */
  888. struct job_truncate {
  889. struct lwt_unix_job job;
  890. char *name;
  891. off_t offset;
  892. int result;
  893. int error_code;
  894. };
  895. #define Job_truncate_val(v) *(struct job_truncate**)Data_custom_val(v)
  896. static void worker_truncate(struct job_truncate *job)
  897. {
  898. job->result = truncate(job->name, job->offset);
  899. job->error_code = errno;
  900. }
  901. CAMLprim value lwt_unix_truncate_job(value val_name, value val_offset)
  902. {
  903. struct job_truncate *job = lwt_unix_new(struct job_truncate);
  904. job->job.worker = (lwt_unix_job_worker)worker_truncate;
  905. job->name = lwt_unix_strdup(String_val(val_name));
  906. job->offset = Long_val(val_offset);
  907. return lwt_unix_alloc_job(&(job->job));
  908. }
  909. CAMLprim value lwt_unix_truncate_result(value val_job)
  910. {
  911. struct job_truncate *job = Job_truncate_val(val_job);
  912. if (job->result < 0) unix_error(job->error_code, "truncate", Nothing);
  913. return Val_unit;
  914. }
  915. CAMLprim value lwt_unix_truncate_free(value val_job)
  916. {
  917. struct job_truncate *job = Job_truncate_val(val_job);
  918. free(job->name);
  919. lwt_unix_free_job(&job->job);
  920. return Val_unit;
  921. }
  922. CAMLprim value lwt_unix_truncate_64_job(value val_name, value val_offset)
  923. {
  924. struct job_truncate *job = lwt_unix_new(struct job_truncate);
  925. job->job.worker = (lwt_unix_job_worker)worker_truncate;
  926. job->name = lwt_unix_strdup(String_val(val_name));
  927. job->offset = Int64_val(val_offset);
  928. return lwt_unix_alloc_job(&(job->job));
  929. }
  930. CAMLprim value lwt_unix_truncate_64_result(value val_job)
  931. {
  932. struct job_truncate *job = Job_truncate_val(val_job);
  933. if (job->result < 0) unix_error(job->error_code, "truncate", Nothing);
  934. return Val_unit;
  935. }
  936. CAMLprim value lwt_unix_truncate_64_free(value val_job)
  937. {
  938. struct job_truncate *job = Job_truncate_val(val_job);
  939. free(job->name);
  940. lwt_unix_free_job(&job->job);
  941. return Val_unit;
  942. }
  943. /* +-----------------------------------------------------------------+
  944. | JOB: ftruncate |
  945. +-----------------------------------------------------------------+ */
  946. struct job_ftruncate {
  947. struct lwt_unix_job job;
  948. int fd;
  949. off_t offset;
  950. int result;
  951. int error_code;
  952. };
  953. #define Job_ftruncate_val(v) *(struct job_ftruncate**)Data_custom_val(v)
  954. static void worker_ftruncate(struct job_ftruncate *job)
  955. {
  956. job->result = ftruncate(job->fd, job->offset);
  957. job->error_code = errno;
  958. }
  959. CAMLprim value lwt_unix_ftruncate_job(value val_fd, value val_offset)
  960. {
  961. struct job_ftruncate *job = lwt_unix_new(struct job_ftruncate);
  962. job->job.worker = (lwt_unix_job_worker)worker_ftruncate;
  963. job->fd = Int_val(val_fd);
  964. job->offset = Long_val(val_offset);
  965. return lwt_unix_alloc_job(&(job->job));
  966. }
  967. CAMLprim value lwt_unix_ftruncate_result(value val_job)
  968. {
  969. struct job_ftruncate *job = Job_ftruncate_val(val_job);
  970. if (job->result < 0) unix_error(job->error_code, "ftruncate", Nothing);
  971. return Val_unit;
  972. }
  973. CAMLprim value lwt_unix_ftruncate_free(value val_job)
  974. {
  975. struct job_ftruncate *job = Job_ftruncate_val(val_job);
  976. lwt_unix_free_job(&job->job);
  977. return Val_unit;
  978. }
  979. CAMLprim value lwt_unix_ftruncate_64_job(value val_fd, value val_offset)
  980. {
  981. struct job_ftruncate *job = lwt_unix_new(struct job_ftruncate);
  982. job->job.worker = (lwt_unix_job_worker)worker_ftruncate;
  983. job->fd = Int_val(val_fd);
  984. job->offset = Int64_val(val_offset);
  985. return lwt_unix_alloc_job(&(job->job));
  986. }
  987. CAMLprim value lwt_unix_ftruncate_64_result(value val_job)
  988. {
  989. struct job_ftruncate *job = Job_ftruncate_val(val_job);
  990. if (job->result < 0) unix_error(job->error_code, "ftruncate", Nothing);
  991. return Val_unit;
  992. }
  993. CAMLprim value lwt_unix_ftruncate_64_free(value val_job)
  994. {
  995. struct job_ftruncate *job = Job_ftruncate_val(val_job);
  996. lwt_unix_free_job(&job->job);
  997. return Val_unit;
  998. }
  999. /* +-----------------------------------------------------------------+
  1000. | JOB: stat |
  1001. +-----------------------------------------------------------------+ */
  1002. struct job_stat {
  1003. struct lwt_unix_job job;
  1004. char *name;
  1005. struct stat stat;
  1006. int result;
  1007. int error_code;
  1008. };
  1009. #define Job_stat_val(v) *(struct job_stat**)Data_custom_val(v)
  1010. static value copy_stat(int use_64, struct stat *buf)
  1011. {
  1012. CAMLparam0();
  1013. CAMLlocal5(atime, mtime, ctime, offset, v);
  1014. atime = copy_double((double) buf->st_atime);
  1015. mtime = copy_double((double) buf->st_mtime);
  1016. ctime = copy_double((double) buf->st_ctime);
  1017. offset = use_64 ? caml_copy_int64(buf->st_size) : Val_int(buf->st_size);
  1018. v = alloc_small(12, 0);
  1019. Field(v, 0) = Val_int (buf->st_dev);
  1020. Field(v, 1) = Val_int (buf->st_ino);
  1021. switch (buf->st_mode & S_IFMT) {
  1022. case S_IFREG:
  1023. Field(v, 2) = Val_int(0);
  1024. break;
  1025. case S_IFDIR:
  1026. Field(v, 2) = Val_int(1);
  1027. break;
  1028. case S_IFCHR:
  1029. Field(v, 2) = Val_int(2);
  1030. break;
  1031. case S_IFBLK:
  1032. Field(v, 2) = Val_int(3);
  1033. break;
  1034. case S_IFLNK:
  1035. Field(v, 2) = Val_int(4);
  1036. break;
  1037. case S_IFIFO:
  1038. Field(v, 2) = Val_int(5);
  1039. break;
  1040. case S_IFSOCK:
  1041. Field(v, 2) = Val_int(6);
  1042. break;
  1043. default:
  1044. Field(v, 2) = Val_int(0);
  1045. break;
  1046. }
  1047. Field(v, 3) = Val_int(buf->st_mode & 07777);
  1048. Field(v, 4) = Val_int(buf->st_nlink);
  1049. Field(v, 5) = Val_int(buf->st_uid);
  1050. Field(v, 6) = Val_int(buf->st_gid);
  1051. Field(v, 7) = Val_int(buf->st_rdev);
  1052. Field(v, 8) = offset;
  1053. Field(v, 9) = atime;
  1054. Field(v, 10) = mtime;
  1055. Field(v, 11) = ctime;
  1056. CAMLreturn(v);
  1057. }
  1058. static void worker_stat(struct job_stat *job)
  1059. {
  1060. job->result = stat(job->name, &(job->stat));
  1061. job->error_code = errno;
  1062. }
  1063. CAMLprim value lwt_unix_stat_job(value val_name)
  1064. {
  1065. struct job_stat *job = lwt_unix_new(struct job_stat);
  1066. job->job.worker = (lwt_unix_job_worker)worker_stat;
  1067. job->name = lwt_unix_strdup(String_val(val_name));
  1068. return lwt_unix_alloc_job(&(job->job));
  1069. }
  1070. CAMLprim value lwt_unix_stat_result(value val_job)
  1071. {
  1072. struct job_stat *job = Job_stat_val(val_job);
  1073. if (job->result < 0) unix_error(job->error_code, "stat", Nothing);
  1074. return copy_stat(0, &(job->stat));
  1075. }
  1076. CAMLprim value lwt_unix_stat_free(value val_job)
  1077. {
  1078. struct job_stat *job = Job_stat_val(val_job);
  1079. free(job->name);
  1080. lwt_unix_free_job(&job->job);
  1081. return Val_unit;
  1082. }
  1083. CAMLprim value lwt_unix_stat_64_job(value val_name)
  1084. {
  1085. struct job_stat *job = lwt_unix_new(struct job_stat);
  1086. job->job.worker = (lwt_unix_job_worker)worker_stat;
  1087. job->name = lwt_unix_strdup(String_val(val_name));
  1088. return lwt_unix_alloc_job(&(job->job));
  1089. }
  1090. CAMLprim value lwt_unix_stat_64_result(value val_job)
  1091. {
  1092. struct job_stat *job = Job_stat_val(val_job);
  1093. if (job->result < 0) unix_error(job->error_code, "stat", Nothing);
  1094. return copy_stat(1, &(job->stat));
  1095. }
  1096. CAMLprim value lwt_unix_stat_64_free(value val_job)
  1097. {
  1098. struct job_stat *job = Job_stat_val(val_job);
  1099. free(job->name);
  1100. lwt_unix_free_job(&job->job);
  1101. return Val_unit;
  1102. }
  1103. /* +-----------------------------------------------------------------+
  1104. | JOB: lstat |
  1105. +-----------------------------------------------------------------+ */
  1106. struct job_lstat {
  1107. struct lwt_unix_job job;
  1108. char *name;
  1109. struct stat lstat;
  1110. int result;
  1111. int error_code;
  1112. };
  1113. #define Job_lstat_val(v) *(struct job_lstat**)Data_custom_val(v)
  1114. static void worker_lstat(struct job_lstat *job)
  1115. {
  1116. job->result = lstat(job->name, &(job->lstat));
  1117. job->error_code = errno;
  1118. }
  1119. CAMLprim value lwt_unix_lstat_job(value val_name)
  1120. {
  1121. struct job_lstat *job = lwt_unix_new(struct job_lstat);
  1122. job->job.worker = (lwt_unix_job_worker)worker_lstat;
  1123. job->name = lwt_unix_strdup(String_val(val_name));
  1124. return lwt_unix_alloc_job(&(job->job));
  1125. }
  1126. CAMLprim value lwt_unix_lstat_result(value val_job)
  1127. {
  1128. struct job_lstat *job = Job_lstat_val(val_job);
  1129. if (job->result < 0) unix_error(job->error_code, "lstat", Nothing);
  1130. return copy_stat(0, &(job->lstat));
  1131. }
  1132. CAMLprim value lwt_unix_lstat_free(value val_job)
  1133. {
  1134. struct job_lstat *job = Job_lstat_val(val_job);
  1135. free(job->name);
  1136. lwt_unix_free_job(&job->job);
  1137. return Val_unit;
  1138. }
  1139. CAMLprim value lwt_unix_lstat_64_job(value val_name)
  1140. {
  1141. struct job_lstat *job = lwt_unix_new(struct job_lstat);
  1142. job->job.worker = (lwt_unix_job_worker)worker_lstat;
  1143. job->name = lwt_unix_strdup(String_val(val_name));
  1144. return lwt_unix_alloc_job(&(job->job));
  1145. }
  1146. CAMLprim value lwt_unix_lstat_64_result(value val_job)
  1147. {
  1148. struct job_lstat *job = Job_lstat_val(val_job);
  1149. if (job->result < 0) unix_error(job->error_code, "lstat", Nothing);
  1150. return copy_stat(1, &(job->lstat));
  1151. }
  1152. CAMLprim value lwt_unix_lstat_64_free(value val_job)
  1153. {
  1154. struct job_lstat *job = Job_lstat_val(val_job);
  1155. free(job->name);
  1156. lwt_unix_free_job(&job->job);
  1157. return Val_unit;
  1158. }
  1159. /* +-----------------------------------------------------------------+
  1160. | JOB: fstat |
  1161. +-----------------------------------------------------------------+ */
  1162. struct job_fstat {
  1163. struct lwt_unix_job job;
  1164. int fd;
  1165. struct stat fstat;
  1166. int result;
  1167. int error_code;
  1168. };
  1169. #define Job_fstat_val(v) *(struct job_fstat**)Data_custom_val(v)
  1170. static void worker_fstat(struct job_fstat *job)
  1171. {
  1172. job->result = fstat(job->fd, &(job->fstat));
  1173. job->error_code = errno;
  1174. }
  1175. CAMLprim value lwt_unix_fstat_job(value val_fd)
  1176. {
  1177. struct job_fstat *job = lwt_unix_new(struct job_fstat);
  1178. job->job.worker = (lwt_unix_job_worker)worker_fstat;
  1179. job->fd = Int_val(val_fd);
  1180. return lwt_unix_alloc_job(&(job->job));
  1181. }
  1182. CAMLprim value lwt_unix_fstat_result(value val_job)
  1183. {
  1184. struct job_fstat *job = Job_fstat_val(val_job);
  1185. if (job->result < 0) unix_error(job->error_code, "fstat", Nothing);
  1186. return copy_stat(0, &(job->fstat));
  1187. }
  1188. CAMLprim value lwt_unix_fstat_free(value val_job)
  1189. {
  1190. struct job_fstat *job = Job_fstat_val(val_job);
  1191. lwt_unix_free_job(&job->job);
  1192. return Val_unit;
  1193. }
  1194. CAMLprim value lwt_unix_fstat_64_job(value val_fd)
  1195. {
  1196. struct job_fstat *job = lwt_unix_new(struct job_fstat);
  1197. job->job.worker = (lwt_unix_job_worker)worker_fstat;
  1198. job->fd = Int_val(val_fd);
  1199. return lwt_unix_alloc_job(&(job->job));
  1200. }
  1201. CAMLprim value lwt_unix_fstat_64_result(value val_job)
  1202. {
  1203. struct job_fstat *job = Job_fstat_val(val_job);
  1204. if (job->result < 0) unix_error(job->error_code, "fstat", Nothing);
  1205. return copy_stat(1, &(job->fstat));
  1206. }
  1207. CAMLprim value lwt_unix_fstat_64_free(value val_job)
  1208. {
  1209. struct job_fstat *job = Job_fstat_val(val_job);
  1210. lwt_unix_free_job(&job->job);
  1211. return Val_unit;
  1212. }
  1213. /* +-----------------------------------------------------------------+
  1214. | JOB: isatty |
  1215. +-----------------------------------------------------------------+ */
  1216. struct job_isatty {
  1217. struct lwt_unix_job job;
  1218. int fd;
  1219. int result;
  1220. };
  1221. #define Job_isatty_val(v) *(struct job_isatty**)Data_custom_val(v)
  1222. static void worker_isatty(struct job_isatty *job)
  1223. {
  1224. job->result = isatty(job->fd);
  1225. }
  1226. CAMLprim value lwt_unix_isatty_job(value val_fd)
  1227. {
  1228. struct job_isatty *job = lwt_unix_new(struct job_isatty);
  1229. job->job.worker = (lwt_unix_job_worker)worker_isatty;
  1230. job->fd = Int_val(val_fd);
  1231. return lwt_unix_alloc_job(&(job->job));
  1232. }
  1233. CAMLprim value lwt_unix_isatty_result(value val_job)
  1234. {
  1235. struct job_isatty *job = Job_isatty_val(val_job);
  1236. return Val_bool(job->result);
  1237. }
  1238. CAMLprim value lwt_unix_isatty_free(value val_job)
  1239. {
  1240. struct job_isatty *job = Job_isatty_val(val_job);
  1241. lwt_unix_free_job(&job->job);
  1242. return Val_unit;
  1243. }
  1244. /* +-----------------------------------------------------------------+
  1245. | JOB: unlink |
  1246. +-----------------------------------------------------------------+ */
  1247. struct job_unlink {
  1248. struct lwt_unix_job job;
  1249. char *name;
  1250. int result;
  1251. int error_code;
  1252. };
  1253. #define Job_unlink_val(v) *(struct job_unlink**)Data_custom_val(v)
  1254. static void worker_unlink(struct job_unlink *job)
  1255. {
  1256. job->result = unlink(job->name);
  1257. job->error_code = errno;
  1258. }
  1259. CAMLprim value lwt_unix_unlink_job(value val_name)
  1260. {
  1261. struct job_unlink *job = lwt_unix_new(struct job_unlink);
  1262. job->job.worker = (lwt_unix_job_worker)worker_unlink;
  1263. job->name = lwt_unix_strdup(String_val(val_name));
  1264. return lwt_unix_alloc_job(&(job->job));
  1265. }
  1266. CAMLprim value lwt_unix_unlink_result(value val_job)
  1267. {
  1268. struct job_unlink *job = Job_unlink_val(val_job);
  1269. if (job->result < 0) unix_error(job->error_code, "unlink", Nothing);
  1270. return Val_unit;
  1271. }
  1272. CAMLprim value lwt_unix_unlink_free(value val_job)
  1273. {
  1274. struct job_unlink *job = Job_unlink_val(val_job);
  1275. free(job->name);
  1276. lwt_unix_free_job(&job->job);
  1277. return Val_unit;
  1278. }
  1279. /* +-----------------------------------------------------------------+
  1280. | JOB: rename |
  1281. +-----------------------------------------------------------------+ */
  1282. struct job_rename {
  1283. struct lwt_unix_job job;
  1284. char *name1;
  1285. char *name2;
  1286. int result;
  1287. int error_code;
  1288. };
  1289. #define Job_rename_val(v) *(struct job_rename**)Data_custom_val(v)
  1290. static void worker_rename(struct job_rename *job)
  1291. {
  1292. job->result = rename(job->name1, job->name2);
  1293. job->error_code = errno;
  1294. }
  1295. CAMLprim value lwt_unix_rename_job(value val_name1, value val_name2)
  1296. {
  1297. struct job_rename *job = lwt_unix_new(struct job_rename);
  1298. job->job.worker = (lwt_unix_job_worker)worker_rename;
  1299. job->name1 = lwt_unix_strdup(String_val(val_name1));
  1300. job->name2 = lwt_unix_strdup(String_val(val_name2));
  1301. return lwt_unix_alloc_job(&(job->job));
  1302. }
  1303. CAMLprim value lwt_unix_rename_result(value val_job)
  1304. {
  1305. struct job_rename *job = Job_rename_val(val_job);
  1306. if (job->result < 0) unix_error(job->error_code, "rename", Nothing);
  1307. return Val_unit;
  1308. }
  1309. CAMLprim value lwt_unix_rename_free(value val_job)
  1310. {
  1311. struct job_rename *job = Job_rename_val(val_job);
  1312. free(job->name1);
  1313. free(job->name2);
  1314. lwt_unix_free_job(&job->job);
  1315. return Val_unit;
  1316. }
  1317. /* +-----------------------------------------------------------------+
  1318. | JOB: link |
  1319. +-----------------------------------------------------------------+ */
  1320. struct job_link {
  1321. struct lwt_unix_job job;
  1322. char *name1;
  1323. char *name2;
  1324. int result;
  1325. int error_code;
  1326. };
  1327. #define Job_link_val(v) *(struct job_link**)Data_custom_val(v)
  1328. static void worker_link(struct job_link *job)
  1329. {
  1330. job->result = link(job->name1, job->name2);
  1331. job->error_code = errno;
  1332. }
  1333. CAMLprim value lwt_unix_link_job(value val_name1, value val_name2)
  1334. {
  1335. struct job_link *job = lwt_unix_new(struct job_link);
  1336. job->job.worker = (lwt_unix_job_worker)worker_link;
  1337. job->name1 = lwt_unix_strdup(String_val(val_name1));
  1338. job->name2 = lwt_unix_strdup(String_val(val_name2));
  1339. return lwt_unix_alloc_job(&(job->job));
  1340. }
  1341. CAMLprim value lwt_unix_link_result(value val_job)
  1342. {
  1343. struct job_link *job = Job_link_val(val_job);
  1344. if (job->result < 0) unix_error(job->error_code, "link", Nothing);
  1345. return Val_unit;
  1346. }
  1347. CAMLprim value lwt_unix_link_free(value val_job)
  1348. {
  1349. struct job_link *job = Job_link_val(val_job);
  1350. free(job->name1);
  1351. free(job->name2);
  1352. lwt_unix_free_job(&job->job);
  1353. return Val_unit;
  1354. }
  1355. /* +-----------------------------------------------------------------+
  1356. | JOB: chmod |
  1357. +-----------------------------------------------------------------+ */
  1358. struct job_chmod {
  1359. struct lwt_unix_job job;
  1360. char *name;
  1361. int perms;
  1362. int result;
  1363. int error_code;
  1364. };
  1365. #define Job_chmod_val(v) *(struct job_chmod**)Data_custom_val(v)
  1366. static void worker_chmod(struct job_chmod *job)
  1367. {
  1368. job->result = chmod(job->name, job->perms);
  1369. job->error_code = errno;
  1370. }
  1371. CAMLprim value lwt_unix_chmod_job(value val_name, value val_perms)
  1372. {
  1373. struct job_chmod *job = lwt_unix_new(struct job_chmod);
  1374. job->job.worker = (lwt_unix_job_worker)worker_chmod;
  1375. job->name = lwt_unix_strdup(String_val(val_name));
  1376. job->perms = Int_val(val_perms);
  1377. return lwt_unix_alloc_job(&(job->job));
  1378. }
  1379. CAMLprim value lwt_unix_chmod_result(value val_job)
  1380. {
  1381. struct job_chmod *job = Job_chmod_val(val_job);
  1382. if (job->result < 0) unix_error(job->error_code, "chmod", Nothing);
  1383. return Val_unit;
  1384. }
  1385. CAMLprim value lwt_unix_chmod_free(value val_job)
  1386. {
  1387. struct job_chmod *job = Job_chmod_val(val_job);
  1388. free(job->name);
  1389. lwt_unix_free_job(&job->job);
  1390. return Val_unit;
  1391. }
  1392. /* +-----------------------------------------------------------------+
  1393. | JOB: fchmod |
  1394. +-----------------------------------------------------------------+ */
  1395. struct job_fchmod {
  1396. struct lwt_unix_job job;
  1397. int fd;
  1398. int perms;
  1399. int result;
  1400. int error_code;
  1401. };
  1402. #define Job_fchmod_val(v) *(struct job_fchmod**)Data_custom_val(v)
  1403. static void worker_fchmod(struct job_fchmod *job)
  1404. {
  1405. job->result = fchmod(job->fd, job->perms);
  1406. job->error_code = errno;
  1407. }
  1408. CAMLprim value lwt_unix_fchmod_job(value val_fd, value val_perms)
  1409. {
  1410. struct job_fchmod *job = lwt_unix_new(struct job_fchmod);
  1411. job->job.worker = (lwt_unix_job_worker)worker_fchmod;
  1412. job->fd = Int_val(val_fd);
  1413. job->perms = Int_val(val_perms);
  1414. return lwt_unix_alloc_job(&(job->job));
  1415. }
  1416. CAMLprim value lwt_unix_fchmod_result(value val_job)
  1417. {
  1418. struct job_fchmod *job = Job_fchmod_val(val_job);
  1419. if (job->result < 0) unix_error(job->error_code, "fchmod", Nothing);
  1420. return Val_unit;
  1421. }
  1422. CAMLprim value lwt_unix_fchmod_free(value val_job)
  1423. {
  1424. struct job_fchmod *job = Job_fchmod_val(val_job);
  1425. lwt_unix_free_job(&job->job);
  1426. return Val_unit;
  1427. }
  1428. /* +-----------------------------------------------------------------+
  1429. | JOB: chown |
  1430. +-----------------------------------------------------------------+ */
  1431. struct job_chown {
  1432. struct lwt_unix_job job;
  1433. char *name;
  1434. int uid;
  1435. int gid;
  1436. int result;
  1437. int error_code;
  1438. };
  1439. #define Job_chown_val(v) *(struct job_chown**)Data_custom_val(v)
  1440. static void worker_chown(struct job_chown *job)
  1441. {
  1442. job->result = chown(job->name, job->uid, job->gid);
  1443. job->error_code = errno;
  1444. }
  1445. CAMLprim value lwt_unix_chown_job(value val_name, value val_uid, value val_gid)
  1446. {
  1447. struct job_chown *job = lwt_unix_new(struct job_chown);
  1448. job->job.worker = (lwt_unix_job_worker)worker_chown;
  1449. job->name = lwt_unix_strdup(String_val(val_name));
  1450. job->uid = Int_val(val_uid);
  1451. job->gid = Int_val(val_gid);
  1452. return lwt_unix_alloc_job(&(job->job));
  1453. }
  1454. CAMLprim value lwt_unix_chown_result(value val_job)
  1455. {
  1456. struct job_chown *job = Job_chown_val(val_job);
  1457. if (job->result < 0) unix_error(job->error_code, "chown", Nothing);
  1458. return Val_unit;
  1459. }
  1460. CAMLprim value lwt_unix_chown_free(value val_job)
  1461. {
  1462. struct job_chown *job = Job_chown_val(val_job);
  1463. free(job->name);
  1464. lwt_unix_free_job(&job->job);
  1465. return Val_unit;
  1466. }
  1467. /* +-----------------------------------------------------------------+
  1468. | JOB: fchown |
  1469. +-----------------------------------------------------------------+ */
  1470. struct job_fchown {
  1471. struct lwt_unix_job job;
  1472. int fd;
  1473. int uid;
  1474. int gid;
  1475. int result;
  1476. int error_code;
  1477. };
  1478. #define Job_fchown_val(v) *(struct job_fchown**)Data_c

Large files files are truncated, but you can click here to view the full file