aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libfsimage/common/fsimage_grub.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libfsimage/common/fsimage_grub.c')
-rw-r--r--tools/libfsimage/common/fsimage_grub.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/tools/libfsimage/common/fsimage_grub.c b/tools/libfsimage/common/fsimage_grub.c
new file mode 100644
index 0000000000..252445f58e
--- /dev/null
+++ b/tools/libfsimage/common/fsimage_grub.c
@@ -0,0 +1,276 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef __sun__
+#define _XOPEN_SOURCE 500
+#endif
+#include <stdlib.h>
+#include <strings.h>
+#include <errno.h>
+
+#include "fsimage_grub.h"
+#include "fsimage_priv.h"
+
+static char *disk_read_junk;
+
+typedef struct fsig_data {
+ char fd_buf[FSYS_BUFLEN];
+} fsig_data_t;
+
+typedef struct fsig_file_data {
+ char ffd_buf[FSYS_BUFLEN];
+ uint64_t ffd_curpos;
+ uint64_t ffd_filepos;
+ uint64_t ffd_filemax;
+ int ffd_int1;
+ int ffd_int2;
+ int ffd_errnum;
+} fsig_file_data_t;
+
+fsi_file_t *
+fsig_file_alloc(fsi_t *fsi)
+{
+ fsi_file_t *ffi;
+ fsig_file_data_t *data = malloc(sizeof (fsig_file_data_t));
+
+ if (data == NULL)
+ return (NULL);
+
+ bzero(data, sizeof (fsig_file_data_t));
+ bcopy(fsig_fs_buf(fsi), data->ffd_buf, FSYS_BUFLEN);
+
+ if ((ffi = fsip_file_alloc(fsi, data)) == NULL) {
+ free(data);
+ return (NULL);
+ }
+
+ return (ffi);
+}
+
+void *
+fsig_fs_buf(fsi_t *fsi)
+{
+ fsig_data_t *data = fsip_fs_data(fsi);
+ return ((void *)data->fd_buf);
+}
+
+void *
+fsig_file_buf(fsi_file_t *ffi)
+{
+ fsig_file_data_t *data = fsip_file_data(ffi);
+ return ((void *)data->ffd_buf);
+}
+
+uint64_t *
+fsig_filepos(fsi_file_t *ffi)
+{
+ fsig_file_data_t *data = fsip_file_data(ffi);
+ return (&data->ffd_filepos);
+}
+
+uint64_t *
+fsig_filemax(fsi_file_t *ffi)
+{
+ fsig_file_data_t *data = fsip_file_data(ffi);
+ return (&data->ffd_filemax);
+}
+
+int *
+fsig_int1(fsi_file_t *ffi)
+{
+ fsig_file_data_t *data = fsip_file_data(ffi);
+ return (&data->ffd_int1);
+}
+
+int *
+fsig_int2(fsi_file_t *ffi)
+{
+ fsig_file_data_t *data = fsip_file_data(ffi);
+ return (&data->ffd_int2);
+}
+
+int *
+fsig_errnum(fsi_file_t *ffi)
+{
+ fsig_file_data_t *data = fsip_file_data(ffi);
+ return (&data->ffd_errnum);
+}
+
+char **
+fsig_disk_read_junk(void)
+{
+ return (&disk_read_junk);
+}
+
+int
+fsig_devread(fsi_file_t *ffi, unsigned int sector, unsigned int offset,
+ unsigned int bufsize, char *buf)
+{
+ uint64_t off = ffi->ff_fsi->f_off + ((uint64_t)sector * 512) + offset;
+ ssize_t bytes_read = 0;
+
+ while (bufsize) {
+ ssize_t ret = pread(ffi->ff_fsi->f_fd, buf + bytes_read,
+ bufsize, (off_t)off);
+ if (ret == -1)
+ return (0);
+ if (ret == 0)
+ return (0);
+
+ bytes_read += ret;
+ bufsize -= ret;
+ }
+
+ return (1);
+}
+
+int
+fsig_substring(const char *s1, const char *s2)
+{
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ return (0);
+ s1++;
+ s2++;
+ }
+
+ if (*s1 == '\0')
+ return (-1);
+
+ return (1);
+}
+
+static int
+fsig_mount(fsi_t *fsi, const char *path)
+{
+ fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;
+ fsi_file_t *ffi;
+ fsi->f_data = malloc(sizeof (fsig_data_t));
+
+ if (fsi->f_data == NULL)
+ return (-1);
+
+ if ((ffi = fsig_file_alloc(fsi)) == NULL) {
+ free(fsi->f_data);
+ fsi->f_data = NULL;
+ return (-1);
+ }
+
+ bzero(fsi->f_data, sizeof (fsig_data_t));
+
+ if (!ops->fpo_mount(ffi)) {
+ fsip_file_free(ffi);
+ free(fsi->f_data);
+ fsi->f_data = NULL;
+ return (-1);
+ }
+
+ bcopy(fsig_file_buf(ffi), fsig_fs_buf(fsi), FSYS_BUFLEN);
+ fsip_file_free(ffi);
+ return (0);
+}
+
+static int
+fsig_umount(fsi_t *fsi)
+{
+ return (0);
+}
+
+static fsi_file_t *
+fsig_open(fsi_t *fsi, const char *name)
+{
+ fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;
+ char *path = strdup(name);
+ fsi_file_t *ffi = NULL;
+
+ if (path == NULL || (ffi = fsig_file_alloc(fsi)) == NULL)
+ goto out;
+
+ if (ops->fpo_dir(ffi, path) == 0) {
+ fsip_file_free(ffi);
+ ffi = NULL;
+ errno = ENOENT;
+ }
+
+out:
+ free(path);
+ return (ffi);
+}
+
+static ssize_t
+fsig_pread(fsi_file_t *ffi, void *buf, size_t nbytes, uint64_t off)
+{
+ fsig_plugin_ops_t *ops = ffi->ff_fsi->f_plugin->fp_data;
+ fsig_file_data_t *data = fsip_file_data(ffi);
+
+ data->ffd_filepos = off;
+
+ if (data->ffd_filepos >= data->ffd_filemax)
+ return (0);
+
+ /* FIXME: check */
+ if (data->ffd_filepos + nbytes > data->ffd_filemax)
+ nbytes = data->ffd_filemax - data->ffd_filepos;
+
+ errnum = 0;
+ return (ops->fpo_read(ffi, buf, nbytes));
+}
+
+static ssize_t
+fsig_read(fsi_file_t *ffi, void *buf, size_t nbytes)
+{
+ fsig_file_data_t *data = fsip_file_data(ffi);
+ ssize_t ret;
+
+ ret = fsig_pread(ffi, buf, nbytes, data->ffd_curpos);
+ data->ffd_curpos = data->ffd_filepos;
+ return (ret);
+}
+
+static int
+fsig_close(fsi_file_t *ffi)
+{
+ fsip_file_free(ffi);
+ return (0);
+}
+
+static fsi_plugin_ops_t fsig_grub_ops = {
+ .fpo_version = FSIMAGE_PLUGIN_VERSION,
+ .fpo_mount = fsig_mount,
+ .fpo_umount = fsig_umount,
+ .fpo_open = fsig_open,
+ .fpo_read = fsig_read,
+ .fpo_pread = fsig_pread,
+ .fpo_close = fsig_close
+};
+
+fsi_plugin_ops_t *
+fsig_init(fsi_plugin_t *plugin, fsig_plugin_ops_t *ops)
+{
+ if (ops->fpo_version > FSIMAGE_PLUGIN_VERSION)
+ return (NULL);
+
+ plugin->fp_data = ops;
+
+ return (&fsig_grub_ops);
+}