% Copyright 2018 <NAME>, Inc.
%
% Permission is hereby granted, free of charge, to any person
% obtaining a copy of this software and associated documentation files
% (the "Software"), to deal in the Software without restriction,
% including without limitation the rights to use, copy, modify, merge,
% publish, distribute, sublicense, and/or sell copies of the Software,
% and to permit persons to whom the Software is furnished to do so,
% subject to the following conditions:
%
% The above copyright notice and this permission notice shall be
% included in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
% BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
% SOFTWARE.

\chapter {Operating System Interface}\label{chap:osi}

\section {Introduction}

This chapter describes the operating system interface. Swish is
written in Chez Scheme and runs on Linux, macOS, and Windows. It
provides asynchronous I/O via libuv~\cite{libuv} and database support
via SQLite~\cite{sqlite-guide}.

\section {Theory of Operation}

The operating system interface is written in C99~\cite{c99} as a
shared library that links to the Chez Scheme, libuv, and SQLite
libraries. Please refer to Chapter~4 of the \emph{Chez Scheme Version
  9 User's Guide}~\cite{chez-scheme-users-guide} for information on
the foreign function interface. C++ is not used because C++
destructors may interact badly with setjmp/longjmp, used by Chez
Scheme and Swish.

The single-threaded version of Chez Scheme is used because of its
simplicity. All Scheme code runs in the main thread, and all C code
must call Scheme functions from the main thread only. In order to keep
this thread responsive, operations that block for more than a couple
milliseconds are performed asynchronously.

Operations that take longer should be run in a worker thread. Results
are communicated back to the main thread using a libuv async
handle. Beware of running long operations in the libuv thread pool
because there are only a few worker threads (four by default).

For each asynchronous function in the operating system interface, a
Scheme callback procedure is passed as the last argument.  This
callback procedure is later returned to Scheme in a list that includes
the results of the asynchronous function call. This approach is
simpler and more efficient than calling the callback procedure
directly from the C side.

Any time C code stores a pointer to a non-immediate Scheme object, the
object must be locked. The operating system interface locks Scheme
objects when it stores them in data structures managed in the C heap
and unlocks them when the data structures are deallocated.

The operating system interface uses port objects for files, console
input, pipes to other processes, and TCP/IP connections. A port object
is created by the various open functions, which return a port handle
that is used for read, write, and close operations. Once a port is
closed, its port object is freed.

Whenever Scheme receives a handle to an object allocated in the C
heap, the handle is wrapped in a Scheme record and registered with a
guardian. Each type of handle has an associated finalizer (see
\code{add-finalizer}) that uses its guardian to free the objects from
the C heap after each garbage collection (see the finalizer process in
\S\ref{finalizer-process}).

For interface functions that can fail, an error pair\index{error pair}
\code{(\var{who} . \var{errno})} is returned, where \var{who} is a
symbol representing the name of the particular function that failed
and \var{errno} is either an error number or, in the case of certain
SQLite functions, a pair whose car is the error number and cdr is the
English error string.

Section~\ref{sec:osi-api} describes the programming interface from the
C side. The Scheme library \code{(osi)} provides foreign procedures
for each C function using the same name. For functions that may return
an error pair, two Scheme procedures are defined: one that converts
the error pair into an exception, and one with an asterisk suffix that
returns the error pair. For example, if the \code{osi\_read\_port*}
procedure returns error pair \code{(\var{who} . \var{errno})}, the
\code{osi\_read\_port} procedure raises exception \code{\#(osi-error
  osi\_read\_port \var{who} \var{errno})}.

\section {Programming Interface}\label{sec:osi-api}

Unless otherwise noted, all C strings are encoded in UTF-8.

\subsection {C Interface}

A single libuv I/O loop is used, \code{osi\_loop}, which is unique to
the operating system interface in order to avoid collisions with other
libuv integrations.

\defineentry{osi\_init}
\begin{function}
  \code{void osi\_init(void);}
\end{function}

The \code{osi\_init} function disables libuv stdio inheritance,
initializes \code{osi\_loop}, initializes the timer used by
\code{osi\_get\_callbacks}, and sets the list of callbacks to
\code{()}. On Windows, it calls \code{timeBeginPeriod} to set the
timer resolution to 1 ms. This function must be called exactly once
from the main thread before any other \code{osi\_*} functions are
called.

\defineentry{osi\_add\_callback\_list}
\begin{function}
  \code{void osi\_add\_callback\_list(ptr \var{callback}, ptr \var{args});}
\end{function}

The \code{osi\_add\_callback\_list} function adds the callback list
\code{(\var{callback} . \var{args})} to the list of callbacks.
This function must be called only on the main thread and only within the
context of the event-loop's call to \code{osi\_get\_callbacks}, e.g., within a
libuv callback such as \code{uv\_async\_cb}.

\defineentry{osi\_add\_callback1}
\begin{function}
  \code{void osi\_add\_callback1(ptr \var{callback}, ptr \var{arg});}
\end{function}

The \code{osi\_add\_callback1} function adds the callback list
\code{(\var{callback} \var{arg})} to the list of callbacks.
This function must be called only on the main thread and only within the
context of the event-loop's call to \code{osi\_get\_callbacks}, e.g., within a
libuv callback such as \code{uv\_async\_cb}.

\defineentry{osi\_add\_callback2}
\begin{function}
  \code{void osi\_add\_callback2(ptr \var{callback}, ptr \var{arg1},
    ptr \var{arg2});}
\end{function}

The \code{osi\_add\_callback2} function adds the callback list
\code{(\var{callback} \var{arg1} \var{arg2})} to the list of
callbacks.
This function must be called only on the main thread and only within the
context of the event-loop's call to \code{osi\_get\_callbacks}, e.g., within a
libuv callback such as \code{uv\_async\_cb}.

\defineentry{osi\_add\_callback3}
\begin{function}
  \code{void osi\_add\_callback3(ptr \var{callback}, ptr \var{arg1},
    ptr \var{arg2}, ptr \var{arg3});}
\end{function}

The \code{osi\_add\_callback3} function adds the callback list
\code{(\var{callback} \var{arg1} \var{arg2} \var{arg3})} to the list
of callbacks.
This function must be called only on the main thread and only within the
context of the event-loop's call to \code{osi\_get\_callbacks}, e.g., within a
libuv callback such as \code{uv\_async\_cb}.

\defineentry{osi\_make\_error\_pair}
\begin{function}
  \code{ptr osi\_make\_error\_pair(const char* \var{who}, int \var{error});}
\end{function}

The \code{osi\_make\_error\_pair} function returns the error pair
\code{(\var{who} . \var{error})}. This function must be called on the
main thread only.

\defineentry{osi\_send\_request}
\begin{function}
  \code{int osi\_send\_request(handle\_request\_func \var{handler}, void* \var{payload});}
\end{function}

The \code{osi\_send\_request} function blocks the calling thread until
the main thread returns from calling
\code{\var{handler}(\var{payload})} within \code{osi\_get\_callbacks}.
The \var{handler} function should execute quickly to avoid blocking
the event loop. Typical handlers call \code{osi\_add\_callback\_list}
or one of its variants. \code{osi\_send\_request} returns zero if
successful.  Otherwise, it returns a libuv error code. Calling it from
the main thread returns \code{UV\_EPERM}.

\defineentry{osi\_string\_to\_utf8}
\begin{function}
  \code{char* osi\_string\_to\_utf8(ptr \var{s}, size\_t* \var{utf8\_len});}
\end{function}

The \code{osi\_string\_to\_utf8} function returns the address of a
freshly allocated nul-terminated string representing the Scheme string
\var{s}. The length in bytes of this string excluding the terminating
nul is written to \code{*\var{utf8\_len}}. It returns NULL if
\code{malloc} fails. It is the caller's responsibility to call
\code{free} when this memory is no longer needed.

\defineentry{swish\_run}
\begin{function}
  \code{int swish\_run(int \var{argc}, const char* \var{argv}[], void (*\var{custom\_init})(void));}
\end{function}

The \code{swish\_run} function:
\begin{enumerate} % keep in sync with swish_service
\item resolves the boot file based on
  \code{\var{argv}[0]} by replacing the extension, if any, with
  \code{.boot},
\item initializes Scheme by calling \code{Sscheme\_init},
  \code{Sregister\_boot\_file}, and \code{Sbuild\_heap},
\item initializes the operating system interface by calling \code{osi\_init},
\item establishes a context for \code{osi\_exit},
\item starts the application by invoking the value of the \code{scheme-start} parameter, and
\item returns the status provided by \code{osi\_exit}.
\end{enumerate}

\defineentry{swish\_service}\label{swishservice}
\begin{function}
  \codebegin
#if defined(\_\_linux\_\_)
int swish\_service(int \var{argc}, const char* \var{argv}[]);
#elif defined(\_WIN32)
int swish\_service(const wchar\_t* \var{service\_name}, const wchar\_t* \var{logfile},
                  int \var{argc}, const char* \var{argv}[]);
#endif \strut\codeend
\end{function}

On Linux, the \code{swish\_service} function:
\begin{enumerate} % keep in sync with swish_run
\item resolves the boot file based on
  \code{\var{argv}[0]} by replacing the extension, if any, with
  \code{.boot},
\item initializes Scheme by calling \code{Sscheme\_init},
  \code{Sregister\_boot\_file}, and \code{Sbuild\_heap},
\item initializes the operating system interface by calling \code{osi\_init},
\item adds a handler to listen for messages from
  \code{systemd-logind} on the D-Bus system bus,
\item establishes a context for \code{osi\_exit},
\item starts the application by invoking the value of the \code{scheme-start} parameter,
\item tears down the handler on exit, and
\item returns the status provided to \code{osi\_exit}.
\end{enumerate}

If the handler receives a \code{PrepareForShutdown} message with the argument
true, it calls \code{\$shutdown}.
If it receives a \code{PrepareForSleep} message, it calls
\code{\$suspend} if the argument is true
and \code{\$resume} if the argument is false.
See Figure~\ref{fig:service-callbacks} for information on these callbacks.

On Windows, the \code{swish\_service} function:
\begin{enumerate}
\item redirects stdout and stderr to \var{logfile} and stdin from NUL,
\item connects to the Service Control Manager, establishing a
  new thread of execution to:
  \begin{enumerate} % keep in sync with swish_run
    \item resolve the boot file based on \code{\var{argv}[0]} by
      replacing the extension, if any, with \code{.boot},
    \item initialize Scheme by calling \code{Sscheme\_init},
      \code{Sregister\_boot\_file}, and \code{Sbuild\_heap},
    \item initialize the operating system interface by calling \code{osi\_init},
    \item register a control handler with the Service Control Manager,
    \item establish a context for \code{osi\_exit}, and
    \item start the application by invoking the value of the
      \code{scheme-start} parameter
  \end{enumerate}
\item sets the service status to the status provided by \code{osi\_exit}.
\end{enumerate}

Once running as a service, the Service Control Manager may send
control messages to the process via the control handler. For a stop
message, the control handler calls the \code{\$shutdown} top-level
procedure.  For a suspend power event or resume power event, the
control handler calls \code{\$suspend} or \code{\$resume}
respectively.
See Figure~\ref{fig:service-callbacks} for information on these callbacks.

\begin{figure}[H]
\begin{tabular}{lll}
  symbol & default top-level value & with statistics gen-server~(Chapter \ref{chap:stats}) \\
  \hline
  \code{\$shutdown} & \code{application:shutdown} & \code{application:shutdown} \\
  \code{\$suspend} & \code{void} & \code{statistics:suspend} \\
  \code{\$resume} & \code{void} & \code{statistics:resume} \\
  \hline
\end{tabular}
\caption{Service callbacks. \label{fig:service-callbacks}}
\end{figure}

\subsection {System Functions and Procedures}

\defineentry{osi\_get\_argv}
\begin{function}
  \code{ptr osi\_get\_argv(void);}
\end{function}

The \code{osi\_get\_argv} function returns a Scheme vector of strings
constructed from the most recent arguments passed to
\code{osi\_set\_argv}.

\defineentry{osi\_get\_bytes\_used}
\begin{function}
  \code{size\_t osi\_get\_bytes\_used(void);}
\end{function}

The \code{osi\_get\_bytes\_used} function returns the number of bytes
used by the C run-time heap. On Linux, it calls the \code{mallinfo}
function. On macOS, it calls the \code{mstats} function. On Windows,
it calls the \code{\_heapwalk} function.

\defineentry{osi\_get\_free\_memory}
\begin{procedure}
  \code{(osi\_get\_free\_memory)}
\end{procedure}
\returns{} an unsigned integer

The \code{osi\_get\_free\_memory} procedure returns the number of bytes of free
memory as reported by \code{uv\_get\_free\_memory}.

