From adc2476fa213797d849ae80fa8b5fcd9eba5dc4f Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Mon, 1 Sep 2008 12:53:43 -0700 Subject: [PATCH] Output numbers in 3-digit groups by default (e.g. 1,234,567). Also improved the human-readable output functions, including adding the ability to output negative numbers. --- fileio.c | 3 +- flist.c | 6 +-- generator.c | 24 +++++---- hlink.c | 3 +- ifuncs.h | 40 +++++++++++++++ io.c | 2 +- lib/compat.c | 114 ++++++++++++++++++++++++++++++++++-------- log.c | 12 ++--- main.c | 38 +++++++------- match.c | 13 ++--- options.c | 14 +++++- packaging/var-checker | 7 +++ progress.c | 8 +-- receiver.c | 11 ++-- rsync.yo | 22 ++++++-- sender.c | 7 +-- t_stub.c | 2 +- testsuite/daemon.test | 7 +-- tls.c | 10 +++- trimslash.c | 1 + util.c | 18 +------ wildtest.c | 1 + xattrs.c | 2 +- 23 files changed, 254 insertions(+), 111 deletions(-) diff --git a/fileio.c b/fileio.c index 93cf5737..38f9eb4b 100644 --- a/fileio.c +++ b/fileio.c @@ -20,6 +20,7 @@ */ #include "rsync.h" +#include "ifuncs.h" #ifndef ENODATA #define ENODATA EAGAIN @@ -233,7 +234,7 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len) OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET); if (ret != read_start) { rsyserr(FERROR, errno, "lseek returned %s, not %s", - big_num(ret, 0), big_num(read_start, 0)); + big_num(ret), big_num(read_start)); exit_cleanup(RERR_FILEIO); } map->p_fd_offset = read_start; diff --git a/flist.c b/flist.c index 92e89a26..7c64d86d 100644 --- a/flist.c +++ b/flist.c @@ -321,7 +321,7 @@ static void flist_expand(struct file_list *flist, int extra) if (DEBUG_GTE(FLIST, 1) && flist->malloced != FLIST_START) { rprintf(FCLIENT, "[%s] expand file_list pointer array to %s bytes, did%s move\n", who_am_i(), - big_num(sizeof flist->files[0] * flist->malloced, 0), + big_num(sizeof flist->files[0] * flist->malloced), (new_ptr == flist->files) ? " not" : ""); } @@ -488,7 +488,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file, } else if (DEBUG_GTE(HLINK, 3)) { rprintf(FINFO, "[%s] dev:inode for #%d is %s:%s\n", who_am_i(), first_ndx + ndx, - big_num(tmp_dev, 0), big_num(tmp_ino, 0)); + big_num(tmp_dev), big_num(tmp_ino)); } } } else { @@ -2819,7 +2819,7 @@ static void output_flist(struct file_list *flist) "[%s] i=%d %s %s%s%s%s mode=0%o len=%s%s%s flags=%x\n", who, i + flist->ndx_start, root, dir, slash, name, trail, - (int)file->mode, big_num(F_LENGTH(file), 0), + (int)file->mode, comma_num(F_LENGTH(file)), uidbuf, gidbuf, file->flags); } } diff --git a/generator.c b/generator.c index 80e9826d..af6f22a2 100644 --- a/generator.c +++ b/generator.c @@ -21,6 +21,7 @@ */ #include "rsync.h" +#include "ifuncs.h" extern int dry_run; extern int do_xfers; @@ -53,6 +54,7 @@ extern int ignore_errors; extern int remove_source_files; extern int delay_updates; extern int update_only; +extern int human_readable; extern int ignore_existing; extern int ignore_non_existing; extern int inplace; @@ -806,8 +808,8 @@ static void sum_sizes_sqroot(struct sum_struct *sum, int64 len) if (sum->count && DEBUG_GTE(DELTASUM, 2)) { rprintf(FINFO, "count=%s rem=%ld blength=%ld s2length=%d flength=%s\n", - big_num(sum->count, 0), (long)sum->remainder, (long)sum->blength, - sum->s2length, big_num(sum->flength, 0)); + big_num(sum->count), (long)sum->remainder, (long)sum->blength, + sum->s2length, big_num(sum->flength)); } } @@ -858,7 +860,7 @@ static int generate_and_send_sums(int fd, OFF_T len, int f_out, int f_copy) if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO, "chunk[%s] offset=%s len=%ld sum1=%08lx\n", - big_num(i, 0), big_num(offset - n1, 0), (long)n1, + big_num(i), big_num(offset - n1), (long)n1, (unsigned long)sum1); } write_int(f_out, sum1); @@ -1199,6 +1201,7 @@ static void list_file_entry(struct file_struct *f) { char permbuf[PERMSTRING_SIZE]; int64 len; + int colwidth = human_readable ? 14 : 11; if (!F_IS_ACTIVE(f)) { /* this can happen if duplicate names were removed */ @@ -1212,15 +1215,16 @@ static void list_file_entry(struct file_struct *f) #ifdef SUPPORT_LINKS if (preserve_links && S_ISLNK(f->mode)) { - rprintf(FINFO, "%s %11s %s %s -> %s\n", - permbuf, big_num(len, 0), timestring(f->modtime), - f_name(f, NULL), F_SYMLINK(f)); + rprintf(FINFO, "%s %*s %s %s -> %s\n", + permbuf, colwidth, comma_num(len), + timestring(f->modtime), f_name(f, NULL), + F_SYMLINK(f)); } else #endif { - rprintf(FINFO, "%s %11s %s %s\n", - permbuf, big_num(len, 0), timestring(f->modtime), - f_name(f, NULL)); + rprintf(FINFO, "%s %*s %s %s\n", + permbuf, colwidth, comma_num(len), + timestring(f->modtime), f_name(f, NULL)); } } @@ -1905,7 +1909,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO, "gen mapped %s of size %s\n", - fnamecmp, big_num(sx.st.st_size, 0)); + fnamecmp, big_num(sx.st.st_size)); } if (DEBUG_GTE(DELTASUM, 2)) diff --git a/hlink.c b/hlink.c index cdafa9fa..212f5153 100644 --- a/hlink.c +++ b/hlink.c @@ -21,6 +21,7 @@ */ #include "rsync.h" +#include "ifuncs.h" extern int dry_run; extern int list_only; @@ -73,7 +74,7 @@ struct ht_int64_node *idev_find(int64 dev, int64 ino) if (DEBUG_GTE(HLINK, 3)) { rprintf(FINFO, "[%s] created hashtable for dev %s\n", - who_am_i(), big_num(dev, 0)); + who_am_i(), big_num(dev)); } } } else diff --git a/ifuncs.h b/ifuncs.h index e032c67f..6562764e 100644 --- a/ifuncs.h +++ b/ifuncs.h @@ -67,6 +67,46 @@ d_name(struct dirent *di) #endif } +static inline char * +big_num(int64 num) +{ + return do_big_num(num, 0, NULL); +} + +static inline char * +comma_num(int64 num) +{ + extern int human_readable; + return do_big_num(num, human_readable != 0, NULL); +} + +static inline char * +human_num(int64 num) +{ + extern int human_readable; + return do_big_num(num, human_readable, NULL); +} + +static inline char * +big_dnum(double dnum, int decimal_digits) +{ + return do_big_dnum(dnum, 0, decimal_digits); +} + +static inline char * +comma_dnum(double dnum, int decimal_digits) +{ + extern int human_readable; + return do_big_dnum(dnum, human_readable != 0, decimal_digits); +} + +static inline char * +human_dnum(double dnum, int decimal_digits) +{ + extern int human_readable; + return do_big_dnum(dnum, human_readable, decimal_digits); +} + static inline int isDigit(const char *ptr) { diff --git a/io.c b/io.c index 1752d86f..d3ae5368 100644 --- a/io.c +++ b/io.c @@ -626,7 +626,7 @@ static void whine_about_eof(int fd) rprintf(FERROR, RSYNC_NAME ": connection unexpectedly closed " "(%s bytes received so far) [%s]\n", - big_num(stats.total_read, 0), who_am_i()); + big_num(stats.total_read), who_am_i()); exit_cleanup(RERR_STREAMIO); } diff --git a/lib/compat.c b/lib/compat.c index 494b64fc..20beeca3 100644 --- a/lib/compat.c +++ b/lib/compat.c @@ -20,6 +20,9 @@ */ #include "rsync.h" +#include "ifuncs.h" + +extern char number_separator; #ifndef HAVE_STRDUP char *strdup(char *s) @@ -152,45 +155,112 @@ int sys_gettimeofday(struct timeval *tv) #endif } +#define HUMANIFY(mult) \ + do { \ + if (num >= mult || num <= -mult) { \ + double dnum = (double)num / mult; \ + char units; \ + if (num < 0) \ + dnum = -dnum; \ + if (dnum < mult) \ + units = 'K'; \ + else if ((dnum /= mult) < mult) \ + units = 'M'; \ + else if ((dnum /= mult) < mult) \ + units = 'G'; \ + else { \ + dnum /= mult; \ + units = 'T'; \ + } \ + if (num < 0) \ + dnum = -dnum; \ + snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); \ + return bufs[n]; \ + } \ + } while (0) + /* Return the int64 number as a string. If the human_flag arg is non-zero, - * we may output the number in K, M, or G units. We can return up to 4 - * buffers at a time. */ -char *big_num(int64 num, int human_flag) + * we may output the number in K, M, G, or T units. If we don't add a unit + * suffix, we will append the fract string, if it is non-NULL. We can + * return up to 4 buffers at a time. */ +char *do_big_num(int64 num, int human_flag, const char *fract) { static char bufs[4][128]; /* more than enough room */ static unsigned int n; char *s; + int len, negated; n = (n + 1) % (sizeof bufs / sizeof bufs[0]); - if (human_flag) { - char units = '\0'; - int mult = human_flag == 1 ? 1000 : 1024; - double dnum = 0; - if (num > mult*mult*mult) { - dnum = (double)num / (mult*mult*mult); - units = 'G'; - } else if (num > mult*mult) { - dnum = (double)num / (mult*mult); - units = 'M'; - } else if (num > mult) { - dnum = (double)num / mult; - units = 'K'; - } - if (units) { - snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); - return bufs[n]; - } + if (human_flag > 1) { + if (human_flag == 2) + HUMANIFY(1000); + else + HUMANIFY(1024); } s = bufs[n] + sizeof bufs[0] - 1; - *s = '\0'; + if (fract) { + len = strlen(fract); + s -= len; + strlcpy(s, fract, len + 1); + } else + *s = '\0'; + + len = 0; if (!num) *--s = '0'; + if (num < 0) { + /* A maximum-size negated number can't fit as a positive, + * so do one digit in negated form to start us off. */ + *--s = (char)(-(num % 10)) + '0'; + num = -(num / 10); + len++; + negated = 1; + } else + negated = 0; + while (num) { + if (human_flag) { + if (len == 3) { + *--s = number_separator; + len = 1; + } else + len++; + } *--s = (char)(num % 10) + '0'; num /= 10; } + + if (negated) + *--s = '-'; + return s; } + +/* Return the double number as a string. If the human_flag option is > 1, + * we may output the number in K, M, G, or T units. The buffer we use for + * our result is either a single static buffer defined here, or a buffer + * we get from do_big_num(). */ +char *do_big_dnum(double dnum, int human_flag, int decimal_digits) +{ + static char tmp_buf[128]; +#if SIZEOF_INT64 >= 8 + char *fract; + + snprintf(tmp_buf, sizeof tmp_buf, "%.*f", decimal_digits, dnum); + + if (!human_flag || (dnum < 1000.0 && dnum > -1000.0)) + return tmp_buf; + + for (fract = tmp_buf+1; isDigit(fract); fract++) {} + + return do_big_num((int64)dnum, human_flag, fract); +#else + /* A big number might lose digits converting to a too-short int64, + * so let's just return the raw double conversion. */ + snprintf(tmp_buf, sizeof tmp_buf, "%.*f", decimal_digits, dnum); + return tmp_buf; +#endif +} diff --git a/log.c b/log.c index 6d66e20a..adf3a4ad 100644 --- a/log.c +++ b/log.c @@ -514,7 +514,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op, case 'l': strlcat(fmt, "s", sizeof fmt); snprintf(buf2, sizeof buf2, fmt, - big_num(F_LENGTH(file), 0)); + comma_num(F_LENGTH(file))); n = buf2; break; case 'U': @@ -631,7 +631,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op, initial_stats->total_read; } strlcat(fmt, "s", sizeof fmt); - snprintf(buf2, sizeof buf2, fmt, big_num(b, 0)); + snprintf(buf2, sizeof buf2, fmt, comma_num(b)); n = buf2; break; case 'c': @@ -643,7 +643,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op, initial_stats->total_read; } strlcat(fmt, "s", sizeof fmt); - snprintf(buf2, sizeof buf2, fmt, big_num(b, 0)); + snprintf(buf2, sizeof buf2, fmt, comma_num(b)); n = buf2; break; case 'C': @@ -854,9 +854,9 @@ void log_exit(int code, const char *file, int line) { if (code == 0) { rprintf(FLOG,"sent %s bytes received %s bytes total size %s\n", - big_num(stats.total_written, 0), - big_num(stats.total_read, 0), - big_num(stats.total_size, 0)); + comma_num(stats.total_written), + comma_num(stats.total_read), + comma_num(stats.total_size)); } else if (am_server != 2) { const char *name; diff --git a/main.c b/main.c index c32457d4..942fec36 100644 --- a/main.c +++ b/main.c @@ -35,7 +35,6 @@ extern int am_sender; extern int am_daemon; extern int inc_recurse; extern int blocking_io; -extern int human_readable; extern int always_checksum; extern int remove_source_files; extern int output_needs_newline; @@ -246,43 +245,42 @@ static void output_summary(void) { if (INFO_GTE(STATS, 2)) { rprintf(FCLIENT, "\n"); - rprintf(FINFO,"Number of files: %d\n", stats.num_files); - rprintf(FINFO,"Number of files transferred: %d\n", - stats.num_transferred_files); + rprintf(FINFO,"Number of files: %s\n", comma_num(stats.num_files)); + rprintf(FINFO,"Number of files transferred: %s\n", + comma_num(stats.num_transferred_files)); rprintf(FINFO,"Total file size: %s bytes\n", - big_num(stats.total_size, human_readable)); + human_num(stats.total_size)); rprintf(FINFO,"Total transferred file size: %s bytes\n", - big_num(stats.total_transferred_size, human_readable)); + human_num(stats.total_transferred_size)); rprintf(FINFO,"Literal data: %s bytes\n", - big_num(stats.literal_data, human_readable)); + human_num(stats.literal_data)); rprintf(FINFO,"Matched data: %s bytes\n", - big_num(stats.matched_data, human_readable)); + human_num(stats.matched_data)); rprintf(FINFO,"File list size: %s\n", - big_num(stats.flist_size, human_readable)); + human_num(stats.flist_size)); if (stats.flist_buildtime) { rprintf(FINFO, - "File list generation time: %.3f seconds\n", - (double)stats.flist_buildtime / 1000); + "File list generation time: %s seconds\n", + comma_dnum((double)stats.flist_buildtime / 1000, 3)); rprintf(FINFO, - "File list transfer time: %.3f seconds\n", - (double)stats.flist_xfertime / 1000); + "File list transfer time: %s seconds\n", + comma_dnum((double)stats.flist_xfertime / 1000, 3)); } rprintf(FINFO,"Total bytes sent: %s\n", - big_num(total_written, human_readable)); + human_num(total_written)); rprintf(FINFO,"Total bytes received: %s\n", - big_num(total_read, human_readable)); + human_num(total_read)); } if (INFO_GTE(STATS, 1)) { rprintf(FCLIENT, "\n"); rprintf(FINFO, "sent %s bytes received %s bytes %s bytes/sec\n", - big_num(total_written, human_readable), - big_num(total_read, human_readable), + human_num(total_written), human_num(total_read), human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2)); - rprintf(FINFO, "total size is %s speedup is %.2f%s\n", - big_num(stats.total_size, human_readable), - (double)stats.total_size / (total_written+total_read), + rprintf(FINFO, "total size is %s speedup is %s%s\n", + human_num(stats.total_size), + comma_dnum((double)stats.total_size / (total_written+total_read), 2), write_batch < 0 ? " (BATCH ONLY)" : dry_run ? " (DRY RUN)" : ""); } diff --git a/match.c b/match.c index 7e9b611e..c459af84 100644 --- a/match.c +++ b/match.c @@ -20,6 +20,7 @@ */ #include "rsync.h" +#include "ifuncs.h" extern int checksum_seed; extern int append_mode; @@ -111,7 +112,7 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf, if (DEBUG_GTE(DELTASUM, 2) && i >= 0) { rprintf(FINFO, "match at %s last_match=%s j=%d len=%ld n=%ld\n", - big_num(offset, 0), big_num(last_match, 0), i, + big_num(offset), big_num(last_match), i, (long)s->sums[i].len, (long)n); } @@ -154,7 +155,7 @@ static void hash_search(int f,struct sum_struct *s, if (DEBUG_GTE(DELTASUM, 2)) { rprintf(FINFO, "hash search b=%ld len=%s\n", - (long)s->blength, big_num(len, 0)); + (long)s->blength, big_num(len)); } k = (int32)MIN(len, (OFF_T)s->blength); @@ -173,7 +174,7 @@ static void hash_search(int f,struct sum_struct *s, if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO, "hash search s->blength=%ld len=%s count=%s\n", - (long)s->blength, big_num(len, 0), big_num(s->count, 0)); + (long)s->blength, big_num(len), big_num(s->count)); } do { @@ -182,7 +183,7 @@ static void hash_search(int f,struct sum_struct *s, if (DEBUG_GTE(DELTASUM, 4)) { rprintf(FINFO, "offset=%s sum=%04x%04x\n", - big_num(offset, 0), s2 & 0xFFFF, s1 & 0xFFFF); + big_num(offset), s2 & 0xFFFF, s1 & 0xFFFF); } if (tablesize == TRADITIONAL_TABLESIZE) { @@ -216,7 +217,7 @@ static void hash_search(int f,struct sum_struct *s, if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO, "potential match at %s i=%ld sum=%08x\n", - big_num(offset, 0), (long)i, sum); + big_num(offset), (long)i, sum); } if (!done_csum2) { @@ -413,5 +414,5 @@ void match_report(void) rprintf(FINFO, "total: matches=%d hash_hits=%d false_alarms=%d data=%s\n", total_matches, total_hash_hits, total_false_alarms, - big_num(stats.literal_data, 0)); + big_num(stats.literal_data)); } diff --git a/options.c b/options.c index 11860cbc..e0a84017 100644 --- a/options.c +++ b/options.c @@ -93,7 +93,7 @@ int filesfrom_fd = -1; char *filesfrom_host = NULL; int eol_nulls = 0; int protect_args = 0; -int human_readable = 0; +int human_readable = 1; int recurse = 0; int allow_inc_recurse = 1; int xfer_dirs = -1; @@ -121,6 +121,7 @@ int checksum_seed = 0; int inplace = 0; int delay_updates = 0; long block_size = 0; /* "long" because popt can't set an int32. */ +char number_separator; char *skip_compress = NULL; item_list dparam_list = EMPTY_ITEM_LIST; @@ -1669,7 +1670,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) } } - if (human_readable && argc == 2 && !am_server) { + if (human_readable > 1 && argc == 2 && !am_server) { /* Allow the old meaning of 'h' (--help) on its own. */ usage(FINFO); exit_cleanup(0); @@ -1682,6 +1683,15 @@ int parse_arguments(int *argc_p, const char ***argv_p) verbose > 1 ? "stats3" : "stats2", DEFAULT_PRIORITY); } + if (human_readable) { + char buf[32]; + snprintf(buf, sizeof buf, "%f", 3.14); + if (strchr(buf, '.') != NULL) + number_separator = ','; + else + number_separator = '.'; + } + #ifdef ICONV_OPTION if (iconv_opt && protect_args != 2) { if (!am_server && strcmp(iconv_opt, "-") == 0) diff --git a/packaging/var-checker b/packaging/var-checker index b63428b7..445bea0e 100755 --- a/packaging/var-checker +++ b/packaging/var-checker @@ -6,6 +6,7 @@ use strict; my %add_syscall_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c tls.c trimslash.c ); +my %add_compat_c = map { $_ => 1 } qw( t_stub.c tls.c trimslash.c wildtest.c ); my %add_util_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c ); my %sizes; @@ -14,6 +15,11 @@ undef $/; my $syscall_c = ; $/ = "\n"; close IN; $syscall_c =~ s/^extern\s.*//mg; +open(IN, '<', 'lib/compat.c') or die $!; +undef $/; my $compat_c = ; $/ = "\n"; +close IN; +$compat_c =~ s/^extern\s.*//mg; + open(IN, '<', 'util.c') or die $!; undef $/; my $util_c = ; $/ = "\n"; close IN; @@ -30,6 +36,7 @@ foreach my $fn (@files) { my @externs = /^extern\s+(.*);/mg; $_ .= $syscall_c if $add_syscall_c{$fn}; + $_ .= $compat_c if $add_compat_c{$fn}; $_ .= $util_c if $add_util_c{$fn}; s/INFO_GTE/info_levels/g; s/DEBUG_GTE/debug_levels/g; diff --git a/progress.c b/progress.c index b09ca118..5d445a13 100644 --- a/progress.c +++ b/progress.c @@ -21,11 +21,11 @@ */ #include "rsync.h" +#include "ifuncs.h" extern int am_server; extern int need_unsorted_flist; extern int output_needs_newline; -extern int human_readable; extern struct stats stats; extern struct file_list *cur_flist; @@ -72,7 +72,7 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now, if (is_last) { int len = snprintf(eol, sizeof eol, - " (xfer#%d, to-check=%d/%d)\n", + " (xfr#%d, to-chk=%d/%d)\n", stats.num_transferred_files, stats.num_files - current_file_index - 1, stats.num_files); @@ -124,8 +124,8 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now, output_needs_newline = 0; pct = ofs == size ? 100 : (int) (100.0 * ofs / size); - rprintf(FCLIENT, "\r%12s %3d%% %7.2f%s %s%s", - big_num(ofs, human_readable), pct, rate, units, rembuf, eol); + rprintf(FCLIENT, "\r%15s %3d%% %7.2f%s %s%s", + human_num(ofs), pct, rate, units, rembuf, eol); if (!is_last) { output_needs_newline = 1; rflush(FCLIENT); diff --git a/receiver.c b/receiver.c index 4f5463a9..9b353f56 100644 --- a/receiver.c +++ b/receiver.c @@ -20,6 +20,7 @@ */ #include "rsync.h" +#include "ifuncs.h" extern int dry_run; extern int do_xfers; @@ -181,7 +182,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, mapbuf = map_file(fd_r, size_r, read_size, sum.blength); if (DEBUG_GTE(DELTASUM, 2)) { rprintf(FINFO, "recv mapped %s of size %s\n", - fname_r, big_num(size_r, 0)); + fname_r, big_num(size_r)); } } else mapbuf = NULL; @@ -211,7 +212,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, offset = sum.flength; if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) { rsyserr(FERROR_XFER, errno, "lseek of %s returned %s, not %s", - full_fname(fname), big_num(j, 0), big_num(offset, 0)); + full_fname(fname), big_num(j), big_num(offset)); exit_cleanup(RERR_FILEIO); } } @@ -223,7 +224,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, if (i > 0) { if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO,"data recv %d at %s\n", - i, big_num(offset, 0)); + i, big_num(offset)); } stats.literal_data += i; @@ -248,7 +249,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO, "chunk[%d] of size %ld at %s offset=%s\n", - i, (long)len, big_num(offset2, 0), big_num(offset, 0)); + i, (long)len, big_num(offset2), big_num(offset)); } if (mapbuf) { @@ -268,7 +269,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, rsyserr(FERROR_XFER, errno, "lseek of %s returned %s, not %s", full_fname(fname), - big_num(pos, 0), big_num(offset, 0)); + big_num(pos), big_num(offset)); exit_cleanup(RERR_FILEIO); } continue; diff --git a/rsync.yo b/rsync.yo index efa99904..79cbf07d 100644 --- a/rsync.yo +++ b/rsync.yo @@ -1918,10 +1918,24 @@ would output as "\#012". A literal backslash that is in a filename is not escaped unless it is followed by a hash and 3 digits (0-9). dit(bf(-h, --human-readable)) Output numbers in a more human-readable format. -This makes big numbers output using larger units, with a K, M, or G suffix. If -this option was specified once, these units are K (1000), M (1000*1000), and -G (1000*1000*1000); if the option is repeated, the units are powers of 1024 -instead of 1000. +There are 3 possible levels: (1) output numbers with a separator between each +set of 3 digits (either a comma or a period, depending on if the decimal point +is represented by a period or a comma); (2) output numbers in units of 1000 +(with a character suffix for larger units -- see below); (3) output numbers in +units of 1024. + +The default is human-readable level 1. Each bf(-h) option increases the level +by one. You can take the level down to 0 (to output numbers as pure digits) by +specifing the bf(--no-human-readable) (bf(--no-h)) option. + +The unit letters that are appended in levels 2 and 3 are: K (kilo), M (mega), +G (giga), or T (tera). For example, a 1234567-byte file would output as 1.23M +in level-2 (assuming that a period is your local decimal point). + +Backward compatibility note: versions of rsync prior to 3.1.0 do not support +human-readable level 1, and they default to level 0. Thus, specifying one or +two bf(-h) options behaves the same in old and new versions as long as you +didn't specify a bf(--no-h) option prior to one or more bf(-h) options. dit(bf(--partial)) By default, rsync will delete any partially transferred file if the transfer is interrupted. In some circumstances diff --git a/sender.c b/sender.c index ba1d6ffa..2919e553 100644 --- a/sender.c +++ b/sender.c @@ -20,6 +20,7 @@ */ #include "rsync.h" +#include "ifuncs.h" extern int dry_run; extern int do_xfers; @@ -71,7 +72,7 @@ static struct sum_struct *receive_sums(int f) if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO, "count=%s n=%ld rem=%ld\n", - big_num(s->count, 0), (long)s->blength, (long)s->remainder); + big_num(s->count), (long)s->blength, (long)s->remainder); } if (append_mode > 0) { @@ -106,7 +107,7 @@ static struct sum_struct *receive_sums(int f) if (DEBUG_GTE(DELTASUM, 3)) { rprintf(FINFO, "chunk[%d] len=%d offset=%s sum1=%08x\n", - i, s->sums[i].len, big_num(s->sums[i].offset, 0), + i, s->sums[i].len, big_num(s->sums[i].offset), s->sums[i].sum1); } } @@ -319,7 +320,7 @@ void send_files(int f_in, int f_out) if (DEBUG_GTE(DELTASUM, 2)) { rprintf(FINFO, "send_files mapped %s%s%s of size %s\n", - path,slash,fname, big_num(st.st_size, 0)); + path,slash,fname, big_num(st.st_size)); } write_ndx_and_attrs(f_out, ndx, iflags, fname, file, diff --git a/t_stub.c b/t_stub.c index 6a205fa3..d00d4374 100644 --- a/t_stub.c +++ b/t_stub.c @@ -24,10 +24,10 @@ int modify_window = 0; int module_id = -1; int relative_paths = 0; -int human_readable = 0; int module_dirlen = 0; int preserve_xattrs = 0; mode_t orig_umask = 002; +char number_separator = ','; char *partial_dir; char *module_dir; struct filter_list_struct daemon_filter_list; diff --git a/testsuite/daemon.test b/testsuite/daemon.test index 113d6a59..2d003530 100644 --- a/testsuite/daemon.test +++ b/testsuite/daemon.test @@ -25,7 +25,8 @@ chkfile="$scratchdir/rsync.chk" outfile="$scratchdir/rsync.out" SSH="src/support/lsh --no-cd" -DIR_REPL='s/^\(d[^ ]*\) *[0-9][0-9]* /\1 DIR /' +FILE_REPL='s/^\([^d][^ ]*\) *\(..........[0-9]\) /\1 \2 /' +DIR_REPL='s/^\(d[^ ]*\) *[0-9][.,0-9]* /\1 DIR /' LS_REPL='s;[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9];####/##/## ##:##:##;' build_rsyncd_conf @@ -65,7 +66,7 @@ EOT diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed" $RSYNC -r localhost::test-hidden \ - | sed "$DIR_REPL" | sed "$LS_REPL" \ + | sed "$FILE_REPL" | sed "$DIR_REPL" | sed "$LS_REPL" \ | tee "$outfile" cat <"$chkfile" drwxr-xr-x DIR ####/##/## ##:##:## . @@ -79,7 +80,7 @@ EOT diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed" $RSYNC -r localhost::test-from/f* \ - | sed "$DIR_REPL" | sed "$LS_REPL" \ + | sed "$FILE_REPL" | sed "$DIR_REPL" | sed "$LS_REPL" \ | tee "$outfile" cat <"$chkfile" drwxr-xr-x DIR ####/##/## ##:##:## foo diff --git a/tls.c b/tls.c index c01bdc88..501a9326 100644 --- a/tls.c +++ b/tls.c @@ -49,6 +49,7 @@ int link_times = 0; int link_owner = 0; int preserve_perms = 0; int preserve_executability = 0; +char number_separator; #ifdef SUPPORT_XATTRS @@ -180,7 +181,7 @@ static void list_file(const char *fname) (long)major(buf.st_rdev), (long)minor(buf.st_rdev)); } else - printf("%12s", big_num(buf.st_size, 0)); + printf("%15s", do_big_num(buf.st_size, 1, NULL)); printf(" %6ld.%-6ld %6ld %s %s%s\n", (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink, datebuf, fname, linkbuf); @@ -217,6 +218,7 @@ main(int argc, char *argv[]) { poptContext pc; const char **extra_args; + char buf[32]; int opt; pc = poptGetContext(PROGRAM, argc, (const char **)argv, @@ -238,6 +240,12 @@ main(int argc, char *argv[]) if (!extra_args || *extra_args == NULL) tls_usage(1); + snprintf(buf, sizeof buf, "%f", 3.14); + if (strchr(buf, '.') != NULL) + number_separator = ','; + else + number_separator = '.'; + for (; *extra_args; extra_args++) list_file(*extra_args); poptFreeContext(pc); diff --git a/trimslash.c b/trimslash.c index e5cf2f4c..40f2eb9b 100644 --- a/trimslash.c +++ b/trimslash.c @@ -27,6 +27,7 @@ int read_only = 1; int list_only = 0; int preserve_perms = 0; int preserve_executability = 0; +char number_separator = ','; int main(int argc, char **argv) diff --git a/util.c b/util.c index 4b6c11fd..e3402845 100644 --- a/util.c +++ b/util.c @@ -27,7 +27,6 @@ extern int dry_run; extern int module_id; extern int modify_window; extern int relative_paths; -extern int human_readable; extern int preserve_xattrs; extern char *module_dir; extern unsigned int module_dirlen; @@ -1192,21 +1191,6 @@ int unsafe_symlink(const char *dest, const char *src) return (depth < 0); } -/* Return the double number as a string. If the --human-readable option was - * specified, we may output the number in K, M, or G units. We use a buffer - * from big_num() to return our result. */ -char *human_dnum(double dnum, int decimal_digits) -{ - char *buf = big_num(dnum, human_readable); - int len = strlen(buf); - if (isDigit(buf + len - 1)) { - /* There's extra room in buf prior to the start of the num. */ - buf -= decimal_digits + 1; - snprintf(buf, len + decimal_digits + 2, "%.*f", decimal_digits, dnum); - } - return buf; -} - /* Return the date and time as a string. Some callers tweak returned buf. */ char *timestring(time_t t) { @@ -1545,7 +1529,7 @@ void *expand_item_list(item_list *lp, size_t item_size, new_ptr = _realloc_array(lp->items, item_size, new_size); if (DEBUG_GTE(FLIST, 3)) { rprintf(FINFO, "[%s] expand %s to %s bytes, did%s move\n", - who_am_i(), desc, big_num(new_size * item_size, 0), + who_am_i(), desc, big_num(new_size * item_size), new_ptr == lp->items ? " not" : ""); } if (!new_ptr) diff --git a/wildtest.c b/wildtest.c index efda5d6e..1692efe9 100644 --- a/wildtest.c +++ b/wildtest.c @@ -31,6 +31,7 @@ int fnmatch_errors = 0; #endif int wildmatch_errors = 0; +char number_separator = ','; typedef char bool; diff --git a/xattrs.c b/xattrs.c index 051c08d9..2855e583 100644 --- a/xattrs.c +++ b/xattrs.c @@ -136,7 +136,7 @@ static ssize_t get_xattr_names(const char *fname) got_error: rsyserr(FERROR_XFER, errno, "get_xattr_names: llistxattr(\"%s\",%s) failed", - fname, big_num(arg, 0)); + fname, big_num(arg)); return -1; } list_len = sys_llistxattr(fname, NULL, 0); -- 2.34.1