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