File: example.sh

package info (click to toggle)
nbdkit 1.46.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,504 kB
  • sloc: ansic: 63,658; sh: 18,717; makefile: 6,814; python: 1,848; cpp: 1,143; perl: 504; ml: 504; tcl: 62
file content (200 lines) | stat: -rwxr-xr-x 6,348 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/env bash
#
# Example Bash plugin.
#
# This example can be freely used for any purpose.
#
# Run it from the build directory like this:
#
#   ./nbdkit -f -v sh ./plugins/sh/examples/example.sh file=disk.img
#
# Or run it after installing nbdkit like this:
#
#   nbdkit -f -v sh ./plugins/sh/examples/example.sh file=disk.img
#
# The file= prefix is optional: see nbdkit(1) section "Magic
# parameters" and the magic_config_key setting below.
#
# The -f -v arguments are optional.  They cause the server to stay in
# the foreground and print debugging, which is useful when testing.
#
# You can connect to the server using guestfish or qemu, eg:
#
#   guestfish --format=raw -a nbd://localhost
#   ><fs> run
#   ><fs> list-filesystems
#   ><fs> mount /dev/sda1 /

# Note that the exit code of the script matters:
#  0 => OK
#  1 => Error
#  2 => Method is missing
#  3 => False
# For other values, see the nbdkit-sh-plugin(3) manual page.

# Check we're being run from nbdkit.
#
# Because the script has to be executable (for nbdkit to run it) there
# is a danger that someone could run the script standalone which won't
# work.  Use two tests to try to make sure we are run from nbdkit:
#
# - $tmpdir is set to a random, empty directory by nbdkit.  Note the
# contents are deleted when nbdkit exits.
#
# - $1 is set (to a method name).
if [ ! -d $tmpdir ] || [ "x$1" = "x" ]; then
    echo "$0: this script must be run from nbdkit" >&2
    echo "Use ‘nbdkit sh $0’" >&2
    exit 1
fi

# We make a symlink to the file in the tmpdir directory.
f=$tmpdir/file

case "$1" in
    dump_plugin)
        # This is called from: nbdkit sh example.sh --dump-plugin
        echo "example_sh=1"
        ;;

    config)
        # We expect a file=... parameter pointing to the file to serve.
        if [ "$2" = "file" ]; then
            if [ ! -r "$3" ]; then
                echo "file $3 does not exist or is not readable" >&2
                exit 1
            fi
            ln -sf "$(realpath "$3")" $f
        else
            echo "unknown parameter $2=$3" >&2
            exit 1
        fi
        ;;

    config_complete)
        # Check the file parameter was passed.
        if [ ! -L $f ]; then
            echo "file parameter missing" >&2
            exit 1
        fi
        ;;

    thread_model)
        # You must opt-in for parallel behavior; the default is
        # serialize_all_requests.
        echo parallel
        ;;

    list_exports | default_export)
        # The following lists the names of all files in the current
        # directory that do not contain whitespace, backslash, or single
        # quotes.  No description accompanies the export names.
        # The first file listed is used when a client requests export ''.
        find . -type f \! -name "*['\\\\[:space:]]*"
        ;;

    open)
        # Open a new client connection.

        # Create a directory to store per-connection state.  The
        # directory name is printed out by the mktemp command, that
        # output is captured by nbdkit, and it is passed back as the
        # handle parameter ($2) in subsequent calls below.
        #
        # You can use this directory to store per-connection state,
        # and it along with everything in $tmpdir is cleaned up by
        # nbdkit on exit.
        #
        # (This plugin does not actually use per-connection state,
        # it's just an example.)
        mktemp -d $tmpdir/handle-XXXXXX
        ;;

    get_size)
        # Print the disk size on stdout.
        stat -L -c '%s' $f || exit 1
        ;;

    pread)
        # Read the requested part of the disk and write to stdout.
        dd iflag=skip_bytes,count_bytes skip=$4 count=$3 if=$f || exit 1
        ;;

    pwrite)
        # Copy data from stdin and write it to the disk.
        dd oflag=seek_bytes conv=notrunc seek=$4 of=$f || exit 1
        ;;

    can_write)
        # If we provide a pwrite method, we must provide this method
        # (and similarly for flush and trim).  See nbdkit-sh-plugin(3)
        # for details.  This will exit 0 (below) which means true.
        # Use ‘exit 3’ if false.
        ;;

    trim)
        # Punch a hole in the backing file, if supported.
        fallocate -p -o $4 -l $3 -n $f || exit 1
        ;;
    can_trim)
        # We can trim if the fallocate command exists.
        fallocate --help >/dev/null 2>&1 || exit 3
        ;;

    zero)
        # Efficiently zero the backing file, if supported.
        # Try punching a hole if flags includes may_trim, otherwise
        # request to leave the zeroed range allocated.
        # Attempt a fallback to write on any failure, but this requires
        # specific prefix on stderr prior to any message from fallocate;
        # exploit the fact that stderr is ignored on success.
        echo ENOTSUP >&2
        case ,$5, in
            *,may_trim,*) fallocate -p -o $4 -l $3 -n $f || exit 1 ;;
            *)            fallocate -z -o $4 -l $3 -n $f || exit 1 ;;
        esac
        ;;
    can_zero)
        # We can efficiently zero if the fallocate command exists.
        fallocate --help >/dev/null 2>&1 || exit 3
        ;;

    # cache)
        # Implement an efficient prefetch, if desired.
        # It is intentionally omitted from this example.
        # dd iflag=skip_bytes,count_bytes skip=$4 count=$3 \
        #    if=$f of=/dev/null || exit 1
        # ;;

    can_cache)
        # Caching is not advertised to the client unless can_cache prints
        # a tri-state value.  Here, we choose for caching to be a no-op,
        # by omitting counterpart handling for 'cache'.
        echo native
        ;;

    extents)
        # Report extent (block status) information as 'offset length [type]'.
        # This example could omit the handler, since it just matches
        # the default behavior of treating everything as data; but if
        # your code can detect holes, this demonstrates the usage.
        echo "$4           $(($3/2)) 0"
        echo "$(($4+$3/2)) $(($3/2))"
        # echo "$4 $3 hole,zero"
        ;;

    can_extents)
        # Similar to can_write
        ;;

    magic_config_key)
        # See nbdkit(1) section "Magic parameters" for what this does.
        echo "file"
        ;;

    *)
        # Unknown methods must exit with code 2.
        exit 2
esac

exit 0