#include <sys/types.h>
#include <sys/stat.h>

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static int
fail(const char *message)
{
	fprintf(stderr, "%s\n", message);
	return (1);
}

int
main(int argc, char **argv)
{
	char target[256];
	ssize_t length;
	int descriptor;

	if (argc < 3)
		return (fail("usage: B14-chunk-probe OP PATH [TARGET]"));
	if (strcmp(argv[1], "readlink-pass") == 0) {
		if (argc != 4)
			return (fail("readlink-pass requires an expected target"));
		length = readlink(argv[2], target, sizeof(target));
		if (length < 0)
			return (fail("readlink-pass unexpectedly failed"));
		if ((size_t)length != strlen(argv[3]) ||
		    memcmp(target, argv[3], (size_t)length) != 0)
			return (fail("readlink-pass returned the wrong target"));
		return (0);
	}
	if (strcmp(argv[1], "readlink-integrity") == 0) {
		errno = 0;
		if (readlink(argv[2], target, sizeof(target)) >= 0 ||
		    errno != EINTEGRITY)
			return (fail("readlink did not return EINTEGRITY"));
		return (0);
	}
	if (strcmp(argv[1], "open-unsupported") == 0) {
		errno = 0;
		descriptor = open(argv[2], O_RDONLY | O_NONBLOCK);
		if (descriptor >= 0) {
			close(descriptor);
			return (fail("special vnode unexpectedly opened"));
		}
		if (errno != EOPNOTSUPP)
			return (fail("special vnode did not return EOPNOTSUPP"));
		return (0);
	}
	if (strcmp(argv[1], "stat-integrity") == 0 ||
	    strcmp(argv[1], "stat-unsupported") == 0) {
		struct stat status;
		int expected;

		expected = strcmp(argv[1], "stat-integrity") == 0 ?
		    EINTEGRITY : EOPNOTSUPP;
		errno = 0;
		if (lstat(argv[2], &status) == 0 || errno != expected)
			return (fail("stat did not return the expected errno"));
		return (0);
	}
	return (fail("unknown B14 probe operation"));
}
