71 lines
2.1 KiB
C
71 lines
2.1 KiB
C
#include <sys/param.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
#include <limits.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static unsigned int
|
|
parse_number(const char *text)
|
|
{
|
|
char *end;
|
|
unsigned long value;
|
|
|
|
errno = 0;
|
|
value = strtoul(text, &end, 0);
|
|
if (errno != 0 || *end != '\0' || value > UINT_MAX)
|
|
errx(2, "invalid number: %s", text);
|
|
return ((unsigned int)value);
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
struct stat sb;
|
|
unsigned int expected_major, expected_minor;
|
|
bool is_device;
|
|
|
|
if (argc != 3 && argc != 5)
|
|
errx(2, "usage: stat_special char|block path major minor | "
|
|
"stat_special fifo path");
|
|
if (lstat(argv[2], &sb) != 0)
|
|
err(1, "lstat %s", argv[2]);
|
|
is_device = strcmp(argv[1], "char") == 0 || strcmp(argv[1], "block") == 0;
|
|
if (is_device) {
|
|
if (argc != 5)
|
|
errx(2, "device checks require major and minor");
|
|
expected_major = parse_number(argv[3]);
|
|
expected_minor = parse_number(argv[4]);
|
|
if ((strcmp(argv[1], "char") == 0 && !S_ISCHR(sb.st_mode)) ||
|
|
(strcmp(argv[1], "block") == 0 && !S_ISBLK(sb.st_mode)))
|
|
errx(1, "%s has the wrong file type", argv[2]);
|
|
if ((unsigned int)major(sb.st_rdev) != expected_major ||
|
|
(unsigned int)minor(sb.st_rdev) != expected_minor)
|
|
errx(1, "%s rdev=%#jx major=%u minor=%u, expected %u:%u",
|
|
argv[2], (uintmax_t)sb.st_rdev,
|
|
(unsigned int)major(sb.st_rdev),
|
|
(unsigned int)minor(sb.st_rdev), expected_major,
|
|
expected_minor);
|
|
} else if (strcmp(argv[1], "fifo") == 0) {
|
|
if (argc != 3)
|
|
errx(2, "FIFO checks do not take major and minor");
|
|
if (!S_ISFIFO(sb.st_mode))
|
|
errx(1, "%s is not a FIFO", argv[2]);
|
|
if (sb.st_rdev != NODEV)
|
|
errx(1, "%s FIFO st_rdev=%#jx, expected NODEV", argv[2],
|
|
(uintmax_t)sb.st_rdev);
|
|
} else {
|
|
errx(2, "unknown type: %s", argv[1]);
|
|
}
|
|
printf("PASS path=%s type=%s rdev=%#jx major=%u minor=%u\n", argv[2],
|
|
argv[1], (uintmax_t)sb.st_rdev, (unsigned int)major(sb.st_rdev),
|
|
(unsigned int)minor(sb.st_rdev));
|
|
return (0);
|
|
}
|