Up

module Shell_fs

: sig

Shell filesystem

This module emulates a filesystem by submitting shell commands. For example, a directory listing is retrieved via the ls utility instead of opening the directory directly. This also works when logging in to a remote machine, e.g. via ssh.

The following standard POSIX commands are used:

  • dd with options if, of, bs, skip, conv=notrunc, and optionally excl (the latter is a GNU extension)
  • test with options -d, -e, -f, -r, -s, -w, -x
  • ls with options -1, -n, -d, -a, -L
  • rm with options -r and -f
  • mv with option -f
  • ln with option -s
  • mkdir with options -p
  • rmdir
  • cp with option -p

In addition to this, the commands may be embedded in one-line shell scripts.

Filenames with leading minus chars are not supported.

Error reporting is less accurate than for a local filesystem.

Example. List a directory on a remote system:

      let fs = 
        Shell_fs.shell_fs 
          (Shell_fs.ssh_interpreter ~host:"moon" ())
      let files =
        fs # readdir [] "/this/is/a/directory/on/moon"
#
type command_context = {
# sfs_command
: string;(*The command line*)
# sfs_stdin
: Shell.producer;(*stdin from here*)
# sfs_stdout
: Shell.consumer;(*stdout goes here*)
# sfs_stderr
: Shell.consumer;(*stderr goes here*)
# mutable sfs_status
: Unix.process_status option;(*The exit code is put here*)
}
#
type command_interpreter

The interpreter runs the command, and fills in sfs_status

#
val local_interpreter : unit -> command_interpreter

Executes commands on the local machine

#
val cmd_interpreter : (command_context -> Shell_sys.command list) -> command_interpreter

Creates a command interpreter from a function that creates the real command (as pipeline) to execute

#
val ssh_interpreter : ?options:string list -> ?user:string -> host:string -> unit -> command_interpreter

Executes commands via ssh on the machine host as user (defaults to current user). options are further command-line options. By default, only -o BatchMode yes is passed.

#
class type shell_stream_fs =
inherit Netfs.stream_fs
#
method last_stderr : string

The stderr output of the last operation

#
class shell_fs : ?encoding:Netconversion.encoding option -> ?root:string option -> ?dd_has_excl:bool option -> ?tmp_directory:string option -> ?tmp_prefix:string option -> command_interpreter -> shell_stream_fs
#
val shell_fs : ?encoding:Netconversion.encoding -> ?root:string -> ?dd_has_excl:bool -> ?tmp_directory:string -> ?tmp_prefix:string -> command_interpreter -> shell_stream_fs

The shell filesystem.

  • encoding: the assumed character encoding of the filenames. None by default.
  • root: the root of the file tree that is accessed. This can be an absolute path, or a relative path.
  • dd_has_excl: whether the dd command support "conv=excl". Default is false; this is a GNU extension.
  • tmp_directory and tmp_prefix are only meaningful for the write_file method which creates a temporary file. See Netchannels.make_temporary_file for more information.

Utility functions for developing other implementations of shell_stream_fs

#
val execute : command_interpreter -> command_context -> unit

Starts this command. It is not waited until the command is finished. One can either call wait for this, or one of the adapter functions below.

One can only start one command at a time.

#
val wait : command_interpreter -> unit

Waits until the running command is finished

#
val output_stream_adapter : ci:command_interpreter -> close_in:(unit -> unit) -> skip:int64 -> Shell.consumer * Netchannels.in_obj_channel

Arranges that the output of a shell command is made available as an in_obj_channel:

let (c, ch) = output_stream_adapter ~ci ~close_in ~skip

The consumer p can be used in a command_context for either sfs_stdout or sfs_stderr. The channel ch is an input channel, and when reading from it will return the bytes of stdout or stderr.

close_in is called as post-hook when the close_in method of ch is called.

skip bytes of stdout/stderr are skipped at the beginning of the stream.

#
val input_stream_adapter : ci:command_interpreter -> close_out:(unit -> unit) -> Shell.producer * Netchannels.out_obj_channel

Arranges that the input of a shell command is made available as an out_obj_channel:

let (p, ch) = input_stream_adapter ~ci ~close_in

The producer p can be used in a command_context for sfs_stdin. The channel ch is an output channel, and bytes written to it will appear in stdin of the executed command.

close_out is called as post-hook when the close_out method of ch is called.

end