/* * Locate an object in an object set. * * Arguments: * set: the object set to search * compare_fn: a caller-provided function used to compare the * name against an object. This function should return * a negtive value, zero, or a positive value if the * object's name is, respectively, less that, equal * to, or greater than the provided name. * name: the name (value) to find. * * The returned object, if any, is referenced. The caller must * call object_release() when finished with the object. * * Returns the object, if found. Otherwise, returns NULL. * Implementation note: since we store objects in an unordered * linked list, all that's really important is that the compare_fn * return 0 when a match is found, and non-zero otherwise. * Other types of implementations might try to optimize the * storage, e.g. binary search. */ Object * objset_find(Objset *set, CMPFn compare_fn, const void *name) { objset_object *found = NULL; PR_ASSERT(NULL != set); PR_ASSERT(NULL != name); PR_ASSERT(NULL != compare_fn); PR_Lock(set->lock); found = set->head; while (NULL != found) { if (compare_fn(found->obj, name) == 0) { break; } found = found->next; } if (NULL != found) { /* acquire object */ object_acquire(found->obj); } PR_Unlock(set->lock); return found == NULL ? NULL : found->obj; }
static void * ListFindValue( char *node, unsigned limit, unsigned elsize, void *target, bool (*compare_fn)(void *, void *) ) /*****************************************************************************/ { unsigned index; for( index = 0; index < limit; index++ ) { if( compare_fn( node, target ) ) return node; node += elsize; } return NULL; }
/* Helper for FUNC_NAME. */ static int iterate_device (const char *name, void *data) { struct search_ctx *ctx = data; int found = 0; /* Skip floppy drives when requested. */ if (ctx->no_floppy && name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') return 0; #ifdef DO_SEARCH_FS_UUID #define compare_fn grub_strcasecmp #else #define compare_fn grub_strcmp #endif #ifdef DO_SEARCH_FILE { char *buf; grub_file_t file; buf = grub_xasprintf ("(%s)%s", name, ctx->key); if (! buf) return 1; grub_file_filter_disable_compression (); file = grub_file_open (buf); if (file) { found = 1; grub_file_close (file); } grub_free (buf); } #elif defined(DO_SEARCH_PART_UUID) { grub_device_t dev; char *quid; dev = grub_device_open (name); if (dev) { if (grub_gpt_part_uuid (dev, &quid) == GRUB_ERR_NONE) { if (grub_strcasecmp (quid, ctx->key) == 0) found = 1; grub_free (quid); } grub_device_close (dev); } } #elif defined(DO_SEARCH_PART_LABEL) { grub_device_t dev; char *quid; dev = grub_device_open (name); if (dev) { if (grub_gpt_part_label (dev, &quid) == GRUB_ERR_NONE) { if (grub_strcmp (quid, ctx->key) == 0) found = 1; grub_free (quid); } grub_device_close (dev); } } #else { /* SEARCH_FS_UUID or SEARCH_LABEL */ grub_device_t dev; grub_fs_t fs; char *quid; dev = grub_device_open (name); if (dev) { fs = grub_fs_probe (dev); #ifdef DO_SEARCH_FS_UUID #define read_fn uuid #else #define read_fn label #endif if (fs && fs->read_fn) { fs->read_fn (dev, &quid); if (grub_errno == GRUB_ERR_NONE && quid) { if (compare_fn (quid, ctx->key) == 0) found = 1; grub_free (quid); } } grub_device_close (dev); } } #endif if (!ctx->is_cache && found && ctx->count == 0) { struct cache_entry *cache_ent; cache_ent = grub_malloc (sizeof (*cache_ent)); if (cache_ent) { cache_ent->key = grub_strdup (ctx->key); cache_ent->value = grub_strdup (name); if (cache_ent->value && cache_ent->key) { cache_ent->next = cache; cache = cache_ent; } else { grub_free (cache_ent->value); grub_free (cache_ent->key); grub_free (cache_ent); grub_errno = GRUB_ERR_NONE; } } else grub_errno = GRUB_ERR_NONE; } if (found) { ctx->count++; if (ctx->var) grub_env_set (ctx->var, name); else grub_printf (" %s", name); } grub_errno = GRUB_ERR_NONE; return (found && ctx->var); }