[PATCH] savedefault --once

Leandro Dorileo ldorileo at gmail.com
Tue Mar 7 11:01:05 UTC 2006


Hi Otavio

I've reimplemented the whole savedefault --once functionality. Grub is
not writting the saved default entry to second sector of stage 2 but,
now it uses the file /boot/grub/default. This patch closes the bug
254475 but I remember to have seen other related bugs, I'll find them
and report here.



--- stage2/builtins.c-orig	2006-03-04 01:52:35.000000000 +0000
+++ stage2/builtins.c	2006-03-07 06:27:16.000000000 +0000
@@ -86,6 +86,10 @@
    inside other functions.  */
 static int configfile_func (char *arg, int flags);

+static int savedefault_helper(char *arg, int flags);
+
+static int savedefault_shell(char *arg, int flags);
+
 /* Initialize the data for builtins.  */
 void
 init_builtins (void)
@@ -787,7 +791,7 @@
 default_func (char *arg, int flags)
 {
 #ifndef SUPPORT_DISKLESS
-  if (grub_strcmp (arg, "saved") == 0)
+   if (grub_strcmp (arg, "saved") == 0)
     {
       default_entry = saved_entryno;
       return 0;
@@ -3510,9 +3514,92 @@
 
 /* savedefault */
 static int
-savedefault_func (char *arg, int flags)
+savedefault_func(char *arg, int flags)
+{
+#if !defined(SUPPORT_DISKLESS)
+  #if !defined(GRUB_UTIL)
+	savedefault_helper(arg, flags);
+  #else
+	savedefault_shell(arg, flags);
+  #endif
+#else /* !SUPPORT_DISKLESS */
+  errnum = ERR_UNRECOGNIZED;
+  return 1;
+#endif /* !SUPPORT_DISKLESS */
+}
+
+#if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL)
+/* savedefault_shell */
+static int
+savedefault_shell(char *arg, int flags)
 {
-#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
+  int once_only = 0;
+  int new_default;
+  int curr_default = -1;
+  int curr_prev_default = -1;
+  int new_prev_default = -1;
+  FILE *fp;
+  size_t bytes = 10;
+  char line[bytes];
+  char *default_file = (char *) DEFAULT_FILE_BUF;
+  char buf[bytes];
+
+  while (1)
+    {
+      if (grub_memcmp ("--default=", arg, sizeof ("--default=") - 1) == 0)
+        {
+          char *p = arg + sizeof ("--default=") - 1;
+          if (! safe_parse_maxint (&p, &new_default))
+            return 1;
+          arg = skip_to (0, arg);
+        }
+      else if (grub_memcmp ("--once", arg, sizeof ("--once") - 1) == 0)
+        {
+         once_only = 1;
+         arg = skip_to (0, arg);
+	}
+      else
+        break;
+    }
+
+  if(!(fp = fopen(default_file,"w")))
+    {
+      errnum = ERR_READ;
+      goto fail;
+    }
+
+  read(&line, -1);
+
+  sscanf(line, "%d:%d", &curr_prev_default, &curr_default);
+
+  if(curr_default != -1)
+    new_prev_default = curr_default;
+  else
+    {
+      if(curr_prev_default != -1)
+        new_prev_default = curr_prev_default;
+      else
+        new_prev_default = 0;
+    }
+
+  if(once_only)
+    sprintf(buf, "%d:%d\n", new_prev_default, new_default);
+  else
+    sprintf(buf, "%d\n", new_default);
+
+  fprintf(fp, buf);
+
+fail:
+  fclose(fp);
+  return errnum;
+}
+#endif
+
+/* savedefault_helper */
+static int
+savedefault_helper (char *arg, int flags)
+{
+#if !defined(SUPPORT_DISKLESS)
   unsigned long tmp_drive = saved_drive;
   unsigned long tmp_partition = saved_partition;
   char *default_file = (char *) DEFAULT_FILE_BUF;
@@ -3524,6 +3611,7 @@
   int saved_offsets[2];
   int saved_lengths[2];

+
   /* Save sector information about at most two sectors.  */
   auto void disk_read_savesect_func (int sector, int offset, int length);
   void disk_read_savesect_func (int sector, int offset, int length)
@@ -3536,9 +3624,9 @@
 	}
       sector_count++;
     }
-
+
   /* This command is only useful when you boot an entry from the menu
-     interface.  */
+    interface.  */
   if (! (flags & BUILTIN_SCRIPT))
     {
       errnum = ERR_UNRECOGNIZED;
@@ -3585,33 +3673,36 @@
   if (grub_open (default_file))
     {
       int len;
-
       disk_read_hook = disk_read_savesect_func;
       len = grub_read (buf, sizeof (buf));
       disk_read_hook = 0;
       grub_close ();

-      if (len != sizeof (buf))
-	{
-	  /* This is too small. Do not modify the file manually, please!  */
-	  errnum = ERR_READ;
-	  goto fail;
-	}
-
       if (sector_count > 2)
 	{
 	  /* Is this possible?! Too fragmented!  */
 	  errnum = ERR_FSYS_CORRUPT;
 	  goto fail;
 	}
+
+      char *tmp;
+      if((tmp = grub_strstr(buf, ":")) != NULL)
+      {
+       int f_len = grub_strlen(buf) - grub_strlen(tmp);
+       char *def;
+       int a;
+       for(a = 0; a < f_len; a++)
+         grub_memcpy(&def[a], &buf[a], sizeof(char));
+       safe_parse_maxint (&def, &entryno);
+      }

-      /* Set up a string to be written.  */
+     /* Set up a string to be written.  */
       grub_memset (buf, '\n', sizeof (buf));
       grub_sprintf (buf, "%d", entryno);
-
+
       if (saved_lengths[0] < sizeof (buf))
 	{
-	  /* The file is anchored to another file and the first few bytes
+	/* The file is anchored to another file and the first few bytes
 	     are spanned in two sectors. Uggh...  */
 	  if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
 			 sect))
--- stage2/stage2.c-orig	2006-03-07 06:33:40.000000000 +0000
+++ stage2/stage2.c	2006-03-07 06:35:08.000000000 +0000
@@ -901,7 +901,6 @@
       reset ();

       /* Here load the configuration file.  */
-
 #ifdef GRUB_UTIL
       if (use_config_file)
 #endif /* GRUB_UTIL */
@@ -930,8 +929,19 @@
 	      len = grub_read (buf, sizeof (buf));
 	      if (len > 0)
 		{
+		  char *tmp;
+		  char *def;
+		
 		  buf[sizeof (buf) - 1] = 0;
-		  safe_parse_maxint (&p, &saved_entryno);
+		
+		  if((tmp = grub_strstr(p, ":")) != NULL)
+		  {
+		    *tmp++;
+		    grub_memcpy(&def, &tmp, sizeof(p));
+		  }else
+		    grub_memcpy(&def, &p, sizeof(p));
+		
+		  safe_parse_maxint (&def, &saved_entryno);
 		}

 	      grub_close ();







--
Dorileo



More information about the Pkg-grub-devel mailing list