📄 collection.c
字号:
/* 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 2, 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 applications/fs/fsui/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_collection_lib.h"#include "gnunet_util.h"/** * 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) */ unsigned int anonymityLevel; /** * Priority of the collection (NBO). */ unsigned int 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. */voidGNUNET_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 voidWRITEINT (int fd, int val){ int bval; bval = htonl (val); WRITE (fd, &bval, sizeof (int));}static voidwriteCO (){ 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 |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -