grub-devel
[Top][All Lists]
Advanced

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

[RESEND PATCH V3] Backup old boot sectors before installation


From: Zhu Yi
Subject: [RESEND PATCH V3] Backup old boot sectors before installation
Date: Thu, 25 Feb 2010 14:58:29 +0800

Make grub-setup backup the old boot sectors into a file
(bootsectors.bak) before overwriting it. The backup image starts from
the MBR to the end of core.img position (including embed regions).
This makes it possible for a user to later restore it.

A new option -o|--restore (with optional argument) is added for
grub-setup to restore the backup image into the install device.
A simple `dd` won't work when partitioning has been changed after
the backup. The --restore option only restores the MBR and the boot
sectors overwritten by core.img (embed region is excluded).

Signed-off-by: Zhu Yi <address@hidden>
---
Resend the patch after signed the FSF copyright document.

diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c
index c536be0..e8dc2b7 100644
--- a/util/i386/pc/grub-setup.c
+++ b/util/i386/pc/grub-setup.c
@@ -53,6 +53,7 @@ static const grub_gpt_part_type_t 
grub_gpt_partition_type_bios_boot = GRUB_GPT_P
 
 #define DEFAULT_BOOT_FILE      "boot.img"
 #define DEFAULT_CORE_FILE      "core.img"
+#define DEFAULT_BACKUP_FILE    "bootsectors.bak"
 
 /* This is the blocklist used in the diskboot image.  */
 struct boot_blocklist
@@ -85,7 +86,7 @@ grub_refresh (void)
 
 static void
 setup (const char *dir,
-       const char *boot_file, const char *core_file,
+       const char *boot_file, const char *core_file, const char *restore_file,
        const char *root, const char *dest, int must_embed, int force, int 
fs_probe)
 {
   char *boot_path, *core_path, *core_path_dev;
@@ -396,6 +397,59 @@ setup (const char *dir,
   block->len = 0;
   block->segment = 0;
 
+  int grub_disk_backup(grub_disk_t disk, const char *file)
+  {
+    char *path = grub_util_get_path (dir, file);
+    char *buf;
+    grub_size_t size;
+
+    grub_util_info ("opening backup file `%s'", path);
+    fp = fopen (path, "wb");
+    if (! fp) {
+      free (path);
+      return -1;
+    }
+
+    size = GRUB_DISK_SECTOR_SIZE * embed_region.start + core_size;
+    buf = xmalloc (size);
+    if (grub_disk_read (disk, 0, 0, size, buf) != GRUB_ERR_NONE) {
+      free (path);
+      fclose (fp);
+      return -1;
+    }
+
+    grub_util_write_image (buf, size, fp);
+
+    free (buf);
+    free (path);
+    fclose (fp);
+    return 0;
+  }
+
+  void grub_disk_restore(grub_disk_t disk, const char *path)
+  {
+    size_t size = grub_util_get_image_size (path);
+    char *img;
+
+    if (size != GRUB_DISK_SECTOR_SIZE * embed_region.start + core_size)
+      grub_util_error ("Invalid backup image `%s'", path);
+
+    img = grub_util_read_image (path);
+    grub_disk_write (disk, 0, 0, GRUB_DISK_SECTOR_SIZE, img);
+    grub_disk_write (disk, embed_region.start, 0, core_size,
+                    img + GRUB_DISK_SECTOR_SIZE * embed_region.start);
+    free (img);
+  }
+
+  if (restore_file) {
+    grub_disk_restore (dest_dev->disk, restore_file);
+    goto finish;
+  }
+
+  /* Backup old boot sectors */
+  if (grub_disk_backup (dest_dev->disk, DEFAULT_BACKUP_FILE))
+    grub_util_error ("failed to backup previous boot sectors");
+
   /* Write the core image onto the disk.  */
   if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, 
core_img))
     grub_util_error ("%s", grub_errmsg);
@@ -571,6 +625,7 @@ static struct option options[] =
     {"directory", required_argument, 0, 'd'},
     {"device-map", required_argument, 0, 'm'},
     {"root-device", required_argument, 0, 'r'},
+    {"restore", optional_argument, 0, 'o'},
     {"force", no_argument, 0, 'f'},
     {"skip-fs-probe", no_argument, 0, 's'},
     {"help", no_argument, 0, 'h'},
@@ -596,6 +651,7 @@ DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\
   -d, --directory=DIR     use GRUB files in the directory DIR [default=%s]\n\
   -m, --device-map=FILE   use FILE as the device map [default=%s]\n\
   -r, --root-device=DEV   use DEV as the root device [default=guessed]\n\
+  -o, --restore[=FILE]    restore boot sectors from backup image 
[default=%s]\n\
   -f, --force             install even if problems are detected\n\
   -s, --skip-fs-probe     do not probe for filesystems in DEVICE\n\
   -h, --help              display this message and exit\n\
@@ -605,7 +661,8 @@ DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\
 Report bugs to <%s>.\n\
 ",
            DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY,
-           DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
+           DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY "/" DEFAULT_BACKUP_FILE,
+           PACKAGE_BUGREPORT);
 
   exit (status);
 }
@@ -627,6 +684,7 @@ main (int argc, char *argv[])
 {
   char *boot_file = 0;
   char *core_file = 0;
+  char *restore_file = 0;
   char *dir = 0;
   char *dev_map = 0;
   char *root_dev = 0;
@@ -638,7 +696,7 @@ main (int argc, char *argv[])
   /* Check for options.  */
   while (1)
     {
-      int c = getopt_long (argc, argv, "b:c:d:m:r:hVvf", options, 0);
+      int c = getopt_long (argc, argv, "b:c:d:m:r:o::hVvfs", options, 0);
 
       if (c == -1)
        break;
@@ -680,6 +738,17 @@ main (int argc, char *argv[])
            root_dev = xstrdup (optarg);
            break;
 
+         case 'o':
+           if (restore_file)
+             free (restore_file);
+
+           if (optarg)
+             restore_file = xstrdup (optarg);
+           else
+             restore_file = grub_util_get_path (dir ? dir : DEFAULT_DIRECTORY,
+                                                DEFAULT_BACKUP_FILE);
+           break;
+
          case 'f':
            force = 1;
            break;
@@ -788,7 +857,7 @@ main (int argc, char *argv[])
        {
          setup (dir ? : DEFAULT_DIRECTORY,
                 boot_file ? : DEFAULT_BOOT_FILE,
-                core_file ? : DEFAULT_CORE_FILE,
+                core_file ? : DEFAULT_CORE_FILE, restore_file,
                 root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force, 
fs_probe);
        }
     }
@@ -797,7 +866,7 @@ main (int argc, char *argv[])
   /* Do the real work.  */
     setup (dir ? : DEFAULT_DIRECTORY,
           boot_file ? : DEFAULT_BOOT_FILE,
-          core_file ? : DEFAULT_CORE_FILE,
+          core_file ? : DEFAULT_CORE_FILE, restore_file,
           root_dev, dest_dev, must_embed, force, fs_probe);
 
   /* Free resources.  */
@@ -806,6 +875,7 @@ main (int argc, char *argv[])
 
   free (boot_file);
   free (core_file);
+  free (restore_file);
   free (dir);
   free (dev_map);
   free (root_dev);




reply via email to

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