Update Red Hat Copyright Notices
[nbdkit.git] / plugins / sh / example.sh
blobe0e1b7738301af2c53c92963739eefc9250bdc7a
1 #!/usr/bin/env bash
3 # Example Bash plugin.
5 # This example can be freely used for any purpose.
7 # Run it from the build directory like this:
9 # ./nbdkit -f -v sh ./plugins/sh/example.sh file=disk.img
11 # Or run it after installing nbdkit like this:
13 # nbdkit -f -v sh ./plugins/sh/example.sh file=disk.img
15 # The file= prefix is optional: see nbdkit(1) section "Magic
16 # parameters" and the magic_config_key setting below.
18 # The -f -v arguments are optional. They cause the server to stay in
19 # the foreground and print debugging, which is useful when testing.
21 # You can connect to the server using guestfish or qemu, eg:
23 # guestfish --format=raw -a nbd://localhost
24 # ><fs> run
25 # ><fs> list-filesystems
26 # ><fs> mount /dev/sda1 /
28 # Note that the exit code of the script matters:
29 # 0 => OK
30 # 1 => Error
31 # 2 => Method is missing
32 # 3 => False
33 # For other values, see the nbdkit-sh-plugin(3) manual page.
35 # Check we're being run from nbdkit.
37 # Because the script has to be executable (for nbdkit to run it) there
38 # is a danger that someone could run the script standalone which won't
39 # work. Use two tests to try to make sure we are run from nbdkit:
41 # - $tmpdir is set to a random, empty directory by nbdkit. Note the
42 # contents are deleted when nbdkit exits.
44 # - $1 is set (to a method name).
45 if [ ! -d $tmpdir ] || [ "x$1" = "x" ]; then
46 echo "$0: this script must be run from nbdkit" >&2
47 echo "Use ‘nbdkit sh $0’" >&2
48 exit 1
51 # We make a symlink to the file in the tmpdir directory.
52 f=$tmpdir/file
54 case "$1" in
55 dump_plugin)
56 # This is called from: nbdkit sh example.sh --dump-plugin
57 echo "example_sh=1"
60 config)
61 # We expect a file=... parameter pointing to the file to serve.
62 if [ "$2" = "file" ]; then
63 if [ ! -r "$3" ]; then
64 echo "file $3 does not exist or is not readable" >&2
65 exit 1
67 ln -sf "$(realpath "$3")" $f
68 else
69 echo "unknown parameter $2=$3" >&2
70 exit 1
74 config_complete)
75 # Check the file parameter was passed.
76 if [ ! -L $f ]; then
77 echo "file parameter missing" >&2
78 exit 1
82 thread_model)
83 # You must opt-in for parallel behavior; the default is
84 # serialize_all_requests.
85 echo parallel
88 list_exports | default_export)
89 # The following lists the names of all files in the current
90 # directory that do not contain whitespace, backslash, or single
91 # quotes. No description accompanies the export names.
92 # The first file listed is used when a client requests export ''.
93 find . -type f \! -name "*['\\\\[:space:]]*"
96 open)
97 # Open a new client connection.
99 # Create a directory to store per-connection state. The
100 # directory name is printed out by the mktemp command, that
101 # output is captured by nbdkit, and it is passed back as the
102 # handle parameter ($2) in subsequent calls below.
104 # You can use this directory to store per-connection state,
105 # and it along with everything in $tmpdir is cleaned up by
106 # nbdkit on exit.
108 # (This plugin does not actually use per-connection state,
109 # it's just an example.)
110 mktemp -d $tmpdir/handle-XXXXXX
113 get_size)
114 # Print the disk size on stdout.
115 stat -L -c '%s' $f || exit 1
118 pread)
119 # Read the requested part of the disk and write to stdout.
120 dd iflag=skip_bytes,count_bytes skip=$4 count=$3 if=$f || exit 1
123 pwrite)
124 # Copy data from stdin and write it to the disk.
125 dd oflag=seek_bytes conv=notrunc seek=$4 of=$f || exit 1
128 can_write)
129 # If we provide a pwrite method, we must provide this method
130 # (and similarly for flush and trim). See nbdkit-sh-plugin(3)
131 # for details. This will exit 0 (below) which means true.
132 # Use ‘exit 3’ if false.
135 trim)
136 # Punch a hole in the backing file, if supported.
137 fallocate -p -o $4 -l $3 -n $f || exit 1
139 can_trim)
140 # We can trim if the fallocate command exists.
141 fallocate --help >/dev/null 2>&1 || exit 3
144 zero)
145 # Efficiently zero the backing file, if supported.
146 # Try punching a hole if flags includes may_trim, otherwise
147 # request to leave the zeroed range allocated.
148 # Attempt a fallback to write on any failure, but this requires
149 # specific prefix on stderr prior to any message from fallocate;
150 # exploit the fact that stderr is ignored on success.
151 echo ENOTSUP >&2
152 case ,$5, in
153 *,may_trim,*) fallocate -p -o $4 -l $3 -n $f || exit 1 ;;
154 *) fallocate -z -o $4 -l $3 -n $f || exit 1 ;;
155 esac
157 can_zero)
158 # We can efficiently zero if the fallocate command exists.
159 fallocate --help >/dev/null 2>&1 || exit 3
162 # cache)
163 # Implement an efficient prefetch, if desired.
164 # It is intentionally omitted from this example.
165 # dd iflag=skip_bytes,count_bytes skip=$4 count=$3 \
166 # if=$f of=/dev/null || exit 1
167 # ;;
169 can_cache)
170 # Caching is not advertised to the client unless can_cache prints
171 # a tri-state value. Here, we choose for caching to be a no-op,
172 # by omitting counterpart handling for 'cache'.
173 echo native
176 extents)
177 # Report extent (block status) information as 'offset length [type]'.
178 # This example could omit the handler, since it just matches
179 # the default behavior of treating everything as data; but if
180 # your code can detect holes, this demonstrates the usage.
181 echo "$4 $(($3/2)) 0"
182 echo "$(($4+$3/2)) $(($3/2))"
183 # echo "$4 $3 hole,zero"
186 can_extents)
187 # Similar to can_write
190 magic_config_key)
191 # See nbdkit(1) section "Magic parameters" for what this does.
192 echo "file"
196 # Unknown methods must exit with code 2.
197 exit 2
198 esac
200 exit 0