summaryrefslogtreecommitdiff
path: root/tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools.c')
-rw-r--r--tools.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/tools.c b/tools.c
new file mode 100644
index 0000000..d9264f6
--- /dev/null
+++ b/tools.c
@@ -0,0 +1,230 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2005 Dimitri Sokolyuk <demon@vhost.dyndns.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h> /* struct timeval */
+#include <sys/queue.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h> /* setsockopt() */
+
+#include <ctype.h>
+#include <fcntl.h> /* open() */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* strlcat() */
+#include <unistd.h> /* sysconf() */
+#include "meta.h" /* SHA1LEN */
+#include "tools.h"
+#include "version.h"
+
+#ifndef lint
+static const char rcsid[] = "@(#)$Id$";
+#endif /* not lint */
+
+int
+raisenofile(void)
+{
+ struct rlimit rl;
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
+ rl.rlim_cur = rl.rlim_max;
+ return setrlimit(RLIMIT_NOFILE, &rl);
+ }
+ return -1;
+}
+
+/* usable file desctriptors */
+int
+nofile(void)
+{
+ struct rlimit rl;
+ struct stat st;
+ int i, ret;
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
+ ret = i = rl.rlim_cur;
+ while (i)
+ if (!fstat(--i, &st))
+ --ret;
+ return ret;
+ }
+ return -1;
+}
+
+
+int
+bthexdump(char *dst, u_char *src, int len)
+{
+ /* src is a SHA1 hash and is 20 bytes long
+ * dst should be at least 41 bytes long for a simple hexdump,
+ * and 61 bytes long for a quoted printable
+ * (including the terminating `\0' character)
+ */
+ int i, done;
+ char *fmt;
+
+ if (len <= 2 * SHA1LEN)
+ return -1;
+
+ for (i = SHA1LEN, done = 0, *dst = NULL; i > 0; i--) {
+ if (len > 3 * SHA1LEN) {
+ if (isascii(*src) && (isalnum(*src) ||
+ *src == '-' || *src == '.' ||
+ *src == '_' || *src == '~'))
+ fmt = "%c";
+ else
+ fmt = "%%%.2X";
+ } else
+ fmt = "%.2x";
+ done += snprintf(dst + done, len - done, fmt, *src++);
+ }
+
+ return done;
+}
+
+char *
+btfreadall(char *name)
+{
+ FILE *fd;
+ char *buf;
+ off_t len;
+
+ if ((fd = fopen(name, "r")) == NULL)
+ return NULL;
+
+ fseek(fd, 0L, SEEK_END);
+ len = ftell(fd);
+ fseek(fd, 0L, SEEK_SET);
+
+ if ((buf = calloc(len, sizeof(char))) != NULL)
+ if ((fread(buf, sizeof(char), len, fd)) == 0) {
+ free(buf);
+ return NULL;
+ }
+
+ fclose(fd);
+
+ return buf;
+}
+
+#if MMAP
+void *
+btmmapfile(char *name, off_t *len)
+{
+ struct stat stat;
+ int fd;
+ off_t page;
+ void *buf;
+
+ if ((fd = open(name, O_RDONLY)) == -1) {
+ perror("open");
+ return NULL;
+ }
+
+ if (fstat(fd, &stat) == -1) {
+ perror("fstat");
+ close(fd);
+ return NULL;
+ }
+
+ page = sysconf(_SC_PAGESIZE);
+ *len = stat.st_size;
+ if (*len == 0)
+ return NULL;
+ *len += page - (*len % page);
+
+ if ((buf = mmap((void *) NULL, *len, PROT_READ, MAP_SHARED, fd, 0L)) == NULL) {
+ perror("mmap");
+ close(fd);
+ return NULL;
+ }
+
+ close(fd);
+
+ return buf;
+}
+
+void
+btunmapfile(void *buf, off_t len)
+{
+ munmap(buf, len);
+}
+#endif /* MMAP */
+
+void
+btpeerid(u_char *str)
+{
+ const char hex[16] = "0123456789ABCDEF";
+ int i;
+
+ /* we only use unreserved characters (RFC 3986) as PEER_ID,
+ * so we don't need to percent-encode them and
+ * it's still random enough (16^12 possibilities)
+ * OBSOLETE since we use array to store that value
+ */
+ snprintf((char *) str, 9, "-XB%.2d%.2d-", VERSION_MAJOR, VERSION_MINOR);
+ for (i = 8; i < SHA1LEN; i++)
+ str[i] = hex[arc4random() % sizeof(hex)];
+}
+
+__dead void
+usage(const char *usagearg)
+{
+ extern char *__progname;
+
+ fprintf(stderr, "usage: %s %s\n", __progname, usagearg);
+ exit(1);
+}
+
+int
+setrcvtimeo(int s, int msec)
+{
+ struct timeval tv;
+
+ tv.tv_sec = msec / 1000;
+ tv.tv_usec = (msec % 1000) * 1000;
+
+ return setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
+}
+
+void
+twiddle(void)
+{
+ static int pos;
+
+ putchar("|/-\\"[pos++ & 3]);
+ putchar('\b');
+}
+
+char *
+metric(double len)
+{
+ static char buf[16];
+ char *units[] = {
+ "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", NULL
+ };
+ int n = 0;
+
+ for (n = 0; len >= 1024 && n < sizeof(units) / sizeof(units[0]); n++)
+ len /= 1024;
+
+ snprintf(buf, sizeof(buf), "%.2f %s", len, units[n]);
+
+ return buf;
+}