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

📄 unindex.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/ecrs/unindex.c * @author Krista Bennett * @author Christian Grothoff * * Unindex file. * * TODO: * - code cleanup (share more with upload.c) */#include "platform.h"#include "gnunet_protocols.h"#include "gnunet_ecrs_lib.h"#include "gnunet_fs_lib.h"#include "gnunet_getoption_lib.h"#include "ecrs_core.h"#include "ecrs.h"#include "fs.h"#include "tree.h"#define STRICT_CHECKS GNUNET_NO/** * Append the given key and query to the iblock[level]. * If iblock[level] is already full, compute its chk * and push it to level+1.  iblocks is guaranteed to * be big enough. * * This function matches exactly upload.c::pushBlock, * except in the call to 'GNUNET_FS_delete'.  TODO: refactor * to avoid code duplication (move to block.c, pass * GNUNET_FS_delete as argument!). */static intpushBlock (struct GNUNET_ClientServerConnection *sock,           const GNUNET_EC_ContentHashKey * chk, unsigned int level,           GNUNET_DatastoreValue ** iblocks){  unsigned int size;  unsigned int present;  GNUNET_DatastoreValue *value;  GNUNET_EC_DBlock *db;  GNUNET_EC_ContentHashKey ichk;  size = ntohl (iblocks[level]->size) - sizeof (GNUNET_DatastoreValue);  present =    (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey);  db = (GNUNET_EC_DBlock *) & iblocks[level][1];  if (present == GNUNET_ECRS_CHK_PER_INODE)    {      GNUNET_EC_file_block_get_key (db, size, &ichk.key);      GNUNET_EC_file_block_get_query (db, size, &ichk.query);      if (GNUNET_OK != pushBlock (sock, &ichk, level + 1, iblocks))        {          GNUNET_GE_BREAK (NULL, 0);          return GNUNET_SYSERR;        }      GNUNET_EC_file_block_encode (db, size, &ichk.query, &value);#if STRICT_CHECKS      if (GNUNET_SYSERR == GNUNET_FS_delete (sock, value))        {          GNUNET_free (value);          GNUNET_GE_BREAK (NULL, 0);          return GNUNET_SYSERR;        }#else      GNUNET_FS_delete (sock, value);#endif      GNUNET_free (value);      size = sizeof (GNUNET_EC_DBlock);    }  /* append GNUNET_EC_ContentHashKey */  memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey));  iblocks[level]->size = htonl (size +                                sizeof (GNUNET_EC_ContentHashKey) +                                sizeof (GNUNET_DatastoreValue));  return GNUNET_OK;}/** * Undo sym-linking operation: * a) check if we have a symlink * b) delete symbolic link */static intundoSymlinking (struct GNUNET_GE_Context *ectx,                const char *fn,                const GNUNET_HashCode * fileId,                struct GNUNET_ClientServerConnection *sock){  GNUNET_EncName enc;  char *serverDir;  char *serverFN;  struct stat buf;#ifndef S_ISLNK  if (1)    return GNUNET_OK;           /* symlinks do not exist? */#endif  if (0 != LSTAT (fn, &buf))    {      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_ERROR | GNUNET_GE_BULK |                                   GNUNET_GE_USER | GNUNET_GE_ADMIN, "stat",                                   fn);      return GNUNET_SYSERR;    }#ifdef S_ISLNK  if (!S_ISLNK (buf.st_mode))    return GNUNET_OK;#endif  serverDir =    GNUNET_get_daemon_configuration_value (sock, "FS", "INDEX-DIRECTORY");  if (serverDir == NULL)    return GNUNET_OK;  serverFN = GNUNET_malloc (strlen (serverDir) + 2 + sizeof (GNUNET_EncName));  strcpy (serverFN, serverDir);  GNUNET_free (serverDir);  if (serverFN[strlen (serverFN) - 1] != DIR_SEPARATOR)    strcat (serverFN, DIR_SEPARATOR_STR);  GNUNET_hash_to_enc (fileId, &enc);  strcat (serverFN, (char *) &enc);  if (0 != UNLINK (serverFN))    {      GNUNET_GE_LOG_STRERROR_FILE (ectx,                                   GNUNET_GE_ERROR | GNUNET_GE_BULK |                                   GNUNET_GE_USER | GNUNET_GE_ADMIN, "unlink",                                   serverFN);      GNUNET_free (serverFN);      return GNUNET_SYSERR;    }  GNUNET_free (serverFN);  return GNUNET_OK;}/** * Unindex a file. * * @return GNUNET_SYSERR if the unindexing failed (i.e. not indexed) */intGNUNET_ECRS_file_unindex (struct GNUNET_GE_Context *ectx,                          struct GNUNET_GC_Configuration *cfg,                          const char *filename,                          GNUNET_ECRS_UploadProgressCallback upcb,                          void *upcbClosure, GNUNET_ECRS_TestTerminate tt,                          void *ttClosure){  unsigned long long filesize;  unsigned long long pos;  unsigned int treedepth;  int fd;  int i;  unsigned int size;  GNUNET_DatastoreValue **iblocks;  GNUNET_DatastoreValue *dblock;  GNUNET_EC_DBlock *db;  GNUNET_DatastoreValue *value;  struct GNUNET_ClientServerConnection *sock;  GNUNET_HashCode fileId;  GNUNET_EC_ContentHashKey chk;  GNUNET_CronTime eta;  GNUNET_CronTime start;  GNUNET_CronTime now;  int wasIndexed;  start = GNUNET_get_time ();  if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename))    {      GNUNET_GE_BREAK (ectx, 0);      return GNUNET_SYSERR;    }  if (GNUNET_OK !=      GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES))    return GNUNET_SYSERR;  sock = GNUNET_client_connection_create (ectx, cfg);  if (sock == NULL)    return GNUNET_SYSERR;  eta = 0;  if (upcb != NULL)    upcb (filesize, 0, eta, upcbClosure);  if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId))    {      GNUNET_client_connection_destroy (sock);      GNUNET_GE_BREAK (ectx, 0);      return GNUNET_SYSERR;    }  now = GNUNET_get_time ();  eta = now + 2 * (now - start);  /* very rough estimate: GNUNET_hash reads once through the file,     we'll do that once more and write it.  But of course     the second read may be cached, and we have the encryption,     so a factor of two is really, really just a rough estimate */  start = now;  /* reset the counter since the formula later does not     take the time for GNUNET_hash_file into account */  treedepth = GNUNET_ECRS_compute_depth (filesize);  /* Test if file is indexed! */  wasIndexed = GNUNET_FS_test_indexed (sock, &fileId);  fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);  if (fd == -1)    {      GNUNET_client_connection_destroy (sock);      return GNUNET_SYSERR;    }  dblock =    GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +                   sizeof (GNUNET_EC_DBlock));  dblock->size =    htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +           sizeof (GNUNET_EC_DBlock));  dblock->anonymity_level = htonl (0);  dblock->priority = htonl (0);  dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);  dblock->expiration_time = GNUNET_htonll (0);  db = (GNUNET_EC_DBlock *) & dblock[1];  db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);  iblocks =    GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1));  for (i = 0; i <= treedepth; i++)    {      iblocks[i] =        GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +                       GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock));      iblocks[i]->size =        htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock));      iblocks[i]->anonymity_level = htonl (0);      iblocks[i]->priority = htonl (0);      iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);      iblocks[i]->expiration_time = GNUNET_htonll (0);      ((GNUNET_EC_DBlock *) & iblocks[i][1])->type =        htonl (GNUNET_ECRS_BLOCKTYPE_DATA);    }  pos = 0;  while (pos < filesize)    {      if (upcb != NULL)        upcb (filesize, pos, eta, upcbClosure);      if (tt != NULL)        if (GNUNET_OK != tt (ttClosure))          goto FAILURE;      size = GNUNET_ECRS_DBLOCK_SIZE;      if (size > filesize - pos)        {          size = filesize - pos;          memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE);        }      dblock->size =        htonl (sizeof (GNUNET_DatastoreValue) + size +               sizeof (GNUNET_EC_DBlock));      if (size != READ (fd, &db[1], size))        {          GNUNET_GE_LOG_STRERROR_FILE (ectx,                                       GNUNET_GE_ERROR | GNUNET_GE_USER |                                       GNUNET_GE_ADMIN | GNUNET_GE_BULK,                                       "READ", filename);          goto FAILURE;        }      if (tt != NULL)        if (GNUNET_OK != tt (ttClosure))          goto FAILURE;      GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock),                                    &chk.key);      GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock),                                      &chk.query);      if (GNUNET_OK != pushBlock (sock, &chk, 0,        /* dblocks are on level 0 */                                  iblocks))        {          GNUNET_GE_BREAK (ectx, 0);          goto FAILURE;        }      if (!wasIndexed)        {          if (GNUNET_OK ==              GNUNET_EC_file_block_encode (db, size, &chk.query, &value))            {              *value = *dblock; /* copy options! */#if STRICT_CHECKS              if (GNUNET_OK != GNUNET_FS_delete (sock, value))                {                  GNUNET_free (value);                  GNUNET_GE_BREAK (ectx, 0);                  goto FAILURE;                }#else              GNUNET_FS_delete (sock, value);#endif              GNUNET_free (value);            }          else            {              goto FAILURE;            }        }      pos += size;      now = GNUNET_get_time ();      eta = (GNUNET_CronTime) (start +                               (((double) (now - start) / (double) pos))                               * (double) filesize);    }  if (tt != NULL)    if (GNUNET_OK != tt (ttClosure))      goto FAILURE;  for (i = 0; i < treedepth; i++)    {      size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue);      db = (GNUNET_EC_DBlock *) & iblocks[i][1];      GNUNET_EC_file_block_get_key (db, size, &chk.key);      GNUNET_EC_file_block_get_query (db, size, &chk.query);      if (GNUNET_OK != pushBlock (sock, &chk, i + 1, iblocks))        {          GNUNET_GE_BREAK (ectx, 0);          goto FAILURE;        }      GNUNET_EC_file_block_encode (db, size, &chk.query, &value);#if STRICT_CHECKS      if (GNUNET_OK != GNUNET_FS_delete (sock, value))        {          GNUNET_free (value);          GNUNET_GE_BREAK (ectx, 0);          goto FAILURE;        }#else      GNUNET_FS_delete (sock, value);#endif      GNUNET_free (value);      GNUNET_free (iblocks[i]);      iblocks[i] = NULL;    }  if (wasIndexed)    {      if (GNUNET_OK == undoSymlinking (ectx, filename, &fileId, sock))        {          if (GNUNET_OK !=              GNUNET_FS_unindex (sock, GNUNET_ECRS_DBLOCK_SIZE, &fileId))            {              GNUNET_GE_BREAK (ectx, 0);              goto FAILURE;            }        }      else        {          GNUNET_GE_BREAK (ectx, 0);          goto FAILURE;        }    }  GNUNET_free (iblocks[treedepth]);  /* free resources */  GNUNET_free (iblocks);  GNUNET_free (dblock);  CLOSE (fd);  GNUNET_client_connection_destroy (sock);  return GNUNET_OK;FAILURE:  for (i = 0; i <= treedepth; i++)    GNUNET_free_non_null (iblocks[i]);  GNUNET_free (iblocks);  GNUNET_free (dblock);  CLOSE (fd);  GNUNET_client_connection_destroy (sock);  return GNUNET_SYSERR;}/* end of unindex.c */

⌨️ 快捷键说明

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