]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Some number & string improvements
authorWayne Davison <wayne@opencoder.net>
Sat, 11 Jul 2020 17:32:59 +0000 (10:32 -0700)
committerWayne Davison <wayne@opencoder.net>
Sat, 11 Jul 2020 18:39:36 +0000 (11:39 -0700)
- Use strdup(do_big_num(...)) to replace num_to_byte_string(...).
- Allow a ',' for a decimal point in a SIZE option in some locales.
- Get rid of old (now unused) strdup() compatibility function.
- Try harder to include the newline in a single error message write.

cleanup.c
configure.ac
lib/compat.c
log.c
options.c
rsync.1.md
util2.c

index a2d6b384f4dfef9a03c0cbdbe2e758ae19f084d2..f9a5d76ba6ff0e30252d2042ec28d9be22f4cad8 100644 (file)
--- a/cleanup.c
+++ b/cleanup.c
@@ -222,10 +222,6 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
                 * we don't want to output a duplicate error. */
                if ((exit_code && line > 0)
                 || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1)))) {
-#ifdef HAVE_USLEEP /* A tiny delay just in case both sender & receiver are sending a msg at the same time. */
-                       if (am_server && exit_code)
-                               usleep(50);
-#endif
                        log_exit(exit_code, exit_file, exit_line);
                }
 
index a49e6addca3dcc64bd9d35f7f0629b8a86455123..69c8f933a59411a35f3865bb99b5a6acebbd7e31 100644 (file)
@@ -820,7 +820,7 @@ dnl AC_FUNC_MEMCMP
 
 AC_FUNC_UTIME_NULL
 AC_FUNC_ALLOCA
-AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
+AC_CHECK_FUNCS(waitpid wait4 getcwd chown chmod lchmod mknod mkfifo \
     fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
     chflags getattrlist \
     memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
index 26a2aa6024a812d4d4865025a8d1a0eba8b3fcba..513d79b236c9a49a537719a4e3720f29698341e3 100644 (file)
 
 static char number_separator;
 
-#ifndef HAVE_STRDUP
- char *strdup(char *s)
+char get_number_separator(void)
 {
-       int len = strlen(s) + 1;
-       char *ret = (char *)malloc(len);
-       if (ret)
-               memcpy(ret, s, len);
-       return ret;
+       if (!number_separator) {
+               char buf[32];
+               snprintf(buf, sizeof buf, "%f", 3.14);
+               if (strchr(buf, '.') != NULL)
+                       number_separator = ',';
+               else
+                       number_separator = '.';
+       }
+
+       return number_separator;
+}
+
+char get_decimal_point(void)
+{
+       return get_number_separator() == ',' ? '.' : ',';
 }
-#endif
 
 #ifndef HAVE_GETCWD
  char *getcwd(char *buf, int size)
@@ -155,30 +163,6 @@ 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, 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
@@ -190,22 +174,35 @@ char *do_big_num(int64 num, int human_flag, const char *fract)
        char *s;
        int len, negated;
 
-       if (human_flag && !number_separator) {
-               char buf[32];
-               snprintf(buf, sizeof buf, "%f", 3.14);
-               if (strchr(buf, '.') != NULL)
-                       number_separator = ',';
-               else
-                       number_separator = '.';
-       }
+       if (human_flag && !number_separator)
+               (void)get_number_separator();
 
        n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
 
        if (human_flag > 1) {
-               if (human_flag == 2)
-                       HUMANIFY(1000);
-               else
-                       HUMANIFY(1024);
+               int mult = human_flag == 2 ? 1000 : 1024;
+               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 if ((dnum /= mult) < mult)
+                               units = 'T';
+                       else {
+                               dnum /= mult;
+                               units = 'P';
+                       }
+                       if (num < 0)
+                               dnum = -dnum;
+                       snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units);
+                       return bufs[n];
+               }
        }
 
        s = bufs[n] + sizeof bufs[0] - 1;
diff --git a/log.c b/log.c
index 73428d311787c47b6c5b65703b856c0686ed7c00..633bcdbce261933fd46993d60b502e313711161a 100644 (file)
--- a/log.c
+++ b/log.c
@@ -350,8 +350,7 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
                output_needs_newline = 0;
        }
 
