zfsboottest.c revision 290986
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/10/tools/tools/zfsboottest/zfsboottest.c 290986 2015-11-17 15:18:52Z avg $ */ 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 STAILQ_FOREACH(spa, &zfs_pools, spa_link) { 140 if (zfs_spa_init(spa)) { 141 fprintf(stderr, "can't init pool %s\n", spa->spa_name); 142 exit(1); 143 } 144 } 145 146 spa_all_status(); 147 148 spa = STAILQ_FIRST(&zfs_pools); 149 if (spa == NULL) { 150 fprintf(stderr, "no pools\n"); 151 exit(1); 152 } 153 154#if 0 155 uint64_t rootobj; 156 if (zfs_get_root(spa, &rootobj)) { 157 fprintf(stderr, "can't get root\n"); 158 exit(1); 159 } 160 161 if (zfs_mount(spa, rootobj, &zfsmnt)) { 162#else 163 if (zfs_mount(spa, 0, &zfsmnt)) { 164 fprintf(stderr, "can't mount\n"); 165 exit(1); 166#endif 167 } 168 169 printf("\n"); 170 for (++i, failures = 0; i < argc; i++) { 171 if (zfs_lookup(&zfsmnt, argv[i], &dn)) { 172 fprintf(stderr, "%s: can't lookup\n", argv[i]); 173 failures++; 174 continue; 175 } 176 177 if (zfs_dnode_stat(spa, &dn, &sb)) { 178 fprintf(stderr, "%s: can't stat\n", argv[i]); 179 failures++; 180 continue; 181 } 182 183 off = 0; 184 MD5Init(&ctx); 185 do { 186 n = sb.st_size - off; 187 n = n > sizeof(buf) ? sizeof(buf) : n; 188 n = zfs_read(spa, &dn, buf, n, off); 189 if (n < 0) { 190 fprintf(stderr, "%s: zfs_read failed\n", 191 argv[i]); 192 failures++; 193 break; 194 } 195 MD5Update(&ctx, buf, n); 196 off += n; 197 } while (off < sb.st_size); 198 if (off < sb.st_size) 199 continue; 200 MD5End(&ctx, hash); 201 printf("%s %s\n", hash, argv[i]); 202 } 203 204 return (failures == 0 ? 0 : 1); 205} 206