grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: hostfs patch


From: Tomas Ebenlendr
Subject: Re: hostfs patch
Date: Sat, 25 Sep 2004 18:25:29 +0200
User-agent: Mutt/1.5.6i

Here is the patch.
I moved the file fakedisk.c to directory disk/, other changes are only
fixes of what Marco noted.

I'll comit it cca on friday if there will be no more comments.

Changelog:
2004-08-08  Tomas Ebenlendr  <address@hidden>

        Added support for accessing files via host filesystem to
        grub-emu.

        * fs/hostfs.c: New file. Connects grub fs interface and libc file
        interface.
        * util/fakedisk.c: New file, implements fake disks.
        * include/grub/fs.h (grub_hostfs_init, grub_hostfs_fini): New
        prototypes.
        * include/grub/fakedisk.h: New file.
        * include/grub/disk.h: New constant GRUB_DISK_DEVICE_FAKEDISK_ID.
        * util/grub-emu.c (main): Added inicialization and destruction
        of hostfs and fakedisk.
        * conf/i386-pc.rmk (grub_emu_SOURCES): Added util/hostdisk.c
        and fs/hostfs.c
        * conf/powerpc-iee1275.rmk (grub_emu_SOURCES): The same.

        * kern/dl.c (grub_dl_load_core): Don't dereference null pointer.


diff -rupN -x CVS -x '*.mk' grub2_savannah/conf/i386-pc.rmk 
grub2_wodiff/conf/i386-pc.rmk
--- grub2_savannah/conf/i386-pc.rmk     2004-09-20 09:23:23.000000000 +0200
+++ grub2_wodiff/conf/i386-pc.rmk       2004-09-25 17:03:24.000000000 +0200
@@ -69,7 +69,8 @@ grub_emu_SOURCES = kern/main.c kern/devi
         kern/misc.c kern/loader.c kern/rescue.c kern/term.c            \
        disk/i386/pc/partition.c kern/env.c commands/ls.c               \
        commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c       
        \
-       util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c fs/ufs.c fs/minix.c fs/hfs.c 
fs/jfs.c\
+       util/i386/pc/biosdisk.c disk/fakedisk.c fs/fat.c fs/ext2.c      \
+       fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c util/hostfs.c             \
        normal/cmdline.c normal/command.c normal/main.c normal/menu.c 
normal/arg.c      \
        util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c
 grub_emu_LDFLAGS = -lncurses
diff -rupN -x CVS -x '*.mk' grub2_savannah/conf/powerpc-ieee1275.rmk 
grub2_wodiff/conf/powerpc-ieee1275.rmk
--- grub2_savannah/conf/powerpc-ieee1275.rmk    2004-09-20 09:23:23.000000000 
+0200
+++ grub2_wodiff/conf/powerpc-ieee1275.rmk      2004-09-25 17:03:42.000000000 
+0200
@@ -25,8 +25,9 @@ grub_emu_SOURCES = kern/main.c kern/devi
        kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c          \
         kern/misc.c kern/loader.c kern/rescue.c kern/term.c            \
        disk/powerpc/ieee1275/partition.c fs/fshelp.c                   \
-       util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c fs/ufs.c fs/minix.c fs/hfs.c 
\
-       fs/jfs.c normal/cmdline.c normal/command.c normal/main.c normal/menu.c  
\
+       util/i386/pc/biosdisk.c disk/fakedisk.c fs/fat.c fs/ext2.c      \
+       fs/ufs.c fs/minix.c fs/hfs.c fs/jfs.c util/hostfs.c             \
+       normal/cmdline.c normal/command.c normal/main.c normal/menu.c   \
        normal/arg.c    \
        util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c \
        kern/env.c commands/ls.c                \
diff -rupN -x CVS -x '*.mk' grub2_savannah/disk/fakedisk.c 
grub2_wodiff/disk/fakedisk.c
--- grub2_savannah/disk/fakedisk.c      1970-01-01 01:00:00.000000000 +0100
+++ grub2_wodiff/disk/fakedisk.c        2004-09-25 17:33:42.000000000 +0200
@@ -0,0 +1,152 @@
+/* fakedisk.c - fake disk device */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/disk.h>
+#include <grub/types.h>
+#include <grub/err.h>
+#include <grub/util/misc.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+#include <grub/fakedisk.h>
+
+/* List of devices.  */
+typedef struct grub_fakedisk_entry *grub_fakedisk_entry_t;
+struct grub_fakedisk_entry
+{
+  char *name;
+  grub_fakedisk_entry_t next;
+};
+static grub_fakedisk_entry_t fakedisks = 0;
+
+static int
+grub_util_fakedisk_iterate (int (*hook) (const char *name))
+{
+  grub_fakedisk_entry_t d;
+  for (d = fakedisks; d; d = d->next)
+    if (hook (d->name))
+      return 1;
+  return 0;
+}
+
+static grub_err_t
+grub_util_fakedisk_open (const char *name, grub_disk_t disk)
+{
+  grub_fakedisk_entry_t d=fakedisks;
+  while (d && (grub_strcmp (name, d->name) != 0))
+    d = d->next;
+  if (!d)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown disk %s", name);
+  disk->has_partitions = 0;
+  /* Id is irrelevant.  */
+  disk->id = -1;
+  /* This shoud be much greater than zero. Some fs claims that disk is
+     totaly bad while fs-probe if total_sectors to low.  */
+  disk->total_sectors = 1234;
+  return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_util_fakedisk_read (grub_disk_t disk __attribute__ ((unused)),
+                        unsigned long sector __attribute__ ((unused)),
+                        unsigned long size __attribute__ ((unused)),
+                        char *buf __attribute__ ((unused)))
+{
+  /* BAD_FS is here for filesystem probe to work.  */
+  grub_error (GRUB_ERR_BAD_FS, "cannot read from fakedisk %s", disk->name);
+  return grub_errno;
+}
+
+
+static grub_err_t
+grub_util_fakedisk_write (grub_disk_t disk __attribute__ ((unused)),
+                         unsigned long sector __attribute__ ((unused)),
+                         unsigned long size __attribute__ ((unused)),
+                         const char *buf __attribute__ ((unused)))
+{
+  grub_error (GRUB_ERR_BAD_FS, "cannot write to fakedisk %s", disk->name);
+  return grub_errno;
+}
+
+
+static struct grub_disk_dev grub_util_fakedisk_dev =
+  {
+    .name = "fakedisk",
+    .id = GRUB_DISK_DEVICE_FAKEDISK_ID,
+    .iterate = grub_util_fakedisk_iterate,
+    .open = grub_util_fakedisk_open,
+    .close = 0,
+    .read = grub_util_fakedisk_read,
+    .write = grub_util_fakedisk_write,
+    .next = 0
+  };
+
+grub_err_t
+grub_fakedisk_register (const char * name)
+{
+  grub_fakedisk_entry_t d = 0;
+
+  if (! name || ! name[0])
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid fakedisk 
registration.");
+
+  d = grub_malloc (sizeof (struct grub_fakedisk_entry));
+  if (! d)
+    goto nomem;
+  d->name = grub_strdup (name);
+  if (! (d->name))
+    goto nomem;
+
+  d->next = fakedisks;
+  fakedisks = d;
+
+  return 0;
+
+nomem:
+  grub_free (d);
+  return grub_error (GRUB_ERR_OUT_OF_MEMORY, "Not enough memory.");
+}
+
+void
+grub_fakedisk_unregister (const char * name)
+{
+  grub_fakedisk_entry_t d = fakedisks, *p = &fakedisks;
+
+  while (d && (grub_strcmp (name, d->name) != 0))
+    d = *(p = &(d->next));
+  if (d)
+    {
+      *p = d->next;
+      grub_free (d->name);
+      grub_free (d);
+    }
+}
+
+void
+grub_util_fakedisk_init (void)
+{
+  grub_disk_dev_register (&grub_util_fakedisk_dev);
+}
+
+void
+grub_util_fakedisk_fini (void)
+{
+  grub_disk_dev_unregister (&grub_util_fakedisk_dev);
+}
+
diff -rupN -x CVS -x '*.mk' grub2_savannah/include/grub/disk.h 
grub2_wodiff/include/grub/disk.h
--- grub2_savannah/include/grub/disk.h  2004-08-24 23:38:50.000000000 +0200
+++ grub2_wodiff/include/grub/disk.h    2004-08-24 23:51:29.000000000 +0200
@@ -30,6 +30,7 @@
 enum grub_disk_dev_id
   {
     GRUB_DISK_DEVICE_BIOSDISK_ID,
+    GRUB_DISK_DEVICE_FAKEDISK_ID,
     GRUB_DISK_DEVICE_OFDISK_ID,
   };
 
diff -rupN -x CVS -x '*.mk' grub2_savannah/include/grub/fakedisk.h 
grub2_wodiff/include/grub/fakedisk.h
--- grub2_savannah/include/grub/fakedisk.h      1970-01-01 01:00:00.000000000 
+0100
+++ grub2_wodiff/include/grub/fakedisk.h        2004-09-22 09:57:58.000000000 
+0200
@@ -0,0 +1,35 @@
+/* fakedisk.h - fake disk device */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_FAKEDISK_HEADER
+#define GRUB_FAKEDISK_HEADER   1
+
+/* Initialization and destruction.  */
+void grub_util_fakedisk_init (void);
+void grub_util_fakedisk_fini (void);
+/* Add one fakedisk device.  */
+grub_err_t grub_fakedisk_register (const char * name);
+/* Remove one fakedisk device.  */
+void grub_fakedisk_unregister (const char * name);
+
+#include <grub/disk.h>
+#define GRUB_IS_FAKEDISK(disk) ((disk)->dev->id == 
GRUB_DISK_DEVICE_FAKEDISK_ID)
+
+#endif /* ! GRUB_FAKEDISK_HEADER */
diff -rupN -x CVS -x '*.mk' grub2_savannah/include/grub/fs.h 
grub2_wodiff/include/grub/fs.h
--- grub2_savannah/include/grub/fs.h    2004-09-20 09:23:31.000000000 +0200
+++ grub2_wodiff/include/grub/fs.h      2004-09-21 19:40:25.000000000 +0200
@@ -74,6 +74,8 @@ void grub_ufs_init (void);
 void grub_ufs_fini (void);
 void grub_minix_init (void);
 void grub_minix_fini (void);
+void grub_hostfs_init (void);
+void grub_hostfs_fini (void);
 void grub_hfs_init (void);
 void grub_hfs_fini (void);
 void grub_jfs_init (void);
diff -rupN -x CVS -x '*.mk' grub2_savannah/kern/dl.c grub2_wodiff/kern/dl.c
--- grub2_savannah/kern/dl.c    2004-08-12 23:39:00.000000000 +0200
+++ grub2_wodiff/kern/dl.c      2004-08-12 23:48:50.000000000 +0200
@@ -548,7 +548,8 @@ grub_dl_load_file (const char *filename)
     goto failed;
 
   mod = grub_dl_load_core (core, size);
-  mod->ref_count = 0;
+  if (mod)
+    mod->ref_count = 0;
 
  failed:
   grub_file_close (file);
diff -rupN -x CVS -x '*.mk' grub2_savannah/util/grub-emu.c 
grub2_wodiff/util/grub-emu.c
--- grub2_savannah/util/grub-emu.c      2004-09-20 09:23:33.000000000 +0200
+++ grub2_wodiff/util/grub-emu.c        2004-09-25 18:07:36.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2003  Free Software Foundation, Inc.
+ *  Copyright (C) 2003,2004  Free Software Foundation, Inc.
  *
  *  GRUB is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,6 +35,8 @@
 #include <grub/util/getroot.h>
 #include <grub/env.h>
 
+#include <grub/fakedisk.h>
+
 #ifdef __NetBSD__
 /* NetBSD uses /boot for its boot block.  */
 # define DEFAULT_DIRECTORY     "/grub"
@@ -154,7 +156,9 @@ main (int argc, char *argv[])
   
   /* XXX: This is a bit unportable.  */
   grub_util_biosdisk_init (args.dev_map);
+  grub_util_fakedisk_init ();
 
+  grub_hostfs_init ();
   /* Initialize the default modules.  */
   grub_fat_init ();
   grub_ext2_init ();
@@ -186,6 +190,8 @@ main (int argc, char *argv[])
   grub_cmp_fini ();
   grub_cat_fini ();
   grub_terminal_fini ();
+  grub_hostfs_fini ();
+  grub_util_fakedisk_fini ();
 
   return 0;
 }
