From 7039a66b58706457c7423de60556e04545432943 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sun, 8 Oct 2006 17:54:47 +0000 Subject: [PATCH] correct largefile support, add comments about it. --- Makefile.flags | 26 +++++++++---------- archival/tar.c | 2 +- archival/unzip.c | 5 ++-- coreutils/cat.c | 7 ++--- coreutils/catv.c | 6 ++--- coreutils/dd.c | 16 ++++++------ e2fsprogs/chattr.c | 4 +-- e2fsprogs/lsattr.c | 8 +++--- e2fsprogs/util.c | 6 ++--- include/libbb.h | 70 ++++++++++++++++++++++++++++++++++---------------- libbb/copyfd.c | 10 ++++---- libbb/loop.c | 4 ++- networking/ftpgetput.c | 20 ++++++++------- networking/httpd.c | 4 +-- networking/wget.c | 24 ++++++++--------- 15 files changed, 121 insertions(+), 91 deletions(-) diff --git a/Makefile.flags b/Makefile.flags index 39c544e..f5eb65f 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -4,16 +4,16 @@ BB_VER = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) -CPPFLAGS += \ - -Iinclude -Ilibbb \ - $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) -I$(srctree)/libbb \ - -include include/autoconf.h \ - -D_GNU_SOURCE -DNDEBUG \ - -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 \ - -D"BB_VER=KBUILD_STR($(BB_VER))" -DBB_BT=AUTOCONF_TIMESTAMP \ - -Wall -Wstrict-prototypes -Wshadow -Werror \ - -funsigned-char -fno-builtin-strlen -finline-limit=0 -static-libgcc \ - -Os -march=i386 -mpreferred-stack-boundary=2 \ - -falign-functions=1 -falign-jumps=1 -falign-loops=1 \ - -fomit-frame-pointer -ffunction-sections -fdata-sections \ - -funsigned-char -fno-builtin-strlen \ +CPPFLAGS += \ + -Iinclude -Ilibbb \ + $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) -I$(srctree)/libbb \ + -include include/autoconf.h \ + -D_GNU_SOURCE -DNDEBUG \ + $(if $(CONFIG_LFS),-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64) \ + -D"BB_VER=KBUILD_STR($(BB_VER))" -DBB_BT=AUTOCONF_TIMESTAMP \ + -Wall -Wstrict-prototypes -Wshadow -Werror \ + -funsigned-char -fno-builtin-strlen -finline-limit=0 -static-libgcc \ + -Os -march=i386 -mpreferred-stack-boundary=2 \ + -falign-functions=1 -falign-jumps=1 -falign-loops=1 \ + -fomit-frame-pointer -ffunction-sections -fdata-sections \ + -funsigned-char -fno-builtin-strlen \ diff --git a/archival/tar.c b/archival/tar.c index b2ae3b2..28bb147 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -376,7 +376,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, /* If it was a regular file, write out the body */ if (inputFileFd >= 0) { - ssize_t readSize = 0; + off_t readSize = 0; /* write the file to the archive */ readSize = bb_copyfd_eof(inputFileFd, tbInfo->tarFd); diff --git a/archival/unzip.c b/archival/unzip.c index f70baeb..2aa380d 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -51,7 +51,6 @@ typedef union { } formatted ATTRIBUTE_PACKED; } zip_header_t; -/* This one never works with LARGEFILE-sized skips */ static void unzip_skip(int fd, off_t skip) { if (lseek(fd, skip, SEEK_CUR) == (off_t)-1) { @@ -75,7 +74,7 @@ static int unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd) { if (zip_header->formatted.method == 0) { /* Method 0 - stored (not compressed) */ - int size = zip_header->formatted.ucmpsize; + off_t size = zip_header->formatted.ucmpsize; if (size && (bb_copyfd_size(src_fd, dst_fd, size) != size)) { bb_error_msg_and_die("cannot complete extraction"); } @@ -202,7 +201,7 @@ int unzip_main(int argc, char **argv) } if (src_fd == -1) { src_fn[orig_src_fn_len] = 0; - bb_error_msg_and_die("Cannot open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); + bb_error_msg_and_die("cannot open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); } } diff --git a/coreutils/cat.c b/coreutils/cat.c index f3baf0a..10eb29c 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -4,7 +4,7 @@ * * Copyright (C) 2003 Manuel Novoa III * - * Licensed under GPLv2 or later, see file License in this tarball for details. + * Licensed under GPLv2, see file License in this tarball for details. */ /* BB_AUDIT SUSv3 compliant */ @@ -26,8 +26,9 @@ int cat_main(int argc, char **argv) } do { - if ((f = bb_wfopen_input(*argv)) != NULL) { - int r = bb_copyfd_eof(fileno(f), STDOUT_FILENO); + f = bb_wfopen_input(*argv); + if (f) { + off_t r = bb_copyfd_eof(fileno(f), STDOUT_FILENO); bb_fclose_nonstdin(f); if (r >= 0) { continue; diff --git a/coreutils/catv.c b/coreutils/catv.c index 55656b4..a5a8b43 100644 --- a/coreutils/catv.c +++ b/coreutils/catv.c @@ -15,7 +15,7 @@ int catv_main(int argc, char **argv) { int retval = EXIT_SUCCESS, fd; - unsigned long flags; + unsigned flags; flags = getopt32(argc, argv, "etv"); #define CATV_OPT_e (1<<0) @@ -51,8 +51,8 @@ int catv_main(int argc, char **argv) } if (c < 32) { if (c == 10) { - if (flags & CATV_OPT_e) - putchar('$'); + if (flags & CATV_OPT_e) + putchar('$'); } else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) { bb_printf("^%c", c+'@'); continue; diff --git a/coreutils/dd.c b/coreutils/dd.c index d557ae4..d60192e 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -25,12 +25,12 @@ static const struct suffix_mult dd_suffixes[] = { { NULL, 0 } }; -static FILEOFF_TYPE out_full, out_part, in_full, in_part; +static off_t out_full, out_part, in_full, in_part; static void dd_output_status(int ATTRIBUTE_UNUSED cur_signal) { - bb_fprintf(stderr, FILEOFF_FMT"+"FILEOFF_FMT" records in\n" - FILEOFF_FMT"+"FILEOFF_FMT" records out\n", + bb_fprintf(stderr, OFF_FMT"+"OFF_FMT" records in\n" + OFF_FMT"+"OFF_FMT" records out\n", in_full, in_part, out_full, out_part); } @@ -44,7 +44,7 @@ int dd_main(int argc, char **argv) int flags = trunc_flag; size_t oc = 0, ibs = 512, obs = 512; ssize_t n; - FILEOFF_TYPE seek = 0, skip = 0, count = MAX_FILEOFF_TYPE; + off_t seek = 0, skip = 0, count = OFF_T_MAX; int oflag, ifd, ofd; const char *infile = NULL, *outfile = NULL; char *ibuf, *obuf; @@ -108,14 +108,14 @@ int dd_main(int argc, char **argv) obuf = ibuf; if (infile != NULL) - ifd = xopen(infile, O_RDONLY | (O_LARGEFILE * ENABLE_LFS)); + ifd = xopen(infile, O_RDONLY); else { ifd = STDIN_FILENO; infile = bb_msg_standard_input; } if (outfile != NULL) { - oflag = O_WRONLY | O_CREAT | (O_LARGEFILE * ENABLE_LFS); + oflag = O_WRONLY | O_CREAT; if (!seek && (flags & trunc_flag)) oflag |= O_TRUNC; @@ -137,7 +137,7 @@ int dd_main(int argc, char **argv) } if (skip) { - if (LSEEK(ifd, skip * ibs, SEEK_CUR) < 0) { + if (lseek(ifd, skip * ibs, SEEK_CUR) < 0) { while (skip-- > 0) { n = safe_read(ifd, ibuf, ibs); if (n < 0) @@ -149,7 +149,7 @@ int dd_main(int argc, char **argv) } if (seek) { - if (LSEEK(ofd, seek * obs, SEEK_CUR) < 0) + if (lseek(ofd, seek * obs, SEEK_CUR) < 0) goto die_outfile; } diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c index 618d8c4..4c34162 100644 --- a/e2fsprogs/chattr.c +++ b/e2fsprogs/chattr.c @@ -112,9 +112,9 @@ static int chattr_dir_proc(const char *, struct dirent *, void *); static void change_attributes(const char * name) { unsigned long fsflags; - STRUCT_STAT st; + struct stat st; - if (LSTAT(name, &st) == -1) { + if (lstat(name, &st) == -1) { bb_error_msg("stat %s failed", name); return; } diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c index 1b7cf44..13d5acf 100644 --- a/e2fsprogs/lsattr.c +++ b/e2fsprogs/lsattr.c @@ -72,9 +72,9 @@ static int lsattr_dir_proc(const char *, struct dirent *, void *); static void lsattr_args(const char *name) { - STRUCT_STAT st; + struct stat st; - if (LSTAT(name, &st) == -1) { + if (lstat(name, &st) == -1) { bb_perror_msg("stating %s", name); } else { if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT)) @@ -87,12 +87,12 @@ static void lsattr_args(const char *name) static int lsattr_dir_proc(const char *dir_name, struct dirent *de, void *private) { - STRUCT_STAT st; + struct stat st; char *path; path = concat_path_file(dir_name, de->d_name); - if (LSTAT(path, &st) == -1) + if (lstat(path, &st) == -1) bb_perror_msg(path); else { if (de->d_name[0] != '.' || (flags & OPT_ALL)) { diff --git a/e2fsprogs/util.c b/e2fsprogs/util.c index aaee50a..e68c457 100644 --- a/e2fsprogs/util.c +++ b/e2fsprogs/util.c @@ -33,12 +33,12 @@ void proceed_question(void) void check_plausibility(const char *device, int force) { int val; - STRUCT_STAT s; - val = STAT(device, &s); + struct stat s; + val = stat(device, &s); if (force) return; if(val == -1) - bb_perror_msg_and_die("Could not stat %s", device); + bb_perror_msg_and_die("cannot stat %s", device); if (!S_ISBLK(s.st_mode)) { printf("%s is not a block special device.\n", device); proceed_question(); diff --git a/include/libbb.h b/include/libbb.h index a7c7704..bc86e5f 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -61,30 +61,56 @@ #define PATH_MAX 256 #endif +/* Not (yet) used, but tested to work correctly +#define MAXINT(T) (T)( \ + ((T)-1) > 0 \ + ? (T)-1 \ + : (T)~((T)1 << (sizeof(T)*8-1)) \ + ) + +#define MININT(T) (T)( \ + ((T)-1) > 0 \ + ? (T)0 \ + : ((T)1 << (sizeof(T)*8-1)) \ + ) +*/ + /* Large file support */ -#ifdef CONFIG_LFS -# define FILEOFF_TYPE off64_t -# define FILEOFF_FMT "%lld" -# define LSEEK lseek64 -# define STAT stat64 -# define LSTAT lstat64 -# define STRUCT_STAT struct stat64 -# define STRTOOFF strtoll -# define SAFE_STRTOOFF safe_strtoll +/* Note that CONFIG_LFS forces bbox to be built with all common ops + * (stat, lseek etc) mapped to "largefile" variants by libc. + * Practically it means that open() automatically has O_LARGEFILE added + * and all filesize/file_offset parameters and struct members are "large" + * (in today's world - signed 64bit). For full support of large files, + * we need a few helper #defines (below) and careful use of off_t + * instead of int/ssize_t. No lseek64(), O_LARGEFILE etc necessary */ +#if ENBALE_LFS +/* CONFIG_LFS is on */ +# if ULONG_MAX > 0xffffffff +/* "long" is long enough on this system */ +# define STRTOOFF strtol +# define SAFE_STRTOOFF safe_strtol +# define OFF_FMT "%ld" +# else +/* "long" is too short, need "lomg long" */ +# define STRTOOFF strtoll +# define SAFE_STRTOOFF safe_strtoll +# define OFF_FMT "%lld" +# endif #else -# define FILEOFF_TYPE off_t -# define FILEOFF_FMT "%ld" -# define LSEEK lseek -# define STAT stat -# define LSTAT lstat -# define STRUCT_STAT struct stat -# define STRTOOFF strtol -# define SAFE_STRTOOFF safe_strtol -/* Do we need to undefine O_LARGEFILE? */ +# if 0 /* UINT_MAX == 0xffffffff */ +/* Doesn't work. off_t is a long. gcc will throw warnings on printf("%d", off_t) + * even if long==int on this arch. Crap... */ +# define STRTOOFF strtol +# define SAFE_STRTOOFF safe_strtoi +# define OFF_FMT "%d" +# else +# define STRTOOFF strtol +# define SAFE_STRTOOFF safe_strtol +# define OFF_FMT "%ld" +# endif #endif /* scary. better ideas? (but do *test* them first!) */ -#define MAX_FILEOFF_TYPE \ - ((FILEOFF_TYPE)~((FILEOFF_TYPE)1 << (sizeof(FILEOFF_TYPE)*8-1))) +#define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1))) /* Some useful definitions */ #undef FALSE @@ -203,8 +229,8 @@ extern char *find_block_device(char *path); extern char *bb_get_line_from_file(FILE *file); extern char *bb_get_chomped_line_from_file(FILE *file); extern char *bb_get_chunk_from_file(FILE *file, int *end); -extern int bb_copyfd_size(int fd1, int fd2, const off_t size); -extern int bb_copyfd_eof(int fd1, int fd2); +extern off_t bb_copyfd_size(int fd1, int fd2, off_t size); +extern off_t bb_copyfd_eof(int fd1, int fd2); extern char bb_process_escape_sequence(const char **ptr); extern char *bb_get_last_path_component(char *path); extern FILE *bb_wfopen(const char *path, const char *mode); diff --git a/libbb/copyfd.c b/libbb/copyfd.c index e9300a9..87126eb 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c @@ -21,10 +21,10 @@ #endif -static ssize_t bb_full_fd_action(int src_fd, int dst_fd, size_t size) +static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) { int status = -1; - size_t total = 0; + off_t total = 0; RESERVE_CONFIG_BUFFER(buffer,BUFSIZ); if (src_fd < 0) goto out; @@ -56,11 +56,11 @@ static ssize_t bb_full_fd_action(int src_fd, int dst_fd, size_t size) out: RELEASE_CONFIG_BUFFER(buffer); - return status ? status : (ssize_t)total; + return status ? status : total; } -int bb_copyfd_size(int fd1, int fd2, const off_t size) +off_t bb_copyfd_size(int fd1, int fd2, off_t size) { if (size) { return bb_full_fd_action(fd1, fd2, size); @@ -68,7 +68,7 @@ int bb_copyfd_size(int fd1, int fd2, const off_t size) return 0; } -int bb_copyfd_eof(int fd1, int fd2) +off_t bb_copyfd_eof(int fd1, int fd2) { return bb_full_fd_action(fd1, fd2, 0); } diff --git a/libbb/loop.c b/libbb/loop.c index 1b296d9..14835ec 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -133,7 +133,9 @@ int set_loop(char **device, const char *file, unsigned long long offset) without using losetup manually is problematic.) */ } else if (strcmp(file,(char *)loopinfo.lo_file_name) - || offset!=loopinfo.lo_offset) rc = -1; + || offset != loopinfo.lo_offset) { + rc = -1; + } close(dfd); try_again: if (*device) break; diff --git a/networking/ftpgetput.c b/networking/ftpgetput.c index 902528f..5d13e28 100644 --- a/networking/ftpgetput.c +++ b/networking/ftpgetput.c @@ -104,9 +104,11 @@ static FILE *ftp_login(ftp_host_info_t *server) } #if !ENABLE_FTPGET -#define ftp_receive 0 +int ftp_receive(ftp_host_info_t *server, FILE *control_stream, + const char *local_path, char *server_path); #else -static int ftp_receive(ftp_host_info_t *server, FILE *control_stream, +static +int ftp_receive(ftp_host_info_t *server, FILE *control_stream, const char *local_path, char *server_path) { char buf[512]; @@ -122,10 +124,8 @@ static int ftp_receive(ftp_host_info_t *server, FILE *control_stream, fd_data = xconnect_ftpdata(server, buf); if (ftpcmd("SIZE ", server_path, control_stream, buf) == 213) { - unsigned long value=filesize; - if (safe_strtoul(buf + 4, &value)) + if (SAFE_STRTOOFF(buf + 4, &filesize)) bb_error_msg_and_die("SIZE error: %s", buf + 4); - filesize = value; } else { filesize = -1; do_continue = 0; @@ -139,7 +139,7 @@ static int ftp_receive(ftp_host_info_t *server, FILE *control_stream, if (do_continue) { struct stat sbuf; if (lstat(local_path, &sbuf) < 0) { - bb_perror_msg_and_die("fstat()"); + bb_perror_msg_and_die("lstat"); } if (sbuf.st_size > 0) { beg_range = sbuf.st_size; @@ -149,7 +149,7 @@ static int ftp_receive(ftp_host_info_t *server, FILE *control_stream, } if (do_continue) { - sprintf(buf, "REST %ld", (long)beg_range); + sprintf(buf, "REST "OFF_FMT, beg_range); if (ftpcmd(buf, NULL, control_stream, buf) != 350) { do_continue = 0; } else { @@ -191,9 +191,11 @@ static int ftp_receive(ftp_host_info_t *server, FILE *control_stream, #endif #if !ENABLE_FTPPUT -#define ftp_send 0 +int ftp_send(ftp_host_info_t *server, FILE *control_stream, + const char *server_path, char *local_path); #else -static int ftp_send(ftp_host_info_t *server, FILE *control_stream, +static +int ftp_send(ftp_host_info_t *server, FILE *control_stream, const char *server_path, char *local_path) { struct stat sbuf; diff --git a/networking/httpd.c b/networking/httpd.c index f3fe49c..bbb2dfe 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -919,8 +919,8 @@ static int sendHeaders(HttpResponseNum responseNum) if (config->ContentLength != -1) { /* file */ strftime(timeStr, sizeof(timeStr), RFC1123FMT, gmtime(&config->last_mod)); - len += sprintf(buf+len, "Last-Modified: %s\r\n%s "FILEOFF_FMT"\r\n", - timeStr, Content_length, (FILEOFF_TYPE) config->ContentLength); + len += sprintf(buf+len, "Last-Modified: %s\r\n%s "OFF_FMT"\r\n", + timeStr, Content_length, (off_t) config->ContentLength); } strcat(buf, "\r\n"); len += 2; diff --git a/networking/wget.c b/networking/wget.c index e7b19f2..74feccc 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -29,9 +29,9 @@ static char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc); static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf); /* Globals (can be accessed from signal handlers */ -static FILEOFF_TYPE content_len; /* Content-length of the file */ -static FILEOFF_TYPE beg_range; /* Range at which continue begins */ -static FILEOFF_TYPE transferred; /* Number of bytes transferred so far */ +static off_t content_len; /* Content-length of the file */ +static off_t beg_range; /* Range at which continue begins */ +static off_t transferred; /* Number of bytes transferred so far */ static int chunked; /* chunked transfer encoding */ #ifdef CONFIG_FEATURE_WGET_STATUSBAR static void progressmeter(int flag); @@ -215,10 +215,10 @@ int wget_main(int argc, char **argv) opt |= WGET_OPT_QUIET; opt &= ~WGET_OPT_CONTINUE; } else if (opt & WGET_OPT_CONTINUE) { - output_fd = open(fname_out, O_WRONLY|O_LARGEFILE); + output_fd = open(fname_out, O_WRONLY); if (output_fd >= 0) { - beg_range = LSEEK(output_fd, 0, SEEK_END); - if (beg_range == (FILEOFF_TYPE)-1) + beg_range = lseek(output_fd, 0, SEEK_END); + if (beg_range == (off_t)-1) bb_perror_msg_and_die("lseek"); } /* File doesn't exist. We do not create file here yet. @@ -282,7 +282,7 @@ int wget_main(int argc, char **argv) #endif if (beg_range) - fprintf(sfp, "Range: bytes="FILEOFF_FMT"-\r\n", beg_range); + fprintf(sfp, "Range: bytes="OFF_FMT"-\r\n", beg_range); if(extra_headers_left < sizeof(extra_headers)) fputs(extra_headers,sfp); fprintf(sfp,"Connection: close\r\n\r\n"); @@ -413,7 +413,7 @@ read_response: dfp = open_socket(&s_in); if (beg_range) { - sprintf(buf, "REST "FILEOFF_FMT, beg_range); + sprintf(buf, "REST "OFF_FMT, beg_range); if (ftpcmd(buf, NULL, sfp, buf) == 350) content_len -= beg_range; } @@ -435,7 +435,7 @@ read_response: /* Do it before progressmeter (want to have nice error message) */ if (output_fd < 0) output_fd = xopen3(fname_out, - O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_LARGEFILE, 0666); + O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0666); if (!(opt & WGET_OPT_QUIET)) progressmeter(-1); @@ -685,10 +685,10 @@ static void progressmeter(int flag) { static struct timeval lastupdate; - static FILEOFF_TYPE lastsize, totalsize; + static off_t lastsize, totalsize; struct timeval now, td, tvwait; - FILEOFF_TYPE abbrevsize; + off_t abbrevsize; int elapsed, ratio, barlength, i; char buf[256]; @@ -739,7 +739,7 @@ progressmeter(int flag) if (tvwait.tv_sec >= STALLTIME) { fprintf(stderr, " - stalled -"); } else { - FILEOFF_TYPE to_download = totalsize - beg_range; + off_t to_download = totalsize - beg_range; if (transferred <= 0 || elapsed <= 0 || transferred > to_download || chunked) { fprintf(stderr, "--:--:-- ETA"); } else { -- 2.7.4