Index: grub/stage2/builtins.c =================================================================== --- grub.orig/stage2/builtins.c 2008-06-02 18:06:08.942580000 +0100 +++ grub/stage2/builtins.c 2008-06-06 18:35:07.548390000 +0100 @@ -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) @@ -3512,7 +3516,109 @@ static int savedefault_func (char *arg, int flags) { -#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) +#if !defined(SUPPORT_DISKLESS) + #if !defined(GRUB_UTIL) + return savedefault_helper(arg, flags); + #else + return 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) + { + 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]; + int i; + + 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; + } + + *default_file = 0; + grub_strncat (default_file, config_file, DEFAULT_FILE_BUFLEN); + for (i = grub_strlen(default_file); i >= 0; i--) + if (default_file[i] == '/') + { + i++; + break; + } + default_file[i] = 0; + grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i); + + if(!(fp = fopen(default_file,"r"))) + { + errnum = ERR_READ; + goto fail; + } + + fgets(line, bytes, fp); + fclose(fp); + + 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", new_prev_default, new_default); + else + sprintf(buf, "%d", new_default); + + if(!(fp = fopen(default_file,"w"))) + { + errnum = ERR_READ; + goto fail; + } + + 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; @@ -3588,22 +3694,26 @@ disk_read_hook = disk_read_savesect_func; len = grub_read (buf, sizeof (buf)); + buf[9]='\0';/* Make sure grub_strstr() below terminates */ 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; + buf[f_len] = '\0'; + def = buf; + safe_parse_maxint (&def, &entryno); + } /* Set up a string to be written. */ grub_memset (buf, '\n', sizeof (buf)); Index: grub/stage2/stage2.c =================================================================== --- grub.orig/stage2/stage2.c 2008-06-02 18:06:08.858579000 +0100 +++ grub/stage2/stage2.c 2008-06-06 18:04:03.585354000 +0100 @@ -49,7 +49,8 @@ return 0; #endif /* GRUB_UTIL */ - preset_menu_offset = 0; + if (preset_menu_offset) + return 0; return preset_menu != 0; } @@ -934,7 +935,11 @@ len = grub_read (buf, sizeof (buf)); if (len > 0) { + char *tmp; buf[sizeof (buf) - 1] = 0; + if((tmp = grub_strstr(p, ":")) != NULL) + p = tmp + 1; + safe_parse_maxint (&p, &saved_entryno); }