162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#define _GNU_SOURCE
362306a36Sopenharmony_ci#include <errno.h>
462306a36Sopenharmony_ci#include <fcntl.h>
562306a36Sopenharmony_ci#include <limits.h>
662306a36Sopenharmony_ci#include <stdio.h>
762306a36Sopenharmony_ci#include <stdlib.h>
862306a36Sopenharmony_ci#include <unistd.h>
962306a36Sopenharmony_ci#include <sys/types.h>
1062306a36Sopenharmony_ci#include <sys/stat.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciint main(int argc, char *argv[])
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	int fd;
1562306a36Sopenharmony_ci	size_t size;
1662306a36Sopenharmony_ci	ssize_t spliced;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	if (argc < 2) {
1962306a36Sopenharmony_ci		fprintf(stderr, "Usage: %s INPUT [BYTES]\n", argv[0]);
2062306a36Sopenharmony_ci		return EXIT_FAILURE;
2162306a36Sopenharmony_ci	}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	fd = open(argv[1], O_RDONLY);
2462306a36Sopenharmony_ci	if (fd < 0) {
2562306a36Sopenharmony_ci		perror(argv[1]);
2662306a36Sopenharmony_ci		return EXIT_FAILURE;
2762306a36Sopenharmony_ci	}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	if (argc == 3)
3062306a36Sopenharmony_ci		size = atol(argv[2]);
3162306a36Sopenharmony_ci	else {
3262306a36Sopenharmony_ci		struct stat statbuf;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci		if (fstat(fd, &statbuf) < 0) {
3562306a36Sopenharmony_ci			perror(argv[1]);
3662306a36Sopenharmony_ci			return EXIT_FAILURE;
3762306a36Sopenharmony_ci		}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci		if (statbuf.st_size > INT_MAX) {
4062306a36Sopenharmony_ci			fprintf(stderr, "%s: Too big\n", argv[1]);
4162306a36Sopenharmony_ci			return EXIT_FAILURE;
4262306a36Sopenharmony_ci		}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		size = statbuf.st_size;
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* splice(2) file to stdout. */
4862306a36Sopenharmony_ci	spliced = splice(fd, NULL, STDOUT_FILENO, NULL,
4962306a36Sopenharmony_ci		      size, SPLICE_F_MOVE);
5062306a36Sopenharmony_ci	if (spliced < 0) {
5162306a36Sopenharmony_ci		perror("splice");
5262306a36Sopenharmony_ci		return EXIT_FAILURE;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	close(fd);
5662306a36Sopenharmony_ci	return EXIT_SUCCESS;
5762306a36Sopenharmony_ci}
58