📄 gnunet-auto-share.c
字号:
/*
This file is part of GNUnet.
(C) 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/tools/gnunet-auto-share.c
* @brief Tool to share directories
* @author Christian Grothoff
*/
#include "platform.h"
#include "gnunet_directories.h"
#include "gnunet_fs_lib.h"
#include "gnunet_fsui_lib.h"
#include "gnunet_util.h"
#include <extractor.h>
#define PIDFILE_DATA "GNUNET-AUTO-SHARE", "PIDFILE", GNUNET_DEFAULT_HOME_DIRECTORY DIR_SEPARATOR_STR "gnunet-auto-share.pid"
struct FileRecord
{
struct FileRecord *next;
char *filename;
time_t mtime;
time_t last_seen;
off_t size;
GNUNET_HashCode hc;
};
struct DirectoryRecord
{
struct DirectoryRecord *next;
struct FileRecord *records;
char *dirname;
int records_changed;
int run;
};
static struct GNUNET_FSUI_UploadList *ul;
static struct GNUNET_ClientServerConnection *sock;
static struct GNUNET_GC_Configuration *meta_cfg;
static int upload_done;
static struct GNUNET_GC_Configuration *cfg;
static struct GNUNET_GE_Context *ectx;
static struct GNUNET_FSUI_Context *ctx;
static char *cfgFilename =
#ifndef MINGW
GNUNET_DEFAULT_CLIENT_CONFIG_FILE
#else
GNUNET_DEFAULT_CLIENT_SITE_CONFIG_FILE
#endif
;
static struct GNUNET_ECRS_URI *gloKeywords;
static unsigned int anonymity = 1;
static unsigned int priority = 365;
static int do_no_direct_references;
static int debug_flag;
static FILE *myout;
#ifdef MINGW
/**
* Windows service information
*/
static SERVICE_STATUS theServiceStatus;
static SERVICE_STATUS_HANDLE hService;
#endif
/**
* Print progess message.
*/
static void *
printstatus (void *ctx, const GNUNET_FSUI_Event * event)
{
unsigned long long *verboselevel = ctx;
char *fstring;
switch (event->type)
{
case GNUNET_FSUI_upload_progress:
if ((*verboselevel > 2) && (event->data.UploadProgress.uc.pos != ul))
{
fprintf (myout,
_("Upload of `%s' at %llu out of %llu bytes.\n"),
event->data.UploadProgress.filename,
event->data.UploadProgress.completed,
event->data.UploadProgress.total);
fflush (myout);
}
break;
case GNUNET_FSUI_upload_completed:
if (*verboselevel)
{
fstring =
GNUNET_ECRS_uri_to_string (event->data.UploadCompleted.uri);
fprintf (myout,
_("Upload of `%s' complete, URI is `%s'.\n"),
event->data.UploadCompleted.filename, fstring);
fflush (myout);
GNUNET_free (fstring);
}
if (ul == event->data.UploadCompleted.uc.pos)
upload_done = GNUNET_YES;
break;
case GNUNET_FSUI_upload_aborted:
fprintf (myout, _("Upload aborted.\n"));
fflush (myout);
upload_done = GNUNET_YES;
break;
case GNUNET_FSUI_upload_error:
fprintf (myout,
_("Error uploading file: %s\n"),
event->data.UploadError.message);
fflush (myout);
upload_done = GNUNET_YES;
break;
case GNUNET_FSUI_upload_started:
if ((*verboselevel > 1) && (ul == NULL))
{
fprintf (myout,
_("Starting upload of `%s'.\n"),
event->data.UploadStarted.filename);
fflush (myout);
}
break;
case GNUNET_FSUI_upload_stopped:
break;
case GNUNET_FSUI_upload_suspended:
if ((ul != NULL) && (event->data.UploadSuspended.uc.pos == ul))
{
fprintf (myout, _("Uploading suspended.\n"));
fflush (myout);
ul = NULL;
}
break;
case GNUNET_FSUI_upload_resumed:
if (ul == NULL)
{
ul = event->data.UploadResumed.uc.pos;
if (GNUNET_FSUI_ACTIVE != event->data.UploadResumed.state)
{
upload_done = GNUNET_YES;
}
else
{
fprintf (myout, _("Uploading `%s' resumed.\n"),
event->data.UploadResumed.filename);
fflush (myout);
}
}
break;
default:
fprintf (myout, _("Unexpected event: %d\n"), event->type);
fflush (myout);
GNUNET_GE_BREAK (ectx, 0);
break;
}
return NULL;
}
/**
* All gnunet-auto-share command line options
*/
static struct GNUNET_CommandLineOption gnunetauto_shareOptions[] = {
{'a', "anonymity", "LEVEL",
gettext_noop ("set the desired LEVEL of sender-anonymity"),
1, &GNUNET_getopt_configure_set_uint, &anonymity},
GNUNET_COMMAND_LINE_OPTION_CFG_FILE (&cfgFilename), /* -c */
{'@', "win-service", NULL, "", 0,
&GNUNET_getopt_configure_set_option, "GNUNET-AUTO-SHARE:WINSERVICE"},
{'d', "debug", NULL,
gettext_noop ("run in debug mode; gnunet-auto-share will "
"not daemonize and error messages will "
"be written to stderr instead of a logfile"),
0, &GNUNET_getopt_configure_set_one, &debug_flag},
{'D', "disable-direct", NULL,
gettext_noop
("do not use libextractor to add additional references to directory entries and/or the published file"),
0, &GNUNET_getopt_configure_set_one, &do_no_direct_references},
GNUNET_COMMAND_LINE_OPTION_HELP (gettext_noop ("Automatically share a directory.")), /* -h */
GNUNET_COMMAND_LINE_OPTION_HOSTNAME, /* -H */
{'K', "global-key", "KEYWORD",
gettext_noop ("add an additional keyword for all files and directories"
" (this option can be specified multiple times)"),
1, &GNUNET_ECRS_getopt_configure_set_keywords, &gloKeywords},
GNUNET_COMMAND_LINE_OPTION_LOGGING, /* -L */
{'p', "priority", "PRIORITY",
gettext_noop ("specify the priority of the content"),
1, &GNUNET_getopt_configure_set_uint, &priority},
GNUNET_COMMAND_LINE_OPTION_VERSION (PACKAGE_VERSION), /* -v */
GNUNET_COMMAND_LINE_OPTION_VERBOSE,
GNUNET_COMMAND_LINE_OPTION_END,
};
static char *
get_record_file_name (const char *dirname)
{
GNUNET_EncName enc;
GNUNET_HashCode hc;
GNUNET_hash (dirname, strlen (dirname), &hc);
GNUNET_hash_to_enc (&hc, &enc);
return GNUNET_get_home_filename (ectx, cfg,
#ifndef MINGW
GNUNET_NO,
#else
GNUNET_YES,
#endif
"auto-share-info",
(const char *) &enc, NULL);
}
/**
* Write the given record to the buffer.
* @param buf if NULL, only calculate size
* @return number of bytes written (or number
* of bytes that would be written)
*/
static unsigned int
write_file_record (char *buf, unsigned int max, const struct FileRecord *rec)
{
unsigned int wi;
unsigned long long wl;
if ((buf != NULL) &&
(max <
sizeof (unsigned long long) * 3 + sizeof (GNUNET_HashCode) +
strlen (rec->filename) + sizeof (unsigned int)))
{
GNUNET_GE_BREAK (NULL, 0);
return 0;
}
if (buf != NULL)
{
wi = htonl (strlen (rec->filename));
memcpy (buf, &wi, sizeof (unsigned int));
buf += sizeof (unsigned int);
memcpy (buf, &rec->hc, sizeof (GNUNET_HashCode));
buf += sizeof (GNUNET_HashCode);
wl = GNUNET_htonll (rec->mtime);
memcpy (buf, &wl, sizeof (unsigned long long));
buf += sizeof (unsigned long long);
wl = GNUNET_htonll (rec->last_seen);
memcpy (buf, &wl, sizeof (unsigned long long));
buf += sizeof (unsigned long long);
wl = GNUNET_htonll (rec->size);
memcpy (buf, &wl, sizeof (unsigned long long));
buf += sizeof (unsigned long long);
memcpy (buf, rec->filename, strlen (rec->filename));
}
return sizeof (unsigned long long) * 3 + sizeof (GNUNET_HashCode) +
strlen (rec->filename) + sizeof (unsigned int);
}
/**
* Read a file record.
* @param head old head of the list, afterwards points to
* the new head
* @param size number of bytes available in buf
* @return 0 on error, otherwise number of bytes read
*/
static unsigned int
read_file_record (const char *buf,
unsigned int size, struct FileRecord **head)
{
unsigned int wi;
unsigned long long wl;
struct FileRecord *r;
if (size < sizeof (unsigned int))
{
GNUNET_GE_BREAK (NULL, 0);
return 0;
}
memcpy (&wi, buf, sizeof (unsigned int));
if (size <
ntohl (wi) + sizeof (unsigned long long) * 3 +
sizeof (GNUNET_HashCode) + sizeof (unsigned int))
{
GNUNET_GE_BREAK (NULL, 0);
return 0;
}
buf += sizeof (unsigned int);
r = GNUNET_malloc (sizeof (struct FileRecord));
r->next = *head;
memcpy (&r->hc, buf, sizeof (GNUNET_HashCode));
buf += sizeof (GNUNET_HashCode);
memcpy (&wl, buf, sizeof (unsigned long long));
r->mtime = (time_t) GNUNET_ntohll (wl);
buf += sizeof (unsigned long long);
memcpy (&wl, buf, sizeof (unsigned long long));
r->last_seen = (time_t) GNUNET_ntohll (wl);
buf += sizeof (unsigned long long);
memcpy (&wl, buf, sizeof (unsigned long long));
r->size = (off_t) GNUNET_ntohll (wl);
buf += sizeof (unsigned long long);
r->filename = GNUNET_malloc (ntohl (wi) + 1);
r->filename[ntohl (wi)] = '\0';
memcpy (r->filename, buf, ntohl (wi));
*head = r;
return ntohl (wi) + sizeof (unsigned long long) * 3 +
sizeof (GNUNET_HashCode) + sizeof (unsigned int);
}
static struct FileRecord *
read_all_records (const char *dir_name)
{
long off;
unsigned int d;
unsigned long long size;
char *record_fn;
int fd;
char *buf;
struct FileRecord *ret;
record_fn = get_record_file_name (dir_name);
if ((GNUNET_OK !=
GNUNET_disk_file_size (ectx,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -