iso: Implement --dump-plugin option
[nbdkit.git] / plugins / iso / iso.c
blob87e654e6c707de374182c18432a154c27b9d66d8
1 /* nbdkit
2 * Copyright (C) 2018-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 <string.h>
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
42 #include <nbdkit-plugin.h>
44 #include "cleanup.h"
45 #include "string-vector.h"
46 #include "utils.h"
48 /* List of directories parsed from the command line. */
49 static string_vector dirs = empty_vector;
51 /* xorriso or genisoimage or mkisofs program, picked at compile time,
52 * but can be overridden at run time.
54 static const char *isoprog = ISOPROG;
56 /* Extra parameters for isoprog. */
57 static const char *params = NULL;
59 /* The temporary ISO. */
60 static int fd = -1;
62 /* Construct the temporary ISO. */
63 static int
64 make_iso (void)
66 const char *tmpdir;
67 CLEANUP_FREE char *template = NULL;
68 CLEANUP_FREE char *command = NULL;
69 size_t command_len = 0;
70 FILE *fp;
71 size_t i;
72 int r;
74 /* Path for temporary file. */
75 tmpdir = getenv ("TMPDIR");
76 if (tmpdir == NULL)
77 tmpdir = LARGE_TMPDIR;
78 if (asprintf (&template, "%s/isoXXXXXX", tmpdir) == -1) {
79 nbdkit_error ("asprintf: %m");
80 return -1;
83 fd = mkstemp (template);
84 if (fd == -1) {
85 nbdkit_error ("mkstemp: %s: %m", template);
86 return -1;
88 unlink (template);
90 /* Construct the isoprog command. */
91 fp = open_memstream (&command, &command_len);
92 if (fp == NULL) {
93 nbdkit_error ("open_memstream: %m");
94 return -1;
97 shell_quote (isoprog, fp);
98 #if ISOPROG_IS_XORRISO
99 /* This is necessary to make xorriso command line parsing behave
100 * like mkisofs.
102 fprintf (fp, " -as mkisofs");
103 #endif
104 fprintf (fp, " -quiet");
105 if (params)
106 fprintf (fp, " %s", params);
107 for (i = 0; i < dirs.len; ++i) {
108 fputc (' ', fp);
109 shell_quote (dirs.ptr[i], fp);
111 /* Redirect output to the temporary file. */
112 fprintf (fp, " >&%d", fd);
114 if (fclose (fp) == EOF) {
115 nbdkit_error ("memstream failed: %m");
116 return -1;
119 /* Run the command. */
120 nbdkit_debug ("%s", command);
121 r = system (command);
122 if (exit_status_to_nbd_error (r, isoprog) == -1)
123 return -1;
125 return 0;
128 static void
129 iso_unload (void)
131 string_vector_iter (&dirs, (void *) free);
132 free (dirs.ptr);
134 if (fd >= 0)
135 close (fd);
138 static int
139 iso_config (const char *key, const char *value)
141 char *dir;
143 if (strcmp (key, "dir") == 0) {
144 dir = nbdkit_realpath (value);
145 if (dir == NULL)
146 return -1;
148 if (string_vector_append (&dirs, dir) == -1) {
149 nbdkit_error ("realloc: %m");
150 free (dir);
151 return -1;
154 else if (strcmp (key, "params") == 0) {
155 params = value;
157 else if (strcmp (key, "prog") == 0) {
158 isoprog = value;
160 else {
161 nbdkit_error ("unknown parameter '%s'", key);
162 return -1;
165 return 0;
168 static int
169 iso_config_complete (void)
171 if (dirs.len == 0) {
172 nbdkit_error ("you must supply the dir=<DIRECTORY> parameter "
173 "after the plugin name on the command line");
174 return -1;
177 return 0;
180 #define iso_config_help \
181 "dir=<DIRECTORY> (required) The directory to serve.\n" \
182 "params='<PARAMS>' Extra parameters to pass.\n" \
183 "prog=<ISOPROG> The program used to make ISOs." \
185 static void
186 iso_dump_plugin (void)
188 printf ("iso_prog=%s\n", ISOPROG);
191 static int
192 iso_get_ready (void)
194 return make_iso ();
197 static void *
198 iso_open (int readonly)
200 return NBDKIT_HANDLE_NOT_NEEDED;
203 #define THREAD_MODEL NBDKIT_THREAD_MODEL_PARALLEL
205 /* Get the file size. */
206 static int64_t
207 iso_get_size (void *handle)
209 struct stat statbuf;
211 if (fstat (fd, &statbuf) == -1) {
212 nbdkit_error ("fstat: %m");
213 return -1;
216 return statbuf.st_size;
219 /* Serves the same data over multiple connections. */
220 static int
221 iso_can_multi_conn (void *handle)
223 return 1;
226 static int
227 iso_can_cache (void *handle)
229 /* Let nbdkit call pread to populate the file system cache. */
230 return NBDKIT_CACHE_EMULATE;
233 /* Read data from the file. */
234 static int
235 iso_pread (void *handle, void *buf, uint32_t count, uint64_t offset)
237 while (count > 0) {
238 ssize_t r = pread (fd, buf, count, offset);
239 if (r == -1) {
240 nbdkit_error ("pread: %m");
241 return -1;
243 if (r == 0) {
244 nbdkit_error ("pread: unexpected end of file");
245 return -1;
247 buf += r;
248 count -= r;
249 offset += r;
252 return 0;
255 static struct nbdkit_plugin plugin = {
256 .name = "iso",
257 .longname = "nbdkit iso plugin",
258 .version = PACKAGE_VERSION,
259 .unload = iso_unload,
260 .config = iso_config,
261 .config_complete = iso_config_complete,
262 .config_help = iso_config_help,
263 .magic_config_key = "dir",
264 .dump_plugin = iso_dump_plugin,
265 .get_ready = iso_get_ready,
266 .open = iso_open,
267 .get_size = iso_get_size,
268 .can_multi_conn = iso_can_multi_conn,
269 .can_cache = iso_can_cache,
270 .pread = iso_pread,
271 .errno_is_preserved = 1,
274 NBDKIT_REGISTER_PLUGIN(plugin)