\defineentry{osi\_get\_total\_memory}
\begin{procedure}
  \code{(osi\_get\_total\_memory)}
\end{procedure}
\returns{} an unsigned integer

The \code{osi\_get\_total\_memory} procedure returns the number of bytes of
total physical memory as reported by \code{uv\_get\_total\_memory}.

\defineentry{osi\_get\_callbacks}
\begin{function}
  \code{ptr osi\_get\_callbacks(uint64\_t \var{timeout});}
\end{function}

The \code{osi\_get\_callbacks} function returns a list of callback
lists in reverse order of time received. When the list is empty, it
blocks up to \var{timeout} milliseconds before returning. Each
callback list has the form \code{(\var{callback} \var{result} \etc)},
where \var{callback} is the callback procedure passed to the
asynchronous function that returned one or more \var{result}s.

\defineentry{osi\_get\_error\_text}
\begin{function}
  \code{const char* osi\_get\_error\_text(int \var{err});}
\end{function}

The \code{osi\_get\_error\_text} function returns the English string
for the given error number.

\defineentry{osi\_get\_hostname}
\begin{function}
  \code{ptr osi\_get\_hostname(void);}
\end{function}

The \code{osi\_get\_hostname} function returns the host name from
\code{uv\_os\_gethostname}.

\defineentry{osi\_get\_uname}
\begin{function}
  \code{ptr osi\_get\_uname(void);}
\end{function}

The \code{osi\_get\_uname} function returns a \code{<uname>} tuple
of the values retrieved by \code{uv\_os\_uname}.

\defineentry{\code{<uname>}}\label{uname-tuple}
\begin{tuple}\code{<uname>}\end{tuple}\antipar
\begin{argtbl}
  \argrow{system}{operating system name as a string}
  \argrow{release}{operating system release as a string}
  \argrow{version}{operating system version as a string}
  \argrow{machine}{hardware architecture identifier as a string}
\end{argtbl}

\defineentry{osi\_get\_hrtime}
\begin{function}
  uint64\_t \code{osi\_get\_hrtime(void);}
\end{function}

The \code{osi\_get\_hrtime} function returns the current
high-resolution real time in nanoseconds from \code{uv\_hrtime}. It is
not related to the time of day and is not subject to clock drift.

\defineentry{osi\_get\_time}
\begin{function}
  uint64\_t \code{osi\_get\_time(void);}
\end{function}

The \code{osi\_get\_time} function returns the current clock time in
milliseconds in UTC since the UNIX epoch January 1, 1970. On Windows,
it calls the \code{GetSystemTimeAsFileTime} function in
\texttt{kernel32.dll}. On all other systems, it calls the
\code{clock\_gettime} function with \code{CLOCK\_REALTIME}.

\defineentry{osi\_is\_quantum\_over}
\begin{function}
  \code{int osi\_is\_quantum\_over(void);}
\end{function}

The \code{osi\_is\_quantum\_over} function returns 1 if the current time
from \code{uv\_hrtime} is greater than or equal to the threshold set
by the most recent call to \code{osi\_set\_quantum} and 0 otherwise.

\defineentry{osi\_list\_uv\_handles}
\begin{function}
  \code{ptr osi\_list\_uv\_handles(void);}
\end{function}

The \code{osi\_list\_uv\_handles} function calls \code{uv\_walk} and
returns a list of pairs \code{(\var{handle} . \var{type})}, where
\var{handle} is the address of the \code{uv\_handle\_t} and \var{type}
is the \code{uv\_handle\_type}.

\defineentry{osi\_make\_uuid}
\begin{function}
  \code{ptr osi\_make\_uuid(void);}
\end{function}

The \code{osi\_make\_uuid} function returns a new universally unique
identifier (UUID) as a bytevector. On Windows, it calls the
\code{UuidCreate} function in \texttt{rpcrt4.dll}. On all other
systems, it calls the \code{uuid\_generate} function.

\defineentry{string->uuid}
\begin{procedure}
  \code{(string->uuid \var{s})}
\end{procedure}
\returns{} a UUID bytevector

