From aa4f9a2fd8a077c4e61e78fc397b47e541b0c140 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Fri, 28 Jan 2011 19:14:17 +0100 Subject: libbb/copy_file.c: use smallints instead of signed chars Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/copy_file.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'libbb') diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 57d9dbfdb..9333a8d49 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -78,9 +78,9 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) /* NB: each struct stat is ~100 bytes */ struct stat source_stat; struct stat dest_stat; - signed char retval = 0; - signed char dest_exists = 0; - signed char ovr; + smallint retval = 0; + smallint dest_exists = 0; + smallint ovr; /* Inverse of cp -d ("cp without -d") */ #define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0)) @@ -147,7 +147,6 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) return -1; } - /* Create DEST */ if (dest_exists) { if (!S_ISDIR(dest_stat.st_mode)) { bb_error_msg("target '%s' is not a directory", dest); @@ -156,6 +155,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) /* race here: user can substitute a symlink between * this check and actual creation of files inside dest */ } else { + /* Create DEST */ mode_t mode; saved_umask = umask(0); -- cgit v1.2.3-55-g6feb From 55ae0e9238e1979f0200700ec5dbd0df8d32f7a2 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen <curaga@operamail.com> Date: Mon, 31 Jan 2011 06:27:35 +0100 Subject: df,find_mount_point: optionally don't ignore rootfs Signed-off-by: Lauri Kasanen <curaga@operamail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- coreutils/df.c | 2 +- libbb/Config.src | 19 +++++++++++++++++++ libbb/find_mount_point.c | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) (limited to 'libbb') diff --git a/coreutils/df.c b/coreutils/df.c index af9b77b23..70fd1f4fd 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -160,7 +160,7 @@ int df_main(int argc UNUSED_PARAM, char **argv) } /* GNU coreutils 6.10 skips certain mounts, try to be compatible. */ - if (strcmp(device, "rootfs") == 0) + if (ENABLE_FEATURE_SKIP_ROOTFS && strcmp(device, "rootfs") == 0) continue; #ifdef WHY_WE_DO_IT_FOR_DEV_ROOT_ONLY diff --git a/libbb/Config.src b/libbb/Config.src index 85892d3fe..dfb897d5f 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -161,6 +161,25 @@ config FEATURE_COPYBUF_KB Bigger buffers will be allocated with mmap, with fallback to 4 kb stack buffer if mmap fails. +config FEATURE_SKIP_ROOTFS + bool "Skip rootfs in mount table" + default y + help + Ignore rootfs entry in mount table. + + In Linux, kernel has a special filesystem, rootfs, which is initially + mounted on /. It contains initramfs data, if kernel is configured + to have one. Usually, another file system is mounted over / early + in boot process, and therefore most tools which manipulate + mount table, such as df, will skip rootfs entry. + + However, some systems do not mount anything on /. + If you need to configure busybox for one of these systems, + you may find useful to turn this option off to make df show + initramfs statistic. + + Otherwise, choose Y. + config MONOTONIC_SYSCALL bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" default n diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c index 361698a6b..56637ad92 100644 --- a/libbb/find_mount_point.c +++ b/libbb/find_mount_point.c @@ -43,7 +43,7 @@ struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) /* rootfs mount in Linux 2.6 exists always, * and it makes sense to always ignore it. * Otherwise people can't reference their "real" root! */ - if (strcmp(mountEntry->mnt_fsname, "rootfs") == 0) + if (ENABLE_FEATURE_SKIP_ROOTFS && strcmp(mountEntry->mnt_fsname, "rootfs") == 0) continue; if (strcmp(name, mountEntry->mnt_dir) == 0 -- cgit v1.2.3-55-g6feb From c71b469f5daceb717e31cc9ce46b0e058e2c57b6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Wed, 2 Feb 2011 03:28:56 +0100 Subject: libbb: make BB_EXECVP/LP try to exec real binary if there's no /proc/self/exe Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- include/libbb.h | 12 +++++++----- libbb/execable.c | 10 +++++----- libbb/vfork_daemon_rexec.c | 12 ++++++------ 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index 182b47988..e69e27944 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -867,14 +867,16 @@ int exists_execable(const char *filename) FAST_FUNC; * but it may exec busybox and call applet instead of searching PATH. */ #if ENABLE_FEATURE_PREFER_APPLETS -int bb_execvp(const char *file, char *const argv[]) FAST_FUNC; -#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd) +int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC; #define BB_EXECLP(prog,cmd,...) \ - execlp((find_applet_by_name(prog) >= 0) ? CONFIG_BUSYBOX_EXEC_PATH : prog, \ - cmd, __VA_ARGS__) + do { \ + if (find_applet_by_name(prog) >= 0) \ + execlp(bb_busybox_exec_path, cmd, __VA_ARGS__); \ + execlp(prog, cmd, __VA_ARGS__); \ + } while (0) #else #define BB_EXECVP(prog,cmd) execvp(prog,cmd) -#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd, __VA_ARGS__) +#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__) #endif int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; diff --git a/libbb/execable.c b/libbb/execable.c index d37640007..178a00a5f 100644 --- a/libbb/execable.c +++ b/libbb/execable.c @@ -68,12 +68,12 @@ int FAST_FUNC exists_execable(const char *filename) } #if ENABLE_FEATURE_PREFER_APPLETS -/* just like the real execvp, but try to launch an applet named 'file' first - */ -int FAST_FUNC bb_execvp(const char *file, char *const argv[]) +/* just like the real execvp, but try to launch an applet named 'file' first */ +int FAST_FUNC BB_EXECVP(const char *file, char *const argv[]) { - return execvp(find_applet_by_name(file) >= 0 ? bb_busybox_exec_path : file, - argv); + if (find_applet_by_name(file) >= 0) + execvp(bb_busybox_exec_path, argv); + return execvp(file, argv); } #endif diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 5e0fb0d73..cb4781a59 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -182,17 +182,17 @@ int FAST_FUNC spawn_and_wait(char **argv) int a = find_applet_by_name(argv[0]); if (a >= 0 && (APPLET_IS_NOFORK(a) -#if BB_MMU +# if BB_MMU || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */ -#endif +# endif )) { -#if BB_MMU +# if BB_MMU if (APPLET_IS_NOFORK(a)) -#endif +# endif { return run_nofork_applet(a, argv); } -#if BB_MMU +# if BB_MMU /* MMU only */ /* a->noexec is true */ rc = fork(); @@ -201,7 +201,7 @@ int FAST_FUNC spawn_and_wait(char **argv) /* child */ xfunc_error_retval = EXIT_FAILURE; run_applet_no_and_exit(a, argv); -#endif +# endif } #endif /* FEATURE_PREFER_APPLETS */ rc = spawn(argv); -- cgit v1.2.3-55-g6feb From 6307357effb79c8fbc6ccc9d4528c8c1c48a4831 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Wed, 2 Feb 2011 19:05:25 +0100 Subject: move nofork_save_area from libbb.h to vfork_daemon_rexec.c Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- include/libbb.h | 11 ----------- libbb/getopt32.c | 2 +- libbb/vfork_daemon_rexec.c | 48 ++++++++++++++++++---------------------------- 3 files changed, 20 insertions(+), 41 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index 88dceb11d..a0e23697c 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -911,19 +911,8 @@ pid_t wait_any_nohang(int *wstat) FAST_FUNC; int wait4pid(pid_t pid) FAST_FUNC; /* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */ int spawn_and_wait(char **argv) FAST_FUNC; -struct nofork_save_area { - jmp_buf die_jmp; - const char *applet_name; - uint32_t option_mask32; - int die_sleep; - uint8_t xfunc_error_retval; - smallint saved; -}; -void save_nofork_data(struct nofork_save_area *save) FAST_FUNC; -void restore_nofork_data(struct nofork_save_area *save) FAST_FUNC; /* Does NOT check that applet is NOFORK, just blindly runs it */ int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; -int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv) FAST_FUNC; /* Helpers for daemonization. * diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 25bae319e..abd412043 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -531,7 +531,7 @@ getopt32(char **argv, const char *applet_opts, ...) /* In case getopt32 was already called: * reset the libc getopt() function, which keeps internal state. - * run_nofork_applet_prime() does this, but we might end up here + * run_nofork_applet() does this, but we might end up here * also via gunzip_main() -> gzip_main(). Play safe. */ #ifdef __GLIBC__ diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index cb4781a59..af938bed3 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -68,17 +68,22 @@ pid_t FAST_FUNC xspawn(char **argv) } #if ENABLE_FEATURE_PREFER_APPLETS -void FAST_FUNC save_nofork_data(struct nofork_save_area *save) +struct nofork_save_area { + jmp_buf die_jmp; + const char *applet_name; + uint32_t option_mask32; + int die_sleep; + uint8_t xfunc_error_retval; +}; +static void save_nofork_data(struct nofork_save_area *save) { memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); save->applet_name = applet_name; save->xfunc_error_retval = xfunc_error_retval; save->option_mask32 = option_mask32; save->die_sleep = die_sleep; - save->saved = 1; } - -void FAST_FUNC restore_nofork_data(struct nofork_save_area *save) +static void restore_nofork_data(struct nofork_save_area *save) { memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); applet_name = save->applet_name; @@ -87,19 +92,17 @@ void FAST_FUNC restore_nofork_data(struct nofork_save_area *save) die_sleep = save->die_sleep; } -int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv) +int FAST_FUNC run_nofork_applet(int applet_no, char **argv) { int rc, argc; + struct nofork_save_area old; + + save_nofork_data(&old); applet_name = APPLET_NAME(applet_no); xfunc_error_retval = EXIT_FAILURE; - /* Special flag for xfunc_die(). If xfunc will "die" - * in NOFORK applet, xfunc_die() sees negative - * die_sleep and longjmp here instead. */ - die_sleep = -1; - /* In case getopt() or getopt32() was already called: * reset the libc getopt() function, which keeps internal state. * @@ -129,6 +132,11 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n while (argv[argc]) argc++; + /* Special flag for xfunc_die(). If xfunc will "die" + * in NOFORK applet, xfunc_die() sees negative + * die_sleep and longjmp here instead. */ + die_sleep = -1; + rc = setjmp(die_jmp); if (!rc) { /* Some callers (xargs) @@ -137,15 +145,6 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); /* Finally we can call NOFORK applet's main() */ rc = applet_main[applet_no](argc, tmp_argv); - - /* The whole reason behind nofork_save_area is that <applet>_main - * may exit non-locally! For example, in hush Ctrl-Z tries - * (modulo bugs) to dynamically create a child (backgrounded task) - * if it detects that Ctrl-Z was pressed when a NOFORK was running. - * Testcase: interactive "rm -i". - * Don't fool yourself into thinking "and <applet>_main() returns - * quickly here" and removing "useless" nofork_save_area code. */ - } else { /* xfunc died in NOFORK applet */ /* in case they meant to return 0... */ if (rc == -2222) @@ -153,7 +152,7 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n } /* Restoring some globals */ - restore_nofork_data(old); + restore_nofork_data(&old); /* Other globals can be simply reset to defaults */ #ifdef __GLIBC__ @@ -164,15 +163,6 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ } - -int FAST_FUNC run_nofork_applet(int applet_no, char **argv) -{ - struct nofork_save_area old; - - /* Saving globals */ - save_nofork_data(&old); - return run_nofork_applet_prime(&old, applet_no, argv); -} #endif /* FEATURE_PREFER_APPLETS */ int FAST_FUNC spawn_and_wait(char **argv) -- cgit v1.2.3-55-g6feb From b7c9fb27cba3d697e602f8cbf88cde135d8d6c5e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 3 Feb 2011 00:05:48 +0100 Subject: whitespace fixes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- applets/usage_pod.c | 4 ++-- archival/lzop.c | 2 +- e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c | 4 ++-- editors/sed.c | 2 +- libbb/crc32.c | 2 +- libbb/getopt32.c | 8 ++++---- loginutils/getty.c | 2 +- modutils/modprobe.c | 2 +- networking/httpd_ssi.c | 4 ++-- networking/ntpd.c | 2 +- procps/pstree.c | 2 +- shell/shell_common.c | 6 +++--- util-linux/flock.c | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) (limited to 'libbb') diff --git a/applets/usage_pod.c b/applets/usage_pod.c index da0baefc6..0b1c4aadb 100644 --- a/applets/usage_pod.c +++ b/applets/usage_pod.c @@ -31,8 +31,8 @@ #include "usage.h" #define MAKE_USAGE(aname, usage) { aname, usage }, static struct usage_data { - const char *aname; - const char *usage; + const char *aname; + const char *usage; } usage_array[] = { #include "applets.h" }; diff --git a/archival/lzop.c b/archival/lzop.c index 094e78cf9..62455c313 100644 --- a/archival/lzop.c +++ b/archival/lzop.c @@ -401,7 +401,7 @@ struct globals { #define INIT_G() do { } while (0) //#define G (*ptr_to_globals) //#define INIT_G() do { -// SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); +// SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); //} while (0) diff --git a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c b/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c index b9aab440a..7d37d232d 100644 --- a/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c +++ b/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c @@ -155,8 +155,8 @@ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino) blk_t ext2fs_inode_data_blocks(ext2_filsys fs, struct ext2_inode *inode) { - return inode->i_blocks - - (inode->i_file_acl ? fs->blocksize >> 9 : 0); + return inode->i_blocks - + (inode->i_file_acl ? fs->blocksize >> 9 : 0); } diff --git a/editors/sed.c b/editors/sed.c index b91acfb7f..d3555243f 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -124,7 +124,7 @@ struct globals { } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) struct BUG_G_too_big { - char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; + char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; }; #define INIT_G() do { \ G.sed_cmd_tail = &G.sed_cmd_head; \ diff --git a/libbb/crc32.c b/libbb/crc32.c index c63bf0772..ac9836cc9 100644 --- a/libbb/crc32.c +++ b/libbb/crc32.c @@ -59,7 +59,7 @@ uint32_t FAST_FUNC crc32_block_endian0(uint32_t val, const void *buf, unsigned l const void *end = (uint8_t*)buf + len; while (buf != end) { - val = crc_table[(uint8_t)val ^ *(uint8_t*)buf] ^ (val >> 8); + val = crc_table[(uint8_t)val ^ *(uint8_t*)buf] ^ (val >> 8); buf = (uint8_t*)buf + 1; } return val; diff --git a/libbb/getopt32.c b/libbb/getopt32.c index abd412043..f3f1cfcba 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -80,9 +80,9 @@ const char *applet_long_options This struct allows you to define long options: static const char applet_longopts[] ALIGN1 = - //"name\0" has_arg val - "verbose\0" No_argument "v" - ; + //"name\0" has_arg val + "verbose\0" No_argument "v" + ; applet_long_options = applet_longopts; The last member of struct option (val) typically is set to @@ -226,7 +226,7 @@ Special characters: if specified together. In this case you must set opt_complementary = "b--cf:c--bf:f--bc". If two of the mutually exclusive options are found, getopt32 will call - bb_show_usage() and die. + bb_show_usage() and die. "x--x" Variation of the above, it means that -x option should occur at most once. diff --git a/loginutils/getty.c b/loginutils/getty.c index 34f72c465..3f20c8e81 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -334,7 +334,7 @@ static void termios_final(void) * IMAXBEL Echo BEL on input line too long * IUTF8 Appears to affect tty's idea of char widths, * observed to improve backspacing through Unicode chars - */ + */ /* line buffered input (NL or EOL or EOF chars end a line); * recognize INT/QUIT/SUSP chars; diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 8d2ccc562..0d28da7ea 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -170,7 +170,7 @@ struct globals { #define G (*(struct globals*)&bb_common_bufsiz1) #define INIT_G() do { } while (0) struct BUG_G_too_big { - char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; + char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; }; diff --git a/networking/httpd_ssi.c b/networking/httpd_ssi.c index 87f43fcfa..cfe64eb46 100644 --- a/networking/httpd_ssi.c +++ b/networking/httpd_ssi.c @@ -52,9 +52,9 @@ httpd_ssi.c -o httpd_ssi static char* skip_whitespace(char *s) { - while (*s == ' ' || *s == '\t') ++s; + while (*s == ' ' || *s == '\t') ++s; - return s; + return s; } static char line[64 * 1024]; diff --git a/networking/ntpd.c b/networking/ntpd.c index 8fe529edb..3ed05ba29 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -882,7 +882,7 @@ fit(peer_t *p, double rd) // /* Do we have a loop? */ // if (p->refid == p->dstaddr || p->refid == s.refid) // return 0; - return 1; + return 1; } static peer_t* select_and_cluster(void) diff --git a/procps/pstree.c b/procps/pstree.c index ddf5dba59..4cd8cb458 100644 --- a/procps/pstree.c +++ b/procps/pstree.c @@ -76,7 +76,7 @@ struct globals { }; #define G (*ptr_to_globals) #define INIT_G() do { \ - SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ } while (0) diff --git a/shell/shell_common.c b/shell/shell_common.c index e9effd2d0..f02ed81ea 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -368,9 +368,9 @@ shell_builtin_ulimit(char **argv) #endif /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ - argc = 1; - while (argv[argc]) - argc++; + argc = 1; + while (argv[argc]) + argc++; opts = 0; while (1) { diff --git a/util-linux/flock.c b/util-linux/flock.c index be3d552fa..77fe1f809 100644 --- a/util-linux/flock.c +++ b/util-linux/flock.c @@ -19,7 +19,7 @@ int flock_main(int argc UNUSED_PARAM, char **argv) }; #if ENABLE_LONG_OPTS - static const char getopt_longopts[] ALIGN1 = + static const char getopt_longopts[] ALIGN1 = "shared\0" No_argument "s" "exclusive\0" No_argument "x" "unlock\0" No_argument "u" -- cgit v1.2.3-55-g6feb From c5d0f15dbd8087f60b377fa9fc18d08698429189 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 3 Feb 2011 14:14:09 +0100 Subject: libbb: spawn should remove child which failed to exec Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/vfork_daemon_rexec.c | 1 + 1 file changed, 1 insertion(+) (limited to 'libbb') diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index af938bed3..a75eafbd3 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -52,6 +52,7 @@ pid_t FAST_FUNC spawn(char **argv) * Interested party can wait on pid and learn exit code. * If 111 - then it (most probably) failed to exec */ if (failed) { + safe_waitpid(pid, NULL, 0); /* prevent zombie */ errno = failed; return -1; } -- cgit v1.2.3-55-g6feb From 66c5b12dbf85142eea257ba6047191d7c0ee43f3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Tue, 8 Feb 2011 05:07:02 +0100 Subject: ash: fix TMOUT not restoring tty attributes function old new delta pgetc 420 500 +80 readtoken1 3202 3239 +37 read_line_input 3316 3337 +21 udhcpc_main 2610 2630 +20 file_get 266 272 +6 expandarg 958 963 +5 localcmd 257 259 +2 addLines 85 87 +2 read_line 94 95 +1 ed_main 2540 2541 +1 timed_out 1 - -1 lineedit_read_key 256 255 -1 alrm_sighandler 44 - -44 cmdloop 539 434 -105 ------------------------------------------------------------------------------ (add/remove: 0/2 grow/shrink: 10/2 up/down: 175/-151) Total: 24 bytes text data bss dec hex filename 887379 936 17200 905515 dd12b busybox_old 887411 936 17192 905539 dd143 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- editors/ed.c | 6 ++--- include/libbb.h | 5 ++-- libbb/lineedit.c | 12 ++++----- shell/ash.c | 73 ++++++++++++++++++++---------------------------------- shell/hush.c | 2 +- util-linux/fdisk.c | 2 +- 6 files changed, 39 insertions(+), 61 deletions(-) (limited to 'libbb') diff --git a/editors/ed.c b/editors/ed.c index 859668406..b1b6a8d27 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -129,7 +129,7 @@ static void doCommands(void) * 0 on ctrl-C, * >0 length of input string, including terminating '\n' */ - len = read_line_input(": ", buf, sizeof(buf), NULL); + len = read_line_input(NULL, ": ", buf, sizeof(buf), /*timeout*/ -1); if (len <= 0) return; endbuf = &buf[len - 1]; @@ -227,7 +227,7 @@ static void doCommands(void) } if (!dirty) return; - len = read_line_input("Really quit? ", buf, 16, NULL); + len = read_line_input(NULL, "Really quit? ", buf, 16, /*timeout*/ -1); /* read error/EOF - no way to continue */ if (len < 0) return; @@ -541,7 +541,7 @@ static void addLines(int num) * 0 on ctrl-C, * >0 length of input string, including terminating '\n' */ - len = read_line_input("", buf, sizeof(buf), NULL); + len = read_line_input(NULL, "", buf, sizeof(buf), /*timeout*/ -1); if (len <= 0) { /* Previously, ctrl-C was exiting to shell. * Now we exit to ed prompt. Is in important? */ diff --git a/include/libbb.h b/include/libbb.h index dd82e9754..78b390611 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1403,12 +1403,11 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC; * 0 on ctrl-C (the line entered is still returned in 'command'), * >0 length of input string, including terminating '\n' */ -/* NB: ash has timeout code which can be moved into read_line_input, if needed */ -int read_line_input(const char* prompt, char* command, int maxsize, line_input_t *state) FAST_FUNC; +int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; #else #define MAX_HISTORY 0 int read_line_input(const char* prompt, char* command, int maxsize) FAST_FUNC; -#define read_line_input(prompt, command, maxsize, state) \ +#define read_line_input(state, prompt, command, maxsize, timeout) \ read_line_input(prompt, command, maxsize) #endif diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 5dd835cca..afd28b75c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -1809,10 +1809,9 @@ static void win_changed(int nsig) errno = sv_errno; } -static int lineedit_read_key(char *read_key_buffer) +static int lineedit_read_key(char *read_key_buffer, int timeout) { int64_t ic; - int timeout = -1; #if ENABLE_UNICODE_SUPPORT char unicode_buf[MB_CUR_MAX + 1]; int unicode_idx = 0; @@ -1917,7 +1916,7 @@ static int isrtl_str(void) * 0 on ctrl-C (the line entered is still returned in 'command'), * >0 length of input string, including terminating '\n' */ -int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) +int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) { int len; #if ENABLE_FEATURE_TAB_COMPLETION @@ -1991,7 +1990,6 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li new_settings.c_cc[VINTR] = _POSIX_VDISABLE; tcsetattr_stdin_TCSANOW(&new_settings); - /* Now initialize things */ previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); win_changed(0); /* do initial resizing */ #if ENABLE_USERNAME_OR_HOMEDIR @@ -2033,7 +2031,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li int32_t ic, ic_raw; fflush_all(); - ic = ic_raw = lineedit_read_key(read_key_buffer); + ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); #if ENABLE_FEATURE_EDITING_VI newdelflag = 1; @@ -2194,7 +2192,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li case 'd'|VI_CMDMODE_BIT: { int nc, sc; - ic = lineedit_read_key(read_key_buffer); + ic = lineedit_read_key(read_key_buffer, timeout); if (errno) /* error */ goto return_error_indicator; if (ic == ic_raw) { /* "cc", "dd" */ @@ -2258,7 +2256,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li break; case 'r'|VI_CMDMODE_BIT: //FIXME: unicode case? - ic = lineedit_read_key(read_key_buffer); + ic = lineedit_read_key(read_key_buffer, timeout); if (errno) /* error */ goto return_error_indicator; if (ic < ' ' || ic > 255) { diff --git a/shell/ash.c b/shell/ash.c index bdc64790c..aaf21cd6f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -102,8 +102,7 @@ //config: default n //config: depends on ASH //config: help -//config: Enables bash-like auto-logout after "$TMOUT" seconds -//config: of idle time. +//config: Enables bash-like auto-logout after $TMOUT seconds of idle time. //config: //config:config ASH_JOB_CONTROL //config: bool "Job control" @@ -408,6 +407,9 @@ static const char *var_end(const char *var) /* ============ Interrupts / exceptions */ + +static void exitshell(void) NORETURN; + /* * These macros allow the user to suspend the handling of interrupt signals * over a period of time. This is similar to SIGHOLD or to sigblock, but @@ -9573,10 +9575,21 @@ preadfd(void) if (!iflag || g_parsefile->pf_fd != STDIN_FILENO) nr = nonblock_safe_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1); else { + int timeout = -1; +# if ENABLE_ASH_IDLE_TIMEOUT + if (iflag) { + const char *tmout_var = lookupvar("TMOUT"); + if (tmout_var) { + timeout = atoi(tmout_var) * 1000; + if (timeout <= 0) + timeout = -1; + } + } +# endif # if ENABLE_FEATURE_TAB_COMPLETION line_input_state->path_lookup = pathval(); # endif - nr = read_line_input(cmdedit_prompt, buf, IBUFSIZ, line_input_state); + nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); if (nr == 0) { /* Ctrl+C pressed */ if (trap[SIGINT]) { @@ -9587,9 +9600,17 @@ preadfd(void) } goto retry; } - if (nr < 0 && errno == 0) { - /* Ctrl+D pressed */ - nr = 0; + if (nr < 0) { + if (errno == 0) { + /* Ctrl+D pressed */ + nr = 0; + } +# if ENABLE_ASH_IDLE_TIMEOUT + else if (errno == EAGAIN && timeout > 0) { + printf("\007timed out waiting for input: auto-logout\n"); + exitshell(); + } +# endif } } #else @@ -12056,23 +12077,6 @@ evalcmd(int argc UNUSED_PARAM, char **argv) return exitstatus; } -#if ENABLE_ASH_IDLE_TIMEOUT -static smallint timed_out; - -static void alrm_sighandler(int sig UNUSED_PARAM) -{ - /* Close stdin, making interactive command reading stop. - * Otherwise, timeout doesn't trigger until <Enter> is pressed. - */ - int sv = errno; - close(0); - open("/dev/null", O_RDONLY); - errno = sv; - - timed_out = 1; -} -#endif - /* * Read and execute commands. * "Top" is nonzero for the top level command loop; @@ -12089,20 +12093,6 @@ cmdloop(int top) TRACE(("cmdloop(%d) called\n", top)); for (;;) { int skip; -#if ENABLE_ASH_IDLE_TIMEOUT - int tmout_seconds = 0; - - if (top && iflag) { - const char *tmout_var = lookupvar("TMOUT"); - if (tmout_var) { - tmout_seconds = atoi(tmout_var); - if (tmout_seconds > 0) { - signal(SIGALRM, alrm_sighandler); - alarm(tmout_seconds); - } - } - } -#endif setstackmark(&smark); #if JOBS @@ -12115,14 +12105,6 @@ cmdloop(int top) chkmail(); } n = parsecmd(inter); -#if ENABLE_ASH_IDLE_TIMEOUT - if (timed_out) { - printf("\007timed out waiting for input: auto-logout\n"); - break; - } - if (tmout_seconds > 0) - alarm(0); -#endif #if DEBUG if (DEBUG > 2 && debug && (n != NODE_EOF)) showtree(n); @@ -12850,7 +12832,6 @@ ulimitcmd(int argc UNUSED_PARAM, char **argv) /* * Called to exit the shell. */ -static void exitshell(void) NORETURN; static void exitshell(void) { diff --git a/shell/hush.c b/shell/hush.c index e857e7464..00ef361cd 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1902,7 +1902,7 @@ static void get_user_input(struct in_str *i) G.flag_SIGINT = 0; /* buglet: SIGINT will not make new prompt to appear _at once_, * only after <Enter>. (^C will work) */ - r = read_line_input(prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, G.line_input_state); + r = read_line_input(G.line_input_state, prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, /*timeout*/ -1); /* catch *SIGINT* etc (^C is handled by read_line_input) */ check_and_run_traps(0); } while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */ diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 02785ab85..0b93c22cc 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -548,7 +548,7 @@ read_line(const char *prompt) { int sz; - sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL); + sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1); if (sz <= 0) exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ -- cgit v1.2.3-55-g6feb From df4e16c9af6d6270d91d17d31c6098ecb259e5cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 10 Feb 2011 06:29:06 +0100 Subject: wget: use FEATURE_COPYBUF_KB-sized buffer. Much faster for local transfers function old new delta base64enc - 53 +53 gethdr 190 200 +10 ftpcmd 129 133 +4 progress_meter 160 122 -38 retrieve_file_data 431 392 -39 base64enc_512 46 - -46 wget_main 2456 2220 -236 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 2/3 up/down: 67/-359) Total: -292 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/Config.src | 2 +- networking/wget.c | 121 +++++++++++++++++++++++++++--------------------------- 2 files changed, 62 insertions(+), 61 deletions(-) (limited to 'libbb') diff --git a/libbb/Config.src b/libbb/Config.src index dfb897d5f..18bdc5151 100644 --- a/libbb/Config.src +++ b/libbb/Config.src @@ -156,7 +156,7 @@ config FEATURE_COPYBUF_KB range 1 1024 default 4 help - Size of buffer used by cp, mv, install etc. + Size of buffer used by cp, mv, install, wget etc. Buffers which are 4 kb or less will be allocated on stack. Bigger buffers will be allocated with mmap, with fallback to 4 kb stack buffer if mmap fails. diff --git a/networking/wget.c b/networking/wget.c index 0db9b3365..8e636bd39 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -35,12 +35,16 @@ struct globals { #endif smallint chunked; /* chunked transfer encoding */ smallint got_clen; /* got content-length: from server */ + /* Local downloads do benefit from big buffer. + * With 512 byte buffer, it was measured to be + * an order of magnitude slower than with big one. + */ + uint64_t just_to_align_next_member; + char wget_buf[CONFIG_FEATURE_COPYBUF_KB*1024]; } FIX_ALIASING; -#define G (*(struct globals*)&bb_common_bufsiz1) -struct BUG_G_too_big { - char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; -}; +#define G (*ptr_to_globals) #define INIT_G() do { \ + SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \ } while (0) @@ -158,14 +162,14 @@ static char *safe_fgets(char *s, int size, FILE *stream) } #if ENABLE_FEATURE_WGET_AUTHENTICATION -/* Base64-encode character string. buf is assumed to be char buf[512]. */ -static char *base64enc_512(char buf[512], const char *str) +/* Base64-encode character string. */ +static char *base64enc(const char *str) { unsigned len = strlen(str); - if (len > 512/4*3 - 10) /* paranoia */ - len = 512/4*3 - 10; - bb_uuencode(buf, str, len, bb_uuenc_tbl_base64); - return buf; + if (len > sizeof(G.wget_buf)/4*3 - 10) /* paranoia */ + len = sizeof(G.wget_buf)/4*3 - 10; + bb_uuencode(G.wget_buf, str, len, bb_uuenc_tbl_base64); + return G.wget_buf; } #endif @@ -191,7 +195,7 @@ static FILE *open_socket(len_and_sockaddr *lsa) return fp; } -static int ftpcmd(const char *s1, const char *s2, FILE *fp, char *buf) +static int ftpcmd(const char *s1, const char *s2, FILE *fp) { int result; if (s1) { @@ -203,18 +207,18 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp, char *buf) do { char *buf_ptr; - if (fgets(buf, 510, fp) == NULL) { + if (fgets(G.wget_buf, sizeof(G.wget_buf)-2, fp) == NULL) { bb_perror_msg_and_die("error getting response"); } - buf_ptr = strstr(buf, "\r\n"); + buf_ptr = strstr(G.wget_buf, "\r\n"); if (buf_ptr) { *buf_ptr = '\0'; } - } while (!isdigit(buf[0]) || buf[3] != ' '); + } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); - buf[3] = '\0'; - result = xatoi_positive(buf); - buf[3] = ' '; + G.wget_buf[3] = '\0'; + result = xatoi_positive(G.wget_buf); + G.wget_buf[3] = ' '; return result; } @@ -278,7 +282,7 @@ static void parse_url(char *src_url, struct host_info *h) sp = h->host; } -static char *gethdr(char *buf, size_t bufsiz, FILE *fp /*, int *istrunc*/) +static char *gethdr(FILE *fp /*, int *istrunc*/) { char *s, *hdrval; int c; @@ -286,24 +290,24 @@ static char *gethdr(char *buf, size_t bufsiz, FILE *fp /*, int *istrunc*/) /* *istrunc = 0; */ /* retrieve header line */ - if (fgets(buf, bufsiz, fp) == NULL) + if (fgets(G.wget_buf, sizeof(G.wget_buf), fp) == NULL) return NULL; /* see if we are at the end of the headers */ - for (s = buf; *s == '\r'; ++s) + for (s = G.wget_buf; *s == '\r'; ++s) continue; if (*s == '\n') return NULL; /* convert the header name to lower case */ - for (s = buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) { + for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) { /* tolower for "A-Z", no-op for "0-9a-z-." */ *s = (*s | 0x20); } /* verify we are at the end of the header name */ if (*s != ':') - bb_error_msg_and_die("bad header line: %s", sanitize_string(buf)); + bb_error_msg_and_die("bad header line: %s", sanitize_string(G.wget_buf)); /* locate the start of the header value */ *s++ = '\0'; @@ -366,7 +370,6 @@ static char *URL_escape(const char *str) static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_sockaddr *lsa) { - char buf[512]; FILE *sfp; char *str; int port; @@ -375,8 +378,8 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ target->user = xstrdup("anonymous:busybox@"); sfp = open_socket(lsa); - if (ftpcmd(NULL, NULL, sfp, buf) != 220) - bb_error_msg_and_die("%s", sanitize_string(buf+4)); + if (ftpcmd(NULL, NULL, sfp) != 220) + bb_error_msg_and_die("%s", sanitize_string(G.wget_buf + 4)); /* * Splitting username:password pair, @@ -385,24 +388,24 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ str = strchr(target->user, ':'); if (str) *str++ = '\0'; - switch (ftpcmd("USER ", target->user, sfp, buf)) { + switch (ftpcmd("USER ", target->user, sfp)) { case 230: break; case 331: - if (ftpcmd("PASS ", str, sfp, buf) == 230) + if (ftpcmd("PASS ", str, sfp) == 230) break; /* fall through (failed login) */ default: - bb_error_msg_and_die("ftp login: %s", sanitize_string(buf+4)); + bb_error_msg_and_die("ftp login: %s", sanitize_string(G.wget_buf + 4)); } - ftpcmd("TYPE I", NULL, sfp, buf); + ftpcmd("TYPE I", NULL, sfp); /* * Querying file size */ - if (ftpcmd("SIZE ", target->path, sfp, buf) == 213) { - G.content_len = BB_STRTOOFF(buf+4, NULL, 10); + if (ftpcmd("SIZE ", target->path, sfp) == 213) { + G.content_len = BB_STRTOOFF(G.wget_buf + 4, NULL, 10); if (G.content_len < 0 || errno) { bb_error_msg_and_die("SIZE value is garbage"); } @@ -412,20 +415,20 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ /* * Entering passive mode */ - if (ftpcmd("PASV", NULL, sfp, buf) != 227) { + if (ftpcmd("PASV", NULL, sfp) != 227) { pasv_error: - bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(buf)); + bb_error_msg_and_die("bad response to %s: %s", "PASV", sanitize_string(G.wget_buf)); } // Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage] // Server's IP is N1.N2.N3.N4 (we ignore it) // Server's port for data connection is P1*256+P2 - str = strrchr(buf, ')'); + str = strrchr(G.wget_buf, ')'); if (str) str[0] = '\0'; - str = strrchr(buf, ','); + str = strrchr(G.wget_buf, ','); if (!str) goto pasv_error; port = xatou_range(str+1, 0, 255); *str = '\0'; - str = strrchr(buf, ','); + str = strrchr(G.wget_buf, ','); if (!str) goto pasv_error; port += xatou_range(str+1, 0, 255) * 256; set_nport(lsa, htons(port)); @@ -433,20 +436,19 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ *dfpp = open_socket(lsa); if (G.beg_range) { - sprintf(buf, "REST %"OFF_FMT"u", G.beg_range); - if (ftpcmd(buf, NULL, sfp, buf) == 350) + sprintf(G.wget_buf, "REST %"OFF_FMT"u", G.beg_range); + if (ftpcmd(G.wget_buf, NULL, sfp) == 350) G.content_len -= G.beg_range; } - if (ftpcmd("RETR ", target->path, sfp, buf) > 150) - bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(buf)); + if (ftpcmd("RETR ", target->path, sfp) > 150) + bb_error_msg_and_die("bad response to %s: %s", "RETR", sanitize_string(G.wget_buf)); return sfp; } static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) { - char buf[512]; #if ENABLE_FEATURE_WGET_STATUSBAR || ENABLE_FEATURE_WGET_TIMEOUT # if ENABLE_FEATURE_WGET_TIMEOUT unsigned second_cnt; @@ -468,9 +470,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) int n; unsigned rdsz; - rdsz = sizeof(buf); + rdsz = sizeof(G.wget_buf); if (G.got_clen) { - if (G.content_len < (off_t)sizeof(buf)) { + if (G.content_len < (off_t)sizeof(G.wget_buf)) { if ((int)G.content_len <= 0) break; rdsz = (unsigned)G.content_len; @@ -493,7 +495,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) progress_meter(PROGRESS_BUMP); } #endif - n = safe_fread(buf, rdsz, dfp); + n = safe_fread(G.wget_buf, rdsz, dfp); if (n <= 0) { if (ferror(dfp)) { /* perror will not work: ferror doesn't set errno */ @@ -501,7 +503,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) } break; } - xwrite(output_fd, buf, n); + xwrite(output_fd, G.wget_buf, n); #if ENABLE_FEATURE_WGET_STATUSBAR G.transferred += n; progress_meter(PROGRESS_BUMP); @@ -513,10 +515,10 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) if (!G.chunked) break; - safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */ + safe_fgets(G.wget_buf, sizeof(G.wget_buf), dfp); /* This is a newline */ get_clen: - safe_fgets(buf, sizeof(buf), dfp); - G.content_len = STRTOOFF(buf, NULL, 16); + safe_fgets(G.wget_buf, sizeof(G.wget_buf), dfp); + G.content_len = STRTOOFF(G.wget_buf, NULL, 16); /* FIXME: error check? */ if (G.content_len == 0) break; /* all done! */ @@ -529,7 +531,6 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int wget_main(int argc UNUSED_PARAM, char **argv) { - char buf[512]; struct host_info server, target; len_and_sockaddr *lsa; unsigned opt; @@ -709,11 +710,11 @@ int wget_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_WGET_AUTHENTICATION if (target.user) { fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, - base64enc_512(buf, target.user)); + base64enc(target.user)); } if (use_proxy && server.user) { fprintf(sfp, "Proxy-Authorization: Basic %s\r\n", - base64enc_512(buf, server.user)); + base64enc(server.user)); } #endif @@ -743,10 +744,10 @@ int wget_main(int argc UNUSED_PARAM, char **argv) * Retrieve HTTP response line and check for "200" status code. */ read_response: - if (fgets(buf, sizeof(buf), sfp) == NULL) + if (fgets(G.wget_buf, sizeof(G.wget_buf), sfp) == NULL) bb_error_msg_and_die("no response from server"); - str = buf; + str = G.wget_buf; str = skip_non_whitespace(str); str = skip_whitespace(str); // FIXME: no error check @@ -755,7 +756,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv) switch (status) { case 0: case 100: - while (gethdr(buf, sizeof(buf), sfp /*, &n*/) != NULL) + while (gethdr(sfp /*, &n*/) != NULL) /* eat all remaining headers */; goto read_response; case 200: @@ -795,13 +796,13 @@ However, in real world it was observed that some web servers break; /* fall through */ default: - bb_error_msg_and_die("server returned error: %s", sanitize_string(buf)); + bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf)); } /* * Retrieve HTTP headers. */ - while ((str = gethdr(buf, sizeof(buf), sfp /*, &n*/)) != NULL) { + while ((str = gethdr(sfp /*, &n*/)) != NULL) { /* gethdr converted "FOO:" string to lowercase */ smalluint key; /* strip trailing whitespace */ @@ -810,7 +811,7 @@ However, in real world it was observed that some web servers *s = '\0'; s--; } - key = index_in_strings(keywords, buf) + 1; + key = index_in_strings(keywords, G.wget_buf) + 1; if (key == KEY_content_length) { G.content_len = BB_STRTOOFF(str, NULL, 10); if (G.content_len < 0 || errno) { @@ -881,9 +882,9 @@ However, in real world it was observed that some web servers if (dfp != sfp) { /* It's ftp. Close it properly */ fclose(dfp); - if (ftpcmd(NULL, NULL, sfp, buf) != 226) - bb_error_msg_and_die("ftp error: %s", sanitize_string(buf+4)); - /* ftpcmd("QUIT", NULL, sfp, buf); - why bother? */ + if (ftpcmd(NULL, NULL, sfp) != 226) + bb_error_msg_and_die("ftp error: %s", sanitize_string(G.wget_buf + 4)); + /* ftpcmd("QUIT", NULL, sfp); - why bother? */ } return EXIT_SUCCESS; -- cgit v1.2.3-55-g6feb From dee0fc9da1b53efc4c5e0596428dda556995bc26 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 10 Feb 2011 10:01:49 +0100 Subject: save 10 bytes on strings Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/messages.c | 2 +- networking/wget.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'libbb') diff --git a/libbb/messages.c b/libbb/messages.c index 2acbc3bca..fad82c9da 100644 --- a/libbb/messages.c +++ b/libbb/messages.c @@ -22,7 +22,7 @@ const char bb_banner[] ALIGN1 = BANNER; -const char bb_msg_memory_exhausted[] ALIGN1 = "memory exhausted"; +const char bb_msg_memory_exhausted[] ALIGN1 = "out of memory"; const char bb_msg_invalid_date[] ALIGN1 = "invalid date '%s'"; const char bb_msg_unknown[] ALIGN1 = "(unknown)"; const char bb_msg_can_not_create_raw_socket[] ALIGN1 = "can't create raw socket"; diff --git a/networking/wget.c b/networking/wget.c index 8028f1230..74d90040f 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -192,7 +192,7 @@ static FILE *open_socket(len_and_sockaddr *lsa) /* hopefully it understands what ESPIPE means... */ fp = fdopen(xconnect_stream(lsa), "r+"); if (fp == NULL) - bb_perror_msg_and_die("fdopen"); + bb_perror_msg_and_die(bb_msg_memory_exhausted); return fp; } -- cgit v1.2.3-55-g6feb From 805aa9fec923109e90c87eda2f116ee2fa5fe962 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 10 Feb 2011 14:25:51 +0100 Subject: progress bar: better overflow protection; more precise bar function old new delta bb_progress_update 639 749 +110 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- include/libbb.h | 5 +++-- libbb/progress.c | 54 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 25 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index d390e6840..c0178801f 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1592,8 +1592,9 @@ typedef struct bb_progress_t { void bb_progress_init(bb_progress_t *p) FAST_FUNC; void bb_progress_update(bb_progress_t *p, const char *curfile, - off_t beg_range, off_t transferred, - off_t totalsize) FAST_FUNC; + uoff_t beg_range, + uoff_t transferred, + uoff_t totalsize) FAST_FUNC; extern const char *applet_name; diff --git a/libbb/progress.c b/libbb/progress.c index 40608b047..ced04ac32 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -62,35 +62,45 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p) void FAST_FUNC bb_progress_update(bb_progress_t *p, const char *curfile, - off_t beg_range, - off_t transferred, - off_t totalsize) + uoff_t beg_range, + uoff_t transferred, + uoff_t totalsize) { uoff_t beg_and_transferred; unsigned since_last_update, elapsed; unsigned ratio; - int barlength, i; + int barlength; + int kiloscale; /* totalsize == 0 if it is unknown */ + beg_and_transferred = beg_range + transferred; + elapsed = monotonic_sec(); since_last_update = elapsed - p->lastupdate_sec; /* Do not update on every call * (we can be called on every network read!) */ - if (since_last_update == 0 && !totalsize) + if (since_last_update == 0 && beg_and_transferred < totalsize) return; - beg_and_transferred = beg_range + transferred; - ratio = 100; - if (beg_and_transferred < totalsize) { - /* Do not update on every call - * (we can be called on every network read!) */ - if (since_last_update == 0) - return; - /* long long helps to have it working even if !LFS */ - ratio = 100ULL * beg_and_transferred / (uoff_t)totalsize; + /* Scale sizes down if they are close to overflowing. + * If off_t is only 32 bits, this allows calculations + * like (100 * transferred / totalsize) without risking overflow. + * Introduced error is < 0.1% + */ + kiloscale = 0; + if (totalsize >= (1 << 20)) { + totalsize >>= 10; + beg_range >>= 10; + transferred >>= 10; + beg_and_transferred >>= 10; + kiloscale++; } + if (beg_and_transferred >= totalsize) + beg_and_transferred = totalsize; + + ratio = 100 * beg_and_transferred / totalsize; #if ENABLE_UNICODE_SUPPORT init_unicode(); { @@ -106,21 +116,20 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, if (barlength > 0) { /* god bless gcc for variable arrays :) */ char buf[barlength + 1]; - unsigned stars = (unsigned)barlength * ratio / (unsigned)100; + unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; memset(buf, ' ', barlength); buf[barlength] = '\0'; memset(buf, '*', stars); fprintf(stderr, "|%s|", buf); } - i = 0; while (beg_and_transferred >= 100000) { - i++; + kiloscale++; beg_and_transferred >>= 10; } /* see http://en.wikipedia.org/wiki/Tera */ - fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[i]); -#define beg_and_transferred dont_use_beg_and_transferred_below + fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); +#define beg_and_transferred dont_use_beg_and_transferred_below() if (transferred > p->lastsize) { p->lastupdate_sec = elapsed; @@ -137,13 +146,12 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, if (since_last_update >= STALLTIME) { fprintf(stderr, " - stalled -"); } else { - off_t to_download = totalsize - beg_range; - if (!totalsize || transferred <= 0 || (int)elapsed <= 0 || transferred > to_download) { + uoff_t to_download = totalsize - beg_range; + if (!totalsize || (int)elapsed <= 0 || transferred > to_download) { fprintf(stderr, "--:--:-- ETA"); } else { /* to_download / (transferred/elapsed) - elapsed: */ - /* (long long helps to have working ETA even if !LFS) */ - unsigned eta = (unsigned long long)to_download*elapsed/(uoff_t)transferred - elapsed; + unsigned eta = to_download * elapsed / transferred - elapsed; unsigned secs = eta % 3600; unsigned hours = eta / 3600; fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60); -- cgit v1.2.3-55-g6feb From f836f01cc3eb39e5e4c7186f50b456b57fae2010 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 10 Feb 2011 23:02:28 +0100 Subject: wget: shrink progress meter code; strink wget and add debug logging function old new delta fgets_and_trim - 73 +73 retrieve_file_data 367 349 -18 bb_progress_update 723 699 -24 wget_main 2220 2190 -30 ftpcmd 133 87 -46 gethdr 200 153 -47 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/5 up/down: 73/-165) Total: -92 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/progress.c | 95 +++++++++++++++++++++++++++++++++++++------------------ networking/wget.c | 74 +++++++++++++++++++++++-------------------- 2 files changed, 105 insertions(+), 64 deletions(-) (limited to 'libbb') diff --git a/libbb/progress.c b/libbb/progress.c index ced04ac32..a490b8390 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -60,9 +60,16 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p) p->inited = 1; } +/* File already had beg_size bytes. + * Then we started downloading. + * We downloaded "transferred" bytes so far. + * Download is expected to stop when total size (beg_size + transferred) + * will be "totalsize" bytes. + * If totalsize == 0, then it is unknown. + */ void FAST_FUNC bb_progress_update(bb_progress_t *p, const char *curfile, - uoff_t beg_range, + uoff_t beg_size, uoff_t transferred, uoff_t totalsize) { @@ -72,32 +79,53 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, int barlength; int kiloscale; - /* totalsize == 0 if it is unknown */ - - beg_and_transferred = beg_range + transferred; + beg_and_transferred = beg_size + transferred; elapsed = monotonic_sec(); since_last_update = elapsed - p->lastupdate_sec; - /* Do not update on every call - * (we can be called on every network read!) */ + /* + * Do not update on every call + * (we can be called on every network read!) + */ if (since_last_update == 0 && beg_and_transferred < totalsize) return; - /* Scale sizes down if they are close to overflowing. - * If off_t is only 32 bits, this allows calculations - * like (100 * transferred / totalsize) without risking overflow. - * Introduced error is < 0.1% - */ kiloscale = 0; - if (totalsize >= (1 << 20)) { - totalsize >>= 10; - beg_range >>= 10; - transferred >>= 10; - beg_and_transferred >>= 10; - kiloscale++; + /* + * Scale sizes down if they are close to overflowing. + * This allows calculations like (100 * transferred / totalsize) + * without risking overflow: we guarantee 10 highest bits to be 0. + * Introduced error is less than 1 / 2^12 ~= 0.025% + */ + if (ULONG_MAX > 0xffffffff || sizeof(off_t) == 4 || sizeof(off_t) != 8) { + /* + * 64-bit CPU || small off_t: in either case, + * >> is cheap, single-word operation. + * ... || strange off_t: also use this code (it is safe, + * even if suboptimal), because 32/64 optimized one + * works only for 64-bit off_t. + */ + if (totalsize >= (1 << 22)) { + totalsize >>= 10; + beg_size >>= 10; + transferred >>= 10; + beg_and_transferred >>= 10; + kiloscale = 1; + } + } else { + /* 32-bit CPU and 64-bit off_t. + * Pick a shift (40 bits) which is easier to do on 32-bit CPU. + */ + if (totalsize >= (uoff_t)(1ULL << 54)) { + totalsize = (uint32_t)(totalsize >> 32) >> 8; + beg_size = (uint32_t)(beg_size >> 32) >> 8; + transferred = (uint32_t)(transferred >> 32) >> 8; + beg_and_transferred = (uint32_t)(beg_and_transferred >> 32) >> 8; + kiloscale = 4; + } } - if (beg_and_transferred >= totalsize) + if (beg_and_transferred > totalsize) beg_and_transferred = totalsize; ratio = 100 * beg_and_transferred / totalsize; @@ -124,14 +152,14 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, } while (beg_and_transferred >= 100000) { - kiloscale++; beg_and_transferred >>= 10; + kiloscale++; } /* see http://en.wikipedia.org/wiki/Tera */ fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); #define beg_and_transferred dont_use_beg_and_transferred_below() - if (transferred > p->lastsize) { + if (transferred != p->lastsize) { p->lastupdate_sec = elapsed; p->lastsize = transferred; if (since_last_update >= STALLTIME) { @@ -141,20 +169,27 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, } since_last_update = 0; /* we are un-stalled now */ } + elapsed -= p->start_sec; /* now it's "elapsed since start" */ if (since_last_update >= STALLTIME) { fprintf(stderr, " - stalled -"); + } else if (!totalsize || !transferred || (int)elapsed <= 0) { + fprintf(stderr, "--:--:-- ETA"); } else { - uoff_t to_download = totalsize - beg_range; - if (!totalsize || (int)elapsed <= 0 || transferred > to_download) { - fprintf(stderr, "--:--:-- ETA"); - } else { - /* to_download / (transferred/elapsed) - elapsed: */ - unsigned eta = to_download * elapsed / transferred - elapsed; - unsigned secs = eta % 3600; - unsigned hours = eta / 3600; - fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60); - } + unsigned eta, secs, hours; + + totalsize -= beg_size; /* now it's "total to upload" */ + + /* Estimated remaining time = + * estimated_sec_to_dl_totalsize_bytes - elapsed_sec = + * totalsize / average_bytes_sec_so_far - elapsed = + * totalsize / (transferred/elapsed) - elapsed = + * totalsize * elapsed / transferred - elapsed + */ + eta = totalsize * elapsed / transferred - elapsed; + secs = eta % 3600; + hours = eta / 3600; + fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60); } } diff --git a/networking/wget.c b/networking/wget.c index 931882fde..d81426e8d 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -10,6 +10,10 @@ */ #include "libbb.h" +//#define log_io(...) bb_error_msg(__VA_ARGS__) +#define log_io(...) ((void)0) + + struct host_info { // May be used if we ever will want to free() all xstrdup()s... /* char *allocated; */ @@ -197,25 +201,39 @@ static FILE *open_socket(len_and_sockaddr *lsa) return fp; } +/* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ +static char fgets_and_trim(FILE *fp) +{ + char c; + char *buf_ptr; + + if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL) + bb_perror_msg_and_die("error getting response"); + + buf_ptr = strchrnul(G.wget_buf, '\n'); + c = *buf_ptr; + *buf_ptr = '\0'; + buf_ptr = strchrnul(G.wget_buf, '\r'); + *buf_ptr = '\0'; + + log_io("< %s", G.wget_buf); + + return c; +} + static int ftpcmd(const char *s1, const char *s2, FILE *fp) { int result; if (s1) { - if (!s2) s2 = ""; + if (!s2) + s2 = ""; fprintf(fp, "%s%s\r\n", s1, s2); fflush(fp); + log_io("> %s%s", s1, s2); } do { - char *buf_ptr; - - if (fgets(G.wget_buf, sizeof(G.wget_buf)-2, fp) == NULL) { - bb_perror_msg_and_die("error getting response"); - } - buf_ptr = strstr(G.wget_buf, "\r\n"); - if (buf_ptr) { - *buf_ptr = '\0'; - } + fgets_and_trim(fp); } while (!isdigit(G.wget_buf[0]) || G.wget_buf[3] != ' '); G.wget_buf[3] = '\0'; @@ -284,7 +302,7 @@ static void parse_url(char *src_url, struct host_info *h) sp = h->host; } -static char *gethdr(FILE *fp /*, int *istrunc*/) +static char *gethdr(FILE *fp) { char *s, *hdrval; int c; @@ -292,19 +310,16 @@ static char *gethdr(FILE *fp /*, int *istrunc*/) /* *istrunc = 0; */ /* retrieve header line */ - if (fgets(G.wget_buf, sizeof(G.wget_buf), fp) == NULL) - return NULL; + c = fgets_and_trim(fp); - /* see if we are at the end of the headers */ - for (s = G.wget_buf; *s == '\r'; ++s) - continue; - if (*s == '\n') + /* end of the headers? */ + if (G.wget_buf[0] == '\0') return NULL; /* convert the header name to lower case */ for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) { /* tolower for "A-Z", no-op for "0-9a-z-." */ - *s = (*s | 0x20); + *s |= 0x20; } /* verify we are at the end of the header name */ @@ -315,20 +330,12 @@ static char *gethdr(FILE *fp /*, int *istrunc*/) *s++ = '\0'; hdrval = skip_whitespace(s); - /* locate the end of header */ - while (*s && *s != '\r' && *s != '\n') - ++s; - - /* end of header found */ - if (*s) { - *s = '\0'; - return hdrval; + if (c != '\n') { + /* Rats! The buffer isn't big enough to hold the entire header value */ + while (c = getc(fp), c != EOF && c != '\n') + continue; } - /* Rats! The buffer isn't big enough to hold the entire header value */ - while (c = getc(fp), c != EOF && c != '\n') - continue; - /* *istrunc = 1; */ return hdrval; } @@ -520,9 +527,9 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd) if (!G.chunked) break; - fgets(G.wget_buf, sizeof(G.wget_buf), dfp); /* This is a newline */ + fgets_and_trim(dfp); /* This is a newline */ get_clen: - fgets(G.wget_buf, sizeof(G.wget_buf), dfp); + fgets_and_trim(dfp); G.content_len = STRTOOFF(G.wget_buf, NULL, 16); /* FIXME: error check? */ if (G.content_len == 0) @@ -757,8 +764,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv) * Retrieve HTTP response line and check for "200" status code. */ read_response: - if (fgets(G.wget_buf, sizeof(G.wget_buf), sfp) == NULL) - bb_error_msg_and_die("no response from server"); + fgets_and_trim(sfp); str = G.wget_buf; str = skip_non_whitespace(str); -- cgit v1.2.3-55-g6feb From 838d4bb0cd0805e1671073627d86baf100af021b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Thu, 10 Feb 2011 23:35:52 +0100 Subject: progress meter: display >999 hours ETA correctly Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/progress.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'libbb') diff --git a/libbb/progress.c b/libbb/progress.c index a490b8390..3999e0f38 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -156,7 +156,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, kiloscale++; } /* see http://en.wikipedia.org/wiki/Tera */ - fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); + fprintf(stderr, "%6u%c", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); #define beg_and_transferred dont_use_beg_and_transferred_below() if (transferred != p->lastsize) { @@ -173,9 +173,9 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, elapsed -= p->start_sec; /* now it's "elapsed since start" */ if (since_last_update >= STALLTIME) { - fprintf(stderr, " - stalled -"); + fprintf(stderr, " - stalled -"); } else if (!totalsize || !transferred || (int)elapsed <= 0) { - fprintf(stderr, "--:--:-- ETA"); + fprintf(stderr, " --:--:-- ETA"); } else { unsigned eta, secs, hours; @@ -188,8 +188,10 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, * totalsize * elapsed / transferred - elapsed */ eta = totalsize * elapsed / transferred - elapsed; + if (eta >= 1000*60*60) + eta = 1000*60*60 - 1; secs = eta % 3600; hours = eta / 3600; - fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60); + fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60); } } -- cgit v1.2.3-55-g6feb From e52e67cb512e775fd83ca399cc807c363ba59dcc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Fri, 11 Feb 2011 12:59:11 +0100 Subject: libbb/progress.c: make sure we never get negative ETA function old new delta bb_progress_update 738 733 -5 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/progress.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'libbb') diff --git a/libbb/progress.c b/libbb/progress.c index 3999e0f38..1062e9a0d 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -79,16 +79,20 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, int barlength; int kiloscale; - beg_and_transferred = beg_size + transferred; - elapsed = monotonic_sec(); since_last_update = elapsed - p->lastupdate_sec; - /* - * Do not update on every call - * (we can be called on every network read!) - */ - if (since_last_update == 0 && beg_and_transferred < totalsize) + + if (totalsize != 0 && transferred >= totalsize - beg_size) { + /* Last call. Do not skip this update */ + transferred = totalsize - beg_size; /* sanitize just in case */ + } + else if (since_last_update == 0) { + /* + * Do not update on every call + * (we can be called on every network read!) + */ return; + } kiloscale = 0; /* @@ -101,32 +105,29 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, /* * 64-bit CPU || small off_t: in either case, * >> is cheap, single-word operation. - * ... || strange off_t: also use this code (it is safe, - * even if suboptimal), because 32/64 optimized one - * works only for 64-bit off_t. + * ... || strange off_t: also use this code + * (it is safe, just suboptimal wrt code size), + * because 32/64 optimized one works only for 64-bit off_t. */ if (totalsize >= (1 << 22)) { totalsize >>= 10; beg_size >>= 10; transferred >>= 10; - beg_and_transferred >>= 10; kiloscale = 1; } } else { /* 32-bit CPU and 64-bit off_t. - * Pick a shift (40 bits) which is easier to do on 32-bit CPU. + * Use a 40-bit shift, it is easier to do on 32-bit CPU. */ if (totalsize >= (uoff_t)(1ULL << 54)) { totalsize = (uint32_t)(totalsize >> 32) >> 8; beg_size = (uint32_t)(beg_size >> 32) >> 8; transferred = (uint32_t)(transferred >> 32) >> 8; - beg_and_transferred = (uint32_t)(beg_and_transferred >> 32) >> 8; kiloscale = 4; } } - if (beg_and_transferred > totalsize) - beg_and_transferred = totalsize; + beg_and_transferred = beg_size + transferred; ratio = 100 * beg_and_transferred / totalsize; #if ENABLE_UNICODE_SUPPORT @@ -163,7 +164,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, p->lastupdate_sec = elapsed; p->lastsize = transferred; if (since_last_update >= STALLTIME) { - /* We "cut off" these seconds from elapsed time + /* We "cut out" these seconds from elapsed time * by adjusting start time */ p->start_sec += since_last_update; } -- cgit v1.2.3-55-g6feb From d55e13964916af6a083be881bffdb493af287c1d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Fri, 11 Feb 2011 18:56:13 +0100 Subject: progress meter: move file name to bb_progress_t. +20 bytes We were doing expensive unicode conversion on every update Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- include/libbb.h | 12 +++++++++--- libbb/progress.c | 24 +++++++++++------------- networking/tftp.c | 10 +++++----- networking/wget.c | 4 ++-- 4 files changed, 27 insertions(+), 23 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index c0178801f..7581cd4c4 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1587,15 +1587,21 @@ typedef struct bb_progress_t { off_t lastsize; unsigned lastupdate_sec; unsigned start_sec; - smallint inited; + const char *curfile; } bb_progress_t; -void bb_progress_init(bb_progress_t *p) FAST_FUNC; -void bb_progress_update(bb_progress_t *p, const char *curfile, +#define is_bb_progress_inited(p) ((p)->curfile != NULL) +#define bb_progress_free(p) do { \ + if (ENABLE_UNICODE_SUPPORT) free((char*)((p)->curfile)); \ + (p)->curfile = NULL; \ +} while (0) +void bb_progress_init(bb_progress_t *p, const char *curfile) FAST_FUNC; +void bb_progress_update(bb_progress_t *p, uoff_t beg_range, uoff_t transferred, uoff_t totalsize) FAST_FUNC; + extern const char *applet_name; /* Some older linkers don't perform string merging, we used to have common strings diff --git a/libbb/progress.c b/libbb/progress.c index 1062e9a0d..1d260dd08 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -52,12 +52,17 @@ static unsigned int get_tty2_width(void) return width; } -void FAST_FUNC bb_progress_init(bb_progress_t *p) +void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile) { +#if ENABLE_UNICODE_SUPPORT + init_unicode(); + p->curfile = unicode_conv_to_printable_fixedwidth(/*NULL,*/ curfile, 20); +#else + p->curfile = curfile; +#endif p->start_sec = monotonic_sec(); p->lastupdate_sec = p->start_sec; p->lastsize = 0; - p->inited = 1; } /* File already had beg_size bytes. @@ -68,7 +73,6 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p) * If totalsize == 0, then it is unknown. */ void FAST_FUNC bb_progress_update(bb_progress_t *p, - const char *curfile, uoff_t beg_size, uoff_t transferred, uoff_t totalsize) @@ -130,16 +134,10 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, beg_and_transferred = beg_size + transferred; ratio = 100 * beg_and_transferred / totalsize; -#if ENABLE_UNICODE_SUPPORT - init_unicode(); - { - char *buf = unicode_conv_to_printable_fixedwidth(/*NULL,*/ curfile, 20); - fprintf(stderr, "\r%s%4u%% ", buf, ratio); - free(buf); - } -#else - fprintf(stderr, "\r%-20.20s%4u%% ", curfile, ratio); -#endif + if (ENABLE_UNICODE_SUPPORT) + fprintf(stderr, "\r%s%4u%% ", p->curfile, ratio); + else + fprintf(stderr, "\r%-20.20s%4u%% ", p->curfile, ratio); barlength = get_tty2_width() - 49; if (barlength > 0) { diff --git a/networking/tftp.c b/networking/tftp.c index fcd933f6a..2a3991755 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -107,19 +107,19 @@ struct BUG_G_too_big { #if ENABLE_FEATURE_TFTP_PROGRESS_BAR static void tftp_progress_update(void) { - bb_progress_update(&G.pmt, G.file, 0, G.pos, G.size); + bb_progress_update(&G.pmt, 0, G.pos, G.size); } static void tftp_progress_init(void) { - bb_progress_init(&G.pmt); + bb_progress_init(&G.pmt, G.file); tftp_progress_update(); } static void tftp_progress_done(void) { - if (G.pmt.inited) { + if (is_bb_progress_inited(&G.pmt)) { tftp_progress_update(); bb_putchar_stderr('\n'); - G.pmt.inited = 0; + bb_progress_free(p); } } #else @@ -445,7 +445,7 @@ static int tftp_protocol( #if ENABLE_FEATURE_TFTP_PROGRESS_BAR if (ENABLE_TFTP && remote_file) /* tftp */ G.pos = (block_nr - 1) * (uoff_t)blksize; - if (G.pmt.inited) + if (is_bb_progress_inited(&G.pmt)) tftp_progress_update(); #endif /* Was it final ACK? then exit */ diff --git a/networking/wget.c b/networking/wget.c index d81426e8d..f2d7daf2f 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -81,9 +81,9 @@ static void progress_meter(int flag) return; if (flag == PROGRESS_START) - bb_progress_init(&G.pmt); + bb_progress_init(&G.pmt, G.curfile); - bb_progress_update(&G.pmt, G.curfile, G.beg_range, G.transferred, + bb_progress_update(&G.pmt, G.beg_range, G.transferred, G.chunked ? 0 : G.beg_range + G.transferred + G.content_len); if (flag == PROGRESS_END) { -- cgit v1.2.3-55-g6feb From ab8d00d64fc23602875952c08c030f05f206686c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Fri, 11 Feb 2011 19:09:30 +0100 Subject: progress meter: fix bugs found in stall detection and unknown size logic Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- include/libbb.h | 5 +++-- libbb/progress.c | 55 ++++++++++++++++++++++++++++++++----------------------- networking/tftp.c | 2 +- 3 files changed, 36 insertions(+), 26 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index 7581cd4c4..65c319402 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1584,8 +1584,9 @@ int print_flags_separated(const int *masks, const char *labels, int print_flags(const masks_labels_t *ml, int flags) FAST_FUNC; typedef struct bb_progress_t { - off_t lastsize; - unsigned lastupdate_sec; + unsigned last_size; + unsigned last_update_sec; + unsigned last_change_sec; unsigned start_sec; const char *curfile; } bb_progress_t; diff --git a/libbb/progress.c b/libbb/progress.c index 1d260dd08..df43dad5c 100644 --- a/libbb/progress.c +++ b/libbb/progress.c @@ -61,8 +61,9 @@ void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile) p->curfile = curfile; #endif p->start_sec = monotonic_sec(); - p->lastupdate_sec = p->start_sec; - p->lastsize = 0; + p->last_update_sec = p->start_sec; + p->last_change_sec = p->start_sec; + p->last_size = 0; } /* File already had beg_size bytes. @@ -79,12 +80,15 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, { uoff_t beg_and_transferred; unsigned since_last_update, elapsed; - unsigned ratio; int barlength; int kiloscale; + //transferred = 1234; /* use for stall detection testing */ + //totalsize = 0; /* use for unknown size download testing */ + elapsed = monotonic_sec(); - since_last_update = elapsed - p->lastupdate_sec; + since_last_update = elapsed - p->last_update_sec; + p->last_update_sec = elapsed; if (totalsize != 0 && transferred >= totalsize - beg_size) { /* Last call. Do not skip this update */ @@ -131,23 +135,27 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, } } - beg_and_transferred = beg_size + transferred; - - ratio = 100 * beg_and_transferred / totalsize; if (ENABLE_UNICODE_SUPPORT) - fprintf(stderr, "\r%s%4u%% ", p->curfile, ratio); + fprintf(stderr, "\r%s", p->curfile); else - fprintf(stderr, "\r%-20.20s%4u%% ", p->curfile, ratio); - - barlength = get_tty2_width() - 49; - if (barlength > 0) { - /* god bless gcc for variable arrays :) */ - char buf[barlength + 1]; - unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; - memset(buf, ' ', barlength); - buf[barlength] = '\0'; - memset(buf, '*', stars); - fprintf(stderr, "|%s|", buf); + fprintf(stderr, "\r%-20.20s", p->curfile); + + beg_and_transferred = beg_size + transferred; + + if (totalsize != 0) { + unsigned ratio = 100 * beg_and_transferred / totalsize; + fprintf(stderr, "%4u%%", ratio); + + barlength = get_tty2_width() - 49; + if (barlength > 0) { + /* god bless gcc for variable arrays :) */ + char buf[barlength + 1]; + unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; + memset(buf, ' ', barlength); + buf[barlength] = '\0'; + memset(buf, '*', stars); + fprintf(stderr, " |%s|", buf); + } } while (beg_and_transferred >= 100000) { @@ -158,9 +166,10 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, fprintf(stderr, "%6u%c", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); #define beg_and_transferred dont_use_beg_and_transferred_below() - if (transferred != p->lastsize) { - p->lastupdate_sec = elapsed; - p->lastsize = transferred; + since_last_update = elapsed - p->last_change_sec; + if ((unsigned)transferred != p->last_size) { + p->last_change_sec = elapsed; + p->last_size = (unsigned)transferred; if (since_last_update >= STALLTIME) { /* We "cut out" these seconds from elapsed time * by adjusting start time */ @@ -173,7 +182,7 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p, if (since_last_update >= STALLTIME) { fprintf(stderr, " - stalled -"); - } else if (!totalsize || !transferred || (int)elapsed <= 0) { + } else if (!totalsize || !transferred || (int)elapsed < 0) { fprintf(stderr, " --:--:-- ETA"); } else { unsigned eta, secs, hours; diff --git a/networking/tftp.c b/networking/tftp.c index 2a3991755..35cf0dbd9 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -119,7 +119,7 @@ static void tftp_progress_done(void) if (is_bb_progress_inited(&G.pmt)) { tftp_progress_update(); bb_putchar_stderr('\n'); - bb_progress_free(p); + bb_progress_free(&G.pmt); } } #else -- cgit v1.2.3-55-g6feb From 0b8a7723c7351533826283c07b37cf2daa77ecf8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Sat, 12 Feb 2011 01:56:25 +0100 Subject: typo fix Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- libbb/systemd_support.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/systemd_support.c b/libbb/systemd_support.c index 981296dbb..542a3efff 100644 --- a/libbb/systemd_support.c +++ b/libbb/systemd_support.c @@ -33,7 +33,7 @@ //config: If you plan to use busybox daemons on a system where daemons //config: are controlled by systemd, enable this option. //config: If you don't use systemd, it is still safe to enable it, -//config: but yhe downside is increased code size. +//config: but the downside is increased code size. //kbuild:lib-$(CONFIG_FEATURE_SYSTEMD) += systemd_support.o -- cgit v1.2.3-55-g6feb From dc50676cce35cdba3ecba3870c3f752408d6db70 Mon Sep 17 00:00:00 2001 From: Dan Fandrich <dan@coneharvesters.com> Date: Sat, 12 Feb 2011 22:26:57 -0800 Subject: Move stpcpy replacement function into libbb Signed-off-by: Dan Fandrich <dan@coneharvesters.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- include/platform.h | 8 ++++++++ libbb/platform.c | 11 +++++++++++ runit/runsv.c | 24 +++++++----------------- 3 files changed, 26 insertions(+), 17 deletions(-) (limited to 'libbb') diff --git a/include/platform.h b/include/platform.h index 00ebe563b..e390e58e2 100644 --- a/include/platform.h +++ b/include/platform.h @@ -18,6 +18,7 @@ #define HAVE_PTSNAME_R 1 #define HAVE_SETBIT 1 #define HAVE_SIGHANDLER_T 1 +#define HAVE_STPCPY 1 #define HAVE_STRCASESTR 1 #define HAVE_STRCHRNUL 1 #define HAVE_STRSEP 1 @@ -356,6 +357,8 @@ typedef unsigned smalluint; # define ADJ_TICK MOD_CLKB # endif +# undef HAVE_STPCPY + #else # define bb_setpgrp() setpgrp() @@ -376,6 +379,7 @@ typedef unsigned smalluint; # undef HAVE_MEMRCHR # undef HAVE_MKDTEMP # undef HAVE_SETBIT +# undef HAVE_STPCPY # undef HAVE_STRCASESTR # undef HAVE_STRCHRNUL # undef HAVE_STRSEP @@ -413,6 +417,10 @@ extern char *mkdtemp(char *template) FAST_FUNC; typedef void (*sighandler_t)(int); #endif +#ifndef HAVE_STPCPY +extern char *stpcpy(char *p, const char *to_add) FAST_FUNC; +#endif + #ifndef HAVE_STRCASESTR extern char *strcasestr(const char *s, const char *pattern) FAST_FUNC; #endif diff --git a/libbb/platform.c b/libbb/platform.c index ccde2bf02..fe7ce1567 100644 --- a/libbb/platform.c +++ b/libbb/platform.c @@ -134,3 +134,14 @@ char* FAST_FUNC strsep(char **stringp, const char *delim) return start; } #endif + +#ifndef HAVE_STPCPY +char* FAST_FUNC stpcpy(char *p, const char *to_add) +{ + while ((*p = *to_add) != '\0') { + p++; + to_add++; + } + return p; +} +#endif diff --git a/runit/runsv.c b/runit/runsv.c index ebb031837..e76572daa 100644 --- a/runit/runsv.c +++ b/runit/runsv.c @@ -139,16 +139,6 @@ static void s_term(int sig_no UNUSED_PARAM) write(selfpipe.wr, "", 1); /* XXX */ } -/* libbb candidate */ -static char *bb_stpcpy(char *p, const char *to_add) -{ - while ((*p = *to_add) != '\0') { - p++; - to_add++; - } - return p; -} - static int open_trunc_or_warn(const char *name) { /* Why O_NDELAY? */ @@ -192,26 +182,26 @@ static void update_status(struct svdir *s) char *p = stat_buf; switch (s->state) { case S_DOWN: - p = bb_stpcpy(p, "down"); + p = stpcpy(p, "down"); break; case S_RUN: - p = bb_stpcpy(p, "run"); + p = stpcpy(p, "run"); break; case S_FINISH: - p = bb_stpcpy(p, "finish"); + p = stpcpy(p, "finish"); break; } if (s->ctrl & C_PAUSE) - p = bb_stpcpy(p, ", paused"); + p = stpcpy(p, ", paused"); if (s->ctrl & C_TERM) - p = bb_stpcpy(p, ", got TERM"); + p = stpcpy(p, ", got TERM"); if (s->state != S_DOWN) switch (s->sd_want) { case W_DOWN: - p = bb_stpcpy(p, ", want down"); + p = stpcpy(p, ", want down"); break; case W_EXIT: - p = bb_stpcpy(p, ", want exit"); + p = stpcpy(p, ", want exit"); break; } *p++ = '\n'; -- cgit v1.2.3-55-g6feb