-}
-
-/* Output the last N_BYTES bytes of file FILENAME open for reading in FD.
- Return 0 if successful, 1 if an error occurred. */
-
-static int tail_bytes(const char *filename, int fd, off_t n_bytes)
-{
- struct stat stats;
-
- /* FIXME: resolve this like in dd.c. */
- /* Use fstat instead of checking for errno == ESPIPE because
- lseek doesn't work on some special files but doesn't return an
- error, either. */
- if (fstat(fd, &stats)) {
- detailed_error(0, errno, "%s", filename);
- return 1;
- }
-
- if (from_start) {
- if (S_ISREG(stats.st_mode))
- lseek(fd, n_bytes, SEEK_CUR);
- else if (start_bytes(filename, fd, n_bytes))
- return 1;
- dump_remainder(filename, fd);
- } else {
- if (S_ISREG(stats.st_mode)) {
- off_t current_pos, end_pos;
- size_t bytes_remaining;
-
- if ((current_pos = lseek(fd, (off_t) 0, SEEK_CUR)) != -1
- && (end_pos = lseek(fd, (off_t) 0, SEEK_END)) != -1) {
- off_t diff;
-
- /* Be careful here. The current position may actually be
- beyond the end of the file. */
- bytes_remaining = (diff =
- end_pos - current_pos) < 0 ? 0 : diff;
- } else {
- detailed_error(0, errno, "%s", filename);
- return 1;
- }
-
- if (bytes_remaining <= n_bytes) {
- /* From the current position to end of file, there are no
- more bytes than have been requested. So reposition the
- file pointer to the incoming current position and print
- everything after that. */
- lseek(fd, current_pos, SEEK_SET);
- } else {
- /* There are more bytes remaining than were requested.
- Back up. */
- lseek(fd, -n_bytes, SEEK_END);
- }
- dump_remainder(filename, fd);
- } else
- return pipe_bytes(filename, fd, n_bytes);
- }
- return 0;
-}
-
-/* Output the last N_LINES lines of file FILENAME open for reading in FD.
- Return 0 if successful, 1 if an error occurred. */
-
-static int tail_lines(const char *filename, int fd, long int n_lines)
-{
- struct stat stats;
- off_t length;
-
- if (fstat(fd, &stats)) {
- detailed_error(0, errno, "%s", filename);
- return 1;
- }
-
- if (from_start) {
- if (start_lines(filename, fd, n_lines))
- return 1;
- dump_remainder(filename, fd);
- } else {
- /* Use file_lines only if FD refers to a regular file with
- its file pointer positioned at beginning of file. */
- /* FIXME: adding the lseek conjunct is a kludge.
- Once there's a reasonable test suite, fix the true culprit:
- file_lines. file_lines shouldn't presume that the input
- file pointer is initially positioned to beginning of file. */
- if (S_ISREG(stats.st_mode)
- && lseek(fd, (off_t) 0, SEEK_CUR) == (off_t) 0) {
- length = lseek(fd, (off_t) 0, SEEK_END);
- if (length != 0 && file_lines(filename, fd, n_lines, length))
- return 1;
- dump_remainder(filename, fd);
- } else
- return pipe_lines(filename, fd, n_lines);
- }
- return 0;
-}
-
-/* Display the last N_UNITS units of file FILENAME, open for reading
- in FD.
- Return 0 if successful, 1 if an error occurred. */
-
-static int tail(const char *filename, int fd, off_t n_units)
-{
- if (count_lines)
- return tail_lines(filename, fd, (long) n_units);
- else
- return tail_bytes(filename, fd, n_units);
-}
-
-/* Display the last N_UNITS units of file FILENAME.
- "-" for FILENAME means the standard input.
- FILENUM is this file's index in the list of files the user gave.
- Return 0 if successful, 1 if an error occurred. */
-
-static int tail_file(const char *filename, off_t n_units, int filenum)
-{
- int fd, errors;
- struct stat stats;
-
- if (!strcmp(filename, "-")) {
- have_read_stdin = 1;
- filename = "standard input";
- if (print_headers)
- write_header(filename, NULL);
- errors = tail(filename, 0, n_units);
- if (forever_multiple) {
- if (fstat(0, &stats) < 0) {
- detailed_error(0, errno, "standard input");
- errors = 1;
- } else if (!S_ISREG(stats.st_mode)) {
- detailed_error(0, 0,
- "standard input: cannot follow end of non-regular file");
- errors = 1;
- }
- if (errors)
- file_descs[filenum] = -1;
- else {
- file_descs[filenum] = 0;
- file_sizes[filenum] = stats.st_size;
- }
- }
- } else {
- /* Not standard input. */
- fd = open(filename, O_RDONLY);
- if (fd == -1) {
- if (forever_multiple)
- file_descs[filenum] = -1;
- detailed_error(0, errno, "%s", filename);
- errors = 1;
- } else {
- if (print_headers)
- write_header(filename, NULL);
- errors = tail(filename, fd, n_units);
- if (forever_multiple) {
- if (fstat(fd, &stats) < 0) {
- detailed_error(0, errno, "%s", filename);
- errors = 1;
- } else if (!S_ISREG(stats.st_mode)) {
- detailed_error(0, 0,
- "%s: cannot follow end of non-regular file",
- filename);
- errors = 1;
- }
- if (errors) {
- close(fd);
- file_descs[filenum] = -1;
- } else {
- file_descs[filenum] = fd;
- file_sizes[filenum] = stats.st_size;
- }