📄 upload.c
字号:
/* This file is part of GNUnet. (C) 2001, 2002, 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/fsui/upload.c * @brief upload 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 "gnunet_identity_lib.h"#include "fsui.h"#include <extractor.h>#define DEBUG_UPLOAD GNUNET_NO/** * Transform an ECRS progress callback into an FSUI event. * * @param direct is this a direct ECRS trigger, or a recursive * call from a child signaling progress to the parent? */static voidprogressCallbackR (unsigned long long totalBytes, unsigned long long completedBytes, GNUNET_CronTime eta, void *ptr, int direct, int add, int unaccounted){ GNUNET_FSUI_UploadList *utc = ptr; GNUNET_FSUI_Event event; unsigned long long subtotal; GNUNET_FSUI_UploadList *pos; GNUNET_CronTime xeta; GNUNET_CronTime now; event.type = GNUNET_FSUI_upload_progress; event.data.UploadProgress.uc.pos = utc; event.data.UploadProgress.uc.cctx = utc->cctx; event.data.UploadProgress.uc.ppos = utc->parent; event.data.UploadProgress.uc.pcctx = utc->parent->cctx; if (GNUNET_YES == GNUNET_meta_data_test_for_directory (utc->meta)) { if (direct == GNUNET_YES) unaccounted = GNUNET_YES; if ((direct == GNUNET_YES) && (totalBytes == completedBytes)) add = GNUNET_YES; if (add == GNUNET_NO) { event.data.UploadProgress.completed = completedBytes + utc->completed; event.data.UploadProgress.total = utc->total + ((unaccounted == GNUNET_NO) ? 0 : totalBytes); if (totalBytes == completedBytes) utc->completed += completedBytes; } else { GNUNET_GE_ASSERT (NULL, totalBytes == completedBytes); event.data.UploadProgress.completed = completedBytes + utc->completed; event.data.UploadProgress.total = totalBytes + utc->total; utc->total += completedBytes; utc->completed += completedBytes; } } else { /* simple file upload */ event.data.UploadProgress.completed = completedBytes; event.data.UploadProgress.total = totalBytes; utc->completed = completedBytes; } event.data.UploadProgress.eta = eta; event.data.UploadProgress.filename = utc->filename; utc->shared->ctx->ecb (utc->shared->ctx->ecbClosure, &event); if (utc->parent != &utc->shared->ctx->activeUploads) { subtotal = 0; pos = utc->parent->child; while (pos != NULL) { subtotal += pos->completed; pos = pos->next; } now = GNUNET_get_time (); xeta = now; if (subtotal > 0) { xeta = (GNUNET_CronTime) (utc->parent->start_time + (((double) (now - utc->parent->start_time) / (double) subtotal)) * (double) utc->parent->total); } progressCallbackR (totalBytes, completedBytes, xeta, utc->parent, GNUNET_NO, add, unaccounted); }}/** * Transform an ECRS progress callback into an FSUI event. */static voidprogressCallback (unsigned long long totalBytes, unsigned long long completedBytes, GNUNET_CronTime eta, void *ptr){ progressCallbackR (totalBytes, completedBytes, eta, ptr, GNUNET_YES, GNUNET_NO, GNUNET_NO);}static inttestTerminate (void *cls){ GNUNET_FSUI_UploadList *utc = cls; if (utc->state != GNUNET_FSUI_ACTIVE) return GNUNET_SYSERR; return GNUNET_OK;}/** * Take the current directory entries from utc, create * a directory, upload it and store the uri in *uri. */static char *createDirectoryHelper (struct GNUNET_GE_Context *ectx, struct GNUNET_GC_Configuration *cfg, struct GNUNET_FSUI_UploadList *children, struct GNUNET_MetaData *meta, char **error){ GNUNET_ECRS_FileInfo *fis; unsigned int count; unsigned int size; char *data; unsigned long long len; int ret; char *tempName; struct GNUNET_FSUI_UploadList *pos; int handle; struct GNUNET_GE_Memory *mem; struct GNUNET_GE_Context *ee; fis = NULL; size = 0; count = 0; pos = children; while (pos != NULL) { if (pos->uri != NULL) count++; pos = pos->next; } GNUNET_array_grow (fis, size, count); count = 0; pos = children; while (pos != NULL) { if (pos->uri != NULL) { fis[count].uri = pos->uri; fis[count].meta = pos->meta; count++; } pos = pos->next; } GNUNET_GE_BREAK (ectx, count == size); mem = GNUNET_GE_memory_create (2); ee = GNUNET_GE_create_context_memory (GNUNET_GE_USER | GNUNET_GE_ADMIN | GNUNET_GE_ERROR | GNUNET_GE_WARNING | GNUNET_GE_FATAL | GNUNET_GE_BULK | GNUNET_GE_IMMEDIATE, mem); ret = GNUNET_ECRS_directory_create (ee, &data, &len, size, fis, meta); GNUNET_array_grow (fis, size, 0); if (ret != GNUNET_OK) { *error = GNUNET_strdup (GNUNET_GE_memory_get (mem, 0)); GNUNET_GE_free_context (ee); GNUNET_GE_memory_free (mem); return NULL; } pos = children; while (pos != NULL) { if (pos->uri != NULL) GNUNET_URITRACK_add_state (ectx, cfg, pos->uri, GNUNET_URITRACK_DIRECTORY_ADDED); pos = pos->next; } GNUNET_GE_memory_reset (mem); tempName = GNUNET_strdup ("/tmp/gnunet-upload-dir.XXXXXX"); handle = mkstemp (tempName); if (handle == -1) { GNUNET_GE_LOG_STRERROR_FILE (ee, GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_BULK, "mkstemp", tempName); GNUNET_free (tempName); GNUNET_free (data); *error = GNUNET_strdup (GNUNET_GE_memory_get (mem, 0)); GNUNET_GE_free_context (ee); GNUNET_GE_memory_free (mem); return NULL; } if (len != WRITE (handle, data, len)) { GNUNET_GE_LOG_STRERROR_FILE (ee, GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_BULK, "write", tempName); *error = GNUNET_strdup (GNUNET_GE_memory_get (mem, 0)); GNUNET_GE_free_context (ee); GNUNET_GE_memory_free (mem); GNUNET_free (data); return NULL; } GNUNET_GE_free_context (ee); GNUNET_GE_memory_free (mem); CLOSE (handle); GNUNET_free (data); return tempName;}/** * Signal upload error to client. */static voidsignalError (GNUNET_FSUI_UploadList * utc, const char *message){ GNUNET_FSUI_Event event; utc->state = GNUNET_FSUI_ERROR; event.type = GNUNET_FSUI_upload_error; event.data.UploadError.uc.pos = utc; event.data.UploadError.uc.cctx = utc->cctx; event.data.UploadError.uc.ppos = utc->parent; event.data.UploadError.uc.pcctx = utc->parent->cctx; event.data.UploadError.message = message; utc->shared->ctx->ecb (utc->shared->ctx->ecbClosure, &event);}static voidsignalUploadStarted (struct GNUNET_FSUI_UploadList *utc, int first_only){ GNUNET_FSUI_Event event; while (utc != NULL) { event.type = GNUNET_FSUI_upload_started; event.data.UploadStarted.uc.pos = utc; event.data.UploadStarted.uc.cctx = utc->cctx; event.data.UploadStarted.uc.ppos = utc->parent; event.data.UploadStarted.uc.pcctx = utc->parent->cctx; event.data.UploadStarted.total = utc->total; event.data.UploadStarted.anonymityLevel = utc->shared->anonymityLevel; event.data.UploadStarted.filename = utc->filename; utc->cctx = utc->shared->ctx->ecb (utc->shared->ctx->ecbClosure, &event); signalUploadStarted (utc->child, 0); if (first_only) break; utc = utc->next; }}/** * Thread that does the upload. */void *GNUNET_FSUI_uploadThread (void *cls){ GNUNET_FSUI_UploadList *utc = cls; GNUNET_FSUI_UploadList *cpos; GNUNET_FSUI_Event event; GNUNET_ECRS_FileInfo fi; int ret; int is_directory; struct GNUNET_GE_Context *ectx; char *filename; char *pfn; struct GNUNET_ECRS_URI *uri; struct GNUNET_ECRS_URI *loc; size_t tpos; size_t tend; char *error; struct GNUNET_GE_Memory *mem; struct GNUNET_GE_Context *ee; ectx = utc->shared->ctx->ectx; GNUNET_GE_ASSERT (ectx, utc->filename != NULL); cpos = utc->child; while (cpos != NULL) { if (cpos->state == GNUNET_FSUI_ACTIVE) GNUNET_FSUI_uploadThread (cpos); cpos = cpos->next; } if (utc->state != GNUNET_FSUI_ACTIVE) return NULL; /* aborted or suspended */ if (GNUNET_shutdown_test ())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -