/* $Id$ */ /* * Copyright (c) 2005 Dimitri Sokolyuk * * 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 #include /* struct timeval */ #include #include #include #include #include /* setsockopt() */ #include #include /* open() */ #include #include #include /* strlcat() */ #include /* 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 = '\0'; 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)]; } 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; }