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: stable/11/tools/tools/zfsboottest/zfsboottest.c 322215 2017-08-08 05:15:20Z ngie $ */ 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 46int 47pager_output(const char *line) 48{ 49 50 fprintf(stderr, "%s", line); 51 return (0); 52} 53 54#define ZFS_TEST 55#define printf(...) fprintf(stderr, __VA_ARGS__) 56#include "libzfs.h" 57#include "zfsimpl.c" 58#undef printf 59 60static int 61vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) 62{ 63 int fd = *(int *)priv; 64 65 if (pread(fd, buf, bytes, off) != bytes) 66 return (-1); 67 return (0); 68} 69 70static int 71zfs_read(spa_t *spa, dnode_phys_t *dn, void *buf, size_t size, off_t off) 72{ 73 const znode_phys_t *zp = (const znode_phys_t *) dn->dn_bonus; 74 size_t n; 75 int rc; 76 77 n = size; 78 if (off + n > zp->zp_size) 79 n = zp->zp_size - off; 80 81 rc = dnode_read(spa, dn, off, buf, n); 82 if (rc != 0) 83 return (-rc); 84 85 return (n); 86} 87 88int 89main(int argc, char** argv) 90{ 91 char buf[512], hash[33]; 92 MD5_CTX ctx; 93 struct stat sb; 94 struct zfsmount zfsmnt; 95 dnode_phys_t dn; 96#if 0 97 uint64_t rootobj; 98#endif 99 spa_t *spa; 100 off_t off; 101 ssize_t n; 102 int i, failures, *fd; 103 104 zfs_init(); 105 if (argc == 1) { 106 static char *av[] = { 107 "zfsboottest", 108 "/dev/gpt/system0", 109 "/dev/gpt/system1", 110 "-", 111 "/boot/zfsloader", 112 "/boot/support.4th", 113 "/boot/kernel/kernel", 114 NULL, 115 }; 116 argc = sizeof(av) / sizeof(av[0]) - 1; 117 argv = av; 118 } 119 for (i = 1; i < argc; i++) { 120 if (strcmp(argv[i], "-") == 0) 121 break; 122 } 123 fd = malloc(sizeof(fd[0]) * (i - 1)); 124 if (fd == NULL) 125 errx(1, "Unable to allocate memory."); 126 for (i = 1; i < argc; i++) { 127 if (strcmp(argv[i], "-") == 0) 128 break; 129 fd[i - 1] = open(argv[i], O_RDONLY); 130 if (fd[i - 1] == -1) { 131 warn("open(%s) failed", argv[i]); 132 continue; 133 } 134 if (vdev_probe(vdev_read, &fd[i - 1], NULL) != 0) { 135 warnx("vdev_probe(%s) failed", argv[i]); 136 close(fd[i - 1]); 137 } 138 } 139 140 STAILQ_FOREACH(spa, &zfs_pools, spa_link) { 141 if (zfs_spa_init(spa)) { 142 fprintf(stderr, "can't init pool %s\n", spa->spa_name); 143 exit(1); 144 } 145 } 146 147 spa_all_status(); 148 149 spa = STAILQ_FIRST(&zfs_pools); 150 if (spa == NULL) { 151 fprintf(stderr, "no pools\n"); 152 exit(1); 153 } 154 155#if 0 156 uint64_t rootobj; 157 if (zfs_get_root(spa, &rootobj)) { 158 fprintf(stderr, "can't get root\n"); 159 exit(1); 160 } 161 162 if (zfs_mount(spa, rootobj, &zfsmnt)) { 163#else 164 if (zfs_mount(spa, 0, &zfsmnt)) { 165 fprintf(stderr, "can't mount\n"); 166 exit(1); 167#endif 168 } 169 170 printf("\n"); 171 for (++i, failures = 0; i < argc; i++) { 172 if (zfs_lookup(&zfsmnt, argv[i], &dn)) { 173 fprintf(stderr, "%s: can't lookup\n", argv[i]); 174 failures++; 175 continue; 176 } 177 178 if (zfs_dnode_stat(spa, &dn, &sb)) { 179 fprintf(stderr, "%s: can't stat\n", argv[i]); 180 failures++; 181 continue; 182 } 183 184 off = 0; 185 MD5Init(&ctx); 186 do { 187 n = sb.st_size - off; 188 n = n > sizeof(buf) ? sizeof(buf) : n; 189 n = zfs_read(spa, &dn, buf, n, off); 190 if (n < 0) { 191 fprintf(stderr, "%s: zfs_read failed\n", 192 argv[i]); 193 failures++; 194 break; 195 } 196 MD5Update(&ctx, buf, n); 197 off += n; 198 } while (off < sb.st_size); 199 if (off < sb.st_size) 200 continue; 201 MD5End(&ctx, hash); 202 printf("%s %s\n", hash, argv[i]); 203 } 204 205 return (failures == 0 ? 0 : 1); 206} 207