1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889openEio.Stdtypetristate=No|Yes|Unknown(* Note: [blocking] and [seekable] are not atomic,
but it doesn't matter if we query twice in rare cases. *)typet={fd:Rcfd.t;mutableblocking:tristate;mutableseekable:tristate;close_unix:bool;(* Whether closing this also closes the underlying FD. *)mutablerelease_hook:Eio.Switch.hook;(* Use this on close to remove switch's [on_release] hook. *)}leterr_closedop=Invalid_argument(op^": file descriptor used after calling close!")letusetf~if_closed=Rcfd.uset.fdf~if_closedletuse_exnoptf=Rcfd.uset.fdf~if_closed:(fun()->raise(err_closedop))letcloset=Switch.remove_hookt.release_hook;ift.close_unixthen(ifnot(Rcfd.closet.fd)thenraise(err_closed"close"))else(matchRcfd.removet.fdwith|Some_->()|None->raise(err_closed"close"))letremovet=Switch.remove_hookt.release_hook;Rcfd.removet.fdlettristate_of_bool_opt=function|None->Unknown|Sometrue->Yes|Somefalse->Noletof_unix_no_hook?(close_unix=true)?blocking?seekablefd=letseekable=tristate_of_bool_optseekableinletblocking=tristate_of_bool_optblockingin{fd=Rcfd.makefd;blocking;seekable;close_unix;release_hook=Switch.null_hook}letof_unix~sw?blocking?seekable~close_unixfd=lett=of_unix_no_hook?blocking?seekable~close_unixfdint.release_hook<-Switch.on_release_cancellablesw(fun()->closet);texternaleio_is_blocking:Unix.file_descr->bool="eio_unix_is_blocking"letis_blockingt=matcht.blockingwith|No->false|Yes->true|Unknown->uset~if_closed:(Fun.constfalse)@@funfd->letblocking=eio_is_blockingfdint.blocking<-ifblockingthenYeselseNo;blockingletis_seekablet=matcht.seekablewith|No->false|Yes->true|Unknown->uset~if_closed:(Fun.constfalse)@@funfd->letseekable=matchUnix.lseekfd0Unix.SEEK_CURwith|(_:int)->true|exceptionUnix.Unix_error(Unix.ESPIPE,"lseek","")->falseint.seekable<-ifseekablethenYeselseNo;seekableletrecuse_exn_listopxsk=matchxswith|[]->k[]|x::xs->use_exnopx@@funx->use_exn_listopxs@@funxs->k(x::xs)letstdin=of_unix_no_hookUnix.stdinletstdout=of_unix_no_hookUnix.stdoutletstderr=of_unix_no_hookUnix.stderrletppft=Rcfd.ppft.fd