/*
This file is part of GNUnet
(C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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_namespace.c
* @brief create and destroy namespaces
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_constants.h"
#include "gnunet_signatures.h"
#include "gnunet_util_lib.h"
#include "gnunet_fs_service.h"
#include "fs_api.h"
/**
* Maximum legal size for an sblock.
*/
#define MAX_SBLOCK_SIZE (60 * 1024)
/**
* Return the name of the directory in which we store
* our local namespaces (or rather, their public keys).
*
* @param h global fs handle
* @return NULL on error, otherwise the name of the directory
*/
static char *
get_namespace_directory (struct GNUNET_FS_Handle *h)
{
char *dn;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (h->cfg, "FS", "IDENTITY_DIR",
&dn))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"fs", "IDENTITY_DIR");
return NULL;
}
return dn;
}
/**
* Return the name of the directory in which we store
* the update information graph for the given local namespace.
*
* @param ns namespace handle
* @return NULL on error, otherwise the name of the directory
*/
static char *
get_update_information_directory (struct GNUNET_FS_Namespace *ns)
{
char *dn;
char *ret;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (ns->h->cfg, "FS", "UPDATE_DIR",
&dn))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
"fs", "UPDATE_DIR");
return NULL;
}
GNUNET_asprintf (&ret, "%s%s%s", dn, DIR_SEPARATOR_STR, ns->name);
GNUNET_free (dn);
return ret;
}
/**
* Write the namespace update node graph to a file.
*
* @param ns namespace to dump
*/
static void
write_update_information_graph (struct GNUNET_FS_Namespace *ns)
{
char *fn;
struct GNUNET_BIO_WriteHandle *wh;
unsigned int i;
struct NamespaceUpdateNode *n;
char *uris;
fn = get_update_information_directory (ns);
wh = GNUNET_BIO_write_open (fn);
if (NULL == wh)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Failed to open `%s' for writing: %s\n"), STRERROR (errno));
GNUNET_free (fn);
return;
}
if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, ns->update_node_count))
goto END;
for (i = 0; i < ns->update_node_count; i++)
{
n = ns->update_nodes[i];
uris = GNUNET_FS_uri_to_string (n->uri);
if ((GNUNET_OK != GNUNET_BIO_write_string (wh, n->id)) ||
(GNUNET_OK != GNUNET_BIO_write_meta_data (wh, n->md)) ||
(GNUNET_OK != GNUNET_BIO_write_string (wh, n->update)) ||
(GNUNET_OK != GNUNET_BIO_write_string (wh, uris)))
{
GNUNET_free (uris);
break;
}
GNUNET_free (uris);
}
END:
if (GNUNET_OK != GNUNET_BIO_write_close (wh))
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to write `%s': %s\n"),
STRERROR (errno));
GNUNET_free (fn);
}
/**
* Read the namespace update node graph from a file.
*
* @param ns namespace to read
*/
static void
read_update_information_graph (struct GNUNET_FS_Namespace *ns)
{
char *fn;
struct GNUNET_BIO_ReadHandle *rh;
unsigned int i;
struct NamespaceUpdateNode *n;
char *uris;
uint32_t count;
char *emsg;
fn = get_update_information_directory (ns);
if (GNUNET_YES != GNUNET_DISK_file_test (fn))
{
GNUNET_free (fn);
return;
}
rh = GNUNET_BIO_read_open (fn);
if (NULL == rh)
{
GNUNET_free (fn);
return;
}
if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &count))
{
GNUNET_break (0);
goto END;
}
if (count > 1024 * 1024)
{
GNUNET_break (0);
goto END;
}
if (0 == count)
{
GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
GNUNET_free (fn);
return;
}
ns->update_nodes =
GNUNET_malloc (count * sizeof (struct NamespaceUpdateNode *));
for (i = 0; i < count; i++)
{
n = GNUNET_malloc (sizeof (struct NamespaceUpdateNode));
if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "identifier", &n->id,