Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/coreutils/tail.c

    r1772 r2725  
    55 * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    3131    { "k", 1024 },
    3232    { "m", 1024*1024 },
    33     { }
     33    { "", 0 }
    3434};
    3535
    3636struct globals {
    3737    bool status;
    38 };
     38} FIX_ALIASING;
    3939#define G (*(struct globals*)&bb_common_bufsiz1)
    4040
     
    5151    struct stat sbuf;
    5252
    53     /* (A good comment is missing here) */
    54     current = lseek(fd, 0, SEEK_CUR);
    5553    /* /proc files report zero st_size, don't lseek them. */
    56     if (fstat(fd, &sbuf) == 0 && sbuf.st_size)
     54    if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
     55        current = lseek(fd, 0, SEEK_CUR);
    5756        if (sbuf.st_size < current)
    58             lseek(fd, 0, SEEK_SET);
    59 
    60     r = safe_read(fd, buf, count);
     57            xlseek(fd, 0, SEEK_SET);
     58    }
     59
     60    r = full_read(fd, buf, count);
    6161    if (r < 0) {
    6262        bb_perror_msg(bb_msg_read_error);
     
    6767}
    6868
    69 static const char header_fmt[] ALIGN1 = "\n==> %s <==\n";
     69#define header_fmt_str "\n==> %s <==\n"
    7070
    7171static unsigned eat_num(const char *p)
     
    7575    else if (*p == '+') {
    7676        p++;
    77         G.status = EXIT_FAILURE;
     77        G.status = 1; /* mark that we saw "+" */
    7878    }
    7979    return xatou_sfx(p, tail_suffixes);
    8080}
    8181
    82 int tail_main(int argc, char **argv);
     82int tail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    8383int tail_main(int argc, char **argv)
    8484{
     
    8686    unsigned sleep_period = 1;
    8787    bool from_top;
    88     int header_threshhold = 1;
    8988    const char *str_c, *str_n;
    90     USE_FEATURE_FANCY_TAIL(const char *str_s;)
    9189
    9290    char *tailbuf;
    9391    size_t tailbufsize;
    94     int taillen = 0;
    95     int newline = 0;
    96     int nfiles, nread, nwrite, seen, i, opt;
     92    unsigned header_threshhold = 1;
     93    unsigned nfiles;
     94    int i, opt;
    9795
    9896    int *fds;
    99     char *s, *buf;
    10097    const char *fmt;
    10198
    10299#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
    103100    /* Allow legacy syntax of an initial numeric option without -n. */
    104     if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-')
     101    if (argv[1] && (argv[1][0] == '+' || argv[1][0] == '-')
    105102     && isdigit(argv[1][1])
    106103    ) {
    107         /* replacing arg[0] with "-n" can segfault, so... */
    108         argv[1] = xasprintf("-n%s", argv[1]);
    109 #if 0 /* If we ever decide to make tail NOFORK */
    110         char *s = alloca(strlen(argv[1]) + 3);
    111         sprintf(s, "-n%s", argv[1]);
    112         argv[1] = s;
     104        count = eat_num(argv[1]);
     105        argv++;
     106        argc--;
     107    }
    113108#endif
    114     }
    115 #endif
    116 
    117     opt = getopt32(argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"),
    118             &str_c, &str_n USE_FEATURE_FANCY_TAIL(,&str_s));
     109
     110    /* -s NUM, -F imlies -f */
     111    IF_FEATURE_FANCY_TAIL(opt_complementary = "s+:Ff";)
     112    opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:vF"),
     113            &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period));
    119114#define FOLLOW (opt & 0x1)
    120115#define COUNT_BYTES (opt & 0x2)
     
    123118    if (opt & 0x4) count = eat_num(str_n); // -n
    124119#if ENABLE_FEATURE_FANCY_TAIL
    125     if (opt & 0x8) header_threshhold = INT_MAX; // -q
    126     if (opt & 0x10) sleep_period = xatou(str_s); // -s
     120    /* q: make it impossible for nfiles to be > header_threshhold */
     121    if (opt & 0x8) header_threshhold = UINT_MAX; // -q
     122    //if (opt & 0x10) // -s
    127123    if (opt & 0x20) header_threshhold = 0; // -v
     124# define FOLLOW_RETRY (opt & 0x40)
     125#else
     126# define FOLLOW_RETRY 0
    128127#endif
    129128    argc -= optind;
    130129    argv += optind;
    131     from_top = G.status;
     130    from_top = G.status; /* 1 if there was "-c +N" or "-n +N" */
     131    G.status = EXIT_SUCCESS;
    132132
    133133    /* open all the files */
    134     fds = xmalloc(sizeof(int) * (argc + 1));
     134    fds = xmalloc(sizeof(fds[0]) * (argc + 1));
     135    if (!argv[0]) {
     136        struct stat statbuf;
     137
     138        if (fstat(STDIN_FILENO, &statbuf) == 0
     139         && S_ISFIFO(statbuf.st_mode)
     140        ) {
     141            opt &= ~1; /* clear FOLLOW */
     142        }
     143        argv[0] = (char *) bb_msg_standard_input;
     144    }
    135145    nfiles = i = 0;
    136     G.status = EXIT_SUCCESS;
    137     if (argc == 0) {
    138         struct stat statbuf;
    139 
    140         if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {
    141             opt &= ~1; /* clear FOLLOW */
    142         }
    143         *argv = (char *) bb_msg_standard_input;
    144     }
    145146    do {
    146         FILE* fil = fopen_or_warn_stdin(argv[i]);
    147         if (!fil) {
     147        int fd = open_or_warn_stdin(argv[i]);
     148        if (fd < 0 && !FOLLOW_RETRY) {
    148149            G.status = EXIT_FAILURE;
    149150            continue;
    150151        }
    151         fds[nfiles] = fileno(fil);
     152        fds[nfiles] = fd;
    152153        argv[nfiles++] = argv[i];
    153154    } while (++i < argc);
     
    156157        bb_error_msg_and_die("no files");
    157158
     159    /* prepare the buffer */
    158160    tailbufsize = BUFSIZ;
     161    if (!from_top && COUNT_BYTES) {
     162        if (tailbufsize < count + BUFSIZ) {
     163            tailbufsize = count + BUFSIZ;
     164        }
     165    }
     166    tailbuf = xmalloc(tailbufsize);
    159167
    160168    /* tail the files */
    161     if (!from_top && COUNT_BYTES) {
    162         if (tailbufsize < count) {
    163             tailbufsize = count + BUFSIZ;
    164         }
    165     }
    166 
    167     buf = tailbuf = xmalloc(tailbufsize);
    168 
    169     fmt = header_fmt + 1;   /* Skip header leading newline on first output. */
     169    fmt = header_fmt_str + 1; /* skip header leading newline on first output */
    170170    i = 0;
    171171    do {
    172         /* Be careful.  It would be possible to optimize the count-bytes
    173          * case if the file is seekable.  If you do though, remember that
    174          * starting file position may not be the beginning of the file.
    175          * Beware of backing up too far.  See example in wc.c.
    176          */
    177         if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) {
    178             continue;
    179         }
     172        char *buf;
     173        int taillen;
     174        int newlines_seen;
     175        unsigned seen;
     176        int nread;
     177        int fd = fds[i];
     178
     179        if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
     180            continue; /* may happen with -E */
    180181
    181182        if (nfiles > header_threshhold) {
    182183            tail_xprint_header(fmt, argv[i]);
    183             fmt = header_fmt;
     184            fmt = header_fmt_str;
     185        }
     186
     187        if (!from_top) {
     188            off_t current = lseek(fd, 0, SEEK_END);
     189            if (current > 0) {
     190                unsigned off;
     191                if (COUNT_BYTES) {
     192                /* Optimizing count-bytes case if the file is seekable.
     193                 * Beware of backing up too far.
     194                 * Also we exclude files with size 0 (because of /proc/xxx) */
     195                    if (count == 0)
     196                        continue; /* showing zero bytes is easy :) */
     197                    current -= count;
     198                    if (current < 0)
     199                        current = 0;
     200                    xlseek(fd, current, SEEK_SET);
     201                    bb_copyfd_size(fd, STDOUT_FILENO, count);
     202                    continue;
     203                }
     204#if 1 /* This is technically incorrect for *LONG* strings, but very useful */
     205                /* Optimizing count-lines case if the file is seekable.
     206                 * We assume the lines are <64k.
     207                 * (Users complain that tail takes too long
     208                 * on multi-gigabyte files) */
     209                off = (count | 0xf); /* for small counts, be more paranoid */
     210                if (off > (INT_MAX / (64*1024)))
     211                    off = (INT_MAX / (64*1024));
     212                current -= off * (64*1024);
     213                if (current < 0)
     214                    current = 0;
     215                xlseek(fd, current, SEEK_SET);
     216#endif
     217            }
    184218        }
    185219
    186220        buf = tailbuf;
    187221        taillen = 0;
     222        /* "We saw 1st line/byte".
     223         * Used only by +N code ("start from Nth", 1-based): */
    188224        seen = 1;
    189         newline = 0;
    190 
    191         while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
     225        newlines_seen = 0;
     226        while ((nread = tail_read(fd, buf, tailbufsize-taillen)) > 0) {
    192227            if (from_top) {
    193                 nwrite = nread;
     228                int nwrite = nread;
    194229                if (seen < count) {
     230                    /* We need to skip a few more bytes/lines */
    195231                    if (COUNT_BYTES) {
    196232                        nwrite -= (count - seen);
    197233                        seen = count;
    198234                    } else {
    199                         s = buf;
     235                        char *s = buf;
    200236                        do {
    201237                            --nwrite;
     
    206242                    }
    207243                }
    208                 xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);
     244                if (nwrite > 0)
     245                    xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);
    209246            } else if (count) {
    210247                if (COUNT_BYTES) {
    211248                    taillen += nread;
    212                     if (taillen > count) {
     249                    if (taillen > (int)count) {
    213250                        memmove(tailbuf, tailbuf + taillen - count, count);
    214251                        taillen = count;
     
    216253                } else {
    217254                    int k = nread;
    218                     int nbuf = 0;
    219 
    220                     while (k) {
    221                         --k;
     255                    int newlines_in_buf = 0;
     256
     257                    do { /* count '\n' in last read */
     258                        k--;
    222259                        if (buf[k] == '\n') {
    223                             ++nbuf;
     260                            newlines_in_buf++;
    224261                        }
    225                     }
    226 
    227                     if (newline + nbuf < count) {
    228                         newline += nbuf;
     262                    } while (k);
     263
     264                    if (newlines_seen + newlines_in_buf < (int)count) {
     265                        newlines_seen += newlines_in_buf;
    229266                        taillen += nread;
    230267                    } else {
    231                         int extra = 0;
    232 
    233                         if (buf[nread-1] != '\n')
    234                             extra = 1;
    235                         k = newline + nbuf + extra - count;
     268                        int extra = (buf[nread-1] != '\n');
     269                        char *s;
     270
     271                        k = newlines_seen + newlines_in_buf + extra - count;
    236272                        s = tailbuf;
    237273                        while (k) {
    238274                            if (*s == '\n') {
    239                                 --k;
     275                                k--;
    240276                            }
    241                             ++s;
     277                            s++;
    242278                        }
    243279                        taillen += nread - (s - tailbuf);
    244280                        memmove(tailbuf, s, taillen);
    245                         newline = count - extra;
    246                     }
    247                     if (tailbufsize < taillen + BUFSIZ) {
     281                        newlines_seen = count - extra;
     282                    }
     283                    if (tailbufsize < (size_t)taillen + BUFSIZ) {
    248284                        tailbufsize = taillen + BUFSIZ;
    249285                        tailbuf = xrealloc(tailbuf, tailbufsize);
     
    252288                buf = tailbuf + taillen;
    253289            }
    254         }
    255 
     290        } /* while (tail_read() > 0) */
    256291        if (!from_top) {
    257292            xwrite(STDOUT_FILENO, tailbuf, taillen);
    258293        }
    259 
    260         taillen = 0;
    261294    } while (++i < nfiles);
    262295
    263     buf = xrealloc(tailbuf, BUFSIZ);
     296    tailbuf = xrealloc(tailbuf, BUFSIZ);
    264297
    265298    fmt = NULL;
     
    267300    if (FOLLOW) while (1) {
    268301        sleep(sleep_period);
     302
    269303        i = 0;
    270304        do {
     305            int nread;
     306            const char *filename = argv[i];
     307            int fd = fds[i];
     308
     309            if (FOLLOW_RETRY) {
     310                struct stat sbuf, fsbuf;
     311
     312                if (fd < 0
     313                 || fstat(fd, &fsbuf) < 0
     314                 || stat(filename, &sbuf) < 0
     315                 || fsbuf.st_dev != sbuf.st_dev
     316                 || fsbuf.st_ino != sbuf.st_ino
     317                ) {
     318                    int new_fd;
     319
     320                    if (fd >= 0)
     321                        close(fd);
     322                    new_fd = open(filename, O_RDONLY);
     323                    if (new_fd >= 0) {
     324                        bb_error_msg("%s has %s; following end of new file",
     325                            filename, (fd < 0) ? "appeared" : "been replaced"
     326                        );
     327                    } else if (fd >= 0) {
     328                        bb_perror_msg("%s has become inaccessible", filename);
     329                    }
     330                    fds[i] = fd = new_fd;
     331                }
     332            }
     333            if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
     334                continue;
    271335            if (nfiles > header_threshhold) {
    272                 fmt = header_fmt;
    273             }
    274             while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) {
     336                fmt = header_fmt_str;
     337            }
     338            while ((nread = tail_read(fd, tailbuf, BUFSIZ)) > 0) {
    275339                if (fmt) {
    276                     tail_xprint_header(fmt, argv[i]);
     340                    tail_xprint_header(fmt, filename);
    277341                    fmt = NULL;
    278342                }
    279                 xwrite(STDOUT_FILENO, buf, nread);
     343                xwrite(STDOUT_FILENO, tailbuf, nread);
    280344            }
    281345        } while (++i < nfiles);
     
    283347    if (ENABLE_FEATURE_CLEAN_UP) {
    284348        free(fds);
     349        free(tailbuf);
    285350    }
    286351    return G.status;
Note: See TracChangeset for help on using the changeset viewer.