plugins: Wire up rust plugin support for NBD_INFO_INIT_STATE
[nbdkit/ericb.git] / server / plugins.c
blob040dc719224b83537a761d15846da5a04660e729
1 /* nbdkit
2 * Copyright (C) 2013-2020 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <inttypes.h>
40 #include <assert.h>
41 #include <errno.h>
42 #include <sys/socket.h>
44 #include "internal.h"
45 #include "minmax.h"
47 /* We extend the generic backend struct with extra fields relating
48 * to this plugin.
50 struct backend_plugin {
51 struct backend backend;
52 struct nbdkit_plugin plugin;
55 static void
56 plugin_free (struct backend *b)
58 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
60 backend_unload (b, p->plugin.unload);
61 free (p);
64 static int
65 plugin_thread_model (struct backend *b)
67 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
68 int thread_model = p->plugin._thread_model;
69 int r;
71 #if !(defined SOCK_CLOEXEC && defined HAVE_MKOSTEMP && defined HAVE_PIPE2 && \
72 defined HAVE_ACCEPT4)
73 if (thread_model > NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS) {
74 debug ("system lacks atomic CLOEXEC, serializing to avoid fd leaks");
75 thread_model = NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS;
77 #endif
79 if (p->plugin.thread_model) {
80 r = p->plugin.thread_model ();
81 if (r == -1)
82 exit (EXIT_FAILURE);
83 if (r < thread_model)
84 thread_model = r;
87 return thread_model;
90 static const char *
91 plugin_name (struct backend *b)
93 return b->name;
96 static void
97 plugin_usage (struct backend *b)
99 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
100 const char *t;
102 printf ("plugin: %s", b->name);
103 if (p->plugin.longname)
104 printf (" (%s)", p->plugin.longname);
105 printf ("\n");
106 printf ("(%s)\n", b->filename);
107 if (p->plugin.description) {
108 printf ("%s", p->plugin.description);
109 if ((t = strrchr (p->plugin.description, '\n')) == NULL || t[1])
110 printf ("\n");
112 if (p->plugin.config_help) {
113 printf ("%s", p->plugin.config_help);
114 if ((t = strrchr (p->plugin.config_help, '\n')) == NULL || t[1])
115 printf ("\n");
119 static const char *
120 plugin_version (struct backend *b)
122 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
124 return p->plugin.version;
127 /* This implements the --dump-plugin option. */
128 static void
129 plugin_dump_fields (struct backend *b)
131 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
132 char *path;
134 path = nbdkit_realpath (b->filename);
135 printf ("path=%s\n", path);
136 free (path);
138 printf ("name=%s\n", b->name);
139 if (p->plugin.version)
140 printf ("version=%s\n", p->plugin.version);
142 printf ("api_version=%d\n", p->plugin._api_version);
143 printf ("struct_size=%" PRIu64 "\n", p->plugin._struct_size);
144 printf ("max_thread_model=%s\n",
145 name_of_thread_model (p->plugin._thread_model));
146 printf ("thread_model=%s\n",
147 name_of_thread_model (backend->thread_model (backend)));
148 printf ("errno_is_preserved=%d\n", !!p->plugin.errno_is_preserved);
149 if (p->plugin.magic_config_key)
150 printf ("magic_config_key=%s\n", p->plugin.magic_config_key);
152 #define HAS(field) if (p->plugin.field) printf ("has_%s=1\n", #field)
153 HAS (longname);
154 HAS (description);
155 HAS (load);
156 HAS (unload);
157 HAS (dump_plugin);
158 HAS (config);
159 HAS (config_complete);
160 HAS (config_help);
161 HAS (preconnect);
162 HAS (open);
163 HAS (close);
164 HAS (get_size);
165 HAS (can_write);
166 HAS (can_flush);
167 HAS (is_rotational);
168 HAS (can_trim);
169 HAS (_pread_v1);
170 HAS (_pwrite_v1);
171 HAS (_flush_v1);
172 HAS (_trim_v1);
173 HAS (_zero_v1);
174 HAS (can_zero);
175 HAS (can_fua);
176 HAS (pread);
177 HAS (pwrite);
178 HAS (flush);
179 HAS (trim);
180 HAS (zero);
181 HAS (can_multi_conn);
182 HAS (can_extents);
183 HAS (extents);
184 HAS (can_cache);
185 HAS (cache);
186 HAS (thread_model);
187 HAS (can_fast_zero);
188 #undef HAS
190 /* Custom fields. */
191 if (p->plugin.dump_plugin)
192 p->plugin.dump_plugin ();
195 static void
196 plugin_config (struct backend *b, const char *key, const char *value)
198 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
200 debug ("%s: config key=%s, value=%s", b->name, key, value);
202 if (p->plugin.config == NULL) {
203 fprintf (stderr,
204 "%s: %s: this plugin does not need command line configuration\n"
205 "Try using: %s --help %s\n",
206 program_name, b->filename,
207 program_name, b->filename);
208 exit (EXIT_FAILURE);
211 if (p->plugin.config (key, value) == -1)
212 exit (EXIT_FAILURE);
215 static void
216 plugin_config_complete (struct backend *b)
218 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
220 debug ("%s: config_complete", b->name);
222 if (!p->plugin.config_complete)
223 return;
225 if (p->plugin.config_complete () == -1)
226 exit (EXIT_FAILURE);
229 static const char *
230 plugin_magic_config_key (struct backend *b)
232 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
234 return p->plugin.magic_config_key;
237 static int
238 plugin_preconnect (struct backend *b, struct connection *conn, int readonly)
240 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
242 debug ("%s: preconnect", b->name);
244 if (!p->plugin.preconnect)
245 return 0;
247 return p->plugin.preconnect (readonly);
250 static void *
251 plugin_open (struct backend *b, struct connection *conn, int readonly)
253 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
255 assert (p->plugin.open != NULL);
257 return p->plugin.open (readonly);
260 /* We don't expose .prepare and .finalize to plugins since they aren't
261 * necessary. Plugins can easily do the same work in .open and
262 * .close.
264 static int
265 plugin_prepare (struct backend *b, struct connection *conn, void *handle,
266 int readonly)
268 return 0;
271 static int
272 plugin_finalize (struct backend *b, struct connection *conn, void *handle)
274 return 0;
277 static void
278 plugin_close (struct backend *b, struct connection *conn, void *handle)
280 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
282 if (handle && p->plugin.close)
283 p->plugin.close (handle);
286 static int64_t
287 plugin_get_size (struct backend *b, struct connection *conn, void *handle)
289 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
291 assert (p->plugin.get_size != NULL);
293 return p->plugin.get_size (handle);
296 static int
297 plugin_can_write (struct backend *b, struct connection *conn, void *handle)
299 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
301 if (p->plugin.can_write)
302 return p->plugin.can_write (handle);
303 else
304 return p->plugin.pwrite || p->plugin._pwrite_v1;
307 static int
308 plugin_can_flush (struct backend *b, struct connection *conn, void *handle)
310 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
312 if (p->plugin.can_flush)
313 return p->plugin.can_flush (handle);
314 else
315 return p->plugin.flush || p->plugin._flush_v1;
318 static int
319 plugin_is_rotational (struct backend *b, struct connection *conn, void *handle)
321 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
323 if (p->plugin.is_rotational)
324 return p->plugin.is_rotational (handle);
325 else
326 return 0; /* assume false */
329 static int
330 plugin_can_trim (struct backend *b, struct connection *conn, void *handle)
332 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
334 if (p->plugin.can_trim)
335 return p->plugin.can_trim (handle);
336 else
337 return p->plugin.trim || p->plugin._trim_v1;
340 static int
341 plugin_can_zero (struct backend *b, struct connection *conn, void *handle)
343 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
344 int r;
346 /* Note the special case here: the plugin's .can_zero returns a bool
347 * which controls only whether we call .zero; while the backend
348 * expects .can_zero to return a tri-state on level of support.
350 if (p->plugin.can_zero) {
351 r = p->plugin.can_zero (handle);
352 if (r == -1)
353 return -1;
354 return r ? NBDKIT_ZERO_NATIVE : NBDKIT_ZERO_EMULATE;
356 if (p->plugin.zero || p->plugin._zero_v1)
357 return NBDKIT_ZERO_NATIVE;
358 return NBDKIT_ZERO_EMULATE;
361 static int
362 plugin_can_fast_zero (struct backend *b, struct connection *conn, void *handle)
364 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
365 int r;
367 if (p->plugin.can_fast_zero)
368 return p->plugin.can_fast_zero (handle);
369 /* Advertise support for fast zeroes if no .zero or .can_zero is
370 * false: in those cases, we fail fast instead of using .pwrite.
371 * This also works when v1 plugin has only ._zero_v1.
373 if (p->plugin.zero == NULL)
374 return 1;
375 r = backend_can_zero (b, conn);
376 if (r == -1)
377 return -1;
378 return !r;
381 static int
382 plugin_can_extents (struct backend *b, struct connection *conn, void *handle)
384 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
386 if (p->plugin.can_extents)
387 return p->plugin.can_extents (handle);
388 else
389 return p->plugin.extents != NULL;
392 static int
393 plugin_can_fua (struct backend *b, struct connection *conn, void *handle)
395 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
396 int r;
398 /* The plugin must use API version 2 and have .can_fua return
399 NBDKIT_FUA_NATIVE before we will pass the FUA flag on. */
400 if (p->plugin.can_fua) {
401 r = p->plugin.can_fua (handle);
402 if (r > NBDKIT_FUA_EMULATE && p->plugin._api_version == 1)
403 r = NBDKIT_FUA_EMULATE;
404 return r;
406 /* We intend to call .flush even if .can_flush returns false. */
407 if (p->plugin.flush || p->plugin._flush_v1)
408 return NBDKIT_FUA_EMULATE;
409 return NBDKIT_FUA_NONE;
412 static int
413 plugin_can_multi_conn (struct backend *b, struct connection *conn, void *handle)
415 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
417 if (p->plugin.can_multi_conn)
418 return p->plugin.can_multi_conn (handle);
419 else
420 return 0; /* assume false */
423 static int
424 plugin_can_cache (struct backend *b, struct connection *conn, void *handle)
426 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
428 if (p->plugin.can_cache)
429 return p->plugin.can_cache (handle);
430 if (p->plugin.cache)
431 return NBDKIT_CACHE_NATIVE;
432 return NBDKIT_CACHE_NONE;
435 static int
436 plugin_init_sparse (struct backend *b, struct connection *conn, void *handle)
438 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
440 if (p->plugin.init_sparse)
441 return p->plugin.init_sparse (handle);
442 return 0;
445 static int
446 plugin_init_zero (struct backend *b, struct connection *conn, void *handle)
448 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
450 if (p->plugin.init_zero)
451 return p->plugin.init_zero (handle);
452 return 0;
455 /* Plugins and filters can call this to set the true errno, in cases
456 * where !errno_is_preserved.
458 void
459 nbdkit_set_error (int err)
461 threadlocal_set_error (err);
464 /* Grab the appropriate error value.
466 static int
467 get_error (struct backend_plugin *p)
469 int ret = threadlocal_get_error ();
471 if (!ret && p->plugin.errno_is_preserved != 0)
472 ret = errno;
473 return ret ? ret : EIO;
476 static int
477 plugin_pread (struct backend *b, struct connection *conn, void *handle,
478 void *buf, uint32_t count, uint64_t offset, uint32_t flags,
479 int *err)
481 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
482 int r;
484 assert (p->plugin.pread || p->plugin._pread_v1);
486 if (p->plugin.pread)
487 r = p->plugin.pread (handle, buf, count, offset, 0);
488 else
489 r = p->plugin._pread_v1 (handle, buf, count, offset);
490 if (r == -1)
491 *err = get_error (p);
492 return r;
495 static int
496 plugin_flush (struct backend *b, struct connection *conn, void *handle,
497 uint32_t flags, int *err)
499 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
500 int r;
502 if (p->plugin.flush)
503 r = p->plugin.flush (handle, 0);
504 else if (p->plugin._flush_v1)
505 r = p->plugin._flush_v1 (handle);
506 else {
507 *err = EINVAL;
508 return -1;
510 if (r == -1)
511 *err = get_error (p);
512 return r;
515 static int
516 plugin_pwrite (struct backend *b, struct connection *conn, void *handle,
517 const void *buf, uint32_t count, uint64_t offset, uint32_t flags,
518 int *err)
520 int r;
521 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
522 bool fua = flags & NBDKIT_FLAG_FUA;
523 bool need_flush = false;
525 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
526 flags &= ~NBDKIT_FLAG_FUA;
527 need_flush = true;
529 if (p->plugin.pwrite)
530 r = p->plugin.pwrite (handle, buf, count, offset, flags);
531 else if (p->plugin._pwrite_v1)
532 r = p->plugin._pwrite_v1 (handle, buf, count, offset);
533 else {
534 *err = EROFS;
535 return -1;
537 if (r != -1 && need_flush)
538 r = plugin_flush (b, conn, handle, 0, err);
539 if (r == -1 && !*err)
540 *err = get_error (p);
541 return r;
544 static int
545 plugin_trim (struct backend *b, struct connection *conn, void *handle,
546 uint32_t count, uint64_t offset, uint32_t flags, int *err)
548 int r;
549 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
550 bool fua = flags & NBDKIT_FLAG_FUA;
551 bool need_flush = false;
553 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
554 flags &= ~NBDKIT_FLAG_FUA;
555 need_flush = true;
557 if (p->plugin.trim)
558 r = p->plugin.trim (handle, count, offset, flags);
559 else if (p->plugin._trim_v1)
560 r = p->plugin._trim_v1 (handle, count, offset);
561 else {
562 *err = EINVAL;
563 return -1;
565 if (r != -1 && need_flush)
566 r = plugin_flush (b, conn, handle, 0, err);
567 if (r == -1 && !*err)
568 *err = get_error (p);
569 return r;
572 static int
573 plugin_zero (struct backend *b, struct connection *conn, void *handle,
574 uint32_t count, uint64_t offset, uint32_t flags, int *err)
576 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
577 int r = -1;
578 bool may_trim = flags & NBDKIT_FLAG_MAY_TRIM;
579 bool fua = flags & NBDKIT_FLAG_FUA;
580 bool fast_zero = flags & NBDKIT_FLAG_FAST_ZERO;
581 bool emulate = false;
582 bool need_flush = false;
584 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
585 flags &= ~NBDKIT_FLAG_FUA;
586 need_flush = true;
588 if (!count)
589 return 0;
591 if (backend_can_zero (b, conn) == NBDKIT_ZERO_NATIVE) {
592 errno = 0;
593 if (p->plugin.zero)
594 r = p->plugin.zero (handle, count, offset, flags);
595 else if (p->plugin._zero_v1) {
596 if (fast_zero) {
597 *err = EOPNOTSUPP;
598 return -1;
600 r = p->plugin._zero_v1 (handle, count, offset, may_trim);
602 else
603 emulate = true;
604 if (r == -1)
605 *err = emulate ? EOPNOTSUPP : get_error (p);
606 if (r == 0 || (*err != EOPNOTSUPP && *err != ENOTSUP))
607 goto done;
610 if (fast_zero) {
611 assert (r == -1);
612 *err = EOPNOTSUPP;
613 goto done;
616 assert (p->plugin.pwrite || p->plugin._pwrite_v1);
617 flags &= ~NBDKIT_FLAG_MAY_TRIM;
618 threadlocal_set_error (0);
619 *err = 0;
621 while (count) {
622 /* Always contains zeroes, but we can't use const or else gcc 9
623 * will use .rodata instead of .bss and inflate the binary size.
625 static /* const */ char buf[MAX_REQUEST_SIZE];
626 uint32_t limit = MIN (count, sizeof buf);
628 r = plugin_pwrite (b, conn, handle, buf, limit, offset, flags, err);
629 if (r == -1)
630 break;
631 count -= limit;
634 done:
635 if (r != -1 && need_flush)
636 r = plugin_flush (b, conn, handle, 0, err);
637 if (r == -1 && !*err)
638 *err = get_error (p);
639 return r;
642 static int
643 plugin_extents (struct backend *b, struct connection *conn, void *handle,
644 uint32_t count, uint64_t offset, uint32_t flags,
645 struct nbdkit_extents *extents, int *err)
647 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
648 int r;
650 /* This should be true because plugin_can_extents checks it. */
651 assert (p->plugin.extents);
653 r = p->plugin.extents (handle, count, offset, flags, extents);
654 if (r >= 0 && nbdkit_extents_count (extents) < 1) {
655 nbdkit_error ("extents: plugin must return at least one extent");
656 nbdkit_set_error (EINVAL);
657 r = -1;
659 if (r == -1)
660 *err = get_error (p);
661 return r;
664 static int
665 plugin_cache (struct backend *b, struct connection *conn, void *handle,
666 uint32_t count, uint64_t offset, uint32_t flags,
667 int *err)
669 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
670 int r;
672 /* A plugin may advertise caching but not provide .cache; in that
673 * case, caching is explicitly a no-op. */
674 if (!p->plugin.cache)
675 return 0;
677 r = p->plugin.cache (handle, count, offset, flags);
678 if (r == -1)
679 *err = get_error (p);
680 return r;
683 static struct backend plugin_functions = {
684 .free = plugin_free,
685 .thread_model = plugin_thread_model,
686 .plugin_name = plugin_name,
687 .usage = plugin_usage,
688 .version = plugin_version,
689 .dump_fields = plugin_dump_fields,
690 .config = plugin_config,
691 .config_complete = plugin_config_complete,
692 .magic_config_key = plugin_magic_config_key,
693 .preconnect = plugin_preconnect,
694 .open = plugin_open,
695 .prepare = plugin_prepare,
696 .finalize = plugin_finalize,
697 .close = plugin_close,
698 .get_size = plugin_get_size,
699 .can_write = plugin_can_write,
700 .can_flush = plugin_can_flush,
701 .is_rotational = plugin_is_rotational,
702 .can_trim = plugin_can_trim,
703 .can_zero = plugin_can_zero,
704 .can_fast_zero = plugin_can_fast_zero,
705 .can_extents = plugin_can_extents,
706 .can_fua = plugin_can_fua,
707 .can_multi_conn = plugin_can_multi_conn,
708 .can_cache = plugin_can_cache,
709 .init_sparse = plugin_init_sparse,
710 .init_zero = plugin_init_zero,
711 .pread = plugin_pread,
712 .pwrite = plugin_pwrite,
713 .flush = plugin_flush,
714 .trim = plugin_trim,
715 .zero = plugin_zero,
716 .extents = plugin_extents,
717 .cache = plugin_cache,
720 /* Register and load a plugin. */
721 struct backend *
722 plugin_register (size_t index, const char *filename,
723 void *dl, struct nbdkit_plugin *(*plugin_init) (void))
725 struct backend_plugin *p;
726 const struct nbdkit_plugin *plugin;
727 size_t size;
729 p = malloc (sizeof *p);
730 if (p == NULL) {
731 perror ("strdup");
732 exit (EXIT_FAILURE);
735 p->backend = plugin_functions;
736 backend_init (&p->backend, NULL, index, filename, dl, "plugin");
738 /* Call the initialization function which returns the address of the
739 * plugin's own 'struct nbdkit_plugin'.
741 plugin = plugin_init ();
742 if (!plugin) {
743 fprintf (stderr, "%s: %s: plugin registration function failed\n",
744 program_name, filename);
745 exit (EXIT_FAILURE);
748 /* Check for incompatible future versions. */
749 if (plugin->_api_version < 0 || plugin->_api_version > 2) {
750 fprintf (stderr,
751 "%s: %s: plugin is incompatible with this version of nbdkit "
752 "(_api_version = %d)\n",
753 program_name, filename, plugin->_api_version);
754 exit (EXIT_FAILURE);
757 /* Since the plugin might be much older than the current version of
758 * nbdkit, only copy up to the self-declared _struct_size of the
759 * plugin and zero out the rest. If the plugin is much newer then
760 * we'll only call the "old" fields.
762 size = sizeof p->plugin; /* our struct */
763 memset (&p->plugin, 0, size);
764 if (size > plugin->_struct_size)
765 size = plugin->_struct_size;
766 memcpy (&p->plugin, plugin, size);
768 /* Check for the minimum fields which must exist in the
769 * plugin struct.
771 if (p->plugin.open == NULL) {
772 fprintf (stderr, "%s: %s: plugin must have a .open callback\n",
773 program_name, filename);
774 exit (EXIT_FAILURE);
776 if (p->plugin.get_size == NULL) {
777 fprintf (stderr, "%s: %s: plugin must have a .get_size callback\n",
778 program_name, filename);
779 exit (EXIT_FAILURE);
781 if (p->plugin.pread == NULL && p->plugin._pread_v1 == NULL) {
782 fprintf (stderr, "%s: %s: plugin must have a .pread callback\n",
783 program_name, filename);
784 exit (EXIT_FAILURE);
787 backend_load (&p->backend, p->plugin.name, p->plugin.load);
789 return (struct backend *) p;