コード例 #1
0
/**
 * Print an entry in a directory.
 *
 * @param cls closure (not used)
 * @param filename name of the file in the directory
 * @param uri URI of the file
 * @param meta metadata for the file; metadata for
 *        the directory if everything else is NULL/zero
 * @param length length of the available data for the file
 *           (of type size_t since data must certainly fit
 *            into memory; if files are larger than size_t
 *            permits, then they will certainly not be
 *            embedded with the directory itself).
 * @param data data available for the file (length bytes)
 */
static void
print_entry (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri,
             const struct GNUNET_CONTAINER_MetaData *meta, size_t length,
             const void *data)
{
  char *string;
  char *name;

  name =
      GNUNET_CONTAINER_meta_data_get_by_type (meta,
                                              EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME);
  if (uri == NULL)
  {
    printf (_("Directory `%s' meta data:\n"), name);
    GNUNET_CONTAINER_meta_data_iterate (meta, &item_printer, NULL);
    printf ("\n");
    printf (_("Directory `%s' contents:\n"), name);
    GNUNET_free (name);
    return;
  }
  string = GNUNET_FS_uri_to_string (uri);
  printf ("%s (%s):\n", name, string);
  GNUNET_free (string);
  GNUNET_CONTAINER_meta_data_iterate (meta, &item_printer, NULL);
  printf ("\n");
  GNUNET_free (name);
}
コード例 #2
0
/**
 * Get the first matching MD entry of the given types. Caller is
 * responsible for freeing the return value.  Also, only meta data
 * items that are strings (0-terminated) are returned by this
 * function.
 *
 * @param md metadata to inspect
 * @param ... -1-terminated list of types
 * @return NULL if we do not have any such entry,
 *  otherwise client is responsible for freeing the value!
 */
char *
GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
                                               GNUNET_CONTAINER_MetaData *md,
                                               ...)
{
  char *ret;
  va_list args;
  enum EXTRACTOR_MetaType type;

  if (md == NULL)
    return NULL;
  ret = NULL;
  va_start (args, md);
  while (1)
  {
    type = va_arg (args, enum EXTRACTOR_MetaType);

    if (type == -1)
      break;
    ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type);
    if (ret != NULL)
      break;
  }
  va_end (args);
  return ret;
}
コード例 #3
0
ファイル: fs_directory.c プロジェクト: GNUnet/gnunet
/**
 * Does the meta-data claim that this is a directory?
 * Checks if the mime-type is that of a GNUnet directory.
 *
 * @return #GNUNET_YES if it is, #GNUNET_NO if it is not, #GNUNET_SYSERR if
 *  we have no mime-type information (treat as #GNUNET_NO)
 */
int
GNUNET_FS_meta_data_test_for_directory (const struct GNUNET_CONTAINER_MetaData *md)
{
  char *mime;
  int ret;

  if (NULL == md)
    return GNUNET_SYSERR;
  mime = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_MIMETYPE);
  if (NULL == mime)
    return GNUNET_SYSERR;
  ret = (0 == strcasecmp (mime, GNUNET_FS_DIRECTORY_MIME)) ? GNUNET_YES : GNUNET_NO;
  GNUNET_free (mime);
  return ret;
}
コード例 #4
0
ファイル: fs_directory.c プロジェクト: GNUnet/gnunet
/**
 * Set the MIMETYPE information for the given
 * metadata to "application/gnunet-directory".
 *
 * @param md metadata to add mimetype to
 */