-       trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
-                         ? buf[--len] : 0;
+       trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r') ? buf[--len] : '\0';
 
        if (len && buf[0] == '\r') {
                fputc('\r', f);
@@ -372,7 +371,12 @@ void rwrite(enum logcode code, const char *buf, int len, int is_utf8)
                        iconvbufs(ic, &inbuf, &outbuf, inbuf.pos ? 0 : ICB_INIT);
                        ierrno = errno;
                        if (outbuf.len) {
-                               filtered_fwrite(f, convbuf, outbuf.len, 0, 0);
+                               char trailing = inbuf.len ? '\0' : trailing_CR_or_NL;
+                               filtered_fwrite(f, convbuf, outbuf.len, 0, trailing);
+                               if (trailing) {
+                                       trailing_CR_or_NL = '\0';
+                                       fflush(f);
+                               }
                                outbuf.len = 0;
                        }
                        /* Log one byte of illegal/incomplete sequence and continue with
index eab64b613e00fa1ab8129fd7850cdcc50ec6fdb9..1e438fb10fc7781ae2201f2cbe477c50acd89a9b 100644 (file)
--- a/options.c
+++ b/options.c
@@ -1261,7 +1261,7 @@ static ssize_t parse_size_arg(const char *size_arg, char def_suf, const char *op
        ssize_t limit = -1, size = 1;
 
        for (arg = size_arg; isDigit(arg); arg++) {}
-       if (*arg == '.')
+       if (*arg == '.' || *arg == get_decimal_point()) /* backward compatibility: always allow '.' */
                for (arg++; isDigit(arg); arg++) {}
        switch (*arg && *arg != '+' && *arg != '-' ? *arg++ : def_suf) {
        case 'b': case 'B':
@@ -1714,20 +1714,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                case OPT_MAX_SIZE:
                        if ((max_size = parse_size_arg(max_size_arg, 'b', "max-size", 0, -1, False)) < 0)
                                return 0;
-                       max_size_arg = num_to_byte_string(max_size);
+                       max_size_arg = strdup(do_big_num(max_size, 0, NULL));
                        break;
 
                case OPT_MIN_SIZE:
                        if ((min_size = parse_size_arg(min_size_arg, 'b', "min-size", 0, -1, False)) < 0)
                                return 0;
-                       min_size_arg = num_to_byte_string(min_size);
+                       min_size_arg = strdup(do_big_num(min_size, 0, NULL));
                        break;
 
                case OPT_BWLIMIT: {
                        ssize_t size = parse_size_arg(bwlimit_arg, 'K', "bwlimit", 512, -1, True);
                        if (size < 0)
                                return 0;
-                       bwlimit_arg = num_to_byte_string(size);
+                       bwlimit_arg = strdup(do_big_num(size, 0, NULL));
                        bwlimit = (size + 512) / 1024;
                        break;
                }
@@ -2691,7 +2691,7 @@ void server_options(char **args, int *argc_p)
        }
 
        if (block_size) {
-               if (asprintf(&arg, "-B%u", block_size) < 0)
+               if (asprintf(&arg, "-B%u", (int)block_size) < 0)
                        goto oom;
                args[ac++] = arg;
        }
index 8bca5e33de2b8c8d54615374c7158a138ca250a8..685c5c373b6831c5a9ac1ea597b45462131153f7 100644 (file)
@@ -1726,19 +1726,18 @@ your home directory (remove the '=' for that).
 
     This tells rsync to avoid transferring any file that is larger than the
     specified SIZE.  A numeric value can be suffixed with a string to indicate
-    a size multiplier or left unqualified to specify bytes.  Feel free to use a
-    fractional value along with a suffix, such as `--max-size=1.5m`.
+    the numeric units or left unqualified to specify bytes.  Feel free to use a
+    fractional value along with the units, such as `--max-size=1.5m`.
 
     This option is a transfer rule, not an exclude, so it doesn't affect the
     data that goes into the file-lists, and thus it doesn't affect deletions.
     It just limits the files that the receiver requests to be transferred.
 
-    The accepted suffix letters are: `B`, `K`, `M`, `G`, `T`, and `P` for
-    bytes, kilobytes/kibibytes, megabytes/mebibytes, gigabytes/gibibytes,
-    terabytes/tebibytes, and petabytes/pebibytes.  If you use a single-char
-    suffix or add-on "ib" to it (e.g. "G" or "GiB") then you get units that are
+    The first letter of a units string can be `B` (bytes), `K` (kilo), `M`
+    (mega), `G` (giga), `T` (tera), or `P` (peta).  If the string is a single
+    char or has "ib" added to it (e.g. "G" or "GiB") then the units are
     multiples of 1024.  If you use a two-letter suffix that ends with a "B"
-    (e.g. "kb") then you get units that are multiples of 1000.  The suffix
+    (e.g. "kb") then you get units that are multiples of 1000.  The string's
     letters can be any mix of upper and lower-case that you want to use.
 
     Finally, if the string ends with either "+1" or "-1", it is offset by one
@@ -2814,10 +2813,10 @@ your home directory (remove the '=' for that).
     level by one.  You can take the level down to 0 (to output numbers as pure
     digits) by specifying the `--no-human-readable` (`--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).
+    The unit letters that are appended in levels 2 and 3 are: `K` (kilo), `M`
+    (mega), `G` (giga), `T` (tera), or `P` (peta).  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,
diff --git a/util2.c b/util2.c
index 9566b8db18bd1af8e2a4cfa4153b6e97db524295..6ea6981d00de3de72033bc221efe87c2c25b8ab4 100644 (file)
--- a/util2.c
+++ b/util2.c
@@ -21,7 +21,6 @@
  */
 
 #include "rsync.h"
-#include "ifuncs.h"
 #include "itypes.h"
 #include "inums.h"
 
@@ -71,28 +70,13 @@ int msleep(int t)
        return True;
 }
 
-/* Convert a num manually because the needed %lld precision is not a portable sprintf() escape. */
-char *num_to_byte_string(ssize_t num)
-{
-       char buf[128], *s = buf + sizeof buf - 1;
-
-       *s = '\0';
-       if (!num)
-               *--s = '0';
-       while (num) {
-               *--s = (char)(num % 10) + '0';
-               num /= 10;
-       }
-       return strdup(s);
-}
-
 void *my_alloc(void *ptr, size_t num, size_t size, const char *file, int line)
 {
        if (max_alloc && num >= max_alloc/size) {
                if (!file)
                        return NULL;
                rprintf(FERROR, "[%s] exceeded --max-alloc=%s setting (file=%s, line=%d)\n",
-                       who_am_i(), num_to_byte_string(max_alloc), file, line);
+                       who_am_i(), do_big_num(max_alloc, 0, NULL), file, line);
                exit_cleanup(RERR_MALLOC);
        }
        if (!ptr)