⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file_info.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
字号:
/*     This file is part of GNUnet.     (C) 2003, 2004, 2006 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/uritrack/file_info.c * @brief Helper functions for keeping track of files for building directories. * @author Christian Grothoff * * An mmapped file (STATE_NAME) is used to store the URIs. * An IPC semaphore is used to guard the access. */#include "platform.h"#include "gnunet_directories.h"#include "gnunet_util.h"#include "gnunet_uritrack_lib.h"#include "callbacks.h"#define DEBUG_FILE_INFO GNUNET_NO#define STATE_NAME DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "fs_uridb"#define TRACK_OPTION "fs_uridb_status"static struct GNUNET_IPC_Semaphore *createIPC (struct GNUNET_GE_Context *ectx,           struct GNUNET_GC_Configuration *cfg){  char *ipcName;  struct GNUNET_IPC_Semaphore *sem;  ipcName =    GNUNET_get_home_filename (ectx, cfg, GNUNET_NO, "uritrack_ipc_lock",                              NULL);  sem = GNUNET_IPC_semaphore_create (ectx, ipcName, 1);  GNUNET_free (ipcName);  return sem;}static char *getUriDbName (struct GNUNET_GE_Context *ectx,              struct GNUNET_GC_Configuration *cfg){  return GNUNET_get_home_filename (ectx, cfg, GNUNET_NO, STATE_NAME, NULL);}static char *getToggleName (struct GNUNET_GE_Context *ectx,               struct GNUNET_GC_Configuration *cfg){  return GNUNET_get_home_filename (ectx, cfg, GNUNET_NO, TRACK_OPTION, NULL);}/** * Get the URITRACK URI tracking status. * * @return GNUNET_YES of tracking is enabled, GNUNET_NO if not */intGNUNET_URITRACK_get_tracking_status (struct GNUNET_GE_Context *ectx,                                     struct GNUNET_GC_Configuration *cfg){  int status;  char *tn;  tn = getToggleName (ectx, cfg);  if (GNUNET_YES != GNUNET_disk_file_test (ectx, tn))    {      GNUNET_free (tn);      return GNUNET_NO;         /* default: off */    }  if ((sizeof (int) != GNUNET_disk_file_read (ectx,                                              tn,                                              sizeof (int),                                              &status))      || (ntohl (status) != GNUNET_YES))    {      GNUNET_free (tn);#if DEBUG_FILE_INFO      GNUNET_GE_LOG (ectx,                     GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,                     _("Collecting file identifiers disabled.\n"));#endif      return GNUNET_NO;    }  else    {      GNUNET_free (tn);      return GNUNET_YES;    }}struct CheckPresentClosure{  const GNUNET_ECRS_FileInfo *fi;  int present;};static intcheckPresent (const GNUNET_ECRS_FileInfo * fi,              const GNUNET_HashCode * key, int isRoot, void *closure){  struct CheckPresentClosure *cpc = closure;  if (GNUNET_ECRS_uri_test_equal (fi->uri, cpc->fi->uri))    {      cpc->present = 1;      return GNUNET_SYSERR;    }  return GNUNET_OK;}/** * Makes a URI available for directory building. */voidGNUNET_URITRACK_track (struct GNUNET_GE_Context *ectx,                       struct GNUNET_GC_Configuration *cfg,                       const GNUNET_ECRS_FileInfo * fi){  struct GNUNET_IPC_Semaphore *sem;  char *data;  unsigned int size;  char *suri;  int fh;  char *fn;  struct CheckPresentClosure cpc;  if (GNUNET_NO == GNUNET_URITRACK_get_tracking_status (ectx, cfg))    return;  cpc.present = 0;  cpc.fi = fi;  GNUNET_URITRACK_list (ectx, cfg, GNUNET_NO, &checkPresent, &cpc);  if (cpc.present == 1)    return;  size = GNUNET_meta_data_get_serialized_size (fi->meta,                                               GNUNET_SERIALIZE_FULL                                               |                                               GNUNET_SERIALIZE_NO_COMPRESS);  data = GNUNET_malloc (size);  GNUNET_GE_ASSERT (ectx,                    size == GNUNET_meta_data_serialize (ectx,                                                        fi->meta,                                                        data,                                                        size,                                                        GNUNET_SERIALIZE_FULL                                                        |                                                        GNUNET_SERIALIZE_NO_COMPRESS));  size = htonl (size);  suri = GNUNET_ECRS_uri_to_string (fi->uri);  sem = createIPC (ectx, cfg);  GNUNET_IPC_semaphore_down (sem, GNUNET_YES);  fn = getUriDbName (ectx, cfg);  fh = GNUNET_disk_file_open (ectx,                              fn,                              O_WRONLY | O_APPEND | O_CREAT |                              O_LARGEFILE, S_IRUSR | S_IWUSR);  if (fh != -1)    {      WRITE (fh, suri, strlen (suri) + 1);      WRITE (fh, &size, sizeof (unsigned int));      WRITE (fh, data, ntohl (size));      CLOSE (fh);    }  GNUNET_free (fn);  GNUNET_IPC_semaphore_up (sem);  GNUNET_IPC_semaphore_destroy (sem);  GNUNET_free (data);  GNUNET_free (suri);  GNUNET_URITRACK_internal_notify (fi);}/** * Remove all of the root-nodes of a particular type * from the tracking database. */voidGNUNET_URITRACK_clear (struct GNUNET_GE_Context *ectx,                       struct GNUNET_GC_Configuration *cfg){  struct GNUNET_IPC_Semaphore *sem;  char *fn;  sem = createIPC (ectx, cfg);  GNUNET_IPC_semaphore_down (sem, GNUNET_YES);  fn = getUriDbName (ectx, cfg);  if (GNUNET_YES == GNUNET_disk_file_test (ectx, fn))    {      if (0 != UNLINK (fn))        GNUNET_GE_LOG_STRERROR_FILE (ectx,                                     GNUNET_GE_ERROR | GNUNET_GE_USER |                                     GNUNET_GE_ADMIN | GNUNET_GE_BULK,                                     "unlink", fn);    }  GNUNET_free (fn);  GNUNET_IPC_semaphore_up (sem);  GNUNET_IPC_semaphore_destroy (sem);}/** * Toggle tracking URIs. * * @param onOff GNUNET_YES to enable tracking, GNUNET_NO to disable *  disabling tracking */voidGNUNET_URITRACK_toggle_tracking (struct GNUNET_GE_Context *ectx,                                 struct GNUNET_GC_Configuration *cfg,                                 int onOff){  int o = htonl (onOff);  char *tn;  tn = getToggleName (ectx, cfg);  GNUNET_disk_file_write (ectx, tn, &o, sizeof (int), "600");  GNUNET_free (tn);}/** * Iterate over all entries that match the given context * mask. * * @param iterator function to call on each entry, may be NULL * @param closure extra argument to the callback * @param need_metadata GNUNET_YES if metadata should be *        provided, GNUNET_NO if metadata is not needed (faster) * @return number of entries found */intGNUNET_URITRACK_list (struct GNUNET_GE_Context *ectx,                      struct GNUNET_GC_Configuration *cfg,                      int need_metadata,                      GNUNET_ECRS_SearchResultProcessor iterator,                      void *closure){  struct GNUNET_IPC_Semaphore *sem;  int rval;  char *result;  off_t ret;  off_t pos;  off_t spos;  unsigned int msize;  GNUNET_ECRS_FileInfo fi;  int fd;  char *fn;  struct stat buf;  fn = getUriDbName (ectx, cfg);  sem = createIPC (ectx, cfg);  GNUNET_IPC_semaphore_down (sem, GNUNET_YES);  if ((0 != STAT (fn, &buf)) || (buf.st_size == 0))    {      GNUNET_IPC_semaphore_up (sem);      GNUNET_IPC_semaphore_destroy (sem);      GNUNET_free (fn);      return 0;                 /* no URI db */    }  fd = GNUNET_disk_file_open (ectx, fn, O_LARGEFILE | O_RDONLY);  if (fd == -1)    {      GNUNET_IPC_semaphore_up (sem);      GNUNET_IPC_semaphore_destroy (sem);      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_ERROR | GNUNET_GE_USER |                                   GNUNET_GE_ADMIN | GNUNET_GE_BULK, "open",                                   fn);      GNUNET_free (fn);      return GNUNET_SYSERR;     /* error opening URI db */    }  result = MMAP (NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);  if (result == MAP_FAILED)    {      CLOSE (fd);      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_ERROR | GNUNET_GE_USER |                                   GNUNET_GE_ADMIN | GNUNET_GE_BULK, "mmap",                                   fn);      GNUNET_free (fn);      GNUNET_IPC_semaphore_up (sem);      GNUNET_IPC_semaphore_destroy (sem);      return GNUNET_SYSERR;    }  ret = buf.st_size;  pos = 0;  rval = 0;  while (pos < ret)    {      spos = pos;      while ((spos < ret) && (result[spos] != '\0'))        spos++;      spos++;                   /* skip '\0' */      if (spos + sizeof (int) >= ret)        {          GNUNET_GE_BREAK (ectx, 0);          goto FORMATERROR;        }      fi.uri = GNUNET_ECRS_string_to_uri (ectx, &result[pos]);      if (fi.uri == NULL)        {          GNUNET_GE_BREAK (ectx, 0);          goto FORMATERROR;        }      memcpy (&msize, &result[spos], sizeof (int));      msize = ntohl (msize);      spos += sizeof (int);      if ((spos + msize > ret) || (spos + msize < spos))        {          GNUNET_GE_BREAK (ectx, 0);          GNUNET_ECRS_uri_destroy (fi.uri);          goto FORMATERROR;        }      if (need_metadata == GNUNET_YES)        {          fi.meta = GNUNET_meta_data_deserialize (ectx, &result[spos], msize);          if (fi.meta == NULL)            {              GNUNET_GE_BREAK (ectx, 0);              GNUNET_ECRS_uri_destroy (fi.uri);              goto FORMATERROR;            }        }      else        {          fi.meta = NULL;        }      pos = spos + msize;      if (iterator != NULL)        {          if (GNUNET_OK != iterator (&fi, NULL, GNUNET_NO, closure))            {              if (fi.meta != NULL)                GNUNET_meta_data_destroy (fi.meta);              GNUNET_ECRS_uri_destroy (fi.uri);              if (0 != MUNMAP (result, buf.st_size))                GNUNET_GE_LOG_STRERROR_FILE (ectx,                                             GNUNET_GE_ERROR | GNUNET_GE_ADMIN                                             | GNUNET_GE_BULK, "munmap", fn);              CLOSE (fd);              GNUNET_free (fn);              GNUNET_IPC_semaphore_up (sem);              GNUNET_IPC_semaphore_destroy (sem);              return GNUNET_SYSERR;     /* iteration aborted */            }        }      rval++;      if (fi.meta != NULL)        GNUNET_meta_data_destroy (fi.meta);      GNUNET_ECRS_uri_destroy (fi.uri);    }  if (0 != MUNMAP (result, buf.st_size))    GNUNET_GE_LOG_STRERROR_FILE (ectx,                                 GNUNET_GE_ERROR | GNUNET_GE_ADMIN |                                 GNUNET_GE_BULK, "munmap", fn);  CLOSE (fd);  GNUNET_free (fn);  GNUNET_IPC_semaphore_up (sem);  GNUNET_IPC_semaphore_destroy (sem);  return rval;FORMATERROR:  GNUNET_GE_LOG (ectx,                 GNUNET_GE_WARNING | GNUNET_GE_BULK | GNUNET_GE_USER,                 _("Deleted corrupt URI database in `%s'."), STATE_NAME);  if (0 != MUNMAP (result, buf.st_size))    GNUNET_GE_LOG_STRERROR_FILE (ectx,                                 GNUNET_GE_ERROR | GNUNET_GE_ADMIN |                                 GNUNET_GE_BULK, "munmap", fn);  CLOSE (fd);  GNUNET_free (fn);  GNUNET_IPC_semaphore_up (sem);  GNUNET_IPC_semaphore_destroy (sem);  GNUNET_URITRACK_clear (ectx, cfg);  return GNUNET_SYSERR;}/* end of file_info.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -