/*
 * DF-0134 contrast — read the crafted (out-of-slice) disklabel64 from the
 * image file (already CRC-correct, written by craft_label) and attempt
 * DIOCSDINFO64 (the write/set path, which DOES validate via l64_setdisklabel).
 * It must be rejected with EINVAL, proving the read/set asymmetry.
 *
 * Build: cc -o setlabel setlabel.c
 * Run:   ./setlabel <image> /dev/vnXs0
 */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/disklabel64.h>

int
main(int argc, char **argv)
{
	struct disklabel64 *lp;
	char buf[sizeof(struct disklabel64)];
	int imgfd, devfd, rc;

	if (argc < 3) {
		fprintf(stderr, "usage: %s <image> /dev/vnXs0\n", argv[0]);
		return 2;
	}
	imgfd = open(argv[1], O_RDONLY);
	if (imgfd < 0) { perror("open image"); return 1; }
	if (read(imgfd, buf, sizeof(buf)) != (ssize_t)sizeof(buf)) {
		perror("read image"); close(imgfd); return 1;
	}
	close(imgfd);
	lp = (struct disklabel64 *)buf;

	printf("[*] loaded crafted label from %s: part[1] end=%llu "
	       "(d_total_size=%llu)\n", argv[1],
	       (unsigned long long)(lp->d_partitions[1].p_boffset +
				    lp->d_partitions[1].p_bsize),
	       (unsigned long long)lp->d_total_size);

	devfd = open(argv[2], O_RDWR);
	if (devfd < 0) { perror("open device"); return 1; }

	printf("[*] attempting DIOCSDINFO64 (set path, which validates)...\n");
	rc = ioctl(devfd, DIOCSDINFO64, lp);
	printf("    DIOCSDINFO64 rc=%d errno=%d (%s)\n", rc, errno,
	       rc ? strerror(errno) : "success");
	if (rc && errno == EINVAL)
		printf("[*] SET path REJECTED the out-of-slice label (EINVAL) — "
		       "confirms read path (readdisklabel) lacks the validation "
		       "that set path (setdisklabel) has\n");
	close(devfd);
	return (rc && errno == EINVAL) ? 0 : 1;
}