diff -rupN -x CVS -x '*.mk' grub2_savannah/util/hostfs.c 
grub2_wodiff/util/hostfs.c
--- grub2_savannah/util/hostfs.c        1970-01-01 01:00:00.000000000 +0100
+++ grub2_wodiff/util/hostfs.c  2004-09-25 17:49:02.000000000 +0200
@@ -0,0 +1,235 @@
+/* hostfs.c - host filesystem for grub-emu */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/err.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/types.h>
+#include <grub/fakedisk.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#ifndef GRUB_UTIL
+# error Cannot live without underlying OS.
+#endif
+
+
+#define GRUB_HOST_DEVICE_STRING "host"
+/* Warning: grub consider the fs in utf-8 => use only ascii (0-127)
+   chars, if locale charset is other than utf-8.
+   Locale conversion might be added if need, but grub is not supposed to
+   deal with files with localized names. No grub's native file should be
+   named so.  */
+
+static grub_err_t
+host_mount (grub_device_t device)
+{
+  if (! (GRUB_IS_FAKEDISK (device->disk))
+       && grub_strcmp (device->disk->name, GRUB_HOST_DEVICE_STRING) == 0)
+    return grub_error (GRUB_ERR_BAD_FS, "not a host filesystem");
+  return 0;
+}
+
+/* Maybe not a exact mapping, but at least sufficient.  */
+static grub_err_t
+errno2err (void)
+{
+  grub_err_t r;
+  switch (errno)
+    {
+    case EMFILE:
+    case ENFILE:
+    case ENOMEM:
+      r = GRUB_ERR_OUT_OF_MEMORY;
+      break;
+    case ENOTDIR:
+    case ENOENT:
+      r = GRUB_ERR_FILE_NOT_FOUND;
+      break;
+    case ELOOP:
+      r = GRUB_ERR_SYMLINK_LOOP;
+      break;
+    case EIO:
+      r = GRUB_ERR_FILE_READ_ERROR;
+      break;
+    default:
+      r = GRUB_ERR_BAD_ARGUMENT;
+      break;
+    }
+  return grub_error (r, strerror (errno));
+}
+
+/* Open a file named NAME and initialize FILE.
+   File->data will contain retyped filedescriptor.  */
+static grub_err_t
+grub_host_open (struct grub_file *file, const char *name)
+{
+  struct stat statbuf;
+
+  if (host_mount (file->device))
+    return grub_errno;
+
+  file->data = (void *) open (name, O_RDONLY);
+  if (file->data == (void *) -1)
+    return errno2err ();
+  if (fstat ((int) file->data, &statbuf))
+    {
+      close ((int) file->data);
+      file->data = (void *) -1;
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+                        "Cannot get size. Probably not a regular file. (%s)",
+                        strerror (errno));
+    }
+  file->size = statbuf.st_size;
+  file->offset = 0;
+    
+  return 0;
+}
+
+static grub_err_t
+grub_host_close (grub_file_t file)
+{
+  close ((int) file->data);
+  file->data = (void *) -1;
+  return 0;
+}
+
+/* Read LEN bytes data from FILE into BUF.  */
+static grub_ssize_t
+grub_host_read (grub_file_t file, char *buf, grub_ssize_t len)
+{
+  int rv, rlen;
+
+  for ( rlen = 0, rv = -1; (rlen < len) && rv; rlen += rv)
+    {
+      rv = read ((int) file->data, buf, len - rlen);
+      if (rv == -1)
+       return errno2err ();
+    }
+  return rlen;
+}
+
+
+static grub_err_t
+grub_host_dir (grub_device_t device, const char *path,
+              int (*hook) (const char *filename, int dir))
+{
+  DIR *dir;
+  struct dirent *dent;
+  struct stat stent;
+  char *pathbuf;
+  char *p;
+  unsigned pathlen;
+  unsigned maxname = 32;
+
+  if (host_mount (device))
+    return grub_errno;
+
+  pathlen = grub_strlen (path) + 1;
+  pathbuf = grub_malloc (pathlen + maxname);
+  if (pathbuf == 0)
+    goto mem_fail;
+  
+  grub_strcpy (pathbuf, path);
+  pathbuf [pathlen - 1] = '/';
+  pathbuf [pathlen] = 0;
+  
+  dir = opendir (pathbuf);
+  if (dir == 0)
+    goto errno_fail;
+
+  /* According to manpage readdir does not fail, provided that 'dir'
+     is valid.  */
+  while ((dent = readdir (dir)) != 0)
+    {
+      if (grub_strlen (dent->d_name) >= maxname)
+       {
+         maxname = grub_strlen (dent->d_name);
+         p = grub_realloc (pathbuf, pathlen + maxname);
+         if (p == 0)
+           goto mem_fail;
+         pathbuf = p;
+       }
+      grub_strcpy (pathbuf + pathlen, dent->d_name);
+      if (lstat (pathbuf, &stent) == 0)
+       hook (dent->d_name, (stent.st_mode & S_IFMT) == S_IFDIR);
+      /* else
+       lstat failed, this shouldn't occur. We ignore such entry. */
+    }
+
+  grub_free (pathbuf);
+  return 0;
+
+mem_fail:
+  grub_error (GRUB_ERR_OUT_OF_MEMORY, "Not enough memory.");
+  goto fail;
+
+errno_fail:
+  errno2err ();
+
+fail:
+  grub_free (pathbuf);
+  return grub_errno;
+}
+
+static grub_err_t
+grub_host_label (grub_device_t device, char **label)
+{
+  if (host_mount (device))
+    return grub_errno;
+  *label = 0;
+  return 0;
+}
+
+
+static struct grub_fs grub_host_fs =
+  {
+    .name = "host",
+    .dir = grub_host_dir,
+    .open = grub_host_open,
+    .read = grub_host_read,
+    .close = grub_host_close,
+    .label = grub_host_label,
+    .next = 0
+  };
+
+void
+grub_hostfs_init (void)
+{
+  grub_fakedisk_register (GRUB_HOST_DEVICE_STRING);
+  grub_fs_register (&grub_host_fs);
+}
+
+void
+grub_hostfs_fini (void)
+{
+  grub_fakedisk_unregister (GRUB_HOST_DEVICE_STRING);
+  grub_fs_unregister (&grub_host_fs);
+}
+
============ eop ============
-- 
                                 Tomas 'ebi' Ebenlendr
                                 http://get.to/ebik
                                 PF 2004.73433139167





reply via email to

[Prev in Thread] Current Thread [Next in Thread]