The \code{string->uuid} procedure returns the bytevector \var{uuid}
for string \var{s} such that \code{(uuid->string \var{uuid})} is
equivalent to \var{s}, ignoring case. If \var{s} is not a string with
uppercase or lowercase hexadecimal digits and hyphens as shown in
\code{uuid->string}, exception \code{\#(bad-arg string->uuid \var{s})}
is raised.

\defineentry{uuid->string}
\begin{procedure}
  \code{(uuid->string \var{uuid})}
\end{procedure}
\returns{} a string

The \code{uuid->string} procedure returns the uppercase hexadecimal
string representation of \var{uuid},
$\var{HH}_3\var{HH}_2\var{HH}_1\var{HH}_0\code{-}\var{HH}_5\var{HH}_4\code{-}\var{HH}_7\var{HH}_6\code{-}\var{HH}_8\var{HH}_9\code{-}\var{HH}_{10}\var{HH}_{11}\var{HH}_{12}\var{HH}_{13}\var{HH}_{14}\var{HH}_{15}$,
where $\var{HH}_i$ is the 2-character uppercase hexadecimal
representation of the octet at index $i$ of bytevector \var{uuid}.  If
\var{uuid} is not a bytevector of length 16, exception
\code{\#(bad-arg uuid->string \var{uuid})} is raised.

\defineentry{osi\_set\_argv}
\begin{function}
  \code{void osi\_set\_argv(int \var{argc}, const char *\var{argv}[]);}
\end{function}

The \code{osi\_set\_argv} function stores the \var{argv} pointer to a
C vector of \var{argc} strings for use in the \code{osi\_get\_argv}
function. It does not copy the strings, so the caller must not
deallocate the memory for the arguments.

\defineentry{osi\_set\_quantum}
\begin{function}
  \code{void osi\_set\_quantum(uint64\_t \var{nanoseconds});}
\end{function}

The \code{osi\_set\_quantum} function sets the threshold for
\code{osi\_is\_quantum\_over} to be the current time from
\code{uv\_hrtime} plus the given number of \var{nanoseconds}.

\subsection {Port Functions}

The port functions in this section provide generic read, write, and
close operations for port objects. The specific implementation depends
on the type of port object.

Port handles point to structures whose first element is a pointer to a
virtual function table whose type is \code{osi\_port\_vtable\_t}. This
table defines the specific \code{close}, \code{read}, and \code{write}
procedures.

\defineentry{osi\_read\_port}
\begin{function}
\codebegin
ptr osi\_read\_port(uptr \var{port}, ptr \var{buffer}, size\_t \var{start\_index}, uint32\_t \var{size},\strut
       \     \      int64\_t \var{offset}, ptr \var{callback});\strut
\codeend
\end{function}

The \code{osi\_read\_port} function issues a read on the given
\var{port} of \var{size} bytes into the bytevector \var{buffer} at the
zero-based \var{start\_index}. For file ports, \var{offset} specifies
the starting file position or $-1$ for the current position; for all
other port types, \var{offset} must be $-1$.  The function returns
\code{\#t} when the read operation is issued and an error pair
otherwise. When the read operation finishes, it enqueues the callback
list \code{(\var{callback} \var{result})}, where \var{result} is the
nonnegative number of bytes read when successful and a negative error
code otherwise.

\defineentry{osi\_write\_port}
\begin{function}
\codebegin
ptr osi\_write\_port(uptr \var{port}, ptr \var{buffer}, size\_t \var{start\_index}, uint32\_t \var{size},\strut
       \      \      int64\_t \var{offset}, ptr \var{callback});\strut
\codeend\end{function}

The \code{osi\_write\_port} function issues a write on the given
\var{port} of \var{size} bytes from the bytevector \var{buffer} at the
zero-based \var{start\_index}. For file ports, \var{offset} specifies
the starting file position or $-1$ for the current position; for all
other port types, \var{offset} must be $-1$.  The function returns
\code{\#t} when the write operation is issued and an error pair
otherwise. When the write operation finishes, it enqueues the callback
list \code{(\var{callback} \var{result})}, where \var{result} is the
nonnegative number of bytes written when successful and a negative
error code otherwise.

\defineentry{osi\_close\_port}
\begin{function}
  \code{ptr osi\_close\_port(uptr \var{port}, ptr \var{callback});}
\end{function}

The \code{osi\_close\_port} function issues a close on the given
\var{port}. It returns \code{\#t} when the close operation is issued
and an error pair otherwise. When the close operation finishes, it
deallocates the port object and enqueues the callback list
\code{(\var{callback} \var{errno})}, where \var{errno} is 0 when
successful and a negative error code otherwise.

\subsection {Process Functions}

\defineentry{osi\_exit}
\begin{function}
  \code{void osi\_exit(int \var{status});}
\end{function}

The \code{osi\_exit} function returns \var{status} to the context
established by \code{swish\_run} or \code{swish\_service}, if any.
Otherwise it calls the \code{\_exit} function to terminate the current
process with the given exit \var{status}. It does not return. The
\code{exit} function is not used because on Unix systems it blocks if
there is an outstanding read on stdin.

\defineentry{osi\_spawn}
\begin{function}
  \code{ptr osi\_spawn(const char* \var{path}, ptr \var{args}, ptr \var{callback});}
\end{function}

The \code{osi\_spawn} function uses the \code{uv\_spawn} function to
create a process with the list of string-valued \var{args} whose
standard input, output and error are connected to pipes.  It returns
\code{\#(\var{to-stdin} \var{from-stdout} \var{from-stderr}
  \var{pid})} when the process has been successfully created and an
error pair otherwise.  \var{to-stdin} is a port handle for writing
bytes to standard input, \var{from-stdout} is a port handle for
reading bytes from standard output, \var{from-stderr} is a port handle
for reading bytes from standard error, and \var{pid} is an integer
identifying the process.

When the process exits, the callback list \code{(\var{callback}
  \var{pid} \var{exit-status} \var{term-signal})} is enqueued, where
\var{pid} is the integer process identifier, \var{exit-status} is the
integer exit status, and \var{term-signal} is the integer termination
signal or 0 if the process did not terminate because of a signal.

\defineentry{osi\_spawn\_detached}
\begin{function}
  \code{ptr osi\_spawn\_detached(const char* \var{path}, ptr \var{args});}
\end{function}

The \code{osi\_spawn\_detached} function uses the \code{uv\_spawn}
function to create a process with the list of string-valued \var{args}
and the \code{UV\_PROCESS\_DETACHED} flag set. It returns an integer
identifying the process when the process has been successfully created
and an error pair otherwise.

\defineentry{osi\_get\_pid}
\begin{function}
  \code{int osi\_get\_pid();}
\end{function}

The \code{osi\_get\_pid} function uses the \code{uv\_os\_getpid}
function to return the current operating-system process ID.

\defineentry{osi\_kill}
\begin{function}
  \code{ptr osi\_kill(int \var{pid}, int \var{signum});}
\end{function}

The \code{osi\_kill} function uses the \code{uv\_kill} function to
send termination signal \var{signum} to the process identified by
\var{pid}. It returns \code{\#t} when successful and an error pair
otherwise.

\defineentry{osi\_start\_signal}
\begin{function}
  \code{ptr osi\_start\_signal(int \var{signum});}
\end{function}

The \code{osi\_start\_signal} function uses the \code{uv\_signal\_start}
function to trap the signal \var{signum}.
It returns a signal handle when successful and an error pair
otherwise.
Signals are delivered via the internal \code{@deliver-signal} procedure, which
invokes the handler registered via \code{signal-handler}.

\defineentry{osi\_stop\_signal}
\begin{function}
  \code{ptr osi\_stop\_signal(uptr \var{signal\_handle});}
\end{function}

The \code{osi\_stop\_signal} function stops trapping the signal
and frees the signal handle returned by \code{osi\_start\_signal}.

\subsection {File System Functions}

\defineentry{osi\_open\_fd}
\begin{function}
  \code{ptr osi\_open\_fd(int \var{fd}, int \var{close});}
\end{function}

The \code{osi\_open\_fd} function returns a port handle for the file
descriptor \var{fd} when successful and an error pair otherwise. When
the port is closed, the file descriptor \var{fd} is closed if and only
if \var{close} is non-zero. It is an error to set \var{close} to a
non-zero value on a standard I/O file descriptor ($0 \le \var{fd} \le
2$).

\defineentry{osi\_open\_file}
\begin{function}
  \code{ptr osi\_open\_file(const char* \var{path}, int \var{flags}, int \var{mode}, ptr \var{callback});}
\end{function}

The \code{osi\_open\_file} function issues an open using the
\code{uv\_fs\_open} function and the given \var{path}, \var{flags},
and \var{mode}. It returns \code{\#t} when the open operation is
issued and an error pair otherwise. When the open operation finishes,
it enqueues the callback list \code{(\var{callback} \var{result})},
where \var{result} is the nonnegative port handle when successful and
a negative error code otherwise.

The following constants are defined for \var{flags}:

\begin{tabular}{llllll}
  \code{O\_APPEND}&
  \code{O\_CREAT}&
  \code{O\_DIRECT}&
  \code{O\_DIRECTORY}&
  \code{O\_DSYNC}&
  \code{O\_EXCL}\\
  \code{O\_EXLOCK}&
  \code{O\_NOATIME}&
  \code{O\_NOCTTY}&
  \code{O\_NOFOLLOW}&
  \code{O\_NONBLOCK}&
  \code{O\_RANDOM}\\
  \code{O\_RDONLY}&
  \code{O\_RDWR}&
  \code{O\_SEQUENTIAL}&
  \code{O\_SHORT\_LIVED}&
  \code{O\_SYMLINK}&
  \code{O\_SYNC}\\
  \code{O\_TEMPORARY}&
  \code{O\_TRUNC}&
  \code{O\_WRONLY}\\
\end{tabular}

The following constants are defined for \var{mode}:

\begin{tabular}{llllllll}
  \code{S\_IFMT}&
  \code{S\_IFIFO}&
  \code{S\_IFCHR}&
  \code{S\_IFDIR}&
  \code{S\_IFBLK}&
  \code{S\_IFREG}&
  \code{S\_IFLNK}&
  \code{S\_IFSOCK}\\
\end{tabular}

\defineentry{osi\_get\_executable\_path}
\begin{function}
  \code{ptr osi\_get\_executable\_path(void);}
\end{function}

The \code{osi\_get\_executable\_path} function uses the
\code{uv\_exepath} function to return the full path string of the
executable file of the current process when successful and an error
pair otherwise.

\defineentry{osi\_get\_file\_size}
\begin{function}
  \code{ptr osi\_get\_file\_size(uptr \var{port}, ptr \var{callback});}
\end{function}

The \code{osi\_get\_file\_size} function uses the \code{uv\_fs\_fstat}
function to issue a status operation on the file associated with the
given file \var{port}. It returns \code{\#t} when the status operation
is issued and an error pair otherwise. When the status operation
finishes, it enqueues the callback list \code{(\var{callback}
  \var{result})}, where \var{result} is the nonnegative file size when
successful and a negative error code otherwise.

\defineentry{osi\_get\_real\_path}
\begin{function}
  \code{ptr osi\_get\_real\_path(const char* \var{path}, ptr \var{callback});}
\end{function}

The \code{osi\_get\_real\_path} function uses the
\code{uv\_fs\_realpath} function to issue a realpath operation on the
given \var{path}. It returns \code{\#t} when the realpath operation is
issued and an error pair otherwise. When the realpath operation
finishes, it enqueues the callback list \code{(\var{callback}
  \var{result})}, where \var{result} is the string path when
successful and a negative error code otherwise.

\defineentry{osi\_get\_home\_directory}
\begin{function}
  \code{ptr osi\_get\_home\_directory(void);}
\end{function}

The \code{osi\_get\_home\_directory} function uses the
\code{uv\_os\_homedir} function to return the string path of the
current user's home directory and an error pair otherwise.

\defineentry{osi\_get\_temp\_directory}
\begin{function}
  \code{ptr osi\_get\_temp\_directory(void);}
\end{function}

The \code{osi\_get\_temp\_directory} function uses the
\code{uv\_os\_tmpdir} function to return the string path of the
temporary directory and an error pair otherwise.

\defineentry{osi\_chmod}
\begin{function}
  \code{ptr osi\_chmod(const char* \var{path}, int \var{mode}, ptr \var{callback});}
\end{function}

The \code{osi\_chmod} function issues a chmod operation using the
\code{uv\_fs\_chmod} function and the given \var{path} and
\var{mode}. It returns \code{\#t} when the chmod operation is issued
and an error pair otherwise. When the chmod operation finishes, it
enqueues the callback list \code{(\var{callback} \var{errno})}, where
\var{errno} is 0 when successful and a negative error code otherwise.

\defineentry{osi\_make\_directory}
\begin{function}
  \code{ptr osi\_make\_directory(const char* \var{path}, int \var{mode}, ptr \var{callback});}
\end{function}

The \code{osi\_make\_directory} function issues a mkdir operation
using the \code{uv\_fs\_mkdir} function with the given \var{path} and
\var{mode}. It returns \code{\#t} when the mkdir operation is issued
and an error pair otherwise. When the mkdir operation finishes, it
enqueues the callback list \code{(\var{callback} \var{errno})}, where
\var{errno} is 0 when successful and a negative error code otherwise.

\defineentry{osi\_list\_directory}
\begin{function}
  \code{ptr osi\_list\_directory(const char* \var{path}, ptr \var{callback});}
\end{function}

The \code{osi\_list\_directory} function issues a scandir operation
using the \code{uv\_fs\_scandir} function with the given
\var{path}. It returns \code{\#t} when the scandir operation is issued
and an error pair otherwise. When the scandir operation finishes, it
enqueues the callback list \code{(\var{callback} \var{result})}, where
\var{result} is \code{((\var{name} . \var{type}) \etc)} when successful and
a negative error code otherwise.

\var{name} is the string name of the directory entry, and \var{type}
is one of the following constants:

\begin{tabular}{lllll}
\code{DIRENT\_UNKNOWN}&
\code{DIRENT\_FILE}&
\code{DIRENT\_DIR}&
\code{DIRENT\_LINK}&
\code{DIRENT\_FIFO}\\
\code{DIRENT\_SOCKET}&
\code{DIRENT\_CHAR}&
\code{DIRENT\_BLOCK}
\end{tabular}

\defineentry{osi\_remove\_directory}
\begin{function}
  \code{ptr osi\_remove\_directory(const char* \var{path}, ptr \var{callback});}
\end{function}

The \code{osi\_remove\_directory} function issues a rmdir operation
using the \code{uv\_fs\_rmdir} function with the given \var{path}. It
returns \code{\#t} when the rmdir operation is issued and an error
pair otherwise. When the rmdir operation finishes, it enqueues the
callback list \code{(\var{callback} \var{errno})}, where \var{errno}
is 0 when successful and a negative error code otherwise.

\defineentry{osi\_rename}
\begin{function}
  \code{ptr osi\_rename(const char* \var{path}, const char* \var{new\_path}, ptr \var{callback});}
\end{function}

The \code{osi\_rename} function issues a rename operation using the
\code{uv\_fs\_rename} function of \var{path} to \var{new\_path}. It
returns \code{\#t} when the rename operation is issued and an error
pair otherwise. When the rename operation finishes, it enqueues the
callback list \code{(\var{callback} \var{errno})}, where \var{errno}
is 0 when successful and a negative error code otherwise.

\defineentry{osi\_get\_stat}
\begin{function}
  \code{ptr osi\_get\_stat(const char* \var{path}, int \var{follow}, ptr \var{callback});}
\end{function}

The \code{osi\_get\_stat} function issues a status operation on the
given \var{path}. When \var{follow} is non-zero, it uses the
\code{uv\_fs\_stat} function to follow a symbolic link; otherwise, it
uses the \code{uv\_fs\_lstat} function. It returns \code{\#t} when the
status operation is issued and an error pair otherwise. When the
status operation finishes, it enqueues the callback list
\code{(\var{callback} \var{result})}, where \var{result} is a
\code{<stat>} tuple when successful and a negative error code
otherwise.

\defineentry{\code{<stat>}}
\begin{tuple}\code{<stat>}\end{tuple}\antipar
\begin{argtbl}
  \argrow{dev}{device ID of the device containing the file}
  \argrow{mode}{mode of the file}
  \argrow{nlink}{number of hard links to the file}
  \argrow{uid}{user ID of the file}
  \argrow{gid}{group ID of the file}
  \argrow{rdev}{device ID if file is character or block special}
  \argrow{ino}{file serial number}
  \argrow{size}{For regular files, the file size in bytes. For
    symbolic links, the length in bytes of the path in the link.}
  \argrow{blksize}{optimal block size for I/O}
  \argrow{blocks}{number of blocks allocated for the file}
  \argrow{flags}{user-defined flags for the file}
  \argrow{gen}{file generation number}
  \argrow{atime}{time of last access}
  \argrow{mtime}{time of last data modification}
  \argrow{ctime}{time of last status change}
  \argrow{birthtime}{time of file creation}
\end{argtbl}

The time entries contain \code{(\var{sec} . \var{nsec})}, where
\var{sec} is the number of seconds in UTC since the UNIX epoch January
1, 1970, and \var{nsec} is the number of nanoseconds after \var{sec}.

\defineentry{osi\_unlink}
\begin{function}
  \code{ptr osi\_unlink(const char* \var{path}, ptr \var{callback});}
\end{function}

The \code{osi\_unlink} function issues an unlink operation using the
\code{uv\_fs\_unlink} function with the given \var{path}. It returns
\code{\#t} when the unlink operation is issued and an error pair
otherwise. When the unlink operation finishes, it enqueues the
callback list \code{(\var{callback} \var{errno})}, where \var{errno}
is 0 when successful and a negative error code otherwise.

\defineentry{osi\_watch\_path}
\begin{function}
  \code{ptr osi\_watch\_path(const char* \var{path}, ptr \var{callback});}
\end{function}

The \code{osi\_watch\_path} function uses the
\code{uv\_fs\_event\_start} function to track changes to
\var{path}. When \var{path} is a directory, its subdirectories are not
tracked. Every time a change is detected, a callback list
\code{(\var{callback} \var{filename} \var{events})} is enqueued, where
\var{events} is 1 for rename, 2 for change, and 3 for rename and
change.  If the watcher encounters an error, the callback list
\code{(\var{callback} \var{errno})} is enqueued.

The \code{osi\_watch\_path} function returns a path watcher handle
when successful and an error pair otherwise.

\defineentry{osi\_close\_path\_watcher}
\begin{function}
  \code{void osi\_close\_path\_watcher(uptr \var{watcher});}
\end{function}

The \code{osi\_close\_path\_watcher} function stops and closes the
path \var{watcher} from \code{osi\_watch\_path}.

\subsection {TCP/IP Functions}

\defineentry{osi\_connect\_tcp}
\begin{function}
  \code{ptr osi\_connect\_tcp(const char* \var{node}, const char* \var{service}, ptr \var{callback});}
\end{function}

The \code{osi\_connect\_tcp} function initiates a TCP/IP connection to
host \var{node} on port \var{service}. It returns \code{\#t} when the
operation starts and an error pair otherwise. The \var{node} string
may be a host name or numeric host address string, and the
\var{service} string may be a service name or port number represented
as a string. The \code{uv\_getaddrinfo} function is used to retrieve a
list of addresses. For the first address for which a connection
succeeds using the \code{uv\_tcp\_connect} function, the completion
list \code{(\var{callback} \var{port})} is enqueued, where \var{port}
is a handle to a port that reads from and writes to this
connection. When the operation fails, the callback list
\code{(\var{callback} \var{error-pair})} is enqueued.

\defineentry{osi\_listen\_tcp}
\begin{function}
  \code{ptr osi\_listen\_tcp(const char* \var{address}, uint16\_t \var{port}, ptr \var{callback});}
\end{function}

The \code{osi\_listen\_tcp} function starts a TCP/IP listener on the
given \var{port} of the IPv4 or IPv6 interface specified by
\var{address} using the \code{uv\_listen} function. It returns a
TCP/IP listener handle when successful and an error pair otherwise.

Specify an IPv4 interface \var{address} using dot-decimal notation,
e.g. \code{127.0.0.1}. Use \code{0.0.0.0} to specify all IPv4
interfaces.

Specify an IPv6 interface \var{address} using colon-hexadecimal
notation, e.g. \code{::1}. Use \code{::} to specify all IPv6
interfaces.

Specify \var{port} 0 to have the operating system choose an available
port number, which can be queried using
\code{osi\_get\_tcp\_listener\_port}.

When a connection is accepted, the callback list
\code{(\var{callback} \var{port})} is enqueued, where \var{port} is a
handle to a port that reads from and writes to this connection. When a
connection fails, the callback list \code{(\var{callback}
  \var{error-pair})} is enqueued.

\defineentry{osi\_close\_tcp\_listener}
\begin{function}
  \code{void osi\_close\_tcp\_listener(uptr \var{listener});}
\end{function}

The \code{osi\_close\_tcp\_listener} function closes the given TCP/IP
\var{listener} opened by \code{osi\_listen\_tcp}.

\defineentry{osi\_get\_tcp\_listener\_port}
\begin{function}
  \code{ptr osi\_get\_tcp\_listener\_port(uptr \var{listener});}
\end{function}

The \code{osi\_get\_tcp\_listener\_port} function returns the port
number of the given TCP/IP \var{listener} opened by
\code{osi\_listen\_tcp} when successful and an error pair otherwise.

\defineentry{osi\_get\_ip\_address}
\begin{function}
  \code{ptr osi\_get\_ip\_address(uptr \var{port});}
\end{function}

The \code{osi\_get\_ip\_address} function uses the
\code{uv\_tcp\_getpeername} function to return a string representation
of the address of the peer of a TCP/IP \var{port} opened by
\code{osi\_connect\_tcp} or \code{osi\_listen\_tcp} when successful
and an error pair otherwise.

An IPv4 address is shown in dot-decimal notation followed by a colon
and the port number, e.g. \code{127.0.0.1:80}.

An IPv6 address is shown in bracketed colon-hexadecimal notation
followed by a colon and the port number, e.g. \code{[::1]:80}.

\subsection {SQLite Functions}

For each open SQLite database, a single worker thread performs the
operations so that the main thread is not blocked. SQLite is compiled
in multi-thread mode. The documentation states: ``In this mode, SQLite
can be safely used by multiple threads provided that no single
database connection is used simultaneously in two or more threads.''
\concern{Two threads simultaneously access a SQLite database
  connection.} \mitigation The operating system interface maintains a
busy bit for each database handle. Functions attempting to access a
busy database return the error pair \code{(\var{function-name}
  . \textrm{UV\_EBUSY})}.

SQLite has five data types, which are mapped as follows to Scheme data
types:

\begin{center}
\begin{tabular}{|l|l|}
  \multicolumn{1}{l}{\emph{SQLite}} & \multicolumn{1}{l}{\emph{Scheme}} \\
  \hline
  NULL & \code{\#f} \\
  INTEGER & exact integer \\
  REAL & flonum \\
  TEXT & string \\
  BLOB & bytevector \\
  \hline
\end{tabular}
\end{center}

SQLite extended result codes are enabled. Because the error codes
overlap system error codes, the operating system interface maps them
to system error codes by negating the sum of the result code and
6,000,000. The \code{osi\_get\_error\_text} function supports these
mapped error codes.

SQLite returns additional error information in English strings, so
error pairs from SQLite are often of the form \code{(\var{who}
  . (\var{errno} . \var{text}))}, where \var{errno} is the mapped
SQLite extended result code and \var{text} is the English error
string.

\defineentry{osi\_open\_database}
\begin{function}
  \code{ptr osi\_open\_database(const char* \var{filename}, int \var{flags}, ptr \var{callback});}
\end{function}

The \code{osi\_open\_database} function starts a worker thread that
uses the \code{sqlite3\_open\_v2} function to open the database
specified by the \var{filename} string and \var{flags}. The
\var{flags} specify, for example, whether the database should be
opened in read-only mode or whether it should be created when the file
does not exist. The function returns \code{\#t} when the thread is
created and an error pair otherwise.

When the open operation finishes, it enqueues the callback list
\code{(\var{callback} \var{result})}, where \var{result} is the
database handle when successful and an error pair otherwise.

\defineentry{osi\_close\_database}
\begin{function}
  \code{ptr osi\_close\_database(uptr \var{database}, ptr \var{callback});}
\end{function}

The \code{osi\_close\_database} function starts a close operation in
the given \var{database} worker thread. It returns \code{\#t} when the
operation is started and an error pair otherwise.

After the worker thread finalizes all prepared statements, it uses the
\code{sqlite3\_close} function to close the \var{database}. When
finished, it enqueues the callback list \code{(\var{callback}
  \var{result})}, where \var{result} is \code{\#t} when successful and
an error pair otherwise.

\defineentry{osi\_prepare\_statement}
\begin{function}
  \code{ptr osi\_prepare\_statement(uptr \var{database}, ptr \var{sql}, ptr \var{callback});}
\end{function}

The \code{osi\_prepare\_statement} function starts a prepare operation
on the given \var{database} worker thread. It returns \code{\#t} when
the operation is started and an error pair otherwise.

The worker thread uses the \code{sqlite3\_prepare\_v2} function to
prepare the given \var{sql} statement. It enqueues the callback list
\code{(\var{callback} \var{result})}, where \var{result} is the
statement handle when successful and an error pair otherwise.

\defineentry{osi\_finalize\_statement}
\begin{function}
  \code{ptr osi\_finalize\_statement(uptr \var{statement});}
\end{function}

The \code{osi\_finalize\_statement} function uses the
\code{sqlite3\_finalize} function to finalize the \var{statement}.  It
returns \code{\#t} when successful and an error pair otherwise. The
return code from \code{sqlite3\_finalize} is not checked because the
statement is finalized regardless of the return value.

\defineentry{osi\_bind\_statement}
\begin{function}
  \code{ptr osi\_bind\_statement(uptr \var{statement}, int \var{index}, ptr \var{datum});}
\end{function}

The \code{osi\_bind\_statement} function maps the Scheme \var{datum}
to SQLite and binds it to the prepared \var{statement} at the zero-based SQL
parameter \var{index}.  It returns \code{\#t} when successful and an
error pair otherwise. The error pair \code{(osi\_bind\_statement
  . \textrm{UV\_EINVAL})} is returned when \code{datum} cannot be
mapped to SQLite.

\defineentry{osi\_bind\_statement\_bindings}
\begin{function}
  \code{ptr osi\_bind\_statement\_bindings(uptr \var{statement}, uptr \var{mbindings});}
\end{function}

The \code{osi\_bind\_statement\_bindings} binds the marshaled
bindings \var{mbindings} to the prepared \var{statement}.
It returns \code{\#t} when successful and an
error pair otherwise.

\defineentry{osi\_clear\_statement\_bindings}
\begin{function}
  \code{ptr osi\_clear\_statement\_bindings(uptr \var{statement});}
\end{function}

The \code{osi\_clear\_statement\_bindings} function uses the
\code{sqlite3\_clear\_bindings} function to clear the bindings for the
\var{statement}. It returns \code{\#t} when successful and an error
pair otherwise.

\defineentry{osi\_get\_last\_insert\_rowid}
\begin{function}
  \code{ptr osi\_get\_last\_insert\_rowid(uptr \var{database});}
\end{function}

The \code{osi\_get\_last\_insert\_rowid} function uses the
\code{sqlite3\_last\_insert\_rowid} function to return the last insert
rowid of the \var{database} when successful and an error pair
otherwise.

\defineentry{osi\_get\_statement\_columns}
\begin{function}
  \code{ptr osi\_get\_statement\_columns(uptr \var{statement});}
\end{function}

The \code{osi\_get\_statement\_columns} function uses the
\code{sqlite3\_column\_count} and \code{sqlite3\_column\_name}
functions to return a vector of column name strings for the
\var{statement} when successful and an error pair otherwise.

\defineentry{osi\_get\_statement\_expanded\_sql}
\begin{function}
  \code{ptr osi\_get\_statement\_expanded\_sql(uptr \var{statement});}
\end{function}

The \code{osi\_get\_statement\_expanded\_sql} function uses the
\code{sqlite3\_expanded\_sql} function to return the expanded SQL
string associated with the \var{statement} when successful and an
error pair otherwise.

\defineentry{osi\_reset\_statement}
\begin{function}
  \code{ptr osi\_reset\_statement(uptr \var{statement});}
\end{function}

The \code{osi\_reset\_statement} function uses the
\code{sqlite3\_reset} function to reset the \var{statement}. It
returns \code{\#t} when successful and an error pair otherwise.

\defineentry{osi\_step\_statement}
\begin{function}
  \code{ptr osi\_step\_statement(uptr \var{statement}, ptr \var{callback});}
\end{function}

The \code{osi\_step\_statement} function issues a step operation on
the database worker thread associated with \var{statement}. It returns
\code{\#t} when the operation is started and an error pair otherwise.

The worker thread uses the \code{sqlite3\_step} function to execute
the \var{statement}. If it returns SQLITE\_DONE, the callback list
\code{(\var{callback} \#f)} is enqueued. If it returns SQLITE\_ROW,
the callback list \code{(\var{callback} \#(\var{value} \etc))} is
enqueued with the vector of column values mapped from SQLite to
Scheme. Otherwise, the callback list \code{(\var{callback}
  \var{error-pair})} is enqueued.

\defineentry{osi\_interrupt\_database}
\begin{function}
  \code{ptr osi\_interrupt\_database(uptr \var{database});}
\end{function}

The \code{osi\_interrupt\_database} function calls the
\code{sqlite3\_interrupt} function to interrupt the current operation
of the \var{database}. It returns \code{\#t} when the database is busy
and \code{\#f} otherwise.

\defineentry{osi\_get\_sqlite\_status}
\begin{function}
  \code{ptr osi\_get\_sqlite\_status(int \var{operation}, int \var{resetp});}
\end{function}

The \code{osi\_get\_sqlite\_status} function uses the
\code{sqlite3\_status64} function with the given \var{operation} and
\var{reset} flag to return \code{\#(\var{current} \var{highwater})}
when successful and an error pair otherwise.

\defineentry{osi\_marshal\_bindings}
\begin{function}
  \code{ptr osi\_marshal\_bindings(ptr \var{bindings});}
\end{function}

The \code{osi\_marshal\_bindings} function allocates an internal
structure and copies each Scheme datum in \var{bindings}. The
\var{bindings} argument may be a list or a vector. The result is a
handle to the internal structure or NULL if \var{bindings} is empty.
An error pair is returned when the internal structure cannot be allocated or the
\var{bindings} cannot be mapped to SQLite data types.

\defineentry{osi\_get\_bindings}
\begin{function}
  \code{ptr osi\_get\_bindings(uptr \var{mbindings});}
\end{function}

The \code{osi\_get\_bindings} function allocates a vector
containing a copy of each Scheme datum marshaled into \var{mbindings}
by \code{osi\_marshal\_bindings}.
It is an error to call \code{osi\_get\_bindings} on \var{mbindings}
after calling \code{osi\_unmarshal\_bindings} on \var{mbindings}.

\defineentry{osi\_unmarshal\_bindings}
\begin{function}
  \code{ptr osi\_unmarshal\_bindings(uptr \var{mbindings});}
\end{function}

The \code{osi\_unmarshal\_bindings} function deallocates the internal
structure allocated by \code{osi\_marshal\_bindings}.

\defineentry{osi\_bulk\_execute}
\begin{function}
  \code{ptr osi\_bulk\_execute(ptr \var{statements}, ptr \var{mbindings}, ptr \var{callback});}
\end{function}

The \code{osi\_bulk\_execute} function executes all the queries
defined by \var{statements} and \var{mbindings} on the database worker
thread associated with the statements. The vector \var{statements}
must contain statement handles created by
\code{osi\_prepare\_statement}. All \var{statements} must be prepared
on the same database. The vector \var{mbindings} must contain binding
handles created by \code{osi\_marshal\_bindings}. It returns
\code{\#t} when the operation is started and an error pair otherwise.

When the bulk execute operation finishes, it enqueues the callback
list \code{(\var{callback} \var{result})}, where \var{result} is
\code{\#t} when successful and an error pair otherwise.

\subsection {Message-Digest Functions}

\defineentry{osi\_open\_SHA1}
\begin{function}
  \code{ptr osi\_open\_SHA1();}
\end{function}

The \code{osi\_open\_SHA1} function returns an error pair
or a context for computing the SHA1 message digest.

\defineentry{osi\_hash\_data}
\begin{function}
  \code{ptr osi\_hash\_data(uptr \var{ctxt}, ptr \var{bv}, size\_t \var{start\_index}, uint32\_t \var{size});}
\end{function}

The \code{osi\_hash\_data} function computes the SHA1 message digest
incrementally on the \var{size} bytes at the zero-based \var{start\_index}
of bytevector \var{bv} updating the context \var{ctxt}.
It returns \code{\#t} when successful and an error pair otherwise.

\defineentry{osi\_get\_SHA1}
\begin{function}
  \code{ptr osi\_get\_SHA1(uptr \var{ctxt});}
\end{function}

The \code{osi\_get\_SHA1} function takes a \var{ctxt} that was created by
\code{osi\_open\_SHA1} and updated by calling \code{osi\_hash\_data} on a set
of buffers and returns as a bytevector the SHA1 message digest of the buffers.
If unsuccessful, it returns an error pair.

\defineentry{osi\_close\_SHA1}
\begin{function}
  \code{ptr osi\_close\_SHA1(uptr \var{ctxt});}
\end{function}

The \code{osi\_close\_SHA1} function frees a \var{ctxt}
that was allocated by \code{osi\_open\_SHA1}.
