Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/coreutils/tail.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 30  static const struct suffix_mult tail_suf Line 30  static const struct suffix_mult tail_suf
30   { "b", 512 },   { "b", 512 },
31   { "k", 1024 },   { "k", 1024 },
32   { "m", 1024*1024 },   { "m", 1024*1024 },
33   { }   { "", 0 }
34  };  };
35    
36  struct globals {  struct globals {
# Line 50  static ssize_t tail_read(int fd, char *b Line 50  static ssize_t tail_read(int fd, char *b
50   off_t current;   off_t current;
51   struct stat sbuf;   struct stat sbuf;
52    
  /* (A good comment is missing here) */  
  current = lseek(fd, 0, SEEK_CUR);  
53   /* /proc files report zero st_size, don't lseek them. */   /* /proc files report zero st_size, don't lseek them. */
54   if (fstat(fd, &sbuf) == 0 && sbuf.st_size)   if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
55     current = lseek(fd, 0, SEEK_CUR);
56   if (sbuf.st_size < current)   if (sbuf.st_size < current)
57   lseek(fd, 0, SEEK_SET);   xlseek(fd, 0, SEEK_SET);
58     }
59    
60   r = full_read(fd, buf, count);   r = full_read(fd, buf, count);
61   if (r < 0) {   if (r < 0) {
# Line 85  int tail_main(int argc, char **argv) Line 85  int tail_main(int argc, char **argv)
85   unsigned count = 10;   unsigned count = 10;
86   unsigned sleep_period = 1;   unsigned sleep_period = 1;
87   bool from_top;   bool from_top;
  int header_threshhold = 1;  
88   const char *str_c, *str_n;   const char *str_c, *str_n;
89    
90   char *tailbuf;   char *tailbuf;
91   size_t tailbufsize;   size_t tailbufsize;
92   int taillen = 0;   unsigned header_threshhold = 1;
93   int newlines_seen = 0;   unsigned nfiles;
94   int nfiles, nread, nwrite, i, opt;   int i, opt;
  unsigned seen;  
95    
96   int *fds;   int *fds;
  char *s, *buf;  
97   const char *fmt;   const char *fmt;
98    
99  #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL  #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL
# Line 110  int tail_main(int argc, char **argv) Line 107  int tail_main(int argc, char **argv)
107   }   }
108  #endif  #endif
109    
110   USE_FEATURE_FANCY_TAIL(opt_complementary = "s+";) /* -s N */   /* -s NUM, -F imlies -f */
111   opt = getopt32(argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"),   IF_FEATURE_FANCY_TAIL(opt_complementary = "s+:Ff";)
112   &str_c, &str_n USE_FEATURE_FANCY_TAIL(,&sleep_period));   opt = getopt32(argv, "fc:n:" IF_FEATURE_FANCY_TAIL("qs:vF"),
113     &str_c, &str_n IF_FEATURE_FANCY_TAIL(,&sleep_period));
114  #define FOLLOW (opt & 0x1)  #define FOLLOW (opt & 0x1)
115  #define COUNT_BYTES (opt & 0x2)  #define COUNT_BYTES (opt & 0x2)
116   //if (opt & 0x1) // -f   //if (opt & 0x1) // -f
117   if (opt & 0x2) count = eat_num(str_c); // -c   if (opt & 0x2) count = eat_num(str_c); // -c
118   if (opt & 0x4) count = eat_num(str_n); // -n   if (opt & 0x4) count = eat_num(str_n); // -n
119  #if ENABLE_FEATURE_FANCY_TAIL  #if ENABLE_FEATURE_FANCY_TAIL
120   if (opt & 0x8) header_threshhold = INT_MAX; // -q   /* q: make it impossible for nfiles to be > header_threshhold */
121     if (opt & 0x8) header_threshhold = UINT_MAX; // -q
122     //if (opt & 0x10) // -s
123   if (opt & 0x20) header_threshhold = 0; // -v   if (opt & 0x20) header_threshhold = 0; // -v
124    # define FOLLOW_RETRY (opt & 0x40)
125    #else
126    # define FOLLOW_RETRY 0
127  #endif  #endif
128   argc -= optind;   argc -= optind;
129   argv += optind;   argv += optind;
# Line 128  int tail_main(int argc, char **argv) Line 131  int tail_main(int argc, char **argv)
131   G.status = EXIT_SUCCESS;   G.status = EXIT_SUCCESS;
132    
133   /* open all the files */   /* open all the files */
134   fds = xmalloc(sizeof(int) * (argc + 1));   fds = xmalloc(sizeof(fds[0]) * (argc + 1));
135   if (!argv[0]) {   if (!argv[0]) {
136   struct stat statbuf;   struct stat statbuf;
137    
138   if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) {   if (fstat(STDIN_FILENO, &statbuf) == 0
139     && S_ISFIFO(statbuf.st_mode)
140     ) {
141   opt &= ~1; /* clear FOLLOW */   opt &= ~1; /* clear FOLLOW */
142   }   }
143   *argv = (char *) bb_msg_standard_input;   argv[0] = (char *) bb_msg_standard_input;
144   }   }
145   nfiles = i = 0;   nfiles = i = 0;
146   do {   do {
147   int fd = open_or_warn_stdin(argv[i]);   int fd = open_or_warn_stdin(argv[i]);
148   if (fd < 0) {   if (fd < 0 && !FOLLOW_RETRY) {
149   G.status = EXIT_FAILURE;   G.status = EXIT_FAILURE;
150   continue;   continue;
151   }   }
# Line 161  int tail_main(int argc, char **argv) Line 166  int tail_main(int argc, char **argv)
166   tailbuf = xmalloc(tailbufsize);   tailbuf = xmalloc(tailbufsize);
167    
168   /* tail the files */   /* tail the files */
169   fmt = header_fmt + 1; /* Skip header leading newline on first output. */   fmt = header_fmt + 1; /* skip header leading newline on first output */
170   i = 0;   i = 0;
171   do {   do {
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 */
181    
182   if (nfiles > header_threshhold) {   if (nfiles > header_threshhold) {
183   tail_xprint_header(fmt, argv[i]);   tail_xprint_header(fmt, argv[i]);
184   fmt = header_fmt;   fmt = header_fmt;
185   }   }
186    
187   /* Optimizing count-bytes case if the file is seekable.   if (!from_top) {
188   * Beware of backing up too far.   off_t current = lseek(fd, 0, SEEK_END);
  * Also we exclude files with size 0 (because of /proc/xxx) */  
  if (COUNT_BYTES && !from_top) {  
  off_t current = lseek(fds[i], 0, SEEK_END);  
189   if (current > 0) {   if (current > 0) {
190   if (count == 0)   unsigned off;
191   continue; /* showing zero lines is easy :) */   if (COUNT_BYTES) {
192   current -= count;   /* 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)   if (current < 0)
214   current = 0;   current = 0;
215   xlseek(fds[i], current, SEEK_SET);   xlseek(fd, current, SEEK_SET);
216   bb_copyfd_size(fds[i], STDOUT_FILENO, count);  #endif
  continue;  
217   }   }
218   }   }
219    
220   buf = tailbuf;   buf = tailbuf;
221   taillen = 0;   taillen = 0;
222     /* "We saw 1st line/byte".
223     * Used only by +N code ("start from Nth", 1-based): */
224   seen = 1;   seen = 1;
225   newlines_seen = 0;   newlines_seen = 0;
226   while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {   while ((nread = tail_read(fd, buf, tailbufsize-taillen)) > 0) {
227   if (from_top) {   if (from_top) {
228   nwrite = nread;   int nwrite = nread;
229   if (seen < count) {   if (seen < count) {
230     /* We need to skip a few more bytes/lines */
231   if (COUNT_BYTES) {   if (COUNT_BYTES) {
232   nwrite -= (count - seen);   nwrite -= (count - seen);
233   seen = count;   seen = count;
234   } else {   } else {
235   s = buf;   char *s = buf;
236   do {   do {
237   --nwrite;   --nwrite;
238   if (*s++ == '\n' && ++seen == count) {   if (*s++ == '\n' && ++seen == count) {
# Line 207  int tail_main(int argc, char **argv) Line 241  int tail_main(int argc, char **argv)
241   } while (nwrite);   } while (nwrite);
242   }   }
243   }   }
244   xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);   if (nwrite > 0)
245     xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite);
246   } else if (count) {   } else if (count) {
247   if (COUNT_BYTES) {   if (COUNT_BYTES) {
248   taillen += nread;   taillen += nread;
# Line 231  int tail_main(int argc, char **argv) Line 266  int tail_main(int argc, char **argv)
266   taillen += nread;   taillen += nread;
267   } else {   } else {
268   int extra = (buf[nread-1] != '\n');   int extra = (buf[nread-1] != '\n');
269     char *s;
270    
271   k = newlines_seen + newlines_in_buf + extra - count;   k = newlines_seen + newlines_in_buf + extra - count;
272   s = tailbuf;   s = tailbuf;
# Line 257  int tail_main(int argc, char **argv) Line 293  int tail_main(int argc, char **argv)
293   }   }
294   } while (++i < nfiles);   } while (++i < nfiles);
295    
296   buf = xrealloc(tailbuf, BUFSIZ);   tailbuf = xrealloc(tailbuf, BUFSIZ);
297    
298   fmt = NULL;   fmt = NULL;
299    
300   if (FOLLOW) while (1) {   if (FOLLOW) while (1) {
301   sleep(sleep_period);   sleep(sleep_period);
302    
303   i = 0;   i = 0;
304   do {   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;
335   if (nfiles > header_threshhold) {   if (nfiles > header_threshhold) {
336   fmt = header_fmt;   fmt = header_fmt;
337   }   }
338   while ((nread = tail_read(fds[i], buf, BUFSIZ)) > 0) {   while ((nread = tail_read(fd, tailbuf, BUFSIZ)) > 0) {
339   if (fmt) {   if (fmt) {
340   tail_xprint_header(fmt, argv[i]);   tail_xprint_header(fmt, filename);
341   fmt = NULL;   fmt = NULL;
342   }   }
343   xwrite(STDOUT_FILENO, buf, nread);   xwrite(STDOUT_FILENO, tailbuf, nread);
344   }   }
345   } while (++i < nfiles);   } while (++i < nfiles);
346   }   }

Legend:
Removed from v.983  
changed lines
  Added in v.984