void
GNUNET_FS_meta_data_make_directory (struct GNUNET_CONTAINER_MetaData *md)
{
  char *mime;

  mime =
      GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_MIMETYPE);
  if (mime != NULL)
  {
    GNUNET_break (0 == strcmp (mime, GNUNET_FS_DIRECTORY_MIME));
    GNUNET_free (mime);
    return;
  }
  GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>",
                                     EXTRACTOR_METATYPE_MIMETYPE,
                                     EXTRACTOR_METAFORMAT_UTF8, "text/plain",
                                     GNUNET_FS_DIRECTORY_MIME,
                                     strlen (GNUNET_FS_DIRECTORY_MIME) + 1);
}
コード例 #5
0
ファイル: fs_directory.c プロジェクト: GNUnet/gnunet
/**
 * Iterate over all entries in a directory.  Note that directories
 * are structured such that it is possible to iterate over the
 * individual blocks as well as over the entire directory.  Thus
 * a client can call this function on the buffer in the
 * GNUNET_FS_ProgressCallback.  Also, directories can optionally
 * include the contents of (small) files embedded in the directory
 * itself; for those files, the processor may be given the
 * contents of the file directly by this function.
 * <p>
 *
 * Note that this function maybe called on parts of directories.  Thus
 * parser errors should not be reported _at all_ (with GNUNET_break).
 * Still, if some entries can be recovered despite these parsing
 * errors, the function should try to do this.
 *
 * @param size number of bytes in data
 * @param data pointer to the beginning of the directory
 * @param offset offset of data in the directory
 * @param dep function to call on each entry
 * @param dep_cls closure for dep
 * @return GNUNET_OK if this could be a block in a directory,
 *         GNUNET_NO if this could be part of a directory (but not 100% OK)
 *         GNUNET_SYSERR if 'data' does not represent a directory
 */
int
GNUNET_FS_directory_list_contents (size_t size, const void *data,
                                   uint64_t offset,
                                   GNUNET_FS_DirectoryEntryProcessor dep,
                                   void *dep_cls)
{
  struct GetFullDataClosure full_data;
  const char *cdata = data;
  char *emsg;
  uint64_t pos;
  uint64_t align;
  uint32_t mdSize;
  uint64_t epos;
  struct GNUNET_FS_Uri *uri;
  struct GNUNET_CONTAINER_MetaData *md;
  char *filename;

  if ((offset == 0) &&
      ((size < 8 + sizeof (uint32_t)) ||
       (0 != memcmp (cdata, GNUNET_FS_DIRECTORY_MAGIC, 8))))
    return GNUNET_SYSERR;
  pos = offset;
  if (offset == 0)
  {
    GNUNET_memcpy (&mdSize, &cdata[8], sizeof (uint32_t));
    mdSize = ntohl (mdSize);
    if (mdSize > size - 8 - sizeof (uint32_t))
    {
      /* invalid size */
      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  _("MAGIC mismatch.  This is not a GNUnet directory.\n"));
      return GNUNET_SYSERR;
    }
    md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[8 + sizeof (uint32_t)],
                                                 mdSize);
    if (md == NULL)
    {
      GNUNET_break (0);
      return GNUNET_SYSERR;     /* malformed ! */
    }
    dep (dep_cls, NULL, NULL, md, 0, NULL);
    GNUNET_CONTAINER_meta_data_destroy (md);
    pos = 8 + sizeof (uint32_t) + mdSize;
  }
  while (pos < size)
  {
    /* find end of URI */
    if (cdata[pos] == '\0')
    {
      /* URI is never empty, must be end of block,
       * skip to next alignment */
      align = ((pos / DBLOCK_SIZE) + 1) * DBLOCK_SIZE;
      if (align == pos)
      {
        /* if we were already aligned, still skip a block! */
        align += DBLOCK_SIZE;
      }
      pos = align;
      if (pos >= size)
      {
        /* malformed - or partial download... */
        break;
      }
    }
    epos = pos;
    while ((epos < size) && (cdata[epos] != '\0'))
      epos++;
    if (epos >= size)
      return GNUNET_NO;         /* malformed - or partial download */

    uri = GNUNET_FS_uri_parse (&cdata[pos], &emsg);
    pos = epos + 1;
    if (uri == NULL)
    {
      GNUNET_free (emsg);
      pos--;                    /* go back to '\0' to force going to next alignment */
      continue;
    }
    if (GNUNET_FS_uri_test_ksk (uri))
    {
      GNUNET_FS_uri_destroy (uri);
      GNUNET_break (0);
      return GNUNET_NO;         /* illegal in directory! */
    }

    GNUNET_memcpy (&mdSize, &cdata[pos], sizeof (uint32_t));
    mdSize = ntohl (mdSize);
    pos += sizeof (uint32_t);
    if (pos + mdSize > size)
    {
      GNUNET_FS_uri_destroy (uri);
      return GNUNET_NO;         /* malformed - or partial download */
    }

    md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[pos], mdSize);
    if (md == NULL)
    {
      GNUNET_FS_uri_destroy (uri);
      GNUNET_break (0);
      return GNUNET_NO;         /* malformed ! */
    }
    pos += mdSize;
    filename =
        GNUNET_CONTAINER_meta_data_get_by_type (md,
                                                EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME);
    full_data.size = 0;
    full_data.data = NULL;
    GNUNET_CONTAINER_meta_data_iterate (md, &find_full_data, &full_data);
    if (dep != NULL)
    {
      dep (dep_cls, filename, uri, md, full_data.size, full_data.data);
    }
    GNUNET_free_non_null (full_data.data);
    GNUNET_free_non_null (filename);
    GNUNET_CONTAINER_meta_data_destroy (md);
    GNUNET_FS_uri_destroy (uri);
  }
  return GNUNET_OK;
}
コード例 #6
0
ファイル: gnunet-search.c プロジェクト: tg-x/gnunet
/**
 * Called by FS client to give information about the progress of an
 * operation.
 *
 * @param cls closure
 * @param info details about the event, specifying the event type
 *        and various bits about the event
 * @return client-context (for the next progress call
 *         for this operation; should be set to NULL for
 *         SUSPEND and STOPPED events).  The value returned
 *         will be passed to future callbacks in the respective
 *         field in the GNUNET_FS_ProgressInfo struct.
 */
