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

📄 download.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     This file is part of GNUnet.     (C) 2001, 2002, 2003, 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/download.c * @brief download functions * @author Krista Bennett * @author Christian Grothoff */#include "platform.h"#include "gnunet_util.h"#include "gnunet_ecrs_lib.h"#include "gnunet_uritrack_lib.h"#include "gnunet_fsui_lib.h"#include "fsui.h"#define DEBUG_DTM GNUNET_NO/** * Mark the given URI as found in a directory * in URITRACK. */static intlistURIfoundDirectory (const GNUNET_ECRS_FileInfo * fi,                       const GNUNET_HashCode * key, int isRoot, void *prnt){  GNUNET_FSUI_DownloadList *dl = prnt;  if (isRoot == GNUNET_YES)    return GNUNET_OK;           /* namespace ad, ignore */  GNUNET_URITRACK_add_state (dl->ctx->ectx,                             dl->ctx->cfg, fi->uri,                             GNUNET_URITRACK_DIRECTORY_FOUND);  return GNUNET_OK;}/** * Start to download a file. */static GNUNET_FSUI_DownloadList *startDownload (struct GNUNET_FSUI_Context                                                *ctx,                                                unsigned int anonymityLevel,                                                int is_recursive,                                                const struct GNUNET_ECRS_URI                                                *uri,                                                const struct                                                GNUNET_MetaData *meta,                                                const char *filename,                                                struct GNUNET_FSUI_SearchList                                                *psearch,                                                GNUNET_FSUI_DownloadList *                                                parent);/** * Initiate a (recursive) download of the given * directory entry. */static inttriggerRecursiveDownload (const GNUNET_ECRS_FileInfo * fi,                          const GNUNET_HashCode * key, int isRoot, void *prnt){  GNUNET_FSUI_DownloadList *parent = prnt;  struct GNUNET_GE_Context *ectx;  int i;  GNUNET_FSUI_DownloadList *pos;  char *filename;  char *fullName;  char *dotdot;  ectx = parent->ctx->ectx;  if (isRoot == GNUNET_YES)    return GNUNET_OK;           /* namespace ad, ignore */  GNUNET_URITRACK_track (ectx, parent->ctx->cfg, fi);  for (i = 0; i < parent->completedDownloadsCount; i++)    if (GNUNET_ECRS_uri_test_equal (parent->completedDownloads[i], fi->uri))      return GNUNET_OK;         /* already complete! */  pos = parent->child;  while (pos != NULL)    {      if (GNUNET_ECRS_uri_test_equal (pos->fi.uri, fi->uri))        return GNUNET_OK;       /* already downloading */      pos = pos->next;    }  filename = GNUNET_meta_data_get_by_type (fi->meta, EXTRACTOR_FILENAME);  if (filename == NULL)    {      char *tmp = GNUNET_ECRS_uri_to_string (fi->uri);      GNUNET_GE_ASSERT (ectx,                        strlen (tmp) >=                        strlen (GNUNET_ECRS_URI_PREFIX) +                        strlen (GNUNET_ECRS_FILE_INFIX));      filename =        GNUNET_strdup (&tmp                       [strlen (GNUNET_ECRS_URI_PREFIX) +                        strlen (GNUNET_ECRS_FILE_INFIX)]);      GNUNET_free (tmp);    }  fullName =    GNUNET_malloc (strlen (parent->filename) + 2 + strlen (filename));  strcpy (fullName, parent->filename);  strcat (fullName, filename);  while (NULL != (dotdot = strstr (fullName, "..")))    dotdot[0] = dotdot[1] = '_';  GNUNET_free (filename);#if DEBUG_DTM  GNUNET_GE_LOG (ectx,                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,                 "Starting recursive download of `%s'\n", fullName);#endif  startDownload (parent->ctx,                 parent->anonymityLevel,                 GNUNET_YES, fi->uri, fi->meta, fullName, parent->search,                 parent);  GNUNET_free (fullName);  return GNUNET_OK;}/** * Trigger recursive download. */static voiddownload_recursive (GNUNET_FSUI_DownloadList * dl){  char *dirBlock;  int fd;  char *fn;  size_t totalBytes;  struct GNUNET_MetaData *md;  totalBytes = GNUNET_ECRS_uri_get_file_size (dl->fi.uri);  fn =    GNUNET_malloc (strlen (dl->filename) + strlen (GNUNET_DIRECTORY_EXT) + 1);  strcpy (fn, dl->filename);  fd = strlen (fn) - 1;  if (fn[fd] == '/' || fn[fd] == '\\')    {      fn[fd] = '\0';      strcat (fn, GNUNET_DIRECTORY_EXT);    }  fd = GNUNET_disk_file_open (dl->ctx->ectx, fn, O_LARGEFILE | O_RDONLY);  if (fd != -1)    {      dirBlock = MMAP (NULL, totalBytes, PROT_READ, MAP_SHARED, fd, 0);      if (MAP_FAILED == dirBlock)        {          GNUNET_GE_LOG_STRERROR_FILE (dl->ctx->ectx,                                       GNUNET_GE_ERROR | GNUNET_GE_BULK |                                       GNUNET_GE_ADMIN | GNUNET_GE_USER,                                       "mmap", fn);        }      else        {          md = NULL;          GNUNET_ECRS_directory_list_contents (dl->ctx->ectx,                                               dirBlock,                                               totalBytes,                                               &md,                                               &listURIfoundDirectory, dl);          if (md != NULL)            GNUNET_meta_data_destroy (md);          if (dl->is_recursive)            {              int n;              /* load directory, start downloads */              md = NULL;              GNUNET_mutex_lock (dl->ctx->lock);              n = GNUNET_ECRS_directory_list_contents (dl->ctx->ectx,                                                       dirBlock,                                                       totalBytes,                                                       &md,                                                       &triggerRecursiveDownload,                                                       dl);              GNUNET_mutex_unlock (dl->ctx->lock);              if (n == 0)                GNUNET_disk_directory_create (dl->ctx->ectx, dl->filename);              GNUNET_meta_data_destroy (md);              MUNMAP (dirBlock, totalBytes);            }        }      CLOSE (fd);    }  GNUNET_free (fn);}/** * Update the progress bits (shifting). */static voidupdate_progress_bits(GNUNET_CronTime now,		     GNUNET_FSUI_DownloadList * dl){  GNUNET_CronTime delta;  unsigned int minutes;  if (now < dl->lastProgressTime)    {      GNUNET_GE_BREAK(NULL, 0);      return;    }  delta = now - dl->lastProgressTime;  minutes = delta / GNUNET_CRON_MINUTES;  if (minutes == 0)    return;  if (minutes > 64)    {      dl->progressBits = 0;      dl->lastProgressTime = now;      return;    }  dl->progressBits <<= minutes;  if (dl->progressBits == 0)    dl->lastProgressTime = now;  else    dl->lastProgressTime += minutes * GNUNET_CRON_MINUTES;}/** * Progress notification from ECRS.  Tell FSUI client. */static voiddownloadProgressCallback (unsigned long long totalBytes,                          unsigned long long completedBytes,                          GNUNET_CronTime eta,                          unsigned long long lastBlockOffset,                          const char *lastBlock,                          unsigned int lastBlockSize, void *cls){  GNUNET_FSUI_DownloadList *dl = cls;  GNUNET_FSUI_Event event;  GNUNET_CronTime now;  GNUNET_CronTime run_time;  now = GNUNET_get_time ();  update_progress_bits(now, dl);  dl->progressBits |= 1;  if (dl->total + 1 == totalBytes)    {      /* error! */      dl->state = GNUNET_FSUI_ERROR;      event.type = GNUNET_FSUI_download_error;      event.data.DownloadError.dc.pos = dl;      event.data.DownloadError.dc.cctx = dl->cctx;      event.data.DownloadError.dc.ppos =        dl->parent == &dl->ctx->activeDownloads ? NULL : dl->parent;      event.data.DownloadError.dc.pcctx = dl->parent->cctx;      event.data.DownloadError.dc.spos = dl->search;      event.data.DownloadError.dc.sctx =        dl->search == NULL ? NULL : dl->search->cctx;      event.data.DownloadError.message = lastBlock;      GNUNET_URITRACK_add_state (dl->ctx->ectx,                                 dl->ctx->cfg, dl->fi.uri,                                 GNUNET_URITRACK_DOWNLOAD_ABORTED);      dl->ctx->ecb (dl->ctx->ecbClosure, &event);      return;    }  GNUNET_GE_ASSERT (dl->ctx->ectx, dl->total == totalBytes);  dl->completed = completedBytes;  event.type = GNUNET_FSUI_download_progress;  event.data.DownloadProgress.dc.pos = dl;  event.data.DownloadProgress.dc.cctx = dl->cctx;  event.data.DownloadProgress.dc.ppos =    dl->parent == &dl->ctx->activeDownloads ? NULL : dl->parent;  event.data.DownloadProgress.dc.pcctx = dl->parent->cctx;  event.data.DownloadProgress.dc.spos = dl->search;  event.data.DownloadProgress.dc.sctx =    dl->search == NULL ? NULL : dl->search->cctx;  event.data.DownloadProgress.completed = dl->completed;  event.data.DownloadProgress.total = dl->total;  event.data.DownloadProgress.last_offset = lastBlockOffset;  run_time = now - dl->startTime;  if ((dl->total == 0) || (dl->completed == 0))    {      eta = now;    }  else    {      eta = (GNUNET_CronTime) (dl->startTime +                               (((double) (run_time) /                                 (double) dl->completed)) *                               (double) dl->total);      if (eta < now)        eta = now;    }  event.data.DownloadProgress.eta = eta;  event.data.DownloadProgress.filename = dl->filename;  event.data.DownloadProgress.uri = dl->fi.uri;  event.data.DownloadProgress.last_block = lastBlock;  event.data.DownloadProgress.last_size = lastBlockSize;  dl->ctx->ecb (dl->ctx->ecbClosure, &event);  if ((lastBlockOffset == 0) && (dl->is_directory == GNUNET_SYSERR))    {      /* check if this is a directory */      if ((dl->filename[strlen (dl->filename) - 1] == '/') &&          (lastBlockSize > strlen (GNUNET_DIRECTORY_MAGIC)) &&          (0 == strncmp (GNUNET_DIRECTORY_MAGIC,                         lastBlock, strlen (GNUNET_DIRECTORY_MAGIC))))        dl->is_directory = GNUNET_YES;      else        dl->is_directory = GNUNET_NO;    }  if (totalBytes == completedBytes)    {      dl->state = GNUNET_FSUI_COMPLETED;      GNUNET_URITRACK_add_state (dl->ctx->ectx,                                 dl->ctx->cfg,                                 dl->fi.uri,                                 GNUNET_URITRACK_DOWNLOAD_COMPLETED);    }}/** * Start to download a file. */static GNUNET_FSUI_DownloadList *startDownload (struct GNUNET_FSUI_Context *ctx,               unsigned int anonymityLevel,               int is_recursive,               const struct GNUNET_ECRS_URI *uri,               const struct GNUNET_MetaData *meta,               const char *filename,               struct GNUNET_FSUI_SearchList *psearch,               GNUNET_FSUI_DownloadList * parent){  GNUNET_FSUI_DownloadList *dl;  GNUNET_FSUI_Event event;  GNUNET_GE_ASSERT (NULL, ctx != NULL);  GNUNET_GE_ASSERT (NULL, parent != NULL);  if (!(GNUNET_ECRS_uri_test_chk (uri) || GNUNET_ECRS_uri_test_loc (uri)))    {      GNUNET_GE_BREAK (NULL, 0);        /* wrong type of URI! */      return NULL;    }  dl = GNUNET_malloc (sizeof (GNUNET_FSUI_DownloadList));  memset (dl, 0, sizeof (GNUNET_FSUI_DownloadList));  dl->startTime = 0;            /* not run at all so far! */  dl->runTime = 0;              /* not run at all so far! */  dl->state = GNUNET_FSUI_PENDING;  dl->is_recursive = is_recursive;  dl->parent = parent;  dl->search = psearch;  dl->is_directory = GNUNET_SYSERR;     /* don't know */  dl->anonymityLevel = anonymityLevel;  dl->ctx = ctx;  dl->filename = GNUNET_strdup (filename);  dl->fi.uri = GNUNET_ECRS_uri_duplicate (uri);  dl->fi.meta = GNUNET_meta_data_duplicate (meta);  dl->total = GNUNET_ECRS_uri_get_file_size (uri);  dl->child = NULL;  dl->cctx = NULL;  dl->lastProgressTime = GNUNET_get_time();  dl->progressBits = 1;  /* signal start! */  event.type = GNUNET_FSUI_download_started;  event.data.DownloadStarted.dc.pos = dl;  event.data.DownloadStarted.dc.cctx = NULL;  event.data.DownloadStarted.dc.ppos =    dl->parent == &ctx->activeDownloads ? NULL : dl->parent;  event.data.DownloadStarted.dc.pcctx = dl->parent->cctx;  event.data.DownloadStarted.dc.spos = dl->search;  event.data.DownloadStarted.dc.sctx =    dl->search == NULL ? NULL : dl->search->cctx;  event.data.DownloadStarted.total =

⌨️ 快捷键说明

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