2 * Copyright (C) 2013-2014 Red Hat Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Red Hat nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 #include <nbdkit-plugin.h>
51 static PerlInterpreter
*my_perl
;
52 static const char *script
;
58 const char *argv
[2] = { "nbdkit", NULL
};
60 /* Full Perl interpreter initialization is deferred until we read
61 * the first config parameter (which MUST be "script").
63 PERL_SYS_INIT3 (&argc
, (char ***) &argv
, &environ
);
64 my_perl
= perl_alloc ();
66 nbdkit_error ("out of memory allocating Perl interpreter");
69 perl_construct (my_perl
);
75 if (my_perl
!= NULL
) {
76 perl_destruct (my_perl
);
82 /* We use this function to test if the named callback is defined
83 * in the loaded Perl code.
85 * There is a subtle nbdkit problem here. Because we don't load the
86 * script until the configuration phase, we don't know until too late
87 * which callbacks are defined in Perl. Therefore we cannot set the
88 * .plugin fields to NULL appropriately (also because nbdkit copies
89 * that struct, we cannot modify the struct after the module is
90 * loaded). So what we have to do is copy the default behaviour of
91 * nbdkit for missing Perl callbacks.
94 callback_defined (const char *perl_func_name
)
99 if (asprintf (&cmd
, "defined &%s", perl_func_name
) == -1) {
104 ret
= eval_pv (cmd
, FALSE
);
110 /* Check for a Perl exception, and convert it to an nbdkit error. */
112 check_perl_failure (void)
114 SV
*errsv
= get_sv ("@", TRUE
);
116 if (SvTRUE (errsv
)) {
121 err
= SvPV (errsv
, n
);
123 /* Need to chop off the final \n if there is one. The only way to
124 * do this is to copy the string.
126 err_copy
= strndup (err
, n
);
127 if (err_copy
== NULL
) {
128 nbdkit_error ("malloc failure: original error: %s", err
);
131 if (n
> 0 && err_copy
[n
-1] == '\n')
132 err_copy
[n
-1] = '\0';
134 nbdkit_error ("%s", err_copy
);
144 perl_config (const char *key
, const char *value
)
148 char *argv
[3] = { "nbdkit", NULL
, NULL
};
150 /* The first parameter MUST be "script". */
151 if (strcmp (key
, "script") != 0) {
152 nbdkit_error ("the first parameter must be script=/path/to/perl/script.pl");
159 /* Load the Perl script. */
160 argv
[1] = (char *) script
;
161 if (perl_parse (my_perl
, NULL
, argc
, argv
, NULL
) == -1) {
162 nbdkit_error ("%s: error parsing this script", script
);
166 /* Run the Perl script. Note that top-level definitions such as
167 * global variables don't work at all unless you do this.
169 if (perl_run (my_perl
) == -1) {
170 nbdkit_error ("%s: error running this script", script
);
174 /* Minimal set of callbacks which are required (by nbdkit itself). */
175 if (!callback_defined ("open") ||
176 !callback_defined ("get_size") ||
177 !callback_defined ("pread")) {
178 nbdkit_error ("%s: one of the required callbacks 'open', 'get_size' or 'pread' is not defined by this Perl script. nbdkit requires these callbacks.", script
);
182 else if (callback_defined ("config")) {
185 /* Other parameters are passed to the Perl .config callback. */
189 XPUSHs (sv_2mortal (newSVpv (key
, strlen (key
))));
190 XPUSHs (sv_2mortal (newSVpv (value
, strlen (value
))));
192 call_pv ("config", G_EVAL
|G_VOID
|G_DISCARD
);
198 if (check_perl_failure () == -1)
202 /* Emulate what core nbdkit does if a config callback is NULL. */
203 nbdkit_error ("%s: this plugin does not need command line configuration",
212 perl_config_complete (void)
216 if (callback_defined ("config_complete")) {
221 call_pv ("config_complete", G_EVAL
|G_VOID
|G_DISCARD
);
226 if (check_perl_failure () == -1)
234 perl_open (int readonly
)
239 /* We check in perl_config that this callback is defined. */
243 XPUSHs (readonly
? &PL_sv_yes
: &PL_sv_no
);
245 call_pv ("open", G_EVAL
|G_SCALAR
);
252 if (check_perl_failure () == -1)
255 nbdkit_debug ("open returns handle (SV *) = %p (type %d)",
262 perl_close (void *handle
)
266 nbdkit_debug ("close called with handle (SV *) = %p (type %d)",
267 handle
, SvTYPE ((SV
*) handle
));
269 if (callback_defined ("close")) {
275 call_pv ("close", G_EVAL
|G_VOID
|G_DISCARD
);
281 check_perl_failure (); /* ignore return value */
284 /* Since nbdkit has closed (and forgotten) the handle, we can now
287 SvREFCNT_dec ((SV
*) handle
);
291 perl_get_size (void *handle
)
297 /* We check in perl_config that this callback is defined. */
303 call_pv ("get_size", G_EVAL
|G_SCALAR
);
305 /* For some reason, this only works if split into two separate statements: */
312 if (check_perl_failure () == -1)
315 nbdkit_debug ("get_size returned %" PRIi64
, size
);
321 perl_pread (void *handle
, void *buf
,
322 uint32_t count
, uint64_t offset
)
330 /* We check in perl_config that this callback is defined. */
335 XPUSHs (sv_2mortal (newSViv (count
)));
336 XPUSHs (sv_2mortal (newSViv (offset
)));
338 call_pv ("pread", G_EVAL
|G_SCALAR
);
341 pbuf
= SvPV (sv
, len
);
343 nbdkit_error ("buffer returned from pread is too small");
347 memcpy (buf
, pbuf
, count
);
352 if (check_perl_failure () == -1)
359 perl_pwrite (void *handle
, const void *buf
,
360 uint32_t count
, uint64_t offset
)
364 if (callback_defined ("pwrite")) {
369 XPUSHs (sv_2mortal (newSVpv (buf
, count
)));
370 XPUSHs (sv_2mortal (newSViv (offset
)));
372 call_pv ("pwrite", G_EVAL
|G_VOID
|G_DISCARD
);
378 if (check_perl_failure () == -1)
384 nbdkit_error ("write not implemented");
389 perl_can_write (void *handle
)
395 if (callback_defined ("can_write")) {
396 /* If there's a Perl callback, call it. */
402 call_pv ("can_write", G_EVAL
|G_SCALAR
);
410 if (check_perl_failure () == -1)
415 /* No Perl can_write callback, but there's a Perl pwrite callback
416 * defined, so return 1. (In C modules, nbdkit would do this).
418 else if (callback_defined ("pwrite"))
425 perl_can_flush (void *handle
)
431 if (callback_defined ("can_flush")) {
432 /* If there's a Perl callback, call it. */
438 call_pv ("can_flush", G_EVAL
|G_SCALAR
);
446 if (check_perl_failure () == -1)
451 /* No Perl can_flush callback, but there's a Perl flush callback
452 * defined, so return 1. (In C modules, nbdkit would do this).
454 else if (callback_defined ("flush"))
461 perl_can_trim (void *handle
)
467 if (callback_defined ("can_trim")) {
468 /* If there's a Perl callback, call it. */
474 call_pv ("can_trim", G_EVAL
|G_SCALAR
);
482 if (check_perl_failure () == -1)
487 /* No Perl can_trim callback, but there's a Perl trim callback
488 * defined, so return 1. (In C modules, nbdkit would do this).
490 else if (callback_defined ("trim"))
497 perl_is_rotational (void *handle
)
503 if (callback_defined ("is_rotational")) {
504 /* If there's a Perl callback, call it. */
510 call_pv ("is_rotational", G_EVAL
|G_SCALAR
);
518 if (check_perl_failure () == -1)
528 perl_flush (void *handle
)
532 if (callback_defined ("flush")) {
538 call_pv ("flush", G_EVAL
|G_VOID
|G_DISCARD
);
544 if (check_perl_failure () == -1)
550 /* Ignore lack of flush callback in Perl, although probably nbdkit
551 * will never call this since .can_flush returns false.
557 perl_trim (void *handle
, uint32_t count
, uint64_t offset
)
561 if (callback_defined ("trim")) {
566 XPUSHs (sv_2mortal (newSViv (count
)));
567 XPUSHs (sv_2mortal (newSViv (offset
)));
569 call_pv ("trim", G_EVAL
|G_VOID
|G_DISCARD
);
575 if (check_perl_failure () == -1)
581 /* Ignore lack of trim callback in Perl, although probably nbdkit
582 * will never call this since .can_trim returns false.
587 #define perl_config_help \
588 "script=<FILENAME> (required) The Perl plugin to run.\n" \
589 "[other arguments may be used by the plugin that you load]"
591 #define THREAD_MODEL NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS
593 static struct nbdkit_plugin plugin
= {
595 .version
= PACKAGE_VERSION
,
598 .unload
= perl_unload
,
600 .config
= perl_config
,
601 .config_complete
= perl_config_complete
,
602 .config_help
= perl_config_help
,
607 .get_size
= perl_get_size
,
608 .can_write
= perl_can_write
,
609 .can_flush
= perl_can_flush
,
610 .is_rotational
= perl_is_rotational
,
611 .can_trim
= perl_can_trim
,
614 .pwrite
= perl_pwrite
,
619 NBDKIT_REGISTER_PLUGIN(plugin
)