// The hook caller static Ret call(Args... a) { return hook()(original(), a...); }
// Constructs passing information to the static variables function_hooker(hook_type hooker) { hook() = hooker; original() = MakeCALL(addr, raw_ptr(call)).get(); }
static grub_err_t apple_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition part; struct grub_apple_header aheader; struct grub_apple_part apart; struct grub_disk raw; int partno = 0; unsigned pos = GRUB_DISK_SECTOR_SIZE; /* Enforce raw disk access. */ raw = *disk; raw.partition = 0; part.partmap = &grub_apple_partition_map; if (grub_disk_read (&raw, 0, 0, sizeof (aheader), (char *) &aheader)) return grub_errno; if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC) { grub_dprintf ("partition", "bad magic (found 0x%x; wanted 0x%x\n", grub_be_to_cpu16 (aheader.magic), GRUB_APPLE_HEADER_MAGIC); goto fail; } for (;;) { if (grub_disk_read (&raw, pos / GRUB_DISK_SECTOR_SIZE, pos % GRUB_DISK_SECTOR_SIZE, sizeof (struct grub_apple_part), (char *) &apart)) return grub_errno; if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC) { grub_dprintf ("partition", "partition %d: bad magic (found 0x%x; wanted 0x%x\n", partno, grub_be_to_cpu16 (apart.magic), GRUB_APPLE_PART_MAGIC); break; } part.start = grub_be_to_cpu32 (apart.first_phys_block); part.len = grub_be_to_cpu32 (apart.blockcnt); part.offset = pos; part.index = partno; grub_dprintf ("partition", "partition %d: name %s, type %s, start 0x%x, len 0x%x\n", partno, apart.partname, apart.parttype, grub_be_to_cpu32 (apart.first_phys_block), grub_be_to_cpu32 (apart.blockcnt)); if (hook (disk, &part)) return grub_errno; if (grub_be_to_cpu32 (apart.first_phys_block) == GRUB_DISK_SECTOR_SIZE * 2) return 0; pos += sizeof (struct grub_apple_part); partno++; } if (pos != GRUB_DISK_SECTOR_SIZE) return 0; fail: return grub_error (GRUB_ERR_BAD_PART_TABLE, "Apple partition map not found."); }
__attribute__((constructor)) void load(int argc, const char **argv, const char **envp, const char **apple, struct ProgramVars *pvars) { hook("_puts", test, pvars->mh); }
static void init(void) { hook("init() called inside weak-import."); }
static void shutdown(void) { hook("shutdown() called inside weak-import."); }
static int grub_ext2_iterate_dir (grub_fshelp_node_t dir, int (*hook) (const char *filename, enum grub_fshelp_filetype filetype, grub_fshelp_node_t node, void *closure), void *closure) { unsigned int fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; if (! diro->inode_read) { grub_ext2_read_inode (diro->data, diro->ino, &diro->inode); if (grub_errno) return 0; } /* Search the file. */ while (fpos < grub_le_to_cpu32 (diro->inode.size)) { struct ext2_dirent dirent; grub_ext2_read_file (diro, 0, 0, 0, fpos, sizeof (struct ext2_dirent), (char *) &dirent); if (grub_errno) return 0; if (dirent.direntlen == 0) return 0; if (dirent.namelen != 0) { char filename[dirent.namelen + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; grub_ext2_read_file (diro, 0, 0, 0, fpos + sizeof (struct ext2_dirent), dirent.namelen, filename); if (grub_errno) return 0; fdiro = grub_malloc (sizeof (struct grub_fshelp_node)); if (! fdiro) return 0; fdiro->data = diro->data; fdiro->ino = grub_le_to_cpu32 (dirent.inode); filename[dirent.namelen] = '\0'; if (dirent.filetype != FILETYPE_UNKNOWN) { fdiro->inode_read = 0; if (dirent.filetype == FILETYPE_DIRECTORY) type = GRUB_FSHELP_DIR; else if (dirent.filetype == FILETYPE_SYMLINK) type = GRUB_FSHELP_SYMLINK; else if (dirent.filetype == FILETYPE_REG) type = GRUB_FSHELP_REG; } else { /* The filetype can not be read from the dirent, read the inode to get more information. */ grub_ext2_read_inode (diro->data, grub_le_to_cpu32 (dirent.inode), &fdiro->inode); if (grub_errno) { grub_free (fdiro); return 0; } fdiro->inode_read = 1; if ((grub_le_to_cpu16 (fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY) type = GRUB_FSHELP_DIR; else if ((grub_le_to_cpu16 (fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK) type = GRUB_FSHELP_SYMLINK; else if ((grub_le_to_cpu16 (fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_REG) type = GRUB_FSHELP_REG; } if (hook (filename, type, fdiro, closure)) return 1; } fpos += grub_le_to_cpu16 (dirent.direntlen); } return 0; }
static grub_err_t pc_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition p; struct grub_pc_partition pcdata; struct grub_pc_partition_mbr mbr; struct grub_pc_partition_disk_label label; struct grub_disk raw; /* Enforce raw disk access. */ raw = *disk; raw.partition = 0; p.offset = 0; pcdata.ext_offset = 0; pcdata.dos_part = -1; p.data = &pcdata; p.partmap = &grub_pc_partition_map; while (1) { int i; struct grub_pc_partition_entry *e; /* Read the MBR. */ if (grub_disk_read (&raw, p.offset, 0, sizeof (mbr), (char *) &mbr)) goto finish; /* Check if it is valid. */ if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); /* Analyze DOS partitions. */ for (p.index = 0; p.index < 4; p.index++) { e = mbr.entries + p.index; p.start = p.offset + grub_le_to_cpu32 (e->start); p.len = grub_le_to_cpu32 (e->length); pcdata.bsd_part = -1; pcdata.dos_type = e->type; pcdata.bsd_type = -1; grub_dprintf ("partition", "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n", p.index, e->flag, pcdata.dos_type, (unsigned long long) p.start, (unsigned long long) p.len); /* If this is a GPT partition, this MBR is just a dummy. */ if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0) return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr"); /* If this partition is a normal one, call the hook. */ if (! grub_pc_partition_is_empty (e->type) && ! grub_pc_partition_is_extended (e->type)) { pcdata.dos_part++; if (hook (disk, &p)) return 1; /* Check if this is a BSD partition. */ if (grub_pc_partition_is_bsd (e->type)) { /* Check if the BSD label is within the DOS partition. */ if (p.len <= GRUB_PC_PARTITION_BSD_LABEL_SECTOR) return grub_error (GRUB_ERR_BAD_PART_TABLE, "no space for disk label"); /* Read the BSD label. */ if (grub_disk_read (&raw, (p.start + GRUB_PC_PARTITION_BSD_LABEL_SECTOR), 0, sizeof (label), (char *) &label)) goto finish; /* Check if it is valid. */ if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid disk label magic 0x%x", label.magic); for (pcdata.bsd_part = 0; pcdata.bsd_part < grub_cpu_to_le16 (label.num_partitions); pcdata.bsd_part++) { struct grub_pc_partition_bsd_entry *be = label.entries + pcdata.bsd_part; p.start = grub_le_to_cpu32 (be->offset); p.len = grub_le_to_cpu32 (be->size); pcdata.bsd_type = be->fs_type; if (be->fs_type != GRUB_PC_PARTITION_BSD_TYPE_UNUSED) if (hook (disk, &p)) return 1; } } } else if (pcdata.dos_part < 4) /* If this partition is a logical one, shouldn't increase the partition number. */ pcdata.dos_part++; } /* Find an extended partition. */ for (i = 0; i < 4; i++) { e = mbr.entries + i; if (grub_pc_partition_is_extended (e->type)) { p.offset = pcdata.ext_offset + grub_le_to_cpu32 (e->start); if (! pcdata.ext_offset) pcdata.ext_offset = p.offset; break; } } /* If no extended partition, the end. */ if (i == 4) break; } finish: return grub_errno; }
static grub_err_t grub_cpio_dir (grub_device_t device, const char *path_in, int (*hook) (const char *filename, const struct grub_dirhook_info *info)) { struct grub_cpio_data *data; grub_disk_addr_t ofs; char *prev, *name, *path, *ptr; grub_size_t len; int symlinknest = 0; path = grub_strdup (path_in + 1); if (!path) return grub_errno; canonicalize (path); for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--) *ptr = 0; grub_dl_ref (my_mod); prev = 0; data = grub_cpio_mount (device->disk); if (!data) { grub_free (path); return grub_errno; } len = grub_strlen (path); data->hofs = 0; while (1) { grub_int32_t mtime; grub_uint32_t mode; grub_err_t err; if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode)) goto fail; if (!ofs) break; if (grub_memcmp (path, name, len) == 0 && (name[len] == 0 || name[len] == '/' || len == 0)) { char *p, *n; n = name + len; while (*n == '/') n++; p = grub_strchr (n, '/'); if (p) *p = 0; if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0) { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = (p != NULL) || ((mode & ATTR_TYPE) == ATTR_DIR); info.mtime = mtime; info.mtimeset = 1; if (hook (n, &info)) { grub_free (name); goto fail; } grub_free (prev); prev = name; } else { int restart = 0; err = handle_symlink (data, name, &path, mode, &restart); grub_free (name); if (err) goto fail; if (restart) { len = grub_strlen (path); if (++symlinknest == 8) { grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); goto fail; } ofs = 0; } } } else grub_free (name); data->hofs = ofs; } fail: grub_free (path); grub_free (prev); #ifdef MODE_USTAR grub_free (data->linkname); #endif grub_free (data); grub_dl_unref (my_mod); return grub_errno; }
static int grub_memdisk_iterate (int (*hook) (const char *name)) { return hook ("memdisk"); }
void grub_envblk_iterate (grub_envblk_t envblk, int hook (const char *name, const char *value)) { char *p, *pend; p = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; pend = envblk->buf + envblk->size; while (p < pend) { if (*p != '#') { char *name; char *value; char *name_start, *name_end, *value_start; char *q; int ret; name_start = p; while (p < pend && *p != '=') p++; if (p == pend) /* Broken. */ return; name_end = p; p++; value_start = p; while (p < pend) { if (*p == '\n') break; else if (*p == '\\') p += 2; else p++; } if (p >= pend) /* Broken. */ return; name = g_malloc (p - name_start + 1); if (! name) /* out of memory. */ return; value = name + (value_start - name_start); memcpy (name, name_start, name_end - name_start); name[name_end - name_start] = '\0'; for (p = value_start, q = value; *p != '\n'; ++p) { if (*p == '\\') *q++ = *++p; else *q++ = *p; } *q = '\0'; ret = hook (name, value); g_free (name); if (ret) return; } p = find_next_line (p, pend); } }
/* Iterate over the susp entries, starting with block SUA_BLOCK on the offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for every entry. */ static grub_err_t grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, grub_ssize_t sua_size, grub_err_t (*hook) (struct grub_iso9660_susp_entry *entry, void *hook_arg), void *hook_arg) { char *sua; struct grub_iso9660_susp_entry *entry; grub_err_t err; if (sua_size <= 0) return GRUB_ERR_NONE; sua = grub_malloc (sua_size); if (!sua) return grub_errno; /* Load a part of the System Usage Area. */ err = read_node (node, off, sua_size, sua); if (err) return err; for (entry = (struct grub_iso9660_susp_entry *) sua; (char *) entry < (char *) sua + sua_size - 1 && entry->len > 0; entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len)) { /* The last entry. */ if (grub_strncmp ((char *) entry->sig, "ST", 2) == 0) break; /* Additional entries are stored elsewhere. */ if (grub_strncmp ((char *) entry->sig, "CE", 2) == 0) { struct grub_iso9660_susp_ce *ce; grub_disk_addr_t ce_block; ce = (struct grub_iso9660_susp_ce *) entry; sua_size = grub_le_to_cpu32 (ce->len); off = grub_le_to_cpu32 (ce->off); ce_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ; grub_free (sua); sua = grub_malloc (sua_size); if (!sua) return grub_errno; /* Load a part of the System Usage Area. */ err = grub_disk_read (node->data->disk, ce_block, off, sua_size, sua); if (err) return err; entry = (struct grub_iso9660_susp_entry *) sua; } if (hook (entry, hook_arg)) { grub_free (sua); return 0; } } grub_free (sua); return 0; }
void uwsgi_corerouter_loop(int id, void *data) { int i; struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) data; ucr->cr_stats_server = -1; ucr->cr_table = uwsgi_malloc(sizeof(struct corerouter_session *) * uwsgi.max_fd); for (i = 0; i < (int) uwsgi.max_fd; i++) { ucr->cr_table[i] = NULL; } ucr->i_am_cheap = ucr->cheap; void *events = uwsgi_corerouter_setup_event_queue(ucr, id); if (ucr->has_subscription_sockets) event_queue_add_fd_read(ucr->queue, ushared->gateways[id].internal_subscription_pipe[1]); if (!ucr->socket_timeout) ucr->socket_timeout = 60; if (!ucr->static_node_gracetime) ucr->static_node_gracetime = 30; int i_am_the_first = 1; for(i=0;i<id;i++) { if (!strcmp(ushared->gateways[i].name, ucr->name)) { i_am_the_first = 0; break; } } if (ucr->stats_server && i_am_the_first) { char *tcp_port = strchr(ucr->stats_server, ':'); if (tcp_port) { // disable deferred accept for this socket int current_defer_accept = uwsgi.no_defer_accept; uwsgi.no_defer_accept = 1; ucr->cr_stats_server = bind_to_tcp(ucr->stats_server, uwsgi.listen_queue, tcp_port); uwsgi.no_defer_accept = current_defer_accept; } else { ucr->cr_stats_server = bind_to_unix(ucr->stats_server, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); } event_queue_add_fd_read(ucr->queue, ucr->cr_stats_server); uwsgi_log("*** %s stats server enabled on %s fd: %d ***\n", ucr->short_name, ucr->stats_server, ucr->cr_stats_server); } if (ucr->use_socket) { ucr->to_socket = uwsgi_get_socket_by_num(ucr->socket_num); if (ucr->to_socket) { // fix socket name_len if (ucr->to_socket->name_len == 0 && ucr->to_socket->name) { ucr->to_socket->name_len = strlen(ucr->to_socket->name); } } } if (!ucr->pb_base_dir) { ucr->pb_base_dir = getenv("TMPDIR"); if (!ucr->pb_base_dir) ucr->pb_base_dir = "/tmp"; } int nevents; time_t delta; struct uwsgi_rb_timer *min_timeout; int new_connection; if (ucr->pattern) { init_magic_table(ucr->magic_table); } union uwsgi_sockaddr cr_addr; socklen_t cr_addr_len = sizeof(struct sockaddr_un); ucr->mapper = uwsgi_cr_map_use_void; if (ucr->use_cache) { ucr->cache = uwsgi_cache_by_name(ucr->use_cache); if (!ucr->cache) { uwsgi_log("!!! unable to find cache \"%s\" !!!\n", ucr->use_cache); exit(1); } ucr->mapper = uwsgi_cr_map_use_cache; } else if (ucr->pattern) { ucr->mapper = uwsgi_cr_map_use_pattern; } else if (ucr->has_subscription_sockets) { ucr->mapper = uwsgi_cr_map_use_subscription; if (uwsgi.subscription_dotsplit) { ucr->mapper = uwsgi_cr_map_use_subscription_dotsplit; } } else if (ucr->base) { ucr->mapper = uwsgi_cr_map_use_base; } else if (ucr->code_string_code && ucr->code_string_function) { ucr->mapper = uwsgi_cr_map_use_cs; } else if (ucr->to_socket) { ucr->mapper = uwsgi_cr_map_use_to; } else if (ucr->static_nodes) { ucr->mapper = uwsgi_cr_map_use_static_nodes; } ucr->timeouts = uwsgi_init_rb_timer(); for (;;) { time_t now = uwsgi_now(); // set timeouts and harakiri min_timeout = uwsgi_min_rb_timer(ucr->timeouts, NULL); if (min_timeout == NULL) { delta = -1; } else { delta = min_timeout->value - now; if (delta <= 0) { corerouter_expire_timeouts(ucr, now); delta = 0; } } if (uwsgi.master_process && ucr->harakiri > 0) { ushared->gateways_harakiri[id] = 0; } // wait for events nevents = event_queue_wait_multi(ucr->queue, delta, events, ucr->nevents); now = uwsgi_now(); if (uwsgi.master_process && ucr->harakiri > 0) { ushared->gateways_harakiri[id] = now + ucr->harakiri; } if (nevents == 0) { corerouter_expire_timeouts(ucr, now); } for (i = 0; i < nevents; i++) { // get the interesting fd ucr->interesting_fd = event_queue_interesting_fd(events, i); // something bad happened if (ucr->interesting_fd < 0) continue; // check if the ucr->interesting_fd matches a gateway socket struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets; int taken = 0; while (ugs) { if (ugs->gateway == &ushared->gateways[id] && ucr->interesting_fd == ugs->fd) { if (!ugs->subscription) { #if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL) new_connection = accept4(ucr->interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len, SOCK_NONBLOCK); if (new_connection < 0) { taken = 1; break; } #else new_connection = accept(ucr->interesting_fd, (struct sockaddr *) &cr_addr, &cr_addr_len); if (new_connection < 0) { taken = 1; break; } // set socket in non-blocking mode, on non-linux platforms, clients get the server mode #ifdef __linux__ uwsgi_socket_nb(new_connection); #endif #endif struct corerouter_session *cr = corerouter_alloc_session(ucr, ugs, new_connection, (struct sockaddr *) &cr_addr, cr_addr_len); //something wrong in the allocation if (!cr) break; } else if (ugs->subscription) { uwsgi_corerouter_manage_subscription(ucr, id, ugs); } taken = 1; break; } ugs = ugs->next; } if (taken) { continue; } // manage internal subscription if (ucr->interesting_fd == ushared->gateways[id].internal_subscription_pipe[1]) { uwsgi_corerouter_manage_internal_subscription(ucr, ucr->interesting_fd); } // manage a stats request else if (ucr->interesting_fd == ucr->cr_stats_server) { corerouter_send_stats(ucr); } else { struct corerouter_peer *peer = ucr->cr_table[ucr->interesting_fd]; // something is going wrong... if (peer == NULL) continue; // on error, destroy the session if (event_queue_interesting_fd_has_error(events, i)) { peer->failed = 1; corerouter_close_peer(ucr, peer); continue; } // set timeout (in main_peer too) peer->timeout = corerouter_reset_timeout_fast(ucr, peer, now); peer->session->main_peer->timeout = corerouter_reset_timeout_fast(ucr, peer->session->main_peer, now); ssize_t (*hook)(struct corerouter_peer *) = NULL; // call event hook if (event_queue_interesting_fd_is_read(events, i)) { hook = peer->hook_read; } else if (event_queue_interesting_fd_is_write(events, i)) { hook = peer->hook_write; } if (!hook) continue; // reset errno (as we use it for internal signalling) errno = 0; ssize_t ret = hook(peer); // connection closed if (ret == 0) { corerouter_close_peer(ucr, peer); continue; } else if (ret < 0) { if (errno == EINPROGRESS) continue; // remove keepalive on error peer->session->can_keepalive = 0; corerouter_close_peer(ucr, peer); continue; } } } } }
static int parse_string (const char *str, int (*hook) (const char *var, grub_size_t varlen), char **put) { const char *ptr; int escaped = 0; const char *optr; for (ptr = str; ptr && *ptr; ) switch (*ptr) { case '\\': escaped = !escaped; if (!escaped && put) *((*put)++) = '\\'; ptr++; break; case '$': if (escaped) { escaped = 0; if (put) *((*put)++) = *ptr; ptr++; break; } ptr++; switch (*ptr) { case '{': { optr = ptr + 1; ptr = grub_strchr (optr, '}'); if (!ptr) break; if (hook (optr, ptr - optr)) return 1; ptr++; break; } case '0' ... '9': optr = ptr; while (*ptr >= '0' && *ptr <= '9') ptr++; if (hook (optr, ptr - optr)) return 1; break; case 'a' ... 'z': case 'A' ... 'Z': case '_': optr = ptr; while ((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'z') || (*ptr >= 'A' && *ptr <= 'Z') || *ptr == '_') ptr++; if (hook (optr, ptr - optr)) return 1; break; case '?': case '#': if (hook (ptr, 1)) return 1; ptr++; break; default: if (put) *((*put)++) = '$'; } break; default: if (escaped && put) *((*put)++) = '\\'; escaped = 0; if (put) *((*put)++) = *ptr; ptr++; break; } return 0; }
void grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), int floppy_disks) { int i; clear_seen_devices (); /* Floppies. */ for (i = 0; i < floppy_disks; i++) { char name[16]; struct stat st; get_floppy_disk_name (name, i); if (stat (name, &st) < 0) break; /* In floppies, write the map, whether check_device_readable_unique succeeds or not, because the user just may not insert floppies. */ if (hook (name, 1)) goto out; } #ifdef __linux__ { DIR *dir = opendir ("/dev/disk/by-id"); if (dir) { struct dirent *entry; struct device *devs; size_t devs_len = 0, devs_max = 1024, i; devs = xmalloc (devs_max * sizeof (*devs)); /* Dump all the directory entries into names, resizing if necessary. */ for (entry = readdir (dir); entry; entry = readdir (dir)) { /* Skip current and parent directory entries. */ if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0) continue; /* Skip partition entries. */ if (strstr (entry->d_name, "-part")) continue; /* Skip device-mapper entries; we'll handle the ones we want later. */ if (strncmp (entry->d_name, "dm-", sizeof ("dm-") - 1) == 0) continue; /* Skip RAID entries; they are handled by upper layers. */ if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0) continue; if (devs_len >= devs_max) { devs_max *= 2; devs = xrealloc (devs, devs_max * sizeof (*devs)); } devs[devs_len].stable = xasprintf ("/dev/disk/by-id/%s", entry->d_name); devs[devs_len].kernel = canonicalize_file_name (devs[devs_len].stable); devs_len++; } qsort (devs, devs_len, sizeof (*devs), &compare_devices); closedir (dir); /* Now add all the devices in sorted order. */ for (i = 0; i < devs_len; ++i) { if (check_device_readable_unique (devs[i].stable)) { if (hook (devs[i].stable, 0)) goto out; } free (devs[i].stable); free (devs[i].kernel); } free (devs); } } if (have_devfs ()) { i = 0; while (1) { char discn[32]; char name[PATH_MAX]; struct stat st; /* Linux creates symlinks "/dev/discs/discN" for convenience. The way to number disks is the same as GRUB's. */ sprintf (discn, "/dev/discs/disc%d", i++); if (stat (discn, &st) < 0) break; if (realpath (discn, name)) { strcat (name, "/disc"); if (hook (name, 0)) goto out; } } goto out; } #endif /* __linux__ */ /* IDE disks. */ for (i = 0; i < 96; i++) { char name[16]; get_ide_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } #ifdef __linux__ /* Virtio disks. */ for (i = 0; i < 26; i++) { char name[16]; get_virtio_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } /* ATARAID disks. */ for (i = 0; i < 8; i++) { char name[20]; get_ataraid_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } /* Xen virtual block devices. */ for (i = 0; i < 26; i++) { char name[16]; get_xvd_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } #endif /* __linux__ */ /* The rest is SCSI disks. */ for (i = 0; i < 48; i++) { char name[16]; get_scsi_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } #ifdef __linux__ /* This is for DAC960 - we have /dev/rd/c<controller>d<logical drive>p<partition>. DAC960 driver currently supports up to 8 controllers, 32 logical drives, and 7 partitions. */ { int controller, drive; for (controller = 0; controller < 8; controller++) { for (drive = 0; drive < 15; drive++) { char name[24]; get_dac960_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for Mylex Acceleraid - we have /dev/rd/c<controller>d<logical drive>p<partition>. */ { int controller, drive; for (controller = 0; controller < 8; controller++) { for (drive = 0; drive < 15; drive++) { char name[24]; get_acceleraid_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for CCISS - we have /dev/cciss/c<controller>d<logical drive>p<partition>. */ { int controller, drive; for (controller = 0; controller < 3; controller++) { for (drive = 0; drive < 16; drive++) { char name[24]; get_cciss_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for Compaq Intelligent Drive Array - we have /dev/ida/c<controller>d<logical drive>p<partition>. */ { int controller, drive; for (controller = 0; controller < 3; controller++) { for (drive = 0; drive < 16; drive++) { char name[24]; get_ida_disk_name (name, controller, drive); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } } /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */ { char unit; for (unit = 'a'; unit < 'f'; unit++) { char name[24]; get_i2o_disk_name (name, unit); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } } /* MultiMediaCard (MMC). */ for (i = 0; i < 10; i++) { char name[16]; get_mmc_disk_name (name, i); if (check_device_readable_unique (name)) { if (hook (name, 0)) goto out; } } # ifdef HAVE_DEVICE_MAPPER # define dmraid_check(cond, ...) \ if (! (cond)) \ { \ grub_dprintf ("deviceiter", __VA_ARGS__); \ goto dmraid_end; \ } /* DM-RAID. */ if (grub_device_mapper_supported ()) { struct dm_tree *tree = NULL; struct dm_task *task = NULL; struct dm_names *names = NULL; unsigned int next = 0; void *top_handle, *second_handle; struct dm_tree_node *root, *top, *second; /* Build DM tree for all devices. */ tree = dm_tree_create (); dmraid_check (tree, "dm_tree_create failed\n"); task = dm_task_create (DM_DEVICE_LIST); dmraid_check (task, "dm_task_create failed\n"); dmraid_check (dm_task_run (task), "dm_task_run failed\n"); names = dm_task_get_names (task); dmraid_check (names, "dm_task_get_names failed\n"); dmraid_check (names->dev, "No DM devices found\n"); do { names = (void *) names + next; dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev), MINOR (names->dev)), "dm_tree_add_dev (%s) failed\n", names->name); next = names->next; } while (next); /* Walk the second-level children of the inverted tree; that is, devices which are directly composed of non-DM devices such as hard disks. This class includes all DM-RAID disks and excludes all DM-RAID partitions. */ root = dm_tree_find_node (tree, 0, 0); top_handle = NULL; top = dm_tree_next_child (&top_handle, root, 1); while (top) { second_handle = NULL; second = dm_tree_next_child (&second_handle, top, 1); while (second) { const char *node_name, *node_uuid; char *name; node_name = dm_tree_node_get_name (second); dmraid_check (node_name, "dm_tree_node_get_name failed\n"); node_uuid = dm_tree_node_get_uuid (second); dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n"); if (strncmp (node_uuid, "DMRAID-", 7) != 0) { grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name); goto dmraid_next_child; } name = xasprintf ("/dev/mapper/%s", node_name); if (check_device_readable_unique (name)) { if (hook (name, 0)) { free (name); if (task) dm_task_destroy (task); if (tree) dm_tree_free (tree); goto out; } } free (name); dmraid_next_child: second = dm_tree_next_child (&second_handle, top, 1); } top = dm_tree_next_child (&top_handle, root, 1); } dmraid_end: if (task) dm_task_destroy (task); if (tree) dm_tree_free (tree); } # endif /* HAVE_DEVICE_MAPPER */ #endif /* __linux__ */ out: clear_seen_devices (); }