Annotation of embedaddon/rsync/lib/compat.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:  * Reimplementations of standard functions for platforms that don't have them.
                      3:  *
                      4:  * Copyright (C) 1998 Andrew Tridgell
                      5:  * Copyright (C) 2002 Martin Pool
1.1.1.4 ! misho       6:  * Copyright (C) 2004-2020 Wayne Davison
1.1       misho       7:  *
                      8:  * This program is free software; you can redistribute it and/or modify
                      9:  * it under the terms of the GNU General Public License as published by
                     10:  * the Free Software Foundation; either version 3 of the License, or
                     11:  * (at your option) any later version.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful,
                     14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16:  * GNU General Public License for more details.
                     17:  *
                     18:  * You should have received a copy of the GNU General Public License along
                     19:  * with this program; if not, visit the http://fsf.org website.
                     20:  */
                     21: 
                     22: #include "rsync.h"
1.1.1.2   misho      23: #include "itypes.h"
                     24: 
                     25: static char number_separator;
1.1       misho      26: 
1.1.1.4 ! misho      27: char get_number_separator(void)
1.1       misho      28: {
1.1.1.4 ! misho      29:        if (!number_separator) {
        !            30:                char buf[32];
        !            31:                snprintf(buf, sizeof buf, "%f", 3.14);
        !            32:                if (strchr(buf, '.') != NULL)
        !            33:                        number_separator = ',';
        !            34:                else
        !            35:                        number_separator = '.';
        !            36:        }
        !            37: 
        !            38:        return number_separator;
        !            39: }
        !            40: 
        !            41: char get_decimal_point(void)
        !            42: {
        !            43:        return get_number_separator() == ',' ? '.' : ',';
1.1       misho      44: }
                     45: 
                     46: #ifndef HAVE_GETCWD
                     47:  char *getcwd(char *buf, int size)
                     48: {
                     49:        return getwd(buf);
                     50: }
                     51: #endif
                     52: 
                     53: 
                     54: #ifndef HAVE_WAITPID
                     55:  pid_t waitpid(pid_t pid, int *statptr, int options)
                     56: {
                     57: #ifdef HAVE_WAIT4
                     58:        return wait4(pid, statptr, options, NULL);
                     59: #else
                     60:        /* If wait4 is also not available, try wait3 for SVR3 variants */
                     61:        /* Less ideal because can't actually request a specific pid */
                     62:        /* At least the WNOHANG option is supported */
                     63:        /* Code borrowed from apache fragment written by dwd@bell-labs.com */
                     64:        int tmp_pid, dummystat;;
                     65:        if (kill(pid, 0) == -1) {
                     66:                errno = ECHILD;
                     67:                return -1;
                     68:        }
                     69:        if (statptr == NULL)
                     70:                statptr = &dummystat;
                     71:        while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
                     72:                    (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
                     73:            ;
                     74:        return tmp_pid;
                     75: #endif
                     76: }
                     77: #endif
                     78: 
                     79: 
                     80: #ifndef HAVE_MEMMOVE
                     81:  void *memmove(void *dest, const void *src, size_t n)
                     82: {
                     83:        bcopy((char *) src, (char *) dest, n);
                     84:        return dest;
                     85: }
                     86: #endif
                     87: 
                     88: #ifndef HAVE_STRPBRK
                     89: /**
1.1.1.4 ! misho      90:  * Find the first occurrence in @p s of any character in @p accept.
1.1       misho      91:  *
                     92:  * Derived from glibc
                     93:  **/
                     94:  char *strpbrk(const char *s, const char *accept)
                     95: {
                     96:        while (*s != '\0')  {
                     97:                const char *a = accept;
                     98:                while (*a != '\0') {
                     99:                        if (*a++ == *s) return (char *)s;
                    100:                }
                    101:                ++s;
                    102:        }
                    103: 
                    104:        return NULL;
                    105: }
                    106: #endif
                    107: 
                    108: 
                    109: #ifndef HAVE_STRLCPY
                    110: /**
                    111:  * Like strncpy but does not 0 fill the buffer and always null
                    112:  * terminates.
                    113:  *
                    114:  * @param bufsize is the size of the destination buffer.
                    115:  *
                    116:  * @return index of the terminating byte.
                    117:  **/
                    118:  size_t strlcpy(char *d, const char *s, size_t bufsize)
                    119: {
                    120:        size_t len = strlen(s);
                    121:        size_t ret = len;
                    122:        if (bufsize > 0) {
                    123:                if (len >= bufsize)
                    124:                        len = bufsize-1;
                    125:                memcpy(d, s, len);
                    126:                d[len] = 0;
                    127:        }
                    128:        return ret;
                    129: }
                    130: #endif
                    131: 
                    132: #ifndef HAVE_STRLCAT
                    133: /**
                    134:  * Like strncat() but does not 0 fill the buffer and always null
                    135:  * terminates.
                    136:  *
                    137:  * @param bufsize length of the buffer, which should be one more than
                    138:  * the maximum resulting string length.
                    139:  **/
                    140:  size_t strlcat(char *d, const char *s, size_t bufsize)
                    141: {
                    142:        size_t len1 = strlen(d);
                    143:        size_t len2 = strlen(s);
                    144:        size_t ret = len1 + len2;
                    145: 
                    146:        if (len1 < bufsize - 1) {
                    147:                if (len2 >= bufsize - len1)
                    148:                        len2 = bufsize - len1 - 1;
                    149:                memcpy(d+len1, s, len2);
                    150:                d[len1+len2] = 0;
                    151:        }
                    152:        return ret;
                    153: }
                    154: #endif
                    155: 
                    156: /* some systems don't take the 2nd argument */
                    157: int sys_gettimeofday(struct timeval *tv)
                    158: {
                    159: #ifdef HAVE_GETTIMEOFDAY_TZ
                    160:        return gettimeofday(tv, NULL);
                    161: #else
                    162:        return gettimeofday(tv);
                    163: #endif
                    164: }
1.1.1.2   misho     165: 
                    166: /* Return the int64 number as a string.  If the human_flag arg is non-zero,
                    167:  * we may output the number in K, M, G, or T units.  If we don't add a unit
                    168:  * suffix, we will append the fract string, if it is non-NULL.  We can
                    169:  * return up to 4 buffers at a time. */
                    170: char *do_big_num(int64 num, int human_flag, const char *fract)
                    171: {
                    172:        static char bufs[4][128]; /* more than enough room */
                    173:        static unsigned int n;
                    174:        char *s;
                    175:        int len, negated;
                    176: 
1.1.1.4 ! misho     177:        if (human_flag && !number_separator)
        !           178:                (void)get_number_separator();
1.1.1.2   misho     179: 
                    180:        n = (n + 1) % (sizeof bufs / sizeof bufs[0]);
                    181: 
                    182:        if (human_flag > 1) {
1.1.1.4 ! misho     183:                int mult = human_flag == 2 ? 1000 : 1024;
        !           184:                if (num >= mult || num <= -mult) {
        !           185:                        double dnum = (double)num / mult;
        !           186:                        char units;
        !           187:                        if (num < 0)
        !           188:                                dnum = -dnum;
        !           189:                        if (dnum < mult)
        !           190:                                units = 'K';
        !           191:                        else if ((dnum /= mult) < mult)
        !           192:                                units = 'M';
        !           193:                        else if ((dnum /= mult) < mult)
        !           194:                                units = 'G';
        !           195:                        else if ((dnum /= mult) < mult)
        !           196:                                units = 'T';
        !           197:                        else {
        !           198:                                dnum /= mult;
        !           199:                                units = 'P';
        !           200:                        }
        !           201:                        if (num < 0)
        !           202:                                dnum = -dnum;
        !           203:                        snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units);
        !           204:                        return bufs[n];
        !           205:                }
1.1.1.2   misho     206:        }
                    207: 
                    208:        s = bufs[n] + sizeof bufs[0] - 1;
                    209:        if (fract) {
                    210:                len = strlen(fract);
                    211:                s -= len;
                    212:                strlcpy(s, fract, len + 1);
                    213:        } else
                    214:                *s = '\0';
                    215: 
                    216:        len = 0;
                    217: 
                    218:        if (!num)
                    219:                *--s = '0';
                    220:        if (num < 0) {
                    221:                /* A maximum-size negated number can't fit as a positive,
                    222:                 * so do one digit in negated form to start us off. */
                    223:                *--s = (char)(-(num % 10)) + '0';
                    224:                num = -(num / 10);
                    225:                len++;
                    226:                negated = 1;
                    227:        } else
                    228:                negated = 0;
                    229: 
                    230:        while (num) {
                    231:                if (human_flag) {
                    232:                        if (len == 3) {
                    233:                                *--s = number_separator;
                    234:                                len = 1;
                    235:                        } else
                    236:                                len++;
                    237:                }
                    238:                *--s = (char)(num % 10) + '0';
                    239:                num /= 10;
                    240:        }
                    241: 
                    242:        if (negated)
                    243:                *--s = '-';
                    244: 
                    245:        return s;
                    246: }
                    247: 
                    248: /* Return the double number as a string.  If the human_flag option is > 1,
                    249:  * we may output the number in K, M, G, or T units.  The buffer we use for
                    250:  * our result is either a single static buffer defined here, or a buffer
                    251:  * we get from do_big_num(). */
                    252: char *do_big_dnum(double dnum, int human_flag, int decimal_digits)
                    253: {
                    254:        static char tmp_buf[128];
                    255: #if SIZEOF_INT64 >= 8
                    256:        char *fract;
                    257: 
                    258:        snprintf(tmp_buf, sizeof tmp_buf, "%.*f", decimal_digits, dnum);
                    259: 
                    260:        if (!human_flag || (dnum < 1000.0 && dnum > -1000.0))
                    261:                return tmp_buf;
                    262: 
                    263:        for (fract = tmp_buf+1; isDigit(fract); fract++) {}
                    264: 
                    265:        return do_big_num((int64)dnum, human_flag, fract);
                    266: #else
                    267:        /* A big number might lose digits converting to a too-short int64,
                    268:         * so let's just return the raw double conversion. */
                    269:        snprintf(tmp_buf, sizeof tmp_buf, "%.*f", decimal_digits, dnum);
                    270:        return tmp_buf;
                    271: #endif
                    272: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>