static gboolean
do_plugin_load (GstPluginLoader * l, const gchar * filename, guint tag)
{
  GstPlugin *newplugin;
  GList *chunks = NULL;

  GST_DEBUG ("Plugin scanner loading file %s. tag %u", filename, tag);

#if 0                           /* Test code - crash based on filename */
  if (strstr (filename, "coreelements") == NULL) {
    g_printerr ("Crashing on file %s\n", filename);
    g_printerr ("%d", *(gint *) (NULL));
  }
#endif

  newplugin = gst_plugin_load_file ((gchar *) filename, NULL);
  if (newplugin) {
    guint hdr_pos;
    guint offset;

    /* Now serialise the plugin details and send */
    if (!_priv_gst_registry_chunks_save_plugin (&chunks,
            gst_registry_get_default (), newplugin))
      goto fail;

    /* Store where the header is, write an empty one, then write
     * all the payload chunks, then fix up the header size */
    hdr_pos = l->tx_buf_write;
    offset = HEADER_SIZE;
    put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0);

    if (chunks) {
      GList *walk;
      for (walk = chunks; walk; walk = g_list_next (walk)) {
        GstRegistryChunk *cur = walk->data;
        put_chunk (l, cur, &offset);

        _priv_gst_registry_chunk_free (cur);
      }

      g_list_free (chunks);

      /* Store the size of the written payload */
      GST_WRITE_UINT32_BE (l->tx_buf + hdr_pos + 4, offset - HEADER_SIZE);
    }
#if 0                           /* Test code - corrupt the tx buffer based on filename */
    if (strstr (filename, "sink") != NULL) {
      int fd, res;
      g_printerr ("Corrupting tx buf on file %s\n", filename);
      fd = open ("/dev/urandom", O_RDONLY);
      res = read (fd, l->tx_buf, l->tx_buf_size);
      close (fd);
    }
#endif

    gst_object_unref (newplugin);
  } else {
    put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0);
  }

  return TRUE;
fail:
  put_packet (l, PACKET_PLUGIN_DETAILS, tag, NULL, 0);
  if (chunks) {
    GList *walk;
    for (walk = chunks; walk; walk = g_list_next (walk)) {
      GstRegistryChunk *cur = walk->data;

      _priv_gst_registry_chunk_free (cur);
    }

    g_list_free (chunks);
  }

  return FALSE;
}
/**
 * gst_registry_binary_write_cache:
 * @registry: a #GstRegistry
 * @location: a filename
 *
 * Write the @registry to a cache to file at given @location.
 *
 * Returns: %TRUE on success.
 */
gboolean
priv_gst_registry_binary_write_cache (GstRegistry * registry, GList * plugins,
    const char *location)
{
  GList *walk;
  GstBinaryRegistryMagic magic;
  GList *to_write = NULL;
  unsigned long file_position = 0;
  BinaryRegistryCache *cache;

  GST_INFO ("Building binary registry cache image");

  g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);

  if (!gst_registry_binary_initialize_magic (&magic))
    goto fail;

  /* iterate trough the list of plugins and fit them into binary structures */
  for (walk = plugins; walk != NULL; walk = walk->next) {
    GstPlugin *plugin = GST_PLUGIN (walk->data);

    if (!plugin->filename)
      continue;

    if (GST_OBJECT_FLAG_IS_SET (plugin, GST_PLUGIN_FLAG_CACHED)) {
      GStatBuf statbuf;

      if (g_stat (plugin->filename, &statbuf) < 0 ||
          plugin->file_mtime != statbuf.st_mtime ||
          plugin->file_size != statbuf.st_size)
        continue;
    }

    if (!_priv_gst_registry_chunks_save_plugin (&to_write, registry, plugin)) {
      GST_ERROR ("Can't write binary plugin information for \"%s\"",
          plugin->filename);
    }
  }

  _priv_gst_registry_chunks_save_global_header (&to_write, registry,
      priv_gst_plugin_loading_get_whitelist_hash ());

  GST_INFO ("Writing binary registry cache");

  cache = gst_registry_binary_cache_init (registry, location);
  if (!cache)
    goto fail_free_list;

  /* write magic */
  if (gst_registry_binary_cache_write (cache, file_position,
          &magic, sizeof (GstBinaryRegistryMagic)) !=
      sizeof (GstBinaryRegistryMagic)) {
    GST_ERROR ("Failed to write binary registry magic");
    goto fail_free_list;
  }
  file_position += sizeof (GstBinaryRegistryMagic);

  /* write out data chunks */
  for (walk = to_write; walk; walk = g_list_next (walk)) {
    GstRegistryChunk *cur = walk->data;
    gboolean res;

    res = gst_registry_binary_write_chunk (cache, cur, &file_position);

    _priv_gst_registry_chunk_free (cur);
    walk->data = NULL;
    if (!res)
      goto fail_free_list;
  }
  g_list_free (to_write);

  if (!gst_registry_binary_cache_finish (cache, TRUE))
    return FALSE;

  return TRUE;

  /* Errors */
fail_free_list:
  {
    for (walk = to_write; walk; walk = g_list_next (walk)) {
      GstRegistryChunk *cur = walk->data;

      if (cur)
        _priv_gst_registry_chunk_free (cur);
    }
    g_list_free (to_write);

    if (cache)
      (void) gst_registry_binary_cache_finish (cache, FALSE);
    /* fall through */
  }
fail:
  {
    return FALSE;
  }
}