1d560f352SAndriy Gapon /*-
2d560f352SAndriy Gapon  * Copyright (c) 2010 Doug Rabson
3ed8945cbSAndriy Gapon  * Copyright (c) 2011 Andriy Gapon
4cf43b453SPawel Jakub Dawidek  * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
5d560f352SAndriy Gapon  * All rights reserved.
6d560f352SAndriy Gapon  *
7d560f352SAndriy Gapon  * Redistribution and use in source and binary forms, with or without
8d560f352SAndriy Gapon  * modification, are permitted provided that the following conditions
9d560f352SAndriy Gapon  * are met:
10d560f352SAndriy Gapon  * 1. Redistributions of source code must retain the above copyright
11d560f352SAndriy Gapon  *    notice, this list of conditions and the following disclaimer.
12d560f352SAndriy Gapon  * 2. Redistributions in binary form must reproduce the above copyright
13d560f352SAndriy Gapon  *    notice, this list of conditions and the following disclaimer in the
14d560f352SAndriy Gapon  *    documentation and/or other materials provided with the distribution.
15d560f352SAndriy Gapon  *
16d560f352SAndriy Gapon  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17d560f352SAndriy Gapon  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18d560f352SAndriy Gapon  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19d560f352SAndriy Gapon  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20d560f352SAndriy Gapon  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21d560f352SAndriy Gapon  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22d560f352SAndriy Gapon  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23d560f352SAndriy Gapon  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24d560f352SAndriy Gapon  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25d560f352SAndriy Gapon  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26d560f352SAndriy Gapon  * SUCH DAMAGE.
27d560f352SAndriy Gapon  */
28d560f352SAndriy Gapon 
29d560f352SAndriy Gapon #include <sys/param.h>
305d1186a4SAndriy Gapon #include <sys/disk.h>
31d560f352SAndriy Gapon #include <sys/queue.h>
325d1186a4SAndriy Gapon #include <sys/stat.h>
33cf43b453SPawel Jakub Dawidek #include <err.h>
34d560f352SAndriy Gapon #include <errno.h>
35d560f352SAndriy Gapon #include <fcntl.h>
36cf43b453SPawel Jakub Dawidek #include <md5.h>
37d560f352SAndriy Gapon #include <stdint.h>
38d560f352SAndriy Gapon #include <stdio.h>
39d560f352SAndriy Gapon #include <string.h>
40d560f352SAndriy Gapon #include <stdarg.h>
41d560f352SAndriy Gapon #include <stddef.h>
42d560f352SAndriy Gapon #include <stdlib.h>
43d560f352SAndriy Gapon #include <unistd.h>
44d560f352SAndriy Gapon 
45d560f352SAndriy Gapon #define NBBY 8
46d560f352SAndriy Gapon 
477e299eacSEnji Cooper int
pager_output(const char * line)48d560f352SAndriy Gapon pager_output(const char *line)
49d560f352SAndriy Gapon {
50cf43b453SPawel Jakub Dawidek 
516755788dSEnji Cooper 	fprintf(stderr, "%s", line);
526755788dSEnji Cooper 	return (0);
53d560f352SAndriy Gapon }
54d560f352SAndriy Gapon 
555d1186a4SAndriy Gapon uint64_t
ldi_get_size(void * priv)565d1186a4SAndriy Gapon ldi_get_size(void *priv)
575d1186a4SAndriy Gapon {
585d1186a4SAndriy Gapon 	struct stat sb;
595d1186a4SAndriy Gapon 	int fd;
605d1186a4SAndriy Gapon 
615d1186a4SAndriy Gapon 	fd = *(int *)priv;
625d1186a4SAndriy Gapon 	if (fstat(fd, &sb) != 0)
635d1186a4SAndriy Gapon 		return (0);
645d1186a4SAndriy Gapon 	if (S_ISCHR(sb.st_mode) && ioctl(fd, DIOCGMEDIASIZE, &sb.st_size) != 0)
655d1186a4SAndriy Gapon 		return (0);
665d1186a4SAndriy Gapon 	return (sb.st_size);
675d1186a4SAndriy Gapon }
685d1186a4SAndriy Gapon 
69ed8945cbSAndriy Gapon #define ZFS_TEST
70ed8945cbSAndriy Gapon #define	printf(...)	 fprintf(stderr, __VA_ARGS__)
719871c8abSAndriy Gapon #include "libzfs.h"
72d560f352SAndriy Gapon #include "zfsimpl.c"
73ed8945cbSAndriy Gapon #undef printf
74d560f352SAndriy Gapon 
75d560f352SAndriy Gapon static int
vdev_read(vdev_t * vdev,void * priv,off_t off,void * buf,size_t bytes)76d560f352SAndriy Gapon vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
77d560f352SAndriy Gapon {
78d560f352SAndriy Gapon 	int fd = *(int *)priv;
79d560f352SAndriy Gapon 
80d560f352SAndriy Gapon 	if (pread(fd, buf, bytes, off) != bytes)
81d560f352SAndriy Gapon 		return (-1);
82d560f352SAndriy Gapon 	return (0);
83d560f352SAndriy Gapon }
84d560f352SAndriy Gapon 
85d560f352SAndriy Gapon static int
zfs_read(spa_t * spa,dnode_phys_t * dn,void * buf,size_t size,off_t off)86d560f352SAndriy Gapon zfs_read(spa_t *spa, dnode_phys_t *dn, void *buf, size_t size, off_t off)
87d560f352SAndriy Gapon {
88d560f352SAndriy Gapon 	const znode_phys_t *zp = (const znode_phys_t *) dn->dn_bonus;
89d560f352SAndriy Gapon 	size_t n;
90d560f352SAndriy Gapon 	int rc;
91d560f352SAndriy Gapon 
92d560f352SAndriy Gapon 	n = size;
93d560f352SAndriy Gapon 	if (off + n > zp->zp_size)
94d560f352SAndriy Gapon 		n = zp->zp_size - off;
95d560f352SAndriy Gapon 
96d560f352SAndriy Gapon 	rc = dnode_read(spa, dn, off, buf, n);
97cf43b453SPawel Jakub Dawidek 	if (rc != 0)
98d560f352SAndriy Gapon 		return (-rc);
99d560f352SAndriy Gapon 
100d560f352SAndriy Gapon 	return (n);
101d560f352SAndriy Gapon }
102d560f352SAndriy Gapon 
103d560f352SAndriy Gapon int
main(int argc,char ** argv)104d560f352SAndriy Gapon main(int argc, char** argv)
105d560f352SAndriy Gapon {
106cf43b453SPawel Jakub Dawidek 	char buf[512], hash[33];
107cf43b453SPawel Jakub Dawidek 	MD5_CTX ctx;
108d560f352SAndriy Gapon 	struct stat sb;
109e7953148SAndriy Gapon 	struct zfsmount zfsmnt;
110d560f352SAndriy Gapon 	dnode_phys_t dn;
111e7953148SAndriy Gapon #if 0
112e7953148SAndriy Gapon 	uint64_t rootobj;
113e7953148SAndriy Gapon #endif
114d560f352SAndriy Gapon 	spa_t *spa;
115ed8945cbSAndriy Gapon 	off_t off;
116ed8945cbSAndriy Gapon 	ssize_t n;
117cf43b453SPawel Jakub Dawidek 	int i, failures, *fd;
118d560f352SAndriy Gapon 
119d560f352SAndriy Gapon 	zfs_init();
120d560f352SAndriy Gapon 	if (argc == 1) {
121d560f352SAndriy Gapon 		static char *av[] = {
122cf43b453SPawel Jakub Dawidek 			"zfsboottest",
123cf43b453SPawel Jakub Dawidek 			"/dev/gpt/system0",
124cf43b453SPawel Jakub Dawidek 			"/dev/gpt/system1",
125cf43b453SPawel Jakub Dawidek 			"-",
126fe5e6b2cSWarner Losh 			"/boot/loader",
127cf43b453SPawel Jakub Dawidek 			"/boot/support.4th",
128cf43b453SPawel Jakub Dawidek 			"/boot/kernel/kernel",
129d560f352SAndriy Gapon 			NULL,
130d560f352SAndriy Gapon 		};
131cf43b453SPawel Jakub Dawidek 		argc = sizeof(av) / sizeof(av[0]) - 1;
132d560f352SAndriy Gapon 		argv = av;
133d560f352SAndriy Gapon 	}
134cf43b453SPawel Jakub Dawidek 	for (i = 1; i < argc; i++) {
135cf43b453SPawel Jakub Dawidek 		if (strcmp(argv[i], "-") == 0)
136cf43b453SPawel Jakub Dawidek 			break;
137cf43b453SPawel Jakub Dawidek 	}
138cf43b453SPawel Jakub Dawidek 	fd = malloc(sizeof(fd[0]) * (i - 1));
139cf43b453SPawel Jakub Dawidek 	if (fd == NULL)
140cf43b453SPawel Jakub Dawidek 		errx(1, "Unable to allocate memory.");
141cf43b453SPawel Jakub Dawidek 	for (i = 1; i < argc; i++) {
142cf43b453SPawel Jakub Dawidek 		if (strcmp(argv[i], "-") == 0)
143cf43b453SPawel Jakub Dawidek 			break;
144cf43b453SPawel Jakub Dawidek 		fd[i - 1] = open(argv[i], O_RDONLY);
145cf43b453SPawel Jakub Dawidek 		if (fd[i - 1] == -1) {
146cf43b453SPawel Jakub Dawidek 			warn("open(%s) failed", argv[i]);
147d560f352SAndriy Gapon 			continue;
148cf43b453SPawel Jakub Dawidek 		}
149e307eb94SToomas Soome 		if (vdev_probe(vdev_read, NULL, &fd[i - 1], NULL) != 0) {
150cf43b453SPawel Jakub Dawidek 			warnx("vdev_probe(%s) failed", argv[i]);
151cf43b453SPawel Jakub Dawidek 			close(fd[i - 1]);
152cf43b453SPawel Jakub Dawidek 		}
153d560f352SAndriy Gapon 	}
154d560f352SAndriy Gapon 
1558787f180SAndriy Gapon 	STAILQ_FOREACH(spa, &zfs_pools, spa_link) {
1568787f180SAndriy Gapon 		if (zfs_spa_init(spa)) {
1578787f180SAndriy Gapon 			fprintf(stderr, "can't init pool %s\n", spa->spa_name);
1588787f180SAndriy Gapon 			exit(1);
1598787f180SAndriy Gapon 		}
1608787f180SAndriy Gapon 	}
1618787f180SAndriy Gapon 
1628787f180SAndriy Gapon 	spa_all_status();
1638787f180SAndriy Gapon 
164d560f352SAndriy Gapon 	spa = STAILQ_FIRST(&zfs_pools);
165d560f352SAndriy Gapon 	if (spa == NULL) {
166d560f352SAndriy Gapon 		fprintf(stderr, "no pools\n");
167d560f352SAndriy Gapon 		exit(1);
168d560f352SAndriy Gapon 	}
169d560f352SAndriy Gapon 
170e7953148SAndriy Gapon #if 0
1719871c8abSAndriy Gapon 	uint64_t rootobj;
172e7953148SAndriy Gapon 	if (zfs_get_root(spa, &rootobj)) {
173e7953148SAndriy Gapon 		fprintf(stderr, "can't get root\n");
174e7953148SAndriy Gapon 		exit(1);
175e7953148SAndriy Gapon 	}
176e7953148SAndriy Gapon 
177e7953148SAndriy Gapon 	if (zfs_mount(spa, rootobj, &zfsmnt)) {
178e7953148SAndriy Gapon #else
179e7953148SAndriy Gapon 	if (zfs_mount(spa, 0, &zfsmnt)) {
180e7953148SAndriy Gapon 		fprintf(stderr, "can't mount\n");
181e7953148SAndriy Gapon 		exit(1);
182e7953148SAndriy Gapon #endif
1839871c8abSAndriy Gapon 	}
184e7953148SAndriy Gapon 
185cf43b453SPawel Jakub Dawidek 	printf("\n");
186cf43b453SPawel Jakub Dawidek 	for (++i, failures = 0; i < argc; i++) {
187e7953148SAndriy Gapon 		if (zfs_lookup(&zfsmnt, argv[i], &dn)) {
188cf43b453SPawel Jakub Dawidek 			fprintf(stderr, "%s: can't lookup\n", argv[i]);
189cf43b453SPawel Jakub Dawidek 			failures++;
190cf43b453SPawel Jakub Dawidek 			continue;
191d560f352SAndriy Gapon 		}
192d560f352SAndriy Gapon 
193d560f352SAndriy Gapon 		if (zfs_dnode_stat(spa, &dn, &sb)) {
194cf43b453SPawel Jakub Dawidek 			fprintf(stderr, "%s: can't stat\n", argv[i]);
195cf43b453SPawel Jakub Dawidek 			failures++;
196cf43b453SPawel Jakub Dawidek 			continue;
197d560f352SAndriy Gapon 		}
198d560f352SAndriy Gapon 
199d560f352SAndriy Gapon 		off = 0;
200cf43b453SPawel Jakub Dawidek 		MD5Init(&ctx);
201d560f352SAndriy Gapon 		do {
202ed8945cbSAndriy Gapon 			n = sb.st_size - off;
203ed8945cbSAndriy Gapon 			n = n > sizeof(buf) ? sizeof(buf) : n;
204ed8945cbSAndriy Gapon 			n = zfs_read(spa, &dn, buf, n, off);
205d560f352SAndriy Gapon 			if (n < 0) {
206cf43b453SPawel Jakub Dawidek 				fprintf(stderr, "%s: zfs_read failed\n",
207cf43b453SPawel Jakub Dawidek 				    argv[i]);
208cf43b453SPawel Jakub Dawidek 				failures++;
209cf43b453SPawel Jakub Dawidek 				break;
210d560f352SAndriy Gapon 			}
211cf43b453SPawel Jakub Dawidek 			MD5Update(&ctx, buf, n);
212d560f352SAndriy Gapon 			off += n;
213d560f352SAndriy Gapon 		} while (off < sb.st_size);
214cf43b453SPawel Jakub Dawidek 		if (off < sb.st_size)
215cf43b453SPawel Jakub Dawidek 			continue;
216cf43b453SPawel Jakub Dawidek 		MD5End(&ctx, hash);
217cf43b453SPawel Jakub Dawidek 		printf("%s %s\n", hash, argv[i]);
218cf43b453SPawel Jakub Dawidek 	}
219d560f352SAndriy Gapon 
220cf43b453SPawel Jakub Dawidek 	return (failures == 0 ? 0 : 1);
221d560f352SAndriy Gapon }
222