server: Fix regression for NBD_OPT_INFO before NBD_OPT_GO
[nbdkit/ericb.git] / server / plugins.c
blob727fb0e042bc1eb26bd00429f0d0b5c87b398664
1 /* nbdkit
2 * Copyright (C) 2013-2019 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 nbdkit_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 (open);
162 HAS (close);
163 HAS (get_size);
164 HAS (can_write);
165 HAS (can_flush);
166 HAS (is_rotational);
167 HAS (can_trim);
168 HAS (_pread_old);
169 HAS (_pwrite_old);
170 HAS (_flush_old);
171 HAS (_trim_old);
172 HAS (_zero_old);
173 HAS (can_zero);
174 HAS (can_fua);
175 HAS (pread);
176 HAS (pwrite);
177 HAS (flush);
178 HAS (trim);
179 HAS (zero);
180 HAS (can_multi_conn);
181 HAS (can_extents);
182 HAS (extents);
183 HAS (can_cache);
184 HAS (cache);
185 HAS (thread_model);
186 HAS (can_fast_zero);
187 #undef HAS
189 /* Custom fields. */
190 if (p->plugin.dump_plugin)
191 p->plugin.dump_plugin ();
194 static void
195 plugin_config (struct backend *b, const char *key, const char *value)
197 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
199 debug ("%s: config key=%s, value=%s", b->name, key, value);
201 if (p->plugin.config == NULL) {
202 fprintf (stderr,
203 "%s: %s: this plugin does not need command line configuration\n"
204 "Try using: %s --help %s\n",
205 program_name, b->filename,
206 program_name, b->filename);
207 exit (EXIT_FAILURE);
210 if (p->plugin.config (key, value) == -1)
211 exit (EXIT_FAILURE);
214 static void
215 plugin_config_complete (struct backend *b)
217 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
219 debug ("%s: config_complete", b->name);
221 if (!p->plugin.config_complete)
222 return;
224 if (p->plugin.config_complete () == -1)
225 exit (EXIT_FAILURE);
228 static const char *
229 plugin_magic_config_key (struct backend *b)
231 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
233 return p->plugin.magic_config_key;
236 static int
237 plugin_open (struct backend *b, struct connection *conn, int readonly)
239 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
240 void *handle;
242 assert (connection_get_handle (conn, 0) == NULL);
243 assert (p->plugin.open != NULL);
245 handle = p->plugin.open (readonly);
246 if (!handle)
247 return -1;
249 backend_set_handle (b, conn, handle);
250 return 0;
253 /* We don't expose .prepare and .finalize to plugins since they aren't
254 * necessary. Plugins can easily do the same work in .open and
255 * .close.
257 static int
258 plugin_prepare (struct backend *b, struct connection *conn, int readonly)
260 return 0;
263 static int
264 plugin_finalize (struct backend *b, struct connection *conn)
266 return 0;
269 static void
270 plugin_close (struct backend *b, struct connection *conn)
272 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
274 assert (connection_get_handle (conn, 0));
276 if (p->plugin.close)
277 p->plugin.close (connection_get_handle (conn, 0));
280 static int64_t
281 plugin_get_size (struct backend *b, struct connection *conn)
283 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
285 assert (connection_get_handle (conn, 0));
286 assert (p->plugin.get_size != NULL);
288 return p->plugin.get_size (connection_get_handle (conn, 0));
291 static int
292 plugin_can_write (struct backend *b, struct connection *conn)
294 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
296 assert (connection_get_handle (conn, 0));
298 if (p->plugin.can_write)
299 return p->plugin.can_write (connection_get_handle (conn, 0));
300 else
301 return p->plugin.pwrite || p->plugin._pwrite_old;
304 static int
305 plugin_can_flush (struct backend *b, struct connection *conn)
307 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
309 assert (connection_get_handle (conn, 0));
311 if (p->plugin.can_flush)
312 return p->plugin.can_flush (connection_get_handle (conn, 0));
313 else
314 return p->plugin.flush || p->plugin._flush_old;
317 static int
318 plugin_is_rotational (struct backend *b, struct connection *conn)
320 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
322 assert (connection_get_handle (conn, 0));
324 if (p->plugin.is_rotational)
325 return p->plugin.is_rotational (connection_get_handle (conn, 0));
326 else
327 return 0; /* assume false */
330 static int
331 plugin_can_trim (struct backend *b, struct connection *conn)
333 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
335 assert (connection_get_handle (conn, 0));
337 if (p->plugin.can_trim)
338 return p->plugin.can_trim (connection_get_handle (conn, 0));
339 else
340 return p->plugin.trim || p->plugin._trim_old;
343 static int
344 plugin_can_zero (struct backend *b, struct connection *conn)
346 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
347 int r;
349 assert (connection_get_handle (conn, 0));
351 /* Note the special case here: the plugin's .can_zero returns a bool
352 * which controls only whether we call .zero; while the backend
353 * expects .can_zero to return a tri-state on level of support.
355 if (p->plugin.can_zero) {
356 r = p->plugin.can_zero (connection_get_handle (conn, 0));
357 if (r == -1)
358 return -1;
359 return r ? NBDKIT_ZERO_NATIVE : NBDKIT_ZERO_EMULATE;
361 if (p->plugin.zero || p->plugin._zero_old)
362 return NBDKIT_ZERO_NATIVE;
363 return NBDKIT_ZERO_EMULATE;
366 static int
367 plugin_can_fast_zero (struct backend *b, struct connection *conn)
369 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
370 int r;
372 assert (connection_get_handle (conn, 0));
374 if (p->plugin.can_fast_zero)
375 return p->plugin.can_fast_zero (connection_get_handle (conn, 0));
376 /* Advertise support for fast zeroes if no .zero or .can_zero is
377 * false: in those cases, we fail fast instead of using .pwrite.
378 * This also works when v1 plugin has only ._zero_old.
380 if (p->plugin.zero == NULL)
381 return 1;
382 r = backend_can_zero (b, conn);
383 if (r == -1)
384 return -1;
385 return !r;
388 static int
389 plugin_can_extents (struct backend *b, struct connection *conn)
391 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
393 assert (connection_get_handle (conn, 0));
395 if (p->plugin.can_extents)
396 return p->plugin.can_extents (connection_get_handle (conn, 0));
397 else
398 return p->plugin.extents != NULL;
401 static int
402 plugin_can_fua (struct backend *b, struct connection *conn)
404 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
405 int r;
407 assert (connection_get_handle (conn, 0));
409 /* The plugin must use API version 2 and have .can_fua return
410 NBDKIT_FUA_NATIVE before we will pass the FUA flag on. */
411 if (p->plugin.can_fua) {
412 r = p->plugin.can_fua (connection_get_handle (conn, 0));
413 if (r > NBDKIT_FUA_EMULATE && p->plugin._api_version == 1)
414 r = NBDKIT_FUA_EMULATE;
415 return r;
417 /* We intend to call .flush even if .can_flush returns false. */
418 if (p->plugin.flush || p->plugin._flush_old)
419 return NBDKIT_FUA_EMULATE;
420 return NBDKIT_FUA_NONE;
423 static int
424 plugin_can_multi_conn (struct backend *b, struct connection *conn)
426 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
428 assert (connection_get_handle (conn, 0));
430 if (p->plugin.can_multi_conn)
431 return p->plugin.can_multi_conn (connection_get_handle (conn, 0));
432 else
433 return 0; /* assume false */
436 static int
437 plugin_can_cache (struct backend *b, struct connection *conn)
439 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
441 assert (connection_get_handle (conn, 0));
443 if (p->plugin.can_cache)
444 return p->plugin.can_cache (connection_get_handle (conn, 0));
445 if (p->plugin.cache)
446 return NBDKIT_CACHE_NATIVE;
447 return NBDKIT_CACHE_NONE;
450 /* Plugins and filters can call this to set the true errno, in cases
451 * where !errno_is_preserved.
453 void
454 nbdkit_set_error (int err)
456 threadlocal_set_error (err);
459 /* Grab the appropriate error value.
461 static int
462 get_error (struct backend_plugin *p)
464 int ret = threadlocal_get_error ();
466 if (!ret && p->plugin.errno_is_preserved != 0)
467 ret = errno;
468 return ret ? ret : EIO;
471 static int
472 plugin_pread (struct backend *b, struct connection *conn,
473 void *buf, uint32_t count, uint64_t offset, uint32_t flags,
474 int *err)
476 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
477 int r;
479 assert (connection_get_handle (conn, 0));
480 assert (p->plugin.pread || p->plugin._pread_old);
482 if (p->plugin.pread)
483 r = p->plugin.pread (connection_get_handle (conn, 0), buf, count, offset,
485 else
486 r = p->plugin._pread_old (connection_get_handle (conn, 0), buf, count,
487 offset);
488 if (r == -1)
489 *err = get_error (p);
490 return r;
493 static int
494 plugin_flush (struct backend *b, struct connection *conn, uint32_t flags,
495 int *err)
497 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
498 int r;
500 assert (connection_get_handle (conn, 0));
502 if (p->plugin.flush)
503 r = p->plugin.flush (connection_get_handle (conn, 0), 0);
504 else if (p->plugin._flush_old)
505 r = p->plugin._flush_old (connection_get_handle (conn, 0));
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,
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 assert (connection_get_handle (conn, 0));
527 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
528 flags &= ~NBDKIT_FLAG_FUA;
529 need_flush = true;
531 if (p->plugin.pwrite)
532 r = p->plugin.pwrite (connection_get_handle (conn, 0), buf, count, offset,
533 flags);
534 else if (p->plugin._pwrite_old)
535 r = p->plugin._pwrite_old (connection_get_handle (conn, 0),
536 buf, count, offset);
537 else {
538 *err = EROFS;
539 return -1;
541 if (r != -1 && need_flush)
542 r = plugin_flush (b, conn, 0, err);
543 if (r == -1 && !*err)
544 *err = get_error (p);
545 return r;
548 static int
549 plugin_trim (struct backend *b, struct connection *conn,
550 uint32_t count, uint64_t offset, uint32_t flags, int *err)
552 int r;
553 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
554 bool fua = flags & NBDKIT_FLAG_FUA;
555 bool need_flush = false;
557 assert (connection_get_handle (conn, 0));
559 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
560 flags &= ~NBDKIT_FLAG_FUA;
561 need_flush = true;
563 if (p->plugin.trim)
564 r = p->plugin.trim (connection_get_handle (conn, 0), count, offset, flags);
565 else if (p->plugin._trim_old)
566 r = p->plugin._trim_old (connection_get_handle (conn, 0), count, offset);
567 else {
568 *err = EINVAL;
569 return -1;
571 if (r != -1 && need_flush)
572 r = plugin_flush (b, conn, 0, err);
573 if (r == -1 && !*err)
574 *err = get_error (p);
575 return r;
578 static int
579 plugin_zero (struct backend *b, struct connection *conn,
580 uint32_t count, uint64_t offset, uint32_t flags, int *err)
582 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
583 int r = -1;
584 bool may_trim = flags & NBDKIT_FLAG_MAY_TRIM;
585 bool fua = flags & NBDKIT_FLAG_FUA;
586 bool fast_zero = flags & NBDKIT_FLAG_FAST_ZERO;
587 bool emulate = false;
588 bool need_flush = false;
590 assert (connection_get_handle (conn, 0));
592 if (fua && backend_can_fua (b, conn) != NBDKIT_FUA_NATIVE) {
593 flags &= ~NBDKIT_FLAG_FUA;
594 need_flush = true;
596 if (!count)
597 return 0;
599 if (backend_can_zero (b, conn) == NBDKIT_ZERO_NATIVE) {
600 errno = 0;
601 if (p->plugin.zero)
602 r = p->plugin.zero (connection_get_handle (conn, 0), count, offset,
603 flags);
604 else if (p->plugin._zero_old) {
605 if (fast_zero) {
606 *err = EOPNOTSUPP;
607 return -1;
609 r = p->plugin._zero_old (connection_get_handle (conn, 0), count, offset,
610 may_trim);
612 else
613 emulate = true;
614 if (r == -1)
615 *err = emulate ? EOPNOTSUPP : get_error (p);
616 if (r == 0 || (*err != EOPNOTSUPP && *err != ENOTSUP))
617 goto done;
620 if (fast_zero) {
621 assert (r == -1);
622 *err = EOPNOTSUPP;
623 goto done;
626 assert (p->plugin.pwrite || p->plugin._pwrite_old);
627 flags &= ~NBDKIT_FLAG_MAY_TRIM;
628 threadlocal_set_error (0);
629 *err = 0;
631 while (count) {
632 /* Always contains zeroes, but we can't use const or else gcc 9
633 * will use .rodata instead of .bss and inflate the binary size.
635 static /* const */ char buf[MAX_REQUEST_SIZE];
636 uint32_t limit = MIN (count, sizeof buf);
638 r = plugin_pwrite (b, conn, buf, limit, offset, flags, err);
639 if (r == -1)
640 break;
641 count -= limit;
644 done:
645 if (r != -1 && need_flush)
646 r = plugin_flush (b, conn, 0, err);
647 if (r == -1 && !*err)
648 *err = get_error (p);
649 return r;
652 static int
653 plugin_extents (struct backend *b, struct connection *conn,
654 uint32_t count, uint64_t offset, uint32_t flags,
655 struct nbdkit_extents *extents, int *err)
657 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
658 int r;
660 assert (connection_get_handle (conn, 0));
662 /* This should be true because plugin_can_extents checks it. */
663 assert (p->plugin.extents);
665 r = p->plugin.extents (connection_get_handle (conn, 0), count, offset,
666 flags, extents);
667 if (r >= 0 && nbdkit_extents_count (extents) < 1) {
668 nbdkit_error ("extents: plugin must return at least one extent");
669 nbdkit_set_error (EINVAL);
670 r = -1;
672 if (r == -1)
673 *err = get_error (p);
674 return r;
677 static int
678 plugin_cache (struct backend *b, struct connection *conn,
679 uint32_t count, uint64_t offset, uint32_t flags,
680 int *err)
682 struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
683 int r;
685 assert (connection_get_handle (conn, 0));
687 /* A plugin may advertise caching but not provide .cache; in that
688 * case, caching is explicitly a no-op. */
689 if (!p->plugin.cache)
690 return 0;
692 r = p->plugin.cache (connection_get_handle (conn, 0), count, offset, flags);
693 if (r == -1)
694 *err = get_error (p);
695 return r;
698 static struct backend plugin_functions = {
699 .free = plugin_free,
700 .thread_model = plugin_thread_model,
701 .plugin_name = plugin_name,
702 .usage = plugin_usage,
703 .version = plugin_version,
704 .dump_fields = plugin_dump_fields,
705 .config = plugin_config,
706 .config_complete = plugin_config_complete,
707 .magic_config_key = plugin_magic_config_key,
708 .open = plugin_open,
709 .prepare = plugin_prepare,
710 .finalize = plugin_finalize,
711 .close = plugin_close,
712 .get_size = plugin_get_size,
713 .can_write = plugin_can_write,
714 .can_flush = plugin_can_flush,
715 .is_rotational = plugin_is_rotational,
716 .can_trim = plugin_can_trim,
717 .can_zero = plugin_can_zero,
718 .can_fast_zero = plugin_can_fast_zero,
719 .can_extents = plugin_can_extents,
720 .can_fua = plugin_can_fua,
721 .can_multi_conn = plugin_can_multi_conn,
722 .can_cache = plugin_can_cache,
723 .pread = plugin_pread,
724 .pwrite = plugin_pwrite,
725 .flush = plugin_flush,
726 .trim = plugin_trim,
727 .zero = plugin_zero,
728 .extents = plugin_extents,
729 .cache = plugin_cache,
732 /* Register and load a plugin. */
733 struct backend *
734 plugin_register (size_t index, const char *filename,
735 void *dl, struct nbdkit_plugin *(*plugin_init) (void))
737 struct backend_plugin *p;
738 const struct nbdkit_plugin *plugin;
739 size_t size;
741 p = malloc (sizeof *p);
742 if (p == NULL) {
743 perror ("strdup");
744 exit (EXIT_FAILURE);
747 p->backend = plugin_functions;
748 backend_init (&p->backend, NULL, index, filename, dl, "plugin");
750 /* Call the initialization function which returns the address of the
751 * plugin's own 'struct nbdkit_plugin'.
753 plugin = plugin_init ();
754 if (!plugin) {
755 fprintf (stderr, "%s: %s: plugin registration function failed\n",
756 program_name, filename);
757 exit (EXIT_FAILURE);
760 /* Check for incompatible future versions. */
761 if (plugin->_api_version < 0 || plugin->_api_version > 2) {
762 fprintf (stderr,
763 "%s: %s: plugin is incompatible with this version of nbdkit "
764 "(_api_version = %d)\n",
765 program_name, filename, plugin->_api_version);
766 exit (EXIT_FAILURE);
769 /* Since the plugin might be much older than the current version of
770 * nbdkit, only copy up to the self-declared _struct_size of the
771 * plugin and zero out the rest. If the plugin is much newer then
772 * we'll only call the "old" fields.
774 size = sizeof p->plugin; /* our struct */
775 memset (&p->plugin, 0, size);
776 if (size > plugin->_struct_size)
777 size = plugin->_struct_size;
778 memcpy (&p->plugin, plugin, size);
780 /* Check for the minimum fields which must exist in the
781 * plugin struct.
783 if (p->plugin.open == NULL) {
784 fprintf (stderr, "%s: %s: plugin must have a .open callback\n",
785 program_name, filename);
786 exit (EXIT_FAILURE);
788 if (p->plugin.get_size == NULL) {
789 fprintf (stderr, "%s: %s: plugin must have a .get_size callback\n",
790 program_name, filename);
791 exit (EXIT_FAILURE);
793 if (p->plugin.pread == NULL && p->plugin._pread_old == NULL) {
794 fprintf (stderr, "%s: %s: plugin must have a .pread callback\n",
795 program_name, filename);
796 exit (EXIT_FAILURE);
799 backend_load (&p->backend, p->plugin.name, p->plugin.load);
801 return (struct backend *) p;