/* * rlines -- display the last offset lines of the file. */ static void rlines(FILE *fp, const char *fn, off_t off, struct stat *sbp) { struct mapinfo map; off_t curoff, size; int i; if (!(size = sbp->st_size)) return; map.start = NULL; map.fd = fileno(fp); map.mapoff = map.maxoff = size; /* * Last char is special, ignore whether newline or not. Note that * size == 0 is dealt with above, and size == 1 sets curoff to -1. */ curoff = size - 2; while (curoff >= 0) { if (curoff < map.mapoff && maparound(&map, curoff) != 0) { ierr(fn); return; } for (i = curoff - map.mapoff; i >= 0; i--) if (map.start[i] == '\n' && --off == 0) break; /* `i' is either the map offset of a '\n', or -1. */ curoff = map.mapoff + i; if (i >= 0) break; } curoff++; if (mapprint(&map, curoff, size - curoff) != 0) { ierr(fn); exit(1); } /* Set the file pointer to reflect the length displayed. */ if (fseeko(fp, sbp->st_size, SEEK_SET) == -1) { ierr(fn); return; } if (map.start != NULL && munmap(map.start, map.maplen)) { ierr(fn); return; } }
/* * Print `len' bytes from the file associated with `mip', starting at * absolute file offset `startoff'. May move map window. */ int mapprint(struct mapinfo *mip, off_t startoff, off_t len) { int n; while (len > 0) { if (startoff < mip->mapoff || startoff >= mip->mapoff + (off_t)mip->maplen) { if (maparound(mip, startoff) != 0) return (1); } n = (mip->mapoff + mip->maplen) - startoff; if (n > len) n = len; WR(mip->start + (startoff - mip->mapoff), n); startoff += n; len -= n; } return (0); }
/* * r_reg -- display a regular file in reverse order by line. */ static void r_reg(FILE *fp, enum STYLE style, off_t off, struct stat *sbp) { struct mapinfo map; off_t curoff, size, lineend; int i; if (!(size = sbp->st_size)) return; map.start = NULL; map.mapoff = map.maxoff = size; map.fd = fileno(fp); /* * Last char is special, ignore whether newline or not. Note that * size == 0 is dealt with above, and size == 1 sets curoff to -1. */ curoff = size - 2; lineend = size; while (curoff >= 0) { if (curoff < map.mapoff || curoff >= map.mapoff + (off_t)map.maplen) { if (maparound(&map, curoff) != 0) { ierr(); return; } } for (i = curoff - map.mapoff; i >= 0; i--) { if (style == RBYTES && --off == 0) break; if (map.start[i] == '\n') break; } /* `i' is either the map offset of a '\n', or -1. */ curoff = map.mapoff + i; if (i < 0) continue; /* Print the line and update offsets. */ if (mapprint(&map, curoff + 1, lineend - curoff - 1) != 0) { ierr(); return; } lineend = curoff + 1; curoff--; if (style == RLINES) off--; if (off == 0 && style != REVERSE) { /* Avoid printing anything below. */ curoff = 0; break; } } if (curoff < 0 && mapprint(&map, 0, lineend) != 0) { ierr(); return; } if (map.start != NULL && munmap(map.start, map.maplen)) ierr(); }