Deleted Added
full compact
reverse.c (313100) reverse.c (314427)
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Edward Sze-Tyan Wang.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 23 unchanged lines hidden (view full) ---

32
33#if 0
34#ifndef lint
35static char sccsid[] = "@(#)reverse.c 8.1 (Berkeley) 6/6/93";
36#endif /* not lint */
37#endif
38
39#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Edward Sze-Tyan Wang.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 23 unchanged lines hidden (view full) ---

32
33#if 0
34#ifndef lint
35static char sccsid[] = "@(#)reverse.c 8.1 (Berkeley) 6/6/93";
36#endif /* not lint */
37#endif
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: stable/11/usr.bin/tail/reverse.c 313100 2017-02-02 18:27:20Z asomers $");
40__FBSDID("$FreeBSD: stable/11/usr.bin/tail/reverse.c 314427 2017-02-28 22:49:41Z asomers $");
41
42#include <sys/param.h>
41
42#include <sys/param.h>
43#include <sys/queue.h>
43#include <sys/stat.h>
44#include <sys/mman.h>
45
46#include <err.h>
47#include <errno.h>
48#include <limits.h>
49#include <stdint.h>
50#include <stdio.h>

--- 113 unchanged lines hidden (view full) ---

164 if (curoff < 0 && mapprint(&map, 0, lineend) != 0) {
165 ierr(fn);
166 return;
167 }
168 if (map.start != NULL && munmap(map.start, map.maplen))
169 ierr(fn);
170}
171
44#include <sys/stat.h>
45#include <sys/mman.h>
46
47#include <err.h>
48#include <errno.h>
49#include <limits.h>
50#include <stdint.h>
51#include <stdio.h>

--- 113 unchanged lines hidden (view full) ---

165 if (curoff < 0 && mapprint(&map, 0, lineend) != 0) {
166 ierr(fn);
167 return;
168 }
169 if (map.start != NULL && munmap(map.start, map.maplen))
170 ierr(fn);
171}
172
172typedef struct bf {
173 struct bf *next;
174 struct bf *prev;
175 int len;
176 char *l;
177} BF;
173#define BSZ (128 * 1024)
174typedef struct bfelem {
175 TAILQ_ENTRY(bfelem) entries;
176 size_t len;
177 char l[BSZ];
178} bfelem_t;
178
179/*
180 * r_buf -- display a non-regular file in reverse order by line.
181 *
182 * This is the function that saves the entire input, storing the data in a
183 * doubly linked list of buffers and then displays them in reverse order.
184 * It has the usual nastiness of trying to find the newlines, as there's no
185 * guarantee that a newline occurs anywhere in the file, let alone in any
186 * particular buffer. If we run out of memory, input is discarded (and the
187 * user warned).
188 */
189static void
190r_buf(FILE *fp, const char *fn)
191{
179
180/*
181 * r_buf -- display a non-regular file in reverse order by line.
182 *
183 * This is the function that saves the entire input, storing the data in a
184 * doubly linked list of buffers and then displays them in reverse order.
185 * It has the usual nastiness of trying to find the newlines, as there's no
186 * guarantee that a newline occurs anywhere in the file, let alone in any
187 * particular buffer. If we run out of memory, input is discarded (and the
188 * user warned).
189 */
190static void
191r_buf(FILE *fp, const char *fn)
192{
192 BF *mark, *tl, *tr;
193 int ch, len, llen;
193 struct bfelem *tl, *first = NULL;
194 size_t llen;
194 char *p;
195 char *p;
195 off_t enomem;
196 off_t enomem = 0;
197 TAILQ_HEAD(bfhead, bfelem) head;
196
198
197 tl = NULL;
198#define BSZ (128 * 1024)
199 for (mark = NULL, enomem = 0;;) {
199 TAILQ_INIT(&head);
200
201 while (!feof(fp)) {
202 size_t len;
203
200 /*
201 * Allocate a new block and link it into place in a doubly
202 * linked list. If out of memory, toss the LRU block and
203 * keep going.
204 */
204 /*
205 * Allocate a new block and link it into place in a doubly
206 * linked list. If out of memory, toss the LRU block and
207 * keep going.
208 */
205 if (enomem || (tl = malloc(sizeof(BF))) == NULL ||
206 (tl->l = malloc(BSZ)) == NULL) {
207 if (!mark)
209 while ((tl = malloc(sizeof(bfelem_t))) == NULL) {
210 first = TAILQ_FIRST(&head);
211 if (TAILQ_EMPTY(&head))
208 err(1, "malloc");
212 err(1, "malloc");
209 if (enomem)
210 tl = tl->next;
211 else {
212 if (tl)
213 free(tl);
214 tl = mark;
215 }
216 enomem += tl->len;
217 } else if (mark) {
218 tl->next = mark;
219 tl->prev = mark->prev;
220 mark->prev->next = tl;
221 mark->prev = tl;
222 } else {
223 mark = tl;
224 mark->next = mark->prev = mark;
213 enomem += first->len;
214 TAILQ_REMOVE(&head, first, entries);
215 free(first);
225 }
216 }
217 TAILQ_INSERT_TAIL(&head, tl, entries);
226
227 /* Fill the block with input data. */
218
219 /* Fill the block with input data. */
228 for (p = tl->l, len = 0;
229 len < BSZ && (ch = getc(fp)) != EOF; ++len)
230 *p++ = ch;
231
232 if (ferror(fp)) {
233 ierr(fn);
234 return;
220 len = 0;
221 while ((!feof(fp)) && len < BSZ) {
222 p = tl->l + len;
223 len += fread(p, 1, BSZ - len, fp);
224 if (ferror(fp)) {
225 ierr(fn);
226 return;
227 }
235 }
236
228 }
229
237 /*
238 * If no input data for this block and we tossed some data,
239 * recover it.
240 */
241 if (!len && enomem) {
242 enomem -= tl->len;
243 tl = tl->prev;
244 break;
245 }
246
247 tl->len = len;
230 tl->len = len;
248 if (ch == EOF)
249 break;
250 }
251
252 if (enomem) {
253 warnx("warning: %jd bytes discarded", (intmax_t)enomem);
254 rval = 1;
255 }
256
257 /*
231 }
232
233 if (enomem) {
234 warnx("warning: %jd bytes discarded", (intmax_t)enomem);
235 rval = 1;
236 }
237
238 /*
258 * Step through the blocks in the reverse order read. The last char
259 * is special, ignore whether newline or not.
239 * Now print the lines in reverse order
240 * Outline:
241 * Scan backward for "\n",
242 * print forward to the end of the buffers
243 * free any buffers that start after the "\n" just found
244 * Loop
260 */
245 */
261 for (mark = tl;;) {
262 for (p = tl->l + (len = tl->len) - 1, llen = 0; len--;
263 --p, ++llen)
264 if (*p == '\n') {
265 if (llen) {
246 tl = TAILQ_LAST(&head, bfhead);
247 first = TAILQ_FIRST(&head);
248 while (tl != NULL) {
249 struct bfelem *temp;
250
251 for (p = tl->l + tl->len - 1, llen = 0; p >= tl->l;
252 --p, ++llen) {
253 int start = (tl == first && p == tl->l);
254
255 if ((*p == '\n') || start) {
256 struct bfelem *tr;
257
258 if (start && llen)
259 WR(p, llen + 1);
260 else if (llen)
266 WR(p + 1, llen);
261 WR(p + 1, llen);
267 llen = 0;
262 tr = TAILQ_NEXT(tl, entries);
263 llen = 0;
264 if (tr != NULL) {
265 TAILQ_FOREACH_FROM_SAFE(tr, &head,
266 entries, temp) {
267 if (tr->len)
268 WR(&tr->l, tr->len);
269 TAILQ_REMOVE(&head, tr,
270 entries);
271 free(tr);
272 }
268 }
273 }
269 if (tl == mark)
270 continue;
271 for (tr = tl->next; tr->len; tr = tr->next) {
272 WR(tr->l, tr->len);
273 tr->len = 0;
274 if (tr == mark)
275 break;
276 }
277 }
274 }
275 }
278 tl->len = llen;
276 tl->len = llen;
279 if ((tl = tl->prev) == mark)
280 break;
277 tl = TAILQ_PREV(tl, bfhead, entries);
281 }
278 }
282 tl = tl->next;
283 if (tl->len) {
284 WR(tl->l, tl->len);
285 tl->len = 0;
286 }
287 while ((tl = tl->next)->len) {
288 WR(tl->l, tl->len);
289 tl->len = 0;
290 }
279 TAILQ_REMOVE(&head, first, entries);
280 free(first);
291}
281}