static int is_identifier_char (int c) { return (c != -1 && (grub_isalpha(c) || grub_isdigit(c) || c == '_' || c == '-')); }
static int grub_env_special (const char *name) { if (grub_isdigit (name[0]) || grub_strcmp (name, "#") == 0 || grub_strcmp (name, "*") == 0 || grub_strcmp (name, "@") == 0) return 1; return 0; }
/* Determines the state following STATE, determined by C. */ grub_parser_state_t grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result) { struct grub_parser_state_transition *transition; struct grub_parser_state_transition default_transition; default_transition.to_state = state; default_transition.keep_value = 1; /* Look for a good translation. */ for (transition = state_transitions; transition->from_state; transition++) { if (transition->from_state != state) continue; /* An exact match was found, use it. */ if (transition->input == c) break; if (grub_isspace (transition->input) && !grub_isalpha (c) && !grub_isdigit (c) && c != '_') break; /* A less perfect match was found, use this one if no exact match can be found. */ if (transition->input == 0) break; } if (!transition->from_state) transition = &default_transition; if (transition->keep_value) *result = c; else *result = 0; return transition->to_state; }
char * grub_legacy_parse (const char *buf, char **entryname, char **suffix) { const char *ptr; const char *cmdname; unsigned i, cmdnum; char *args[ARRAY_SIZE (legacy_commands[0].argt)]; *suffix = NULL; for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if (!*ptr || *ptr == '#') { char *ret; int len = grub_strlen (buf); ret = grub_malloc (len + 2); grub_memcpy (ret, buf, len); if (len && ret[len - 1] == '\n') ret[len] = 0; else { ret[len] = '\n'; ret[len + 1] = 0; } return ret; } cmdname = ptr; for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 && legacy_commands[cmdnum].name[ptr - cmdname] == 0 && (!(*entryname != NULL && (legacy_commands[cmdnum].flags & FLAG_NO_MENUENTRY))) && (!(*entryname == NULL && (legacy_commands[cmdnum].flags & FLAG_MENUENTRY_ONLY)))) break; if (cmdnum == ARRAY_SIZE (legacy_commands)) return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); for (; grub_isspace (*ptr) || *ptr == '='; ptr++); if (legacy_commands[cmdnum].flags & FLAG_TITLE) { const char *ptr2; ptr2 = ptr + grub_strlen (ptr); while (ptr2 > ptr && grub_isspace (*(ptr2 - 1))) ptr2--; *entryname = grub_strndup (ptr, ptr2 - ptr); return NULL; } if (legacy_commands[cmdnum].flags & FLAG_TERMINAL) { int dumb = 0, lines = 24; #ifdef TODO int no_echo = 0, no_edit = 0; #endif int hercules = 0; int console = 0, serial = 0, graphics = 0; /* Big enough for any possible resulting command. */ char outbuf[512] = ""; char *outptr; while (*ptr) { /* "[--timeout=SECS] [--silent]" " [console] [serial] [hercules]"*/ if (grub_memcmp (ptr, "--dumb", sizeof ("--dumb") - 1) == 0) dumb = 1; #ifdef TODO if (grub_memcmp (ptr, "--no-echo", sizeof ("--no-echo") - 1) == 0) no_echo = 1; if (grub_memcmp (ptr, "--no-edit", sizeof ("--no-edit") - 1) == 0) no_edit = 1; #endif if (grub_memcmp (ptr, "--lines=", sizeof ("--lines=") - 1) == 0) { lines = grub_strtoul (ptr + sizeof ("--lines=") - 1, 0, 0); if (grub_errno) { lines = 24; grub_errno = GRUB_ERR_NONE; } } if (grub_memcmp (ptr, "console", sizeof ("console") - 1) == 0) console = 1; if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0) serial = 1; if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0) hercules = 1; if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0) graphics = 1; while (*ptr && !grub_isspace (*ptr)) ptr++; while (*ptr && grub_isspace (*ptr)) ptr++; } if (!console && !serial && !hercules && !graphics) return grub_strdup ("terminal_input; terminal_output; terminfo\n"); outptr = outbuf; if (graphics) outptr = grub_stpcpy (outptr, "insmod all_video; "); outptr = grub_stpcpy (outptr, "terminal_input "); if (serial) outptr = grub_stpcpy (outptr, "serial "); if (console || hercules || graphics) outptr = grub_stpcpy (outptr, "console "); outptr = grub_stpcpy (outptr, "; terminal_output "); if (serial) outptr = grub_stpcpy (outptr, "serial "); if (console) outptr = grub_stpcpy (outptr, "console "); if (hercules) outptr = grub_stpcpy (outptr, "mda_text "); if (graphics) outptr = grub_stpcpy (outptr, "gfxterm "); outptr = grub_stpcpy (outptr, "; "); *outptr = '\0'; if (serial) { grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr, "terminfo serial -g 80x%d %s; ", lines, dumb ? "dumb" : "vt100"); outptr += grub_strlen (outptr); } grub_strcpy (outptr, "\n"); return grub_strdup (outbuf); } grub_memset (args, 0, sizeof (args)); { int hold_arg = 0; const char *curarg = NULL; for (i = 0; i < legacy_commands[cmdnum].argc; i++) { grub_size_t curarglen; if (hold_arg) { ptr = curarg; hold_arg = 0; } for (; grub_isspace (*ptr); ptr++); curarg = ptr; if (!*curarg) break; for (; *ptr && !grub_isspace (*ptr); ptr++); if (i != legacy_commands[cmdnum].argc - 1 || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) curarglen = ptr - curarg; else { curarglen = grub_strlen (curarg); while (curarglen > 0 && grub_isspace (curarg[curarglen - 1])) curarglen--; } if (*ptr) ptr++; switch (legacy_commands[cmdnum].argt[i]) { case TYPE_FILE_NO_CONSUME: hold_arg = 1; case TYPE_PARTITION: case TYPE_FILE: args[i] = adjust_file (curarg, curarglen); break; case TYPE_REST_VERBATIM: { char *outptr, *outptr0; int overhead = 3; ptr = curarg; while (*ptr) { for (; *ptr && grub_isspace (*ptr); ptr++); for (; *ptr && !grub_isspace (*ptr); ptr++) if (*ptr == '\'') overhead += 3; if (*ptr) ptr++; overhead += 3; } outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); if (!outptr0) return NULL; ptr = curarg; outptr = outptr0; while (*ptr) { for (; *ptr && grub_isspace (*ptr); ptr++); if (outptr != outptr0) *outptr++ = ' '; *outptr++ = '\''; for (; *ptr && !grub_isspace (*ptr); ptr++) { if (*ptr == '\'') { *outptr++ = '\''; *outptr++ = '\\'; *outptr++ = '\''; *outptr++ = '\''; } else *outptr++ = *ptr; } *outptr++ = '\''; if (*ptr) ptr++; } *outptr++ = 0; } break; case TYPE_VERBATIM: args[i] = grub_legacy_escape (curarg, curarglen); break; case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: case TYPE_OPTION: if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) { args[i] = grub_strndup (curarg, curarglen); break; } args[i] = grub_strdup (""); hold_arg = 1; break; case TYPE_INT: { const char *brk; int base = 10; brk = curarg; if (brk[0] == '0' && brk[1] == 'x') { base = 16; brk += 2; } else if (brk[0] == '0') base = 8; for (; *brk && brk < curarg + curarglen; brk++) { if (base == 8 && (*brk == '8' || *brk == '9')) break; if (grub_isdigit (*brk)) continue; if (base != 16) break; if (!(*brk >= 'a' && *brk <= 'f') && !(*brk >= 'A' && *brk <= 'F')) break; } if (brk == curarg) args[i] = grub_strdup ("0"); else args[i] = grub_strndup (curarg, brk - curarg); } break; case TYPE_VBE_MODE: { unsigned mod; struct grub_vesa_mode_table_entry *modedesc; mod = grub_strtoul (curarg, 0, 0); if (grub_errno) { mod = 0; grub_errno = GRUB_ERR_NONE; } if (mod < GRUB_VESA_MODE_TABLE_START || mod > GRUB_VESA_MODE_TABLE_END) { args[i] = grub_strdup ("auto"); break; } modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START]; if (!modedesc->width) { args[i] = grub_strdup ("auto"); break; } args[i] = grub_xasprintf ("%ux%ux%u", modedesc->width, modedesc->height, modedesc->depth); break; } case TYPE_BOOL: if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') args[i] = grub_strdup ("1"); else args[i] = grub_strdup ("0"); break; } } } while (legacy_commands[cmdnum].argc > 0 && args[legacy_commands[cmdnum].argc - 1] == NULL && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE) && args[legacy_commands[cmdnum + 1].argc] == NULL) cmdnum++; for (; i < legacy_commands[cmdnum].argc; i++) switch (legacy_commands[cmdnum].argt[i]) { case TYPE_FILE_NO_CONSUME: case TYPE_PARTITION: case TYPE_FILE: case TYPE_REST_VERBATIM: case TYPE_VERBATIM: case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: case TYPE_OPTION: args[i] = grub_strdup (""); break; case TYPE_BOOL: case TYPE_INT: args[i] = grub_strdup ("0"); break; case TYPE_VBE_MODE: args[i] = grub_strdup ("auto"); break; } if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) { char *corig = args[legacy_commands[cmdnum].argc - 1]; char *slash = grub_strchr (corig, '/'); char *invert; grub_size_t len; len = grub_strlen (corig); if (!slash) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid color specification `%s'"), args[0]); return NULL; } invert = grub_malloc (len + 1); if (!invert) return NULL; grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); invert[len - (slash - args[0]) - 1] = '/'; grub_memcpy (invert + len - (slash - corig), corig, slash - corig); invert[len] = 0; args[legacy_commands[cmdnum].argc] = invert; } if (legacy_commands[cmdnum].suffix) { *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix, args[legacy_commands[cmdnum].suffixarg]); if (*suffix) return NULL; } { char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], args[3]); grub_free (args[0]); grub_free (args[1]); grub_free (args[2]); grub_free (args[3]); return ret; } }
static char * grub_util_get_raid_grub_dev (const char *os_dev) { char *grub_dev = NULL; if (os_dev[7] == '_' && os_dev[8] == 'd') { /* This a partitionable RAID device of the form /dev/md_dNNpMM. */ char *p, *q; p = strdup (os_dev + sizeof ("/dev/md_d") - 1); q = strchr (p, 'p'); if (q) *q = ','; grub_dev = xasprintf ("md%s", p); free (p); } else if (os_dev[7] == '/' && os_dev[8] == 'd') { /* This a partitionable RAID device of the form /dev/md/dNNpMM. */ char *p, *q; p = strdup (os_dev + sizeof ("/dev/md/d") - 1); q = strchr (p, 'p'); if (q) *q = ','; grub_dev = xasprintf ("md%s", p); free (p); } else if (os_dev[7] >= '0' && os_dev[7] <= '9') { char *p , *q; p = strdup (os_dev + sizeof ("/dev/md") - 1); q = strchr (p, 'p'); if (q) *q = ','; grub_dev = xasprintf ("md%s", p); free (p); } else if (os_dev[7] == '/' && os_dev[8] >= '0' && os_dev[8] <= '9') { char *p , *q; p = strdup (os_dev + sizeof ("/dev/md/") - 1); q = strchr (p, 'p'); if (q) *q = ','; grub_dev = xasprintf ("md%s", p); free (p); } else if (os_dev[7] == '/') { /* mdraid 1.x with a free name. */ char *p , *q; p = strdup (os_dev + sizeof ("/dev/md/") - 1); q = strchr (p, 'p'); if (q) *q = ','; grub_dev = xasprintf ("md/%s", p); free (p); } else grub_util_error (_("unknown kind of RAID device `%s'"), os_dev); { char *mdadm_name = get_mdadm_uuid (os_dev); if (mdadm_name) { const char *q; for (q = os_dev + strlen (os_dev) - 1; q >= os_dev && grub_isdigit (*q); q--); if (q >= os_dev && *q == 'p') { free (grub_dev); grub_dev = xasprintf ("mduuid/%s,%s", mdadm_name, q + 1); goto done; } free (grub_dev); grub_dev = xasprintf ("mduuid/%s", mdadm_name); done: free (mdadm_name); } } return grub_dev; }
static grub_err_t grub_arcdisk_open (const char *name, grub_disk_t disk) { char *fullname, *optr; const char *iptr; int state = 0; grub_err_t err; grub_arc_err_t r; struct grub_arc_fileinfo info; struct arcdisk_hash_ent *hash; if (grub_memcmp (name, "arc/", 4) != 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device"); fullname = grub_malloc (2 * grub_strlen (name) + sizeof (RAW_SUFFIX)); if (!fullname) return grub_errno; optr = fullname; for (iptr = name + 4; *iptr; iptr++) if (state == 0) { if (!grub_isdigit (*iptr)) *optr++ = *iptr; else { *optr++ = '('; *optr++ = *iptr; state = 1; } } else { if (grub_isdigit (*iptr)) *optr++ = *iptr; else { *optr++ = ')'; state = 0; } } if (state) *optr++ = ')'; grub_memcpy (optr, RAW_SUFFIX, sizeof (RAW_SUFFIX)); disk->data = fullname; grub_dprintf ("arcdisk", "opening %s\n", fullname); hash = arcdisk_hash_find (fullname); if (!hash) hash = arcdisk_hash_add (fullname); if (!hash) return grub_errno; err = reopen (fullname); if (err) return err; r = GRUB_ARC_FIRMWARE_VECTOR->getfileinformation (last_handle, &info); if (r) { grub_uint64_t res = 0; int i; grub_dprintf ("arcdisk", "couldn't retrieve size: %ld\n", r); for (i = 40; i >= 9; i--) { grub_uint64_t pos = res | (1ULL << i); char buf[512]; long unsigned count = 0; grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T "\n", pos); if (GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0)) continue; if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf, 0x200, &count)) continue; if (count == 0) continue; res |= (1ULL << i); } grub_dprintf ("arcdisk", "determined disk size 0x%" PRIxGRUB_UINT64_T "\n", res); disk->total_sectors = (res + 0x200) >> 9; } else
static void read_device_map (const char *dev_map) { FILE *fp; char buf[1024]; /* XXX */ int lineno = 0; if (dev_map[0] == '\0') { grub_util_info ("no device.map"); return; } fp = grub_util_fopen (dev_map, "r"); if (! fp) { grub_util_info (_("cannot open `%s': %s"), dev_map, strerror (errno)); return; } while (fgets (buf, sizeof (buf), fp)) { char *p = buf; char *e; char *drive_e, *drive_p; int drive; lineno++; /* Skip leading spaces. */ while (*p && grub_isspace (*p)) p++; /* If the first character is `#' or NUL, skip this line. */ if (*p == '\0' || *p == '#') continue; if (*p != '(') { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), '('); grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); } p++; /* Find a free slot. */ drive = find_free_slot (); if (drive < 0) grub_util_error ("%s:%d: %s", dev_map, lineno, _("device count exceeds limit")); e = p; p = strchr (p, ')'); if (! p) { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), ')'); grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); } map[drive].drive = 0; if ((e[0] == 'f' || e[0] == 'h' || e[0] == 'c') && e[1] == 'd') { char *ptr; for (ptr = e + 2; ptr < p; ptr++) if (!grub_isdigit (*ptr)) break; if (ptr == p) { map[drive].drive = xmalloc (p - e + sizeof ('\0')); strncpy (map[drive].drive, e, p - e + sizeof ('\0')); map[drive].drive[p - e] = '\0'; } if (*ptr == ',') { *p = 0; /* TRANSLATORS: Only one entry is ignored. However the suggestion is to correct/delete the whole file. device.map is a file indicating which devices are available at boot time. Fedora populated it with entries like (hd0,1) /dev/sda1 which would mean that every partition is a separate disk for BIOS. Such entries were inactive in GRUB due to its bug which is now gone. Without this additional check these entries would be harmful now. */ grub_util_warn (_("the device.map entry `%s' is invalid. " "Ignoring it. Please correct or " "delete your device.map"), e); continue; } } drive_e = e; drive_p = p; map[drive].device_map = 1; p++; /* Skip leading spaces. */ while (*p && grub_isspace (*p)) p++; if (*p == '\0') grub_util_error ("%s:%d: %s", dev_map, lineno, _("filename expected")); /* NUL-terminate the filename. */ e = p; while (*e && ! grub_isspace (*e)) e++; *e = '\0'; if (!grub_util_check_file_presence (p)) { free (map[drive].drive); map[drive].drive = NULL; grub_util_info ("Cannot stat `%s', skipping", p); continue; } /* On Linux, the devfs uses symbolic links horribly, and that confuses the interface very much, so use realpath to expand symbolic links. */ map[drive].device = canonicalize_file_name (p); if (! map[drive].device) map[drive].device = xstrdup (p); if (!map[drive].drive) { char c; map[drive].drive = xmalloc (sizeof ("hostdisk/") + strlen (p)); memcpy (map[drive].drive, "hostdisk/", sizeof ("hostdisk/") - 1); strcpy (map[drive].drive + sizeof ("hostdisk/") - 1, p); c = *drive_p; *drive_p = 0; /* TRANSLATORS: device.map is a filename. Not to be translated. device.map specifies disk correspondance overrides. Previously one could create any kind of device name with this. Due to some problems we decided to limit it to just a handful possibilities. */ grub_util_warn (_("the drive name `%s' in device.map is incorrect. " "Using %s instead. " "Please use the form [hfc]d[0-9]* " "(E.g. `hd0' or `cd')"), drive_e, map[drive].drive); *drive_p = c; } grub_util_info ("adding `%s' -> `%s' from device.map", map[drive].drive, map[drive].device); grub_hostdisk_flush_initial_buffer (map[drive].device); } fclose (fp); }
static grub_err_t plan_partition_map_iterate (grub_disk_t disk, grub_partition_iterate_hook_t hook, void *hook_data) { struct grub_partition p; int ptr = 0; grub_err_t err; p.partmap = &grub_plan_partition_map; p.msdostype = 0; for (p.number = 0; ; p.number++) { char sig[sizeof ("part ") - 1]; char c; p.offset = (ptr >> GRUB_DISK_SECTOR_BITS) + 1; p.index = ptr & (GRUB_DISK_SECTOR_SIZE - 1); err = grub_disk_read (disk, 1, ptr, sizeof (sig), sig); if (err) return err; if (grub_memcmp (sig, "part ", sizeof ("part ") - 1) != 0) break; ptr += sizeof (sig); do { err = grub_disk_read (disk, 1, ptr, 1, &c); if (err) return err; ptr++; } while (grub_isdigit (c) || grub_isalpha (c)); if (c != ' ') break; p.start = 0; while (1) { err = grub_disk_read (disk, 1, ptr, 1, &c); if (err) return err; ptr++; if (!grub_isdigit (c)) break; p.start = p.start * 10 + (c - '0'); } if (c != ' ') break; p.len = 0; while (1) { err = grub_disk_read (disk, 1, ptr, 1, &c); if (err) return err; ptr++; if (!grub_isdigit (c)) break; p.len = p.len * 10 + (c - '0'); } if (c != '\n') break; p.len -= p.start; if (hook (disk, &p, hook_data)) return grub_errno; } if (p.number == 0) return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a plan partition table"); return GRUB_ERR_NONE; }