static void *
progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
{
  static unsigned int cnt;
  int is_directory;
  char *uri;
  char *filename;

  switch (info->status)
  {
  case GNUNET_FS_STATUS_SEARCH_START:
    break;
  case GNUNET_FS_STATUS_SEARCH_RESULT:
    if (db != NULL)
      GNUNET_FS_directory_builder_add (db,
                                       info->value.search.specifics.result.uri,
                                       info->value.search.specifics.result.meta,
                                       NULL);
    uri = GNUNET_FS_uri_to_string (info->value.search.specifics.result.uri);
    printf ("#%u:\n", cnt++);
    filename =
        GNUNET_CONTAINER_meta_data_get_by_type (info->value.search.
                                                specifics.result.meta,
                                                EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME);
    is_directory =
        GNUNET_FS_meta_data_test_for_directory (info->value.search.
                                                specifics.result.meta);
    if (filename != NULL)
    {
      GNUNET_DISK_filename_canonicalize (filename);
      if (GNUNET_YES == is_directory)
        printf ("gnunet-download -o \"%s%s\" -R %s\n", filename, GNUNET_FS_DIRECTORY_EXT, uri);
      else
        printf ("gnunet-download -o \"%s\" %s\n", filename, uri);
    }
    else if (GNUNET_YES == is_directory)
      printf ("gnunet-download -o \"collection%s\" -R %s\n", GNUNET_FS_DIRECTORY_EXT, uri);
    else
      printf ("gnunet-download %s\n", uri);
    if (verbose)
      GNUNET_CONTAINER_meta_data_iterate (info->value.search.specifics.
                                          result.meta, &item_printer, NULL);
    printf ("\n");
    fflush (stdout);
    GNUNET_free_non_null (filename);
    GNUNET_free (uri);
    results++;
    if ((results_limit > 0) && (results >= results_limit))
      GNUNET_SCHEDULER_shutdown ();
    break;
  case GNUNET_FS_STATUS_SEARCH_UPDATE:
    break;
  case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED:
    /* ignore */
    break;
  case GNUNET_FS_STATUS_SEARCH_ERROR:
    FPRINTF (stderr, _("Error searching: %s.\n"),
             info->value.search.specifics.error.message);
    GNUNET_SCHEDULER_shutdown ();
    break;
  case GNUNET_FS_STATUS_SEARCH_STOPPED:
    GNUNET_SCHEDULER_add_now (&clean_task, NULL);
    break;
  default:
    FPRINTF (stderr, _("Unexpected status: %d\n"), info->status);
    break;
  }
  return NULL;
}