···175175 set ptr csl;
176176 ptr
177177 end
178178+179179+ module String = struct
180180+ external set : ptr -> string -> unit = "ocaml_uring_set_string" [@@noalloc]
181181+182182+ let alloc t s =
183183+ let ptr = alloc t (String.length s + 1) in
184184+ set ptr s;
185185+ ptr
186186+ end
178187end
179188180189(* Used for the sendmsg/recvmsg calls. Liburing doesn't support sendto/recvfrom at the time of writing. *)
···228237 external submit_accept : t -> id -> Unix.file_descr -> Sockaddr.t -> bool = "ocaml_uring_submit_accept" [@@noalloc]
229238 external submit_cancel : t -> id -> id -> bool = "ocaml_uring_submit_cancel" [@@noalloc]
230239 external submit_openat2 : t -> id -> Unix.file_descr -> Open_how.t -> bool = "ocaml_uring_submit_openat2" [@@noalloc]
240240+ external submit_unlinkat : t -> id -> Unix.file_descr -> Sketch.ptr -> bool -> bool = "ocaml_uring_submit_unlinkat" [@@noalloc]
231241 external submit_send_msg : t -> id -> Unix.file_descr -> Msghdr.t -> Sketch.ptr -> bool = "ocaml_uring_submit_send_msg" [@@noalloc]
232242 external submit_recv_msg : t -> id -> Unix.file_descr -> Msghdr.t -> Sketch.ptr -> bool = "ocaml_uring_submit_recv_msg" [@@noalloc]
233243···357367 in
358368 let open_how = Open_how.v ~open_flags ~perm ~resolve path in
359369 with_id_full t (fun id -> Uring.submit_openat2 t.uring id fd open_how) user_data ~extra_data:open_how
370370+371371+let unlink t ~dir ?(fd=at_fdcwd) path user_data =
372372+ with_id t (fun id ->
373373+ let buf = Sketch.String.alloc t.sketch path in
374374+ Uring.submit_unlinkat t.uring id fd buf dir
375375+ ) user_data
360376361377let read t ~file_offset fd (buf : Cstruct.t) user_data =
362378 with_id_full t (fun id -> Uring.submit_read t.uring fd id buf file_offset) user_data ~extra_data:buf
+7
lib/uring/uring.mli
···145145 @param perm sets the access control bits for newly created files (subject to the process's umask)
146146 @param resolve controls how the pathname is resolved. *)
147147148148+val unlink : 'a t -> dir:bool -> ?fd:Unix.file_descr -> string -> 'a -> 'a job option
149149+(** [unlink t ~dir ~fd path] removes the directory entry [path], which is resolved relative to [fd].
150150+ If [fd] is not given, then the current working directory is used.
151151+ If [path] is a symlink, the link is removed, not the target.
152152+ @param dir If [true], this acts like [rmdir] (only removing empty directories).
153153+ If [false], it acts like [unlink] (only removing non-directories). *)
154154+148155module Poll_mask : sig
149156 include FLAGS
150157
+23
lib/uring/uring_stubs.c
···3333#include <string.h>
3434#include <poll.h>
3535#include <sys/uio.h>
3636+#include <fcntl.h>
3737+#include <unistd.h>
36383739#undef URING_DEBUG
3840#ifdef URING_DEBUG
···606608 sqe = io_uring_get_sqe(ring);
607609 if (!sqe) return (Val_false);
608610 io_uring_prep_accept(sqe, Int_val(v_fd), &(addr->sock_addr_addr.s_gen), &addr->sock_addr_len, SOCK_CLOEXEC);
611611+ io_uring_sqe_set_data(sqe, (void *)Long_val(v_id));
612612+ return (Val_true);
613613+}
614614+615615+value /* noalloc */
616616+ocaml_uring_set_string(value v_sketch_ptr, value v_string)
617617+{
618618+ char *dst = Sketch_ptr_val(v_sketch_ptr);
619619+ strcpy(dst, String_val(v_string));
620620+ return (Val_unit);
621621+}
622622+623623+// Caller must ensure the path pointed to by v_sketch_ptr is not GC'd until the job is finished.
624624+value /* noalloc */
625625+ocaml_uring_submit_unlinkat(value v_uring, value v_id, value v_fd, value v_sketch_ptr, value v_rmdir) {
626626+ struct io_uring *ring = Ring_val(v_uring);
627627+ struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
628628+ int flags = Bool_val(v_rmdir) ? AT_REMOVEDIR : 0;
629629+ char *path = Sketch_ptr_val(v_sketch_ptr);
630630+ if (!sqe) return (Val_false);
631631+ io_uring_prep_unlinkat(sqe, Int_val(v_fd), path, flags);
609632 io_uring_sqe_set_data(sqe, (void *)Long_val(v_id));
610633 return (Val_true);
611634}
+33
tests/main.md
···738738- : unit = ()
739739```
740740741741+## Unlink and rmdir
742742+743743+```ocaml
744744+# let t : unit Uring.t = Uring.create ~queue_depth:2 ();;
745745+val t : unit Uring.t = <abstr>
746746+747747+# close_out (open_out "test-file"); Unix.mkdir "test-dir" 0o700;;
748748+- : unit = ()
749749+750750+# let check () = Sys.file_exists "test-file", Sys.file_exists "test-dir";;
751751+val check : unit -> bool * bool = <fun>
752752+# check ();;
753753+- : bool * bool = (true, true)
754754+755755+# Uring.unlink t ~dir:false "test-file" ();;
756756+- : unit Uring.job option = Some <abstr>
757757+758758+# Uring.unlink t ~dir:true "test-dir" ();;
759759+- : unit Uring.job option = Some <abstr>
760760+761761+# Uring.wait t;;
762762+- : unit Uring.completion_option = Uring.Some {Uring.result = 0; data = ()}
763763+764764+# Uring.wait t;;
765765+- : unit Uring.completion_option = Uring.Some {Uring.result = 0; data = ()}
766766+767767+# check ();;
768768+- : bool * bool = (false, false)
769769+770770+# Uring.exit t;;
771771+- : unit = ()
772772+```
773773+741774## Sketch allocation
742775```ocaml
743776let ldup n x = List.init n (Fun.const x)