+++ /dev/null
-/*
- This file is part of GNUnet.
- (C) 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file fs/fs_collection.c
- * @brief Helper functions for building a collection
- * @author Christian Grothoff
- *
- * A collection is a special kind of namespace. A collection is the
- * set of files provided by the same user, but unlike namespaces it is
- * automatically managed by the GNUnet UI. A collection is a single
- * directory in a namespace that is automatically updated each time
- * the user updates or deletes a file. That is, once the user starts
- * a collection the gnunet-tools will always keep the corresponding
- * directory and namespace entries up-to-date.
- *
- * A good way of thinking about a collection is a lazy user's
- * namespace.
- */
-
-#include "platform.h"
-#include "gnunet_directories.h"
-#include "gnunet_fs_service.h"
-
-
-/**
- * Initialize collection.
- *
- * @param h handle to the file sharing subsystem
- * @param namespace namespace to use for the collection
- * @return GNUNET_OK on success, GNUNET_SYSERR if another
- * namespace is already set for our collection
- */
-int
-GNUNET_FS_collection_start (struct GNUNET_FS_Handle *h,
- struct GNUNET_FS_Namespace *namespace)
-{
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Stop collection.
- *
- * @param h handle to the file sharing subsystem
- * @return GNUNET_OK on success, GNUNET_SYSERR if no collection is active
- */
-int
-GNUNET_FS_collection_stop (struct GNUNET_FS_Handle *h)
-{
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Are we using a collection?
- *
- * @param h handle to the file sharing subsystem
- * @return NULL if there is no collection,
- */
-struct GNUNET_FS_Namespace *
-GNUNET_FS_collection_get(struct GNUNET_FS_Handle *h)
-{
- return NULL;
-}
-
-
-/**
- * Publish an update of the current collection information to the
- * network now. The function has no effect if the collection has not
- * changed since the last publication. If we are currently not
- * collecting, this function does nothing.
- *
- * @param h handle to the file sharing subsystem
- */
-void GNUNET_FS_collection_publish (struct GNUNET_FS_Handle *h)
-{
-}
-
-
-/**
- * If we are currently building a collection, publish the given file
- * information in that collection. If we are currently not
- * collecting, this function does nothing.
- *
- * @param h handle to the file sharing subsystem
- * @param uri uri to add to the collection
- * @param meta metadata for the uri
- */
-void GNUNET_FS_collection_add (const struct GNUNET_FS_Handle *h,
- const struct GNUNET_FS_Uri *uri,
- const struct GNUNET_CONTAINER_MetaData *meta)
-{
-}
-
-
-#if 0
-
-/**
- * Filename used to store collection information
- */
-#define COLLECTION "collection"
-
-#define COLLECTION_ROOT "root"
-
-/**
- * How long does a collection advertisement live?
- */
-#define COLLECTION_ADV_LIFETIME (12 * GNUNET_CRON_MONTHS)
-
-/**
- * @brief information about a collection
- */
-typedef struct CollectionData
-{
-
- /**
- * What is the pseudonym ID for the publication?
- */
- GNUNET_HashCode pid;
-
- /**
- * Anonymity level for the collection. (NBO)
- */
- uint32_t anonymityLevel;
-
- /**
- * Priority of the collection (NBO).
- */
- uint32_t priority;
-
- /**
- * Has this collection changed since the last publication?
- */
- int changed;
-
- /**
- * Revision counter
- */
- unsigned int revision;
-
-} CollectionData;
-
-
-typedef struct
-{
-
- CollectionData data;
-
- /**
- * Metadata describing the collection
- */
- struct GNUNET_MetaData *meta;
-
- /**
- * Files in the collection.
- */
- GNUNET_ECRS_FileInfo *files;
-
- /**
- * How many files are in files?
- */
- unsigned int file_count;
-
-
-} CollectionInfo;
-
-static CollectionInfo *collectionData;
-
-static struct GNUNET_Mutex *lock;
-
-static struct GNUNET_GE_Context *ectx;
-
-static struct GNUNET_GC_Configuration *cfg;
-
-static char *
-getCollectionFileName ()
-{
- return GNUNET_get_home_filename (ectx, cfg, GNUNET_NO, COLLECTION, NULL);
-}
-
-/**
- * Initialize collection module.
- */
-void
-GNUNET_CO_init (struct GNUNET_GE_Context *e,
- struct GNUNET_GC_Configuration *c)
-{
- char *fn;
- int len;
- unsigned int mlen;
- unsigned long long size;
- char *buf;
- int fd;
- const char *pos;
- size_t rsize;
- unsigned int i;
- char *tmp;
-
- cfg = c;
- ectx = e;
- lock = GNUNET_mutex_create (GNUNET_YES);
- fn = getCollectionFileName ();
- if (!GNUNET_disk_file_test (ectx, fn))
- {
- GNUNET_free (fn);
- return;
- }
- /* read collection data */
- if (GNUNET_OK != GNUNET_disk_file_size (ectx, fn, &size, GNUNET_YES))
- {
- GNUNET_free (fn);
- return;
- }
- if ((size > 0x7FFFFFFF) ||
- (size < sizeof (CollectionData) + 2 * sizeof (int)))
- {
- GNUNET_GE_BREAK (ectx, 0);
- UNLINK (fn);
- GNUNET_free (fn);
- return;
- }
- fd = OPEN (fn, O_RDONLY | O_LARGEFILE);
- if (fd == -1)
- {
- GNUNET_GE_BREAK (ectx, 0);
- UNLINK (fn);
- GNUNET_free (fn);
- return;
- }
- rsize = (size_t) size;
- buf = MMAP (NULL, rsize, PROT_READ, MAP_SHARED, fd, 0);
- if (buf == MAP_FAILED)
- {
- GNUNET_GE_LOG_STRERROR_FILE (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
- GNUNET_GE_USER | GNUNET_GE_BULK, "mmap",
- fn);
- CLOSE (fd);
- GNUNET_free (fn);
- return;
- }
- collectionData = GNUNET_malloc (sizeof (CollectionInfo));
- memset (collectionData, 0, sizeof (CollectionInfo));
- memcpy (&collectionData->data, buf, sizeof (CollectionData));
- pos = &buf[sizeof (CollectionData)];
- rsize -= sizeof (CollectionData);
- len = ntohl (*(int *) pos);
- if (len > 1024 * 1024 * 4)
- goto ERR;
- pos += sizeof (int);
- mlen = ntohl (*(unsigned int *) pos);
- pos += sizeof (unsigned int);
- rsize -= 2 * sizeof (int);
- if (mlen > rsize)
- goto ERR;
- GNUNET_array_grow (collectionData->files, collectionData->file_count, len);
- collectionData->meta = GNUNET_meta_data_deserialize (ectx, pos, mlen);
- rsize -= mlen;
- pos += mlen;
- GNUNET_GE_BREAK (ectx, collectionData->meta != NULL);
- for (i = 0; i < collectionData->file_count; i++)
- {
- if (rsize < 2 * sizeof (int))
- {
- GNUNET_GE_BREAK (ectx, 0);
- break;
- }
- len = ntohl (*(int *) pos);
- pos += sizeof (int);
- mlen = ntohl (*(int *) pos);
- pos += sizeof (int);
- rsize -= 2 * sizeof (int);
- if (rsize < mlen + len)
- {
- GNUNET_GE_BREAK (ectx, 0);
- break;
- }
- if (len > 1024 * 16)
- {
- GNUNET_GE_BREAK (ectx, 0);
- len = 1024 * 16;
- }
- tmp = GNUNET_malloc (len + 1);
- tmp[len] = '\0';
- memcpy (tmp, pos, len);
- pos += len;
- rsize -= len;
- collectionData->files[i].uri = GNUNET_ECRS_string_to_uri (ectx, tmp);
- GNUNET_GE_ASSERT (ectx, collectionData->files[i].uri != NULL);
- GNUNET_free (tmp);
- collectionData->files[i].meta
- = GNUNET_meta_data_deserialize (ectx, pos, mlen);
- GNUNET_GE_ASSERT (ectx, collectionData->files[i].meta != NULL);
- pos += mlen;
- rsize -= mlen;
- }
- GNUNET_GE_ASSERT (ectx, rsize == 0);
- MUNMAP (buf, (size_t) size);
- CLOSE (fd);
- GNUNET_free (fn);
- /* kill invalid entries (meta or uri == NULL) */
- for (i = 0; i < collectionData->file_count; i++)
- {
- if ((collectionData->files[i].uri != NULL) &&
- (collectionData->files[i].meta != NULL))
- continue;
- if (collectionData->files[i].uri != NULL)
- GNUNET_ECRS_uri_destroy (collectionData->files[i].uri);
- if (collectionData->files[i].meta != NULL)
- GNUNET_meta_data_destroy (collectionData->files[i].meta);
- collectionData->files[i]
- = collectionData->files[collectionData->file_count - 1];
- GNUNET_array_grow (collectionData->files,
- collectionData->file_count,
- collectionData->file_count - 1);
- }
- return;
-ERR:
- MUNMAP (buf, (size_t) size);
- CLOSE (fd);
- GNUNET_free (fn);
- GNUNET_free (collectionData);
- collectionData = NULL;
-}
-
-static void
-WRITEINT (int fd, int val)
-{
- int bval;
-
- bval = htonl (val);
- WRITE (fd, &bval, sizeof (int));
-}
-
-static void
-writeCO ()
-{
- char *fn;
- unsigned int mlen;
- char *buf;
- int fd;
- unsigned int i;
- char *tmp;
-
- if (collectionData == NULL)
- return;
-
- /* write collection data */
- mlen =
- GNUNET_meta_data_get_serialized_size (collectionData->meta, GNUNET_NO);
- buf = GNUNET_malloc (mlen);
- if (mlen != GNUNET_meta_data_serialize (ectx,
- collectionData->meta, buf,
- mlen, GNUNET_NO))
- {
- GNUNET_GE_BREAK (ectx, 0);
- GNUNET_free (buf);
- return;
- }
-
- fn = getCollectionFileName ();
- fd = OPEN (fn,
- O_CREAT | O_LARGEFILE | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
- if (fd == -1)
- {
- GNUNET_GE_LOG_STRERROR_FILE (ectx,
- GNUNET_GE_USER | GNUNET_GE_ADMIN |
- GNUNET_GE_ERROR | GNUNET_GE_BULK, "open",
- fn);
- GNUNET_free (fn);
- GNUNET_free (buf);
- return;
- }
- GNUNET_GE_BREAK (ectx, collectionData->file_count <= 1024 * 1024 * 4);
- WRITE (fd, collectionData, sizeof (CollectionData));
- WRITEINT (fd, collectionData->file_count);
- WRITEINT (fd, mlen);
- WRITE (fd, buf, mlen);
- GNUNET_free (buf);
- for (i = 0; i < collectionData->file_count; i++)
- {
- mlen =
- GNUNET_meta_data_get_serialized_size (collectionData->files[i].meta,
- GNUNET_NO);
- buf = GNUNET_malloc (mlen);
- if (mlen != GNUNET_meta_data_serialize (ectx,
- collectionData->files[i].meta,
- buf, mlen, GNUNET_NO))
- {
- GNUNET_GE_BREAK (ectx, 0);
- GNUNET_free (buf);
- break;
- }
- tmp = GNUNET_ECRS_uri_to_string (collectionData->files[i].uri);
- WRITEINT (fd, strlen (tmp));
- WRITEINT (fd, mlen);
- GNUNET_GE_BREAK (ectx, strlen (tmp) < 16 * 1024);
- WRITE (fd, tmp, strlen (tmp));
- GNUNET_free (tmp);
- WRITE (fd, buf, mlen);
- GNUNET_free (buf);
- }
- CLOSE (fd);
- GNUNET_free (fn);
-}
-
-static void
-free_collection_data ()
-{
- unsigned int i;
-
- if (collectionData == NULL)
- return;
- GNUNET_meta_data_destroy (collectionData->meta);
- for (i = 0; i < collectionData->file_count; i++)
- {
- GNUNET_meta_data_destroy (collectionData->files[i].meta);
- GNUNET_ECRS_uri_destroy (collectionData->files[i].uri);
- }
- GNUNET_array_grow (collectionData->files, collectionData->file_count, 0);
- GNUNET_free (collectionData);
- collectionData = NULL;
-}
-
-/**
- * Shutdown collection module.
- */
-void
-GNUNET_CO_done ()
-{
- writeCO ();
- free_collection_data ();
- GNUNET_mutex_destroy (lock);
- lock = NULL;
- ectx = NULL;
- cfg = NULL;
-}
-
-
-/**
- * Start collection.
- *
- * @param updateInterval of GNUNET_ECRS_SBLOCK_UPDATE_NONE
- * means to update _immediately_ on any change,
- * wherease GNUNET_ECRS_SBLOCK_UPDATE_SPORADIC means
- * to publish updates when the CO_Context
- * is destroyed (i.e. on exit from the UI).
- */
-int
-GNUNET_CO_collection_start (uint32_t anonymityLevel,
- uint32_t prio,
- const struct GNUNET_MetaData *meta)
-{
- struct GNUNET_ECRS_URI *advertisement;
- struct GNUNET_ECRS_URI *rootURI;
- const char *root = COLLECTION_ROOT;
-
- GNUNET_mutex_lock (lock);
- GNUNET_CO_collection_stop (); /* cancel old collection */
- advertisement = GNUNET_ECRS_keyword_string_to_uri (ectx, COLLECTION);
- GNUNET_GE_ASSERT (ectx, advertisement != NULL);
- rootURI = GNUNET_ECRS_namespace_create (ectx,
- cfg,
- meta,
- anonymityLevel,
- prio,
- GNUNET_get_time () +
- COLLECTION_ADV_LIFETIME,
- advertisement, root);
- GNUNET_ECRS_uri_destroy (advertisement);
- if (rootURI == NULL)
- {
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
- collectionData = GNUNET_malloc (sizeof (CollectionInfo));
- memset (collectionData, 0, sizeof (CollectionInfo));
- GNUNET_ECRS_uri_get_namespace_from_sks (rootURI, &collectionData->data.pid);
- GNUNET_ECRS_uri_destroy (rootURI);
- collectionData->data.priority = htonl (prio);
- collectionData->data.anonymityLevel = htonl (anonymityLevel);
- collectionData->meta = GNUNET_meta_data_duplicate (meta);
- GNUNET_mutex_unlock (lock);
- return GNUNET_OK;
-}
-
-/**
- * Stop collection.
- *
- * @return GNUNET_OK on success, GNUNET_SYSERR if no collection is active
- */
-int
-GNUNET_CO_collection_stop ()
-{
- GNUNET_mutex_lock (lock);
- if (collectionData == NULL)
- {
- GNUNET_mutex_unlock (lock);
- return GNUNET_SYSERR;
- }
- GNUNET_ECRS_namespace_delete (ectx, cfg, &collectionData->data.pid);
- free_collection_data ();
- GNUNET_mutex_unlock (lock);
- return GNUNET_OK;
-}
-
-/**
- * Are we using a collection?
- *
- * @return NULL if there is no collection, otherwise its metadata
- */
-struct GNUNET_MetaData *
-GNUNET_CO_collection_get_name ()
-{
- struct GNUNET_MetaData *meta;
-
- GNUNET_mutex_lock (lock);
- if (collectionData == NULL)
- {
- GNUNET_mutex_unlock (lock);
- return NULL;
- }
- meta = GNUNET_meta_data_duplicate (collectionData->meta);
- GNUNET_mutex_unlock (lock);
- return meta;
-}
-
-/**
- * Publish an update of the current collection information to the
- * network now. The function has no effect if the collection has not
- * changed since the last publication. If we are currently not
- * collecting, this function does nothing.
- */
-void
-GNUNET_CO_collection_publish_now ()
-{
- struct GNUNET_ECRS_URI *uri;
- struct GNUNET_ECRS_URI *directoryURI;
- unsigned long long dirLen;
- char *tmpName;
- int fd;
- char *dirData;
- char this_revision_string[128];
- char next_revision_string[128];
- const char *tmpdir;
-
- GNUNET_mutex_lock (lock);
- if ((collectionData == NULL) ||
- (ntohl (collectionData->data.changed) == GNUNET_NO))
- {
- GNUNET_mutex_unlock (lock);
- return;
- }
-
- tmpdir = getenv ("TMPDIR");
- tmpdir = tmpdir ? tmpdir : "/tmp";
-
-#define TEMPLATE "/gnunet-collectionXXXXXX"
- tmpName = GNUNET_malloc (strlen (tmpdir) + sizeof (TEMPLATE) + 1);
- strcpy (tmpName, tmpdir);
- strcat (tmpName, TEMPLATE);
-#undef TEMPLATE
- fd = mkstemp (tmpName);
- if (fd == -1)
- {
- GNUNET_GE_LOG_STRERROR (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
- GNUNET_GE_BULK, "mkstemp");
- GNUNET_free (tmpName);
- GNUNET_mutex_unlock (lock);
- return;
- }
- dirData = NULL;
- GNUNET_GE_ASSERT (ectx,
- GNUNET_OK == GNUNET_ECRS_directory_create (ectx,
- &dirData,
- &dirLen,
- collectionData->file_count,
- collectionData->files,
- collectionData->meta));
- if (-1 == WRITE (fd, dirData, dirLen))
- {
- GNUNET_GE_LOG_STRERROR (ectx,
- GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
- GNUNET_GE_BULK, "write");
- GNUNET_free (tmpName);
- GNUNET_free (dirData);
- GNUNET_mutex_unlock (lock);
- return;
- }
- GNUNET_free (dirData);
- CLOSE (fd);
- if (GNUNET_OK != GNUNET_ECRS_file_upload (ectx, cfg, tmpName, GNUNET_NO, /* indexing */
- ntohl (collectionData->
- data.anonymityLevel),
- ntohl (collectionData->
- data.priority),
- GNUNET_get_time () +
- COLLECTION_ADV_LIFETIME, NULL,
- NULL, NULL, NULL, &directoryURI))
- {
- UNLINK (tmpName);
- GNUNET_free (tmpName);
- GNUNET_mutex_unlock (lock);
- return;
- }
- UNLINK (tmpName);
- GNUNET_free (tmpName);
- if (ntohl (collectionData->data.revision) == 0)
- strcpy (this_revision_string, COLLECTION_ROOT);
- else
- GNUNET_snprintf (this_revision_string,
- sizeof (this_revision_string),
- _("Revision %u"), ntohl (collectionData->data.revision));
- GNUNET_snprintf (next_revision_string,
- sizeof (next_revision_string),
- _("Revision %u"),
- ntohl (collectionData->data.revision) + 1);
- uri = GNUNET_ECRS_namespace_add_content (ectx,
- cfg,
- &collectionData->data.pid,
- ntohl (collectionData->
- data.anonymityLevel),
- ntohl (collectionData->
- data.priority),
- GNUNET_get_time () +
- COLLECTION_ADV_LIFETIME,
- this_revision_string,
- next_revision_string, directoryURI,
- collectionData->meta);
- if (uri != NULL)
- {
- collectionData->data.revision =
- htonl (ntohl (collectionData->data.revision) + 1);
- collectionData->data.changed = htonl (GNUNET_NO);
- GNUNET_ECRS_uri_destroy (uri);
- }
- GNUNET_mutex_unlock (lock);
-}
-
-/**
- * If we are currently building a collection, publish
- * the given file information in that collection.
- * If we are currently not collecting, this function
- * does nothing.
- */
-void
-GNUNET_CO_collection_add_item (const GNUNET_ECRS_FileInfo * fi)
-{
- unsigned int i;
- GNUNET_ECRS_FileInfo fc;
-
- if ((GNUNET_ECRS_uri_test_ksk (fi->uri)))
- {
- GNUNET_GE_BREAK (ectx, 0);
- return;
- }
- if (lock == NULL)
- {
- GNUNET_GE_BREAK (ectx, 0);
- return;
- }
- GNUNET_mutex_lock (lock);
- if (collectionData == NULL)
- {
- GNUNET_mutex_unlock (lock);
- return;
- }
- for (i = 0; i < collectionData->file_count; i++)
- {
- if (GNUNET_ECRS_uri_test_equal (fi->uri, collectionData->files[i].uri))
- {
- GNUNET_mutex_unlock (lock);
- return;
- }
- }
- fc.uri = GNUNET_ECRS_uri_duplicate (fi->uri);
- fc.meta = GNUNET_meta_data_duplicate (fi->meta);
- GNUNET_array_append (collectionData->files, collectionData->file_count, fc);
- collectionData->data.changed = htonl (GNUNET_YES);
- GNUNET_mutex_unlock (lock);
-}
-
-#endif
-
-/* end of fs_collection.c */