grub_err_t grub_uitree_set_prop (grub_uitree_t node, const char *name, const char *value) { int ofs, len; grub_uiprop_t p, *ptr, next; ofs = grub_strlen (name) + 1; len = ofs + grub_strlen (value) + 1; next = 0; ptr = &node->prop; while (*ptr) { if (! grub_strcmp ((*ptr)->name, name)) { next = (*ptr)->next; break; } ptr = &((*ptr)->next); } p = grub_realloc (*ptr, sizeof (struct grub_uiprop) + len); if (! p) return grub_errno; *ptr = p; p->next = next; grub_strcpy (p->name, name); grub_strcpy (p->name + ofs, value); p->value = &p->name[ofs]; return grub_errno; }
/* Opens 'filename' with compression filters disabled. Optionally disables the PUBKEY filter (that insists upon properly signed files) as well. PUBKEY filter is restored before the function returns. */ static grub_file_t open_envblk_file (char *filename, enum grub_file_type type) { grub_file_t file; char *buf = 0; if (! filename) { const char *prefix; int len; prefix = grub_env_get ("prefix"); if (! prefix) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; } len = grub_strlen (prefix); buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); if (! buf) return 0; filename = buf; grub_strcpy (filename, prefix); filename[len] = '/'; grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG); } file = grub_file_open (filename, type); grub_free (buf); return file; }
static int grub_xnu_scan_dir_for_kexts_hook (const char *filename, const struct grub_dirhook_info *info, void *closure) { struct grub_xnu_scan_dir_for_kexts_closure *c = closure; char *newdirname; if (! info->dir) return 0; if (filename[0] == '.') return 0; if (grub_strlen (filename) < 5 || grub_memcmp (filename + grub_strlen (filename) - 5, ".kext", 5) != 0) return 0; newdirname = grub_malloc (grub_strlen (c->dirname) + grub_strlen (filename) + 2); /* It's a .kext. Try to load it. */ if (newdirname) { grub_strcpy (newdirname, c->dirname); newdirname[grub_strlen (newdirname) + 1] = 0; newdirname[grub_strlen (newdirname)] = '/'; grub_strcpy (newdirname + grub_strlen (newdirname), filename); grub_xnu_load_kext_from_dir (newdirname, c->osbundlerequired, c->maxrecursion); if (grub_errno == GRUB_ERR_BAD_OS) grub_errno = GRUB_ERR_NONE; grub_free (newdirname); } return 0; }
static char * make_dir (const char *prefix, const char *start, const char *end) { char ch; unsigned i; unsigned n; char *result; i = grub_strlen (prefix); n = i + end - start; result = grub_malloc (n + 1); if (! result) return 0; grub_strcpy (result, prefix); while (start < end && (ch = *start++)) if (ch == '\\' && isregexop (*start)) result[i++] = *start++; else result[i++] = ch; result[i] = '\0'; return result; }
static int grub_xnu_load_kext_from_dir_hook (const char *filename, const struct grub_dirhook_info *info, void *closure) { struct grub_xnu_load_kext_from_dir_closure *c = closure; if (grub_strlen (filename) > 15) return 0; grub_strcpy (c->newdirname + grub_strlen (c->dirname) + 1, filename); /* If the kext contains directory "Contents" all real stuff is in this directory. */ if (info->dir && grub_strcasecmp (filename, "Contents") == 0) grub_xnu_load_kext_from_dir (c->newdirname, c->osbundlerequired, c->maxrecursion - 1); /* Directory "Plugins" contains nested kexts. */ if (info->dir && grub_strcasecmp (filename, "Plugins") == 0) grub_xnu_scan_dir_for_kexts (c->newdirname, c->osbundlerequired, c->maxrecursion - 1); /* Directory "MacOS" contains executable, otherwise executable is on the top. */ if (info->dir && grub_strcasecmp (filename, "MacOS") == 0) c->usemacos = 1; /* Info.plist is the file which governs our future actions. */ if (! info->dir && grub_strcasecmp (filename, "Info.plist") == 0 && ! c->plistname) c->plistname = grub_strdup (c->newdirname); return 0; }
static char * make_install_device (void) { /* XXX: This should be enough. */ char dev[100], *ptr = dev; if (grub_prefix[0] != '(') { /* No hardcoded root partition - make it from the boot drive and the partition number encoded at the install time. */ if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) { grub_strcpy (dev, "(pxe"); ptr += sizeof ("(pxe") - 1; } else { grub_snprintf (dev, sizeof (dev), "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', grub_boot_drive & 0x7f); ptr += grub_strlen (ptr); if (grub_install_dos_part >= 0) grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u", grub_install_dos_part + 1); ptr += grub_strlen (ptr); if (grub_install_bsd_part >= 0) grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u", grub_install_bsd_part + 1); ptr += grub_strlen (ptr); } grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix); grub_strcpy (grub_prefix, dev); } else if (grub_prefix[1] == ',' || grub_prefix[1] == ')') { /* We have a prefix, but still need to fill in the boot drive. */ grub_snprintf (dev, sizeof (dev), "(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f', grub_boot_drive & 0x7f, grub_prefix + 1); grub_strcpy (grub_prefix, dev); } return grub_prefix; }
static int grub_ofdisk_iterate (int (*hook) (const char *name), grub_disk_pull_t pull) { unsigned i; if (pull != GRUB_DISK_PULL_NONE) return 0; scan (); for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++) { static struct ofdisk_hash_ent *ent; for (ent = ofdisk_hash[i]; ent; ent = ent->next) { if (!ent->shortest) continue; if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) { grub_ieee1275_phandle_t dev; char tmp[8]; if (grub_ieee1275_finddevice (ent->devpath, &dev)) { grub_dprintf ("disk", "finddevice (%s) failed\n", ent->devpath); continue; } if (grub_ieee1275_get_property (dev, "iconname", tmp, sizeof tmp, 0)) { grub_dprintf ("disk", "get iconname failed\n"); continue; } if (grub_strcmp (tmp, "sdmmc") != 0) { grub_dprintf ("disk", "device is not an SD card\n"); continue; } } if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) continue; { char buffer[sizeof ("ieee1275/") + grub_strlen (ent->shortest)]; char *ptr; ptr = grub_stpcpy (buffer, "ieee1275/"); grub_strcpy (ptr, ent->shortest); if (hook (buffer)) return 1; } } } return 0; }
/* Add CMDLINE to the history buffer. */ static void add_history (const char *cmdline, int no) { grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1), (char *) HISTORY_BUF + MAX_CMDLINE * no, MAX_CMDLINE * (num_history - no)); grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline); if (num_history < HISTORY_SIZE) num_history++; }
grub_uitree_t grub_uitree_create_node (const char *name) { grub_uitree_t n; n = grub_zalloc (sizeof (struct grub_uitree) + grub_strlen (name) + 1); if (! n) return 0; grub_strcpy (n->name, name); return n; }
static void insert_item (grub_autolist_t *list, char *name, char *file) { grub_autolist_t p; p = grub_malloc (sizeof (*p)); if (! p) return; p->name = grub_malloc (grub_strlen (name) + grub_strlen (file) + 2); if (! p->name) { grub_free (p); return; } grub_strcpy (p->name, name); p->value = p->name + grub_strlen (name) + 1; grub_strcpy (p->value, file); grub_list_push (GRUB_AS_LIST_P (list), GRUB_AS_LIST (p)); }
/* Opens 'filename' with compression filters disabled. Optionally disables the PUBKEY filter (that insists upon properly signed files) as well. PUBKEY filter is restored before the function returns. */ static grub_file_t open_envblk_file (char *filename, int untrusted) { grub_file_t file; char *buf = 0; if (! filename) { const char *prefix; int len; prefix = grub_env_get ("prefix"); if (! prefix) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; } len = grub_strlen (prefix); buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); if (! buf) return 0; filename = buf; grub_strcpy (filename, prefix); filename[len] = '/'; grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG); } /* The filters that are disabled will be re-enabled by the call to grub_file_open() after this particular file is opened. */ grub_file_filter_disable_compression (); if (untrusted) grub_file_filter_disable_pubkey (); file = grub_file_open (filename); grub_free (buf); return file; }
int set_variable(const char *name, const char *value) { unsigned int i; unsigned int avail = nexpvars; if (strlen(name) >= sizeof (expvars[0].v_name)) return (ERR_WONT_FIT); if (value != NULL && strlen(value) >= sizeof (expvars[0].v_value)) return (ERR_WONT_FIT); for (i = 0; i < nexpvars; i++) { if (expvars[i].v_flags & EVF_DEFINED) { if (grub_strcmp(expvars[i].v_name, name) == 0) break; } else if (i < avail) { avail = i; } } if (i == nexpvars) { if (avail == nexpvars) return (ERR_WONT_FIT); i = avail; (void) grub_strcpy(expvars[i].v_name, name); expvars[i].v_flags = EVF_DEFINED; } if (value != NULL) { (void) grub_strcpy(expvars[i].v_value, value); expvars[i].v_flags |= EVF_VALUESET; } else { expvars[i].v_flags &= ~EVF_VALUESET; } return (0); }
static grub_err_t grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { grub_ssize_t status, actual; unsigned long long pos; if (disk->data != last_devpath) { if (last_ihandle) grub_ieee1275_close (last_ihandle); last_ihandle = 0; last_devpath = NULL; if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) { char name2[grub_strlen (disk->data) + 3]; char *p; grub_strcpy (name2, disk->data); p = name2 + grub_strlen (name2); *p++ = ':'; *p++ = '0'; *p = 0; grub_ieee1275_open (name2, &last_ihandle); } else grub_ieee1275_open (disk->data, &last_ihandle); if (! last_ihandle) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); last_devpath = disk->data; } pos = sector * 512UL; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", (long long) sector); grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual); if (actual != (grub_ssize_t) (size * 512UL)) return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu", (long long) sector); return 0; }
static int add_subnode (void *fdt, int parentoffset, const char *name) { grub_uint32_t *token = (void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) + parentoffset); grub_uint32_t *end = (void *) struct_end (fdt); unsigned int entry_size = node_entry_size (name); unsigned int struct_size = grub_fdt_get_size_dt_struct(fdt); char *node_name; SKIP_NODE_NAME(node_name, token, end); /* Insert the new subnode just after the properties of the parent node (if any).*/ while (1) { if (token >= end) return -1; switch (grub_be_to_cpu32(*token)) { case FDT_PROP: /* Skip len, nameoff and property value. */ token += prop_entry_size(grub_be_to_cpu32(*(token + 1))) / sizeof(*token); break; case FDT_BEGIN_NODE: case FDT_END_NODE: goto insert; case FDT_NOP: token++; break; default: /* invalid token */ return -1; } } insert: grub_memmove (token + entry_size / sizeof(*token), token, (grub_addr_t) end - (grub_addr_t) token); *token = grub_cpu_to_be32_compile_time(FDT_BEGIN_NODE); token[entry_size / sizeof(*token) - 2] = 0; /* padding bytes */ grub_strcpy((char *) (token + 1), name); token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32_compile_time(FDT_END_NODE); grub_fdt_set_size_dt_struct (fdt, struct_size + entry_size); return ((grub_addr_t) token - (grub_addr_t) fdt - grub_fdt_get_off_dt_struct(fdt)); }
static grub_err_t grub_mb2_tag_name_create (void) { struct multiboot_tag_name *name; grub_addr_t name_addr; grub_err_t err; const char *grub_version = PACKAGE_STRING; err = grub_mb2_tag_alloc (&name_addr, MULTIBOOT2_TAG_NAME, sizeof (struct multiboot_tag_name) + sizeof (grub_version) + 1); if (err) return err; name = (struct multiboot_tag_name *) name_addr; grub_strcpy (name->name, grub_version); return GRUB_ERR_NONE; }
void grub_machine_set_prefix (void) { if (grub_prefix[0] != '(') { char bootpath[IEEE1275_MAX_PATH_LEN]; char *prefix, *path, *colon; grub_ssize_t actual; if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, sizeof (bootpath), &actual)) { /* Should never happen. */ grub_printf ("/chosen/bootpath property missing!\n"); grub_env_set ("prefix", ""); return; } /* Transform an OF device path to a GRUB path. */ colon = grub_strchr (bootpath, ':'); if (colon) { char *part = colon + 1; /* Consistently provide numbered partitions to GRUB. OpenBOOT traditionally uses alphabetical partition specifiers. */ if (part[0] >= 'a' && part[0] <= 'z') part[0] = '1' + (part[0] - 'a'); } prefix = grub_ieee1275_encode_devname (bootpath); path = grub_xasprintf("%s%s", prefix, grub_prefix); grub_strcpy (grub_prefix, path); grub_free (path); grub_free (prefix); } grub_env_set ("prefix", grub_prefix); }
static grub_err_t grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) { grub_ssize_t status; unsigned long long pos; if (disk->data != last_devpath) { if (last_ihandle) grub_ieee1275_close (last_ihandle); last_ihandle = 0; last_devpath = NULL; if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) { char name2[grub_strlen (disk->data) + 3]; char *p; grub_strcpy (name2, disk->data); p = name2 + grub_strlen (name2); *p++ = ':'; *p++ = '0'; *p = 0; grub_ieee1275_open (name2, &last_ihandle); } else grub_ieee1275_open (disk->data, &last_ihandle); if (! last_ihandle) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); last_devpath = disk->data; } pos = sector << GRUB_DISK_SECTOR_BITS; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", (long long) sector); return 0; }
/* Try to load an icon for the specified CLASS_NAME in the directory DIR. Returns 0 if the icon could not be loaded, or returns a pointer to a new bitmap if it was successful. */ static struct grub_video_bitmap * try_loading_icon (grub_gfxmenu_icon_manager_t mgr, const char *dir, const char *class_name) { char *path; int l; path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name) + grub_strlen (icon_extension) + 3); if (! path) return 0; grub_strcpy (path, dir); l = grub_strlen (path); if (path[l-1] != '/') { path[l] = '/'; path[l+1] = 0; } grub_strcat (path, class_name); grub_strcat (path, icon_extension); struct grub_video_bitmap *raw_bitmap; grub_video_bitmap_load (&raw_bitmap, path); grub_free (path); grub_errno = GRUB_ERR_NONE; /* Critical to clear the error!! */ if (! raw_bitmap) return 0; struct grub_video_bitmap *scaled_bitmap; grub_video_bitmap_create_scaled (&scaled_bitmap, mgr->icon_width, mgr->icon_height, raw_bitmap, GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); grub_video_bitmap_destroy (raw_bitmap); if (! scaled_bitmap) return 0; return scaled_bitmap; }
/* Create the tag containing the cmdline and the address of the module data. */ static grub_err_t grub_mb2_tag_module_create (grub_addr_t modaddr, grub_size_t modsize, char *type, int key, int argc, char *argv[]) { struct multiboot_tag_module *module; grub_ssize_t argslen = 0; grub_err_t err; char *p; grub_addr_t module_addr; int i; /* Allocate enough space for the arguments and spaces between them. */ for (i = 0; i < argc; i++) argslen += grub_strlen (argv[i]) + 1; /* Note: includes implicit 1-byte cmdline. */ err = grub_mb2_tag_alloc (&module_addr, key, sizeof (struct multiboot_tag_module) + argslen); if (err) return grub_errno; module = (struct multiboot_tag_module *) module_addr; module->addr = modaddr; module->size = modsize; grub_strcpy(module->type, type); /* Fill in the command line. */ p = module->cmdline; for (i = 0; i < argc; i++) { p = grub_stpcpy (p, argv[i]); *p++ = ' '; } module->cmdline[argslen] = '\0'; return GRUB_ERR_NONE; }
int process_cfg(char *cfg) { // buffer for config file reading static char s[BUFSIZE]; static int s_pos = 0; // second buffer static char str[BUFSIZE]; static int str_pos = 0; char *p, *line, *q; char f, g; unsigned int size, sz; unsigned int rd; int bytes_read = 0; int i; if (u_open(cfg, &size)) { printf("Cannot open config file!\r\n"); return 0; } u_close(); //grub_memset(s, 0, sizeof(s)); sz = size; while (sz) { // read new buffer if (u_open(cfg, &size)) { printf("Cannot open config file!\r\n"); return 0; } u_seek(bytes_read); rd = u_read(buf, sizeof(buf)); if (!rd) { printf("process_cfg(): read returned zero bytes\r\n"); return 0; } sz -= rd; bytes_read += rd; u_close(); if (sz && !rd) { printf("Can't read from config file!\r\n"); return 0; } f = 1; p = buf; while (*p && f) { // read new line from current buffer line = getline(&p, rd); i = grub_strlen(line); if (s_pos + i > BUFSIZE) panic("string s too long to fit in buffer!\r\n", cfg); grub_strcpy(s + s_pos, line); s_pos += i; f = (p - buf < rd); g = f || (!f && (buf[rd - 1] == '\n')); if (g) { // delete CR and LF symbols at the end line = strip(trim(s)); // skip comments ";" i = grub_index(';', line); if (i) line[i - 1] = '\0'; // skip comments "#" i = grub_index('#', line); if (i) line[i - 1] = '\0'; // delete leading and trailing spaces line = strip(line); // line continuation symbol ('^' or '&') support i = grub_strlen(line); if (line[i - 1] == '^' || line[i - 1] == '&') { // the current line continued line[i - 1] = '\0'; if (str_pos + i - 1 > BUFSIZE) panic("string str too long to fit in buffer!\r\n", cfg); grub_strcpy(str + str_pos, line); str_pos += i - 1; s[0] = '\0'; s_pos = 0; continue; } else { // the line ends if (str_pos + i > BUFSIZE) panic("string str too long to fit in buffer!\r\n", cfg); grub_strcpy(str + str_pos, line); str_pos = 0; s[0] = '\0'; s_pos = 0; } // expand variables //expand_vars(s, str); // process the line if (!process_cfg_line(str)) return -1; } } } return 1; }
static char * grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) { char type[64]; /* XXX check size. */ char *device = grub_ieee1275_get_devname (path); char *args = grub_ieee1275_get_devargs (path); char *ret = 0; grub_ieee1275_phandle_t dev; if (!args) /* Shouldn't happen. */ return 0; /* We need to know what type of device it is in order to parse the full file path properly. */ if (grub_ieee1275_finddevice (device, &dev)) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s not found\n", device); goto fail; } if (grub_ieee1275_get_property (dev, "device_type", &type, sizeof type, 0)) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Device %s lacks a device_type property\n", device); goto fail; } if (!grub_strcmp ("block", type)) { /* The syntax of the device arguments is defined in the CHRP and PReP IEEE1275 bindings: "[partition][,[filename]]". */ char *comma = grub_strchr (args, ','); if (ptype == GRUB_PARSE_FILENAME) { if (comma) { char *filepath = comma + 1; ret = grub_malloc (grub_strlen (filepath) + 1); /* Make sure filepath has leading backslash. */ if (filepath[0] != '\\') grub_sprintf (ret, "\\%s", filepath); else grub_strcpy (ret, filepath); } } else if (ptype == GRUB_PARSE_PARTITION) { if (!comma) ret = grub_strdup (args); else ret = grub_strndup (args, (grub_size_t)(comma - args)); } } else { /* XXX Handle net devices by configuring & registering a grub_net_dev here, then return its name? Example path: "net:<server ip>,<file name>,<client ip>,<gateway ip>,<bootp retries>,<tftp retries>". */ grub_printf ("Unsupported type %s for device %s\n", type, device); } fail: grub_free (device); grub_free (args); return ret; }
/* Load extension DIRNAME. (extensions are directories in xnu) */ grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, int maxrecursion) { grub_device_t dev; char *newdirname; char *newpath; char *device_name; grub_fs_t fs; const char *path; char *binsuffix; grub_file_t binfile; newdirname = grub_malloc (grub_strlen (dirname) + 20); if (! newdirname) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate buffer"); grub_strcpy (newdirname, dirname); newdirname[grub_strlen (dirname)] = '/'; newdirname[grub_strlen (dirname) + 1] = 0; device_name = grub_file_get_device_name (dirname); dev = grub_device_open (device_name); if (dev) { struct grub_xnu_load_kext_from_dir_closure c; fs = grub_fs_probe (dev); path = grub_strchr (dirname, ')'); if (! path) path = dirname; else path++; newpath = grub_strchr (newdirname, ')'); if (! newpath) newpath = newdirname; else newpath++; c.dirname = dirname; c.osbundlerequired = osbundlerequired; c.maxrecursion = maxrecursion; c.usemacos = 0; c.plistname = 0; c.newdirname = newdirname; /* Look at the directory. */ if (fs) (fs->dir) (dev, path, grub_xnu_load_kext_from_dir_hook, &c); if (c.plistname && grub_xnu_check_os_bundle_required (c.plistname, osbundlerequired, &binsuffix)) { if (binsuffix) { /* Open the binary. */ char *binname = grub_malloc (grub_strlen (dirname) + grub_strlen (binsuffix) + sizeof ("/MacOS/")); grub_strcpy (binname, dirname); if (c.usemacos) grub_strcpy (binname + grub_strlen (binname), "/MacOS/"); else grub_strcpy (binname + grub_strlen (binname), "/"); grub_strcpy (binname + grub_strlen (binname), binsuffix); grub_dprintf ("xnu", "%s:%s\n", c.plistname, binname); binfile = grub_gzfile_open (binname, 1); if (! binfile) grub_errno = GRUB_ERR_NONE; /* Load the extension. */ grub_xnu_load_driver (c.plistname, binfile); grub_free (binname); grub_free (binsuffix); } else { grub_dprintf ("xnu", "%s:0\n", c.plistname); grub_xnu_load_driver (c.plistname, 0); } } grub_free (c.plistname); grub_device_close (dev); } grub_free (device_name); return GRUB_ERR_NONE; }
static grub_err_t tftp_open (struct grub_file *file, const char *filename) { struct tftphdr *tftph; char *rrq; int i; int rrqlen; int hdrlen; grub_uint8_t open_data[1500]; struct grub_net_buff nb; tftp_data_t data; grub_err_t err; grub_uint8_t *nbd; grub_net_network_level_address_t addr; data = grub_zalloc (sizeof (*data)); if (!data) return grub_errno; nb.head = open_data; nb.end = open_data + sizeof (open_data); grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 1500); err = grub_netbuff_push (&nb, sizeof (*tftph)); if (err) return err; tftph = (struct tftphdr *) nb.data; rrq = (char *) tftph->u.rrq; rrqlen = 0; tftph->opcode = grub_cpu_to_be16_compile_time (TFTP_RRQ); grub_strcpy (rrq, filename); rrqlen += grub_strlen (filename) + 1; rrq += grub_strlen (filename) + 1; grub_strcpy (rrq, "octet"); rrqlen += grub_strlen ("octet") + 1; rrq += grub_strlen ("octet") + 1; grub_strcpy (rrq, "blksize"); rrqlen += grub_strlen ("blksize") + 1; rrq += grub_strlen ("blksize") + 1; grub_strcpy (rrq, "1024"); rrqlen += grub_strlen ("1024") + 1; rrq += grub_strlen ("1024") + 1; grub_strcpy (rrq, "tsize"); rrqlen += grub_strlen ("tsize") + 1; rrq += grub_strlen ("tsize") + 1; grub_strcpy (rrq, "0"); rrqlen += grub_strlen ("0") + 1; rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); if (err) return err; file->not_easily_seekable = 1; file->data = data; data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp); if (!data->pq) return grub_errno; err = grub_net_resolve_address (file->device->net->server, &addr); if (err) { destroy_pq (data); return err; } data->sock = grub_net_udp_open (addr, TFTP_SERVER_PORT, tftp_receive, file); if (!data->sock) { destroy_pq (data); return grub_errno; } /* Receive OACK packet. */ nbd = nb.data; for (i = 0; i < GRUB_NET_TRIES; i++) { nb.data = nbd; err = grub_net_send_udp_packet (data->sock, &nb); if (err) { grub_net_udp_close (data->sock); destroy_pq (data); return err; } grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION), &data->have_oack); if (data->have_oack) break; } if (!data->have_oack) grub_error (GRUB_ERR_TIMEOUT, N_("time out opening `%s'"), filename); else grub_error_load (&data->save_err); if (grub_errno) { grub_net_udp_close (data->sock); destroy_pq (data); return grub_errno; } file->size = data->file_size; return GRUB_ERR_NONE; }
static grub_err_t interactive (void) { const char *ps1 = "lua> "; const char *ps2 = "lua>> "; const char *prompt = ps1; char *line; char *chunk = NULL; size_t len; size_t oldlen = 0; int r; grub_printf ("%s", N_ ("Welcome to lua, press the escape key to exit.")); while ((line = grub_cmdline_get (prompt)) != NULL) { /* len = lenght of chunk + line + newline character */ len = oldlen + grub_strlen (line) + 1; chunk = grub_realloc (chunk, len + 1); grub_strcpy (chunk + oldlen , line); chunk[len - 1] = '\n'; chunk[len] = '\0'; grub_free (line); r = luaL_loadbuffer (state, chunk, len, "stdin"); if (!r) { /* No error: Execute this chunk and prepare to read another */ r = lua_pcall (state, 0, 0, 0); if (r) { handle_lua_error ("Lua"); grub_print_error (); } grub_free (chunk); chunk = NULL; len = 0; prompt = ps1; } else if (incomplete (state, r)) { /* Chunk is incomplete, try reading another line */ prompt = ps2; } else if (r == LUA_ERRSYNTAX) { handle_lua_error ("Lua"); grub_print_error (); /* This chunk is garbage, try starting another one */ grub_free (chunk); chunk = NULL; len = 0; prompt = ps1; } else { /* Handle errors other than syntax errors (out of memory, etc.) */ grub_free (chunk); handle_lua_error ("Lua parser failed"); return grub_errno; } oldlen = len; } grub_free (chunk); lua_gc (state, LUA_GCCOLLECT, 0); return grub_errno; }
static grub_uitree_t grub_uitree_load_buf (const char *prefix, int prefix_len, grub_uitree_t root, char *buf, int size, int flags) { int type, count, sub; char pre; grub_uitree_t node; if (((grub_uint8_t) buf[0] == 0xef) && ((grub_uint8_t) buf[1] == 0xbb) && ((grub_uint8_t) buf[2] == 0xbf)) { buf += 3; size -= 3; } node = root; pre = 0; while ((type = read_token (buf, &pre, size, &count, &sub)) != TOKEN_TYPE_ERROR) { if (type == TOKEN_TYPE_STRING) { char *str, *str2; str = buf; buf += count; size -= count; type = read_token (buf, &pre, size, &count, &sub); str2 = buf; buf += count; size -= count; if (type == TOKEN_TYPE_EQUAL) { char *p; if (read_token (buf, &pre, size, &count, &sub) != TOKEN_TYPE_STRING) break; if (sub) { char *p1, *p2; p = grub_malloc (grub_strlen (buf) + (prefix_len - 2) * sub + 1); if (! p) break; p1 = buf; p2 = p; while (1) { char *t; t = grub_strstr (p1, "$$"); if (t) { grub_memcpy (p2, p1, t - p1); p2 += (t - p1); grub_memcpy (p2, prefix, prefix_len); p2 += prefix_len; p1 = t + 2; } else { grub_strcpy (p2, p1); break; } } } else p = buf; if (grub_uitree_set_prop (node, str, p)) break; if (sub) grub_free (p); buf += count; size -= count; } else if (type == TOKEN_TYPE_LBRACKET) { grub_uitree_t p; int method; if ((flags & GRUB_UITREE_LOAD_FLAG_ROOT) && (node == root)) method = METHOD_REPLACE; else method = METHOD_APPEND; if (*str == '+') { method = METHOD_MERGE; str++; } else if (*str == '-') { method = METHOD_REPLACE; str++; } if (! *str) break; if (flags & GRUB_UITREE_LOAD_FLAG_SINGLE) method = METHOD_APPEND; p = (method == METHOD_APPEND) ? 0 : grub_uitree_find (node, str); if (p) { if (method == METHOD_REPLACE) grub_uitree_reset_node (p); node = p; } else { grub_uitree_t n; n = grub_uitree_create_node (str); if (! n) break; grub_tree_add_child (GRUB_AS_TREE (node), GRUB_AS_TREE (n), -1); node = n; } } else if ((type == TOKEN_TYPE_STRING) && ((! grub_strcmp (str, "include")) || (! grub_strcmp (str, "-include")))) { int ignore_error; grub_uitree_t n; int b; int pos; char *p; ignore_error = (str[0] == '-'); pos = prefix_len; while ((str2[0] == '.') && (str2[1] == '.')) { str2 += 2; if (*str2 == '/') str2++; while ((pos > 0) && (prefix[pos - 1] != '/')) pos--; if (pos > 0) pos--; } p = grub_malloc (pos + grub_strlen (str2) + 2); if (! p) break; grub_memcpy (p, prefix, pos); p[pos++] = '/'; grub_strcpy (p + pos, str2); b = (node == root) ? flags : 0; n = grub_uitree_load_file (node, p, b); grub_free (p); if (ignore_error) grub_errno = 0; else if (grub_errno) break; if ((b & GRUB_UITREE_LOAD_FLAG_SINGLE) && (n != NULL)) return n; } else break; } else if (type == TOKEN_TYPE_RBRACKET) { buf += count; size -= count; if (node == root) break; if ((flags & GRUB_UITREE_LOAD_FLAG_SINGLE) && (node->parent == root)) return node; node = node->parent; } else break; } return 0; }
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; } }
int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, const void *val, grub_uint32_t len) { grub_uint32_t *prop; int prop_name_present = 0; grub_uint32_t nameoff = 0; if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3) || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct (fdt) + nodeoffset)) != FDT_BEGIN_NODE)) return -1; prop = find_prop (fdt, nodeoffset, name); if (prop) { grub_uint32_t prop_len = ALIGN_UP(grub_be_to_cpu32 (*(prop + 1)), sizeof(grub_uint32_t)); grub_uint32_t i; prop_name_present = 1; for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++) *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP); if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t))) { /* Length of new property value is greater than the space allocated for the current value: a new entry needs to be created, so save the nameoff field of the current entry and replace the current entry with NOP tokens. */ nameoff = grub_be_to_cpu32 (*(prop + 2)); *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP); prop = NULL; } } if (!prop || !prop_name_present) { unsigned int needed_space = 0; if (!prop) needed_space = prop_entry_size(len); if (!prop_name_present) needed_space += grub_strlen (name) + 1; if (needed_space > get_free_space (fdt)) return -1; if (rearrange_blocks (fdt, !prop ? prop_entry_size(len) : 0) < 0) return -1; } if (!prop_name_present) { /* Append the property name at the end of the strings block. */ nameoff = grub_fdt_get_size_dt_strings (fdt); grub_strcpy ((char *) fdt + grub_fdt_get_off_dt_strings (fdt) + nameoff, name); grub_fdt_set_size_dt_strings (fdt, grub_fdt_get_size_dt_strings (fdt) + grub_strlen (name) + 1); } if (!prop) { char *node_name = (char *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct (fdt) + nodeoffset + sizeof(grub_uint32_t)); prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4)); grub_memmove (prop + prop_entry_size(len) / sizeof(*prop), prop, struct_end(fdt) - (grub_addr_t) prop); grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt) + prop_entry_size(len)); *prop = grub_cpu_to_be32_compile_time (FDT_PROP); *(prop + 2) = grub_cpu_to_be32 (nameoff); } *(prop + 1) = grub_cpu_to_be32 (len); /* Insert padding bytes at the end of the value; if they are not needed, they will be overwritten by the following memcpy. */ *(prop + prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0; grub_memcpy (prop + 3, val, len); return 0; }
static int grub_iso9660_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_iso9660_dir dirent; grub_off_t offset = 0; grub_off_t len; struct iterate_dir_ctx ctx; len = get_node_size (dir); for (; offset < len; offset += dirent.len) { ctx.symlink = 0; ctx.was_continue = 0; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; /* The end of the block, skip to the next one. */ if (!dirent.len) { offset = (offset / GRUB_ISO9660_BLKSZ + 1) * GRUB_ISO9660_BLKSZ; continue; } { char name[MAX_NAMELEN + 1]; int nameoffset = offset + sizeof (dirent); struct grub_fshelp_node *node; int sua_off = (sizeof (dirent) + dirent.namelen + 1 - (dirent.namelen % 2)); int sua_size = dirent.len - sua_off; sua_off += offset + dir->data->susp_skip; ctx.filename = 0; ctx.filename_alloc = 0; ctx.type = GRUB_FSHELP_UNKNOWN; if (dir->data->rockridge && grub_iso9660_susp_iterate (dir, sua_off, sua_size, susp_iterate_dir, &ctx)) return 0; /* Read the name. */ if (read_node (dir, nameoffset, dirent.namelen, (char *) name)) return 0; node = grub_malloc (sizeof (struct grub_fshelp_node)); if (!node) return 0; node->alloc_dirents = ARRAY_SIZE (node->dirents); node->have_dirents = 1; /* Setup a new node. */ node->data = dir->data; node->have_symlink = 0; /* If the filetype was not stored using rockridge, use whatever is stored in the iso9660 filesystem. */ if (ctx.type == GRUB_FSHELP_UNKNOWN) { if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR) ctx.type = GRUB_FSHELP_DIR; else ctx.type = GRUB_FSHELP_REG; } /* . and .. */ if (!ctx.filename && dirent.namelen == 1 && name[0] == 0) ctx.filename = (char *) "."; if (!ctx.filename && dirent.namelen == 1 && name[0] == 1) ctx.filename = (char *) ".."; /* The filename was not stored in a rock ridge entry. Read it from the iso9660 filesystem. */ if (!dir->data->joliet && !ctx.filename) { char *ptr; name[dirent.namelen] = '\0'; ctx.filename = grub_strrchr (name, ';'); if (ctx.filename) *ctx.filename = '\0'; /* ISO9660 names are not case-preserving. */ ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE; for (ptr = name; *ptr; ptr++) *ptr = grub_tolower (*ptr); if (ptr != name && *(ptr - 1) == '.') *(ptr - 1) = 0; ctx.filename = name; } if (dir->data->joliet && !ctx.filename) { char *semicolon; ctx.filename = grub_iso9660_convert_string ((grub_uint8_t *) name, dirent.namelen >> 1); semicolon = grub_strrchr (ctx.filename, ';'); if (semicolon) *semicolon = '\0'; ctx.filename_alloc = 1; } node->dirents[0] = dirent; while (dirent.flags & FLAG_MORE_EXTENTS) { offset += dirent.len; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) { if (ctx.filename_alloc) grub_free (ctx.filename); grub_free (node); return 0; } if (node->have_dirents >= node->alloc_dirents) { struct grub_fshelp_node *new_node; node->alloc_dirents *= 2; new_node = grub_realloc (node, sizeof (struct grub_fshelp_node) + ((node->alloc_dirents - ARRAY_SIZE (node->dirents)) * sizeof (node->dirents[0]))); if (!new_node) { if (ctx.filename_alloc) grub_free (ctx.filename); grub_free (node); return 0; } node = new_node; } node->dirents[node->have_dirents++] = dirent; } if (ctx.symlink) { if ((node->alloc_dirents - node->have_dirents) * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1) { struct grub_fshelp_node *new_node; new_node = grub_realloc (node, sizeof (struct grub_fshelp_node) + ((node->alloc_dirents - ARRAY_SIZE (node->dirents)) * sizeof (node->dirents[0])) + grub_strlen (ctx.symlink) + 1); if (!new_node) { if (ctx.filename_alloc) grub_free (ctx.filename); grub_free (node); return 0; } node = new_node; } node->have_symlink = 1; grub_strcpy (node->symlink + node->have_dirents * sizeof (node->dirents[0]) - sizeof (node->dirents), ctx.symlink); grub_free (ctx.symlink); ctx.symlink = 0; ctx.was_continue = 0; } if (hook (ctx.filename, ctx.type, node, hook_data)) { if (ctx.filename_alloc) grub_free (ctx.filename); return 1; } if (ctx.filename_alloc) grub_free (ctx.filename); } }
/* Mount the filesystem on the disk DISK. */ static struct grub_hfs_data * grub_hfs_mount (grub_disk_t disk) { struct grub_hfs_data *data; struct grub_hfs_catalog_key key; struct grub_hfs_dirrec dir; int first_block; struct { struct grub_hfs_node node; struct grub_hfs_treeheader head; } treehead; data = grub_malloc (sizeof (struct grub_hfs_data)); if (!data) return 0; /* Read the superblock. */ if (grub_disk_read (disk, GRUB_HFS_SBLOCK, 0, sizeof (struct grub_hfs_sblock), &data->sblock)) goto fail; /* Check if this is a HFS filesystem. */ if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC) { grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem"); goto fail; } /* Check if this is an embedded HFS+ filesystem. */ if (grub_be_to_cpu16 (data->sblock.embed_sig) == GRUB_HFS_EMBED_HFSPLUS_SIG) { grub_error (GRUB_ERR_BAD_FS, "embedded HFS+ filesystem"); goto fail; } data->blksz = grub_be_to_cpu32 (data->sblock.blksz); data->disk = disk; /* Lookup the root node of the extent overflow tree. */ first_block = ((grub_be_to_cpu16 (data->sblock.extent_recs[0].first_block) * GRUB_HFS_BLKS) + grub_be_to_cpu16 (data->sblock.first_block)); if (grub_disk_read (data->disk, first_block, 0, sizeof (treehead), &treehead)) goto fail; data->ext_root = grub_be_to_cpu32 (treehead.head.root_node); data->ext_size = grub_be_to_cpu16 (treehead.head.node_size); /* Lookup the root node of the catalog tree. */ first_block = ((grub_be_to_cpu16 (data->sblock.catalog_recs[0].first_block) * GRUB_HFS_BLKS) + grub_be_to_cpu16 (data->sblock.first_block)); if (grub_disk_read (data->disk, first_block, 0, sizeof (treehead), &treehead)) goto fail; data->cat_root = grub_be_to_cpu32 (treehead.head.root_node); data->cat_size = grub_be_to_cpu16 (treehead.head.node_size); /* Lookup the root directory node in the catalog tree using the volume name. */ key.parent_dir = grub_cpu_to_be32 (1); key.strlen = data->sblock.volname[0]; grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1)); if (grub_hfs_find_node (data, (char *) &key, data->cat_root, 0, (char *) &dir, sizeof (dir)) == 0) { grub_error (GRUB_ERR_BAD_FS, "cannot find the HFS root directory"); goto fail; } if (grub_errno) goto fail; data->rootdir = grub_be_to_cpu32 (dir.dirid); return data; fail: grub_free (data); if (grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_error (GRUB_ERR_BAD_FS, "not a HFS filesystem"); return 0; }
static grub_err_t handle_symlink (struct grub_archelp_data *data, struct grub_archelp_ops *arcops, const char *fn, char **name, grub_uint32_t mode, int *restart) { grub_size_t flen; char *target; char *ptr; char *lastslash; grub_size_t prefixlen; char *rest; char *linktarget; grub_size_t linktarget_len; *restart = 0; if ((mode & GRUB_ARCHELP_ATTR_TYPE) != GRUB_ARCHELP_ATTR_LNK || !arcops->get_link_target) return GRUB_ERR_NONE; flen = grub_strlen (fn); if (grub_memcmp (*name, fn, flen) != 0 || ((*name)[flen] != 0 && (*name)[flen] != '/')) return GRUB_ERR_NONE; rest = *name + flen; lastslash = rest; if (*rest) rest++; while (lastslash >= *name && *lastslash != '/') lastslash--; if (lastslash >= *name) prefixlen = lastslash - *name; else prefixlen = 0; if (prefixlen) prefixlen++; linktarget = arcops->get_link_target (data); if (!linktarget) return grub_errno; if (linktarget[0] == '\0') return GRUB_ERR_NONE; linktarget_len = grub_strlen (linktarget); target = grub_malloc (linktarget_len + grub_strlen (*name) + 2); if (!target) return grub_errno; grub_strcpy (target + prefixlen, linktarget); grub_free (linktarget); if (target[prefixlen] == '/') { ptr = grub_stpcpy (target, target + prefixlen); ptr = grub_stpcpy (ptr, rest); *ptr = 0; grub_dprintf ("archelp", "symlink redirected %s to %s\n", *name, target); grub_free (*name); canonicalize (target); *name = target; *restart = 1; return GRUB_ERR_NONE; } if (prefixlen) { grub_memcpy (target, *name, prefixlen); target[prefixlen-1] = '/'; } grub_strcpy (target + prefixlen + linktarget_len, rest); grub_dprintf ("archelp", "symlink redirected %s to %s\n", *name, target); grub_free (*name); canonicalize (target); *name = target; *restart = 1; return GRUB_ERR_NONE; }