From 88ffe247983a609b002e8509251f24efcad2f5dc Mon Sep 17 00:00:00 2001 From: Emil Renner Berthing Date: Sat, 30 May 2009 21:29:16 +0200 Subject: [PATCH] added proper large file support --- .gitignore | 1 + BSDmakefile | 8 ++++---- GNUmakefile | 10 ++++++---- Makefile | 8 ++++---- hash.c | 26 +++++++++++++++----------- hash_pthreads.c | 13 +++++++++---- init.c | 20 ++++++++++---------- main.c | 4 ++-- mktorrent.h | 13 ++----------- output.c | 14 +++++++------- prefix.c | 43 +++++++++++++++++++++++++++++++++++++++++++ rules.mk | 9 ++++++--- 12 files changed, 109 insertions(+), 60 deletions(-) create mode 100644 prefix.c diff --git a/.gitignore b/.gitignore index 8f159f3..5bc30ce 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ *.[oa] *~ mktorrent +prefix diff --git a/BSDmakefile b/BSDmakefile index 08e0edd..6299527 100644 --- a/BSDmakefile +++ b/BSDmakefile @@ -38,8 +38,8 @@ LIBS += -lcrypto DEFINES += -DUSE_LONG_OPTIONS .endif -.ifdef USE_LONG_LONG -DEFINES += -DUSE_LONG_LONG +.ifdef USE_LARGE_FILES +DEFINES += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 .endif .ifdef NO_HASH_CHECK @@ -60,8 +60,8 @@ all: $(program) .SUFFIXES: .o .c .c.o: - $(CC) $(CFLAGS) $(DEFINES) -DVERSION="\"$(version)\"" -c $(.IMPSRC) + $(CC) $(CFLAGS) $(DEFINES) -DPRIoff="\"`./prefix`d\"" -DVERSION="\"$(version)\"" -c $(.IMPSRC) -$(OBJS): $(HEADERS) +$(OBJS): $(HEADERS) prefix .include "rules.mk" diff --git a/GNUmakefile b/GNUmakefile index aeeb7dc..29244ab 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -38,8 +38,8 @@ ifdef USE_LONG_OPTIONS DEFINES += -DUSE_LONG_OPTIONS endif -ifdef USE_LONG_LONG -DEFINES += -DUSE_LONG_LONG +ifdef USE_LARGE_FILES +DEFINES += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 endif ifdef NO_HASH_CHECK @@ -54,11 +54,13 @@ ifdef DEBUG DEFINES += -DDEBUG endif +OFFPRFX = $(shell ./prefix) + OBJS = $(SRCS:.c=.o) all: $(program) -%.o: %.c $(HEADERS) - $(CC) $(CFLAGS) $(DEFINES) -DVERSION="\"$(version)\"" -c $< +%.o: %.c $(HEADERS) prefix + $(CC) $(CFLAGS) $(DEFINES) -DPRIoff="\"$(OFFPRFX)d\"" -DVERSION="\"$(version)\"" -c $< include rules.mk diff --git a/Makefile b/Makefile index 48dbdaa..4ddddc1 100644 --- a/Makefile +++ b/Makefile @@ -36,11 +36,11 @@ # Enable long options, started with two dashes. #USE_LONG_OPTIONS = 1 -# Use the C type 'unsigned long long'. This is needed on 32bit machines -# to handle torrents > 4Gb properly. Some compilers might not like this. -#USE_LONG_LONG = 1 +# This is needed on certain 32bit OSes (notably 32bit Linux) to support +# files and torrents > 2Gb. +#USE_LARGE_FILES = 1 -# Disable a redundent check to see if the amount of bytes read from files while +# Disable a redundant check to see if the amount of bytes read from files while # hashing matches the sum of reported file sizes. I've never seen this fail. It # will fail if you change files yet to be hashed while mktorrent is running, # but who'd want to do that? diff --git a/hash.c b/hash.c index 72f23e0..1866022 100644 --- a/hash.c +++ b/hash.c @@ -17,16 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef ALLINONE - -#include /* exit() */ -#include /* errno */ -#include /* strerror() */ -#include /* printf() etc. */ -#include /* open() */ -#include /* read(), close() */ +#include /* exit() */ +#include /* off_t */ +#include /* errno */ +#include /* strerror() */ +#include /* printf() etc. */ +#include /* open() */ +#include /* read(), close() */ #ifdef USE_OPENSSL -#include /* SHA1() - remember to compile with -lssl */ +#include /* SHA1() */ #else #include #include "sha1.h" @@ -58,7 +58,7 @@ EXPORT unsigned char *make_hash(metafile_t *m) the read buffer */ SHA_CTX c; /* SHA1 hashing context */ #ifndef NO_HASH_CHECK - fsize_t counter = 0; /* number of bytes hashed + off_t counter = 0; /* number of bytes hashed should match size when done */ #endif @@ -82,7 +82,11 @@ EXPORT unsigned char *make_hash(metafile_t *m) for (f = m->file_list; f; f = f->next) { /* open the current file for reading */ +#if defined _LARGEFILE_SOURCE && defined O_LARGEFILE + if ((fd = open(f->path, O_RDONLY | O_BINARY | O_LARGEFILE)) == -1) { +#else if ((fd = open(f->path, O_RDONLY | O_BINARY)) == -1) { +#endif fprintf(stderr, "Error opening '%s' for reading: %s\n", f->path, strerror(errno)); exit(EXIT_FAILURE); @@ -138,8 +142,8 @@ EXPORT unsigned char *make_hash(metafile_t *m) #ifndef NO_HASH_CHECK counter += r; if (counter != m->size) { - fprintf(stderr, "Counted " PRIfz " bytes, " - "but hashed " PRIfz " bytes. " + fprintf(stderr, "Counted %" PRIoff " bytes, " + "but hashed %" PRIoff " bytes. " "Something is wrong...\n", m->size, counter); exit(EXIT_FAILURE); } diff --git a/hash_pthreads.c b/hash_pthreads.c index 14ba86e..bc9b306 100644 --- a/hash_pthreads.c +++ b/hash_pthreads.c @@ -18,13 +18,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef ALLINONE #include /* exit(), malloc() */ +#include /* off_t */ #include /* errno */ #include /* strerror() */ #include /* printf() etc. */ #include /* open() */ #include /* access(), read(), close() */ #ifdef USE_OPENSSL -#include /* SHA1() - remember to compile with -lssl */ +#include /* SHA1() */ #else #include #include "sha1.h" @@ -209,7 +210,7 @@ static void read_files(metafile_t *m, queue_t *q, unsigned char *pos) ssize_t r = 0; /* number of bytes read from file(s) into the read buffer */ #ifndef NO_HASH_CHECK - fsize_t counter = 0; /* number of bytes hashed + off_t counter = 0; /* number of bytes hashed should match size when done */ #endif piece_t *p = get_free(q, m->piece_length); @@ -218,7 +219,11 @@ static void read_files(metafile_t *m, queue_t *q, unsigned char *pos) for (f = m->file_list; f; f = f->next) { /* open the current file for reading */ +#if defined _LARGEFILE_SOURCE && defined O_LARGEFILE + if ((fd = open(f->path, O_RDONLY | O_BINARY | O_LARGEFILE)) == -1) { +#else if ((fd = open(f->path, O_RDONLY | O_BINARY)) == -1) { +#endif fprintf(stderr, "Error opening '%s' for reading: %s\n", f->path, strerror(errno)); exit(EXIT_FAILURE); @@ -270,8 +275,8 @@ static void read_files(metafile_t *m, queue_t *q, unsigned char *pos) #ifndef NO_HASH_CHECK counter += r; if (counter != m->size) { - fprintf(stderr, "Counted " PRIfz " bytes, " - "but hashed " PRIfz " bytes. " + fprintf(stderr, "Counted %" PRIoff " bytes, " + "but hashed %" PRIoff " bytes. " "Something is wrong...\n", m->size, counter); exit(EXIT_FAILURE); } diff --git a/init.c b/init.c index eb6c950..bc201ef 100644 --- a/init.c +++ b/init.c @@ -17,16 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef ALLINONE - -#include /* exit() */ -#include /* errno */ -#include /* strerror() */ -#include /* printf() etc. */ -#include /* the stat structure */ -#include /* getopt(), getcwd() */ -#include /* strcmp(), strlen(), strncpy() */ +#include /* exit() */ +#include /* off_t */ +#include /* errno */ +#include /* strerror() */ +#include /* printf() etc. */ +#include /* the stat structure */ +#include /* getopt(), getcwd() */ +#include /* strcmp(), strlen(), strncpy() */ #ifdef USE_LONG_OPTIONS -#include /* getopt_long() */ +#include /* getopt_long() */ #endif #include "mktorrent.h" @@ -563,7 +563,7 @@ EXPORT void init(metafile_t *m, int argc, char *argv[]) /* now print the size and piece count if we should be verbose */ if (m->verbose) - printf("\n" PRIfz " bytes in all.\n" + printf("\n%" PRIoff " bytes in all.\n" "That's %u pieces of %u bytes each.\n\n", m->size, m->pieces, m->piece_length); } diff --git a/main.c b/main.c index dc53b1e..45fc7e0 100644 --- a/main.c +++ b/main.c @@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include /* exit() */ +#include /* off_t */ #include /* errno */ #include /* strerror() */ #include /* printf() etc. */ @@ -25,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include /* open() */ #ifdef ALLINONE - #include #include /* access(), read(), close(), getcwd() */ #ifdef USE_LONG_OPTIONS @@ -44,7 +44,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #endif #define EXPORT static -#else +#else /* ALLINONE */ #define EXPORT #endif /* ALLINONE */ diff --git a/mktorrent.h b/mktorrent.h index c22bc07..de8894c 100644 --- a/mktorrent.h +++ b/mktorrent.h @@ -9,15 +9,6 @@ #define DIRSEP_CHAR '/' #endif -/* fsize_t */ -#ifdef USE_LONG_LONG -typedef unsigned long long fsize_t; -#define PRIfz "%llu" -#else -typedef unsigned long fsize_t; -#define PRIfz "%lu" -#endif - /* string list */ struct slist_s; typedef struct slist_s slist_t; @@ -39,7 +30,7 @@ struct flist_s; typedef struct flist_s flist_t; struct flist_s { char *path; - fsize_t size; + off_t size; flist_t *next; }; @@ -60,7 +51,7 @@ typedef struct { #endif /* information calculated by read_dir() */ - fsize_t size; /* combined size of all files */ + off_t size; /* combined size of all files */ flist_t *file_list; /* list of files and their sizes */ unsigned int pieces; /* number of pieces */ } metafile_t; diff --git a/output.c b/output.c index ada8b64..717e6f8 100644 --- a/output.c +++ b/output.c @@ -17,12 +17,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef ALLINONE - -#include /* printf() etc. */ -#include /* strlen() etc. */ -#include /* time() */ +#include /* off_t */ +#include /* printf() etc. */ +#include /* strlen() etc. */ +#include /* time() */ #ifdef USE_OPENSSL -#include /* SHA_DIGEST_LENGTH */ +#include /* SHA_DIGEST_LENGTH */ #else #include #include "sha1.h" @@ -68,7 +68,7 @@ static void write_file_list(FILE *f, flist_t *list) /* the file list contains a dictionary for every file with entries for the length and path write the length first */ - fprintf(f, "d6:lengthi" PRIfz "e4:pathl", list->size); + fprintf(f, "d6:lengthi%" PRIoff "e4:pathl", list->size); /* the file path is written as a list of subdirectories and the last entry is the filename sorry this code is even uglier than the rest */ @@ -146,7 +146,7 @@ EXPORT void write_metainfo(FILE *f, metafile_t *m, unsigned char *hash_string) /* first entry is either 'length', which specifies the length of a single file torrent, or a list of files and their respective sizes */ if (!m->target_is_directory) - fprintf(f, "6:lengthi" PRIfz "e", m->file_list->size); + fprintf(f, "6:lengthi%" PRIoff "e", m->file_list->size); else write_file_list(f, m->file_list); diff --git a/prefix.c b/prefix.c new file mode 100644 index 0000000..5cc1115 --- /dev/null +++ b/prefix.c @@ -0,0 +1,43 @@ +#include +#include +#include + +#ifndef TYPE +#define TYPE off_t +#endif + +int main(int argc, char *argv[]) +{ + unsigned int i; + char *prefix[9]; + + for (i = 0; i < 9; i++) + prefix[i] = NULL; + + prefix[1] = "hh"; + prefix[2] = "h"; + + prefix[8] = "ll"; + prefix[sizeof(int)] = ""; + prefix[sizeof(long int)] = "l"; + +#ifdef DEBUG +#define xstr(s) str(s) +#define str(s) #s + +#ifdef _LARGEFILE_SOURCE + printf("_LARGEFILE_SOURCE is set\n"); +#endif + +#ifdef _FILE_OFFSET_BITS + printf("_FILE_OFFSET_BITS = %lu\n", _FILE_OFFSET_BITS); +#endif + + printf("sizeof(" xstr(TYPE) ") = %lu, %lu bits\n", + sizeof(TYPE), 8*sizeof(TYPE)); +#endif /* DEBUG */ + + printf("%s\n", prefix[sizeof(TYPE)]); + + return EXIT_SUCCESS; +} diff --git a/rules.mk b/rules.mk index 1b0b42d..5960822 100644 --- a/rules.mk +++ b/rules.mk @@ -17,11 +17,14 @@ .PHONY: strip indent clean install uninstall +prefix: prefix.c + $(CC) $(CFLAGS) $(DEFINES) $(LDFLAGS) $< -o $@ + $(program): $(OBJS) $(CC) $(CFLAGS) $(OBJS) -o $(program) $(LDFLAGS) $(LIBS) -allinone: $(SRCS) $(HEADERS) - $(CC) $(CFLAGS) $(DEFINES) -DVERSION="\"$(version)\"" -DALLINONE main.c -o $(program) $(LDFLAGS) $(LIBS) +allinone: $(SRCS) $(HEADERS) prefix + $(CC) $(CFLAGS) $(DEFINES) -DPRIoff="\"`./prefix`d\"" -DVERSION="\"$(version)\"" -DALLINONE main.c -o $(program) $(LDFLAGS) $(LIBS) strip: strip $(program) @@ -30,7 +33,7 @@ indent: indent -kr -i8 *.c *.h clean: - rm -f $(program) *.o *.c~ *.h~ + rm -f $(program) prefix *.o *.c~ *.h~ install: $(program) $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin