1030fdd8aSTomohiro Kusumi /*- 2*26cca7e2STomohiro Kusumi * Copyright (c) 2017-2019 The DragonFly Project 3030fdd8aSTomohiro Kusumi * All rights reserved. 4030fdd8aSTomohiro Kusumi * 5030fdd8aSTomohiro Kusumi * This software was developed by Edward Tomasz Napierala under sponsorship 6030fdd8aSTomohiro Kusumi * from the FreeBSD Foundation. 7030fdd8aSTomohiro Kusumi * 8030fdd8aSTomohiro Kusumi * Redistribution and use in source and binary forms, with or without 9030fdd8aSTomohiro Kusumi * modification, are permitted provided that the following conditions 10030fdd8aSTomohiro Kusumi * are met: 11030fdd8aSTomohiro Kusumi * 1. Redistributions of source code must retain the above copyright 12030fdd8aSTomohiro Kusumi * notice, this list of conditions and the following disclaimer. 13030fdd8aSTomohiro Kusumi * 2. Redistributions in binary form must reproduce the above copyright 14030fdd8aSTomohiro Kusumi * notice, this list of conditions and the following disclaimer in the 15030fdd8aSTomohiro Kusumi * documentation and/or other materials provided with the distribution. 16030fdd8aSTomohiro Kusumi * 17030fdd8aSTomohiro Kusumi * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18030fdd8aSTomohiro Kusumi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19030fdd8aSTomohiro Kusumi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20030fdd8aSTomohiro Kusumi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21030fdd8aSTomohiro Kusumi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22030fdd8aSTomohiro Kusumi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23030fdd8aSTomohiro Kusumi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24030fdd8aSTomohiro Kusumi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25030fdd8aSTomohiro Kusumi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26030fdd8aSTomohiro Kusumi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27030fdd8aSTomohiro Kusumi * SUCH DAMAGE. 28030fdd8aSTomohiro Kusumi */ 29030fdd8aSTomohiro Kusumi 30030fdd8aSTomohiro Kusumi #include <stdio.h> 31030fdd8aSTomohiro Kusumi #include <stdlib.h> 32030fdd8aSTomohiro Kusumi #include <string.h> 33030fdd8aSTomohiro Kusumi #include <err.h> 34030fdd8aSTomohiro Kusumi #include <vfs/hammer2/hammer2_disk.h> 35030fdd8aSTomohiro Kusumi 36030fdd8aSTomohiro Kusumi #include "fstyp.h" 37030fdd8aSTomohiro Kusumi 38030fdd8aSTomohiro Kusumi static hammer2_volume_data_t* 39030fdd8aSTomohiro Kusumi __read_voldata(FILE *fp) 40030fdd8aSTomohiro Kusumi { 41030fdd8aSTomohiro Kusumi hammer2_volume_data_t *voldata; 42030fdd8aSTomohiro Kusumi 43030fdd8aSTomohiro Kusumi voldata = read_buf(fp, 0, sizeof(*voldata)); 44030fdd8aSTomohiro Kusumi if (voldata == NULL) 45030fdd8aSTomohiro Kusumi err(1, "failed to read volume data"); 46030fdd8aSTomohiro Kusumi 47030fdd8aSTomohiro Kusumi return (voldata); 48030fdd8aSTomohiro Kusumi } 49030fdd8aSTomohiro Kusumi 50030fdd8aSTomohiro Kusumi static int 51030fdd8aSTomohiro Kusumi __test_voldata(const hammer2_volume_data_t *voldata) 52030fdd8aSTomohiro Kusumi { 53030fdd8aSTomohiro Kusumi if (voldata->magic != HAMMER2_VOLUME_ID_HBO && 54030fdd8aSTomohiro Kusumi voldata->magic != HAMMER2_VOLUME_ID_ABO) 55030fdd8aSTomohiro Kusumi return (1); 56030fdd8aSTomohiro Kusumi 57030fdd8aSTomohiro Kusumi return (0); 58030fdd8aSTomohiro Kusumi } 59030fdd8aSTomohiro Kusumi 60*26cca7e2STomohiro Kusumi static int 61*26cca7e2STomohiro Kusumi __read_label(FILE *fp, char *label, size_t size) 62*26cca7e2STomohiro Kusumi { 63*26cca7e2STomohiro Kusumi hammer2_blockref_t broot, best, *bref; 64*26cca7e2STomohiro Kusumi hammer2_media_data_t *vols[4], *media; 65*26cca7e2STomohiro Kusumi hammer2_off_t io_off, io_base; 66*26cca7e2STomohiro Kusumi size_t bytes, io_bytes, boff; 67*26cca7e2STomohiro Kusumi int i, best_i, error = 0; 68*26cca7e2STomohiro Kusumi 69*26cca7e2STomohiro Kusumi best_i = -1; 70*26cca7e2STomohiro Kusumi memset(&best, 0, sizeof(best)); 71*26cca7e2STomohiro Kusumi 72*26cca7e2STomohiro Kusumi for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++) { 73*26cca7e2STomohiro Kusumi memset(&broot, 0, sizeof(broot)); 74*26cca7e2STomohiro Kusumi broot.type = HAMMER2_BREF_TYPE_VOLUME; 75*26cca7e2STomohiro Kusumi broot.data_off = (i * HAMMER2_ZONE_BYTES64) | HAMMER2_PBUFRADIX; 76*26cca7e2STomohiro Kusumi vols[i] = read_buf(fp, broot.data_off & ~HAMMER2_OFF_MASK_RADIX, 77*26cca7e2STomohiro Kusumi sizeof(*vols[i])); 78*26cca7e2STomohiro Kusumi broot.mirror_tid = vols[i]->voldata.mirror_tid; 79*26cca7e2STomohiro Kusumi if (best_i < 0 || best.mirror_tid < broot.mirror_tid) { 80*26cca7e2STomohiro Kusumi best_i = i; 81*26cca7e2STomohiro Kusumi best = broot; 82*26cca7e2STomohiro Kusumi } 83*26cca7e2STomohiro Kusumi } 84*26cca7e2STomohiro Kusumi if (best_i == -1) { 85*26cca7e2STomohiro Kusumi error = 1; 86*26cca7e2STomohiro Kusumi goto done; 87*26cca7e2STomohiro Kusumi } 88*26cca7e2STomohiro Kusumi 89*26cca7e2STomohiro Kusumi bref = &vols[best_i]->voldata.sroot_blockset.blockref[0]; 90*26cca7e2STomohiro Kusumi if (bref->type != HAMMER2_BREF_TYPE_INODE) { 91*26cca7e2STomohiro Kusumi error = 2; 92*26cca7e2STomohiro Kusumi goto done; 93*26cca7e2STomohiro Kusumi } 94*26cca7e2STomohiro Kusumi 95*26cca7e2STomohiro Kusumi bytes = bref->data_off & HAMMER2_OFF_MASK_RADIX; 96*26cca7e2STomohiro Kusumi if (bytes) 97*26cca7e2STomohiro Kusumi bytes = (size_t)1 << bytes; 98*26cca7e2STomohiro Kusumi if (bytes != sizeof(hammer2_inode_data_t)) { 99*26cca7e2STomohiro Kusumi error = 3; 100*26cca7e2STomohiro Kusumi goto done; 101*26cca7e2STomohiro Kusumi } 102*26cca7e2STomohiro Kusumi 103*26cca7e2STomohiro Kusumi io_off = bref->data_off & ~HAMMER2_OFF_MASK_RADIX; 104*26cca7e2STomohiro Kusumi io_base = io_off & ~(hammer2_off_t)(HAMMER2_MINIOSIZE - 1); 105*26cca7e2STomohiro Kusumi boff = io_off - io_base; 106*26cca7e2STomohiro Kusumi 107*26cca7e2STomohiro Kusumi io_bytes = HAMMER2_MINIOSIZE; 108*26cca7e2STomohiro Kusumi while (io_bytes + boff < bytes) 109*26cca7e2STomohiro Kusumi io_bytes <<= 1; 110*26cca7e2STomohiro Kusumi if (io_bytes > sizeof(*media)) { 111*26cca7e2STomohiro Kusumi error = 4; 112*26cca7e2STomohiro Kusumi goto done; 113*26cca7e2STomohiro Kusumi } 114*26cca7e2STomohiro Kusumi 115*26cca7e2STomohiro Kusumi media = read_buf(fp, io_base, io_bytes); 116*26cca7e2STomohiro Kusumi if (boff) 117*26cca7e2STomohiro Kusumi memcpy(media, (char*)media + boff, bytes); 118*26cca7e2STomohiro Kusumi 119*26cca7e2STomohiro Kusumi strlcpy(label, media->ipdata.filename, size); 120*26cca7e2STomohiro Kusumi free(media); 121*26cca7e2STomohiro Kusumi done: 122*26cca7e2STomohiro Kusumi for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++) 123*26cca7e2STomohiro Kusumi free(vols[i]); 124*26cca7e2STomohiro Kusumi 125*26cca7e2STomohiro Kusumi return (error); 126*26cca7e2STomohiro Kusumi } 127*26cca7e2STomohiro Kusumi 128030fdd8aSTomohiro Kusumi int 129030fdd8aSTomohiro Kusumi fstyp_hammer2(FILE *fp, char *label, size_t size) 130030fdd8aSTomohiro Kusumi { 131030fdd8aSTomohiro Kusumi hammer2_volume_data_t *voldata; 132030fdd8aSTomohiro Kusumi int error = 1; 133030fdd8aSTomohiro Kusumi 134030fdd8aSTomohiro Kusumi voldata = __read_voldata(fp); 135030fdd8aSTomohiro Kusumi if (__test_voldata(voldata)) 136030fdd8aSTomohiro Kusumi goto done; 137030fdd8aSTomohiro Kusumi 138*26cca7e2STomohiro Kusumi error = __read_label(fp, label, size); 139030fdd8aSTomohiro Kusumi done: 140030fdd8aSTomohiro Kusumi free(voldata); 141030fdd8aSTomohiro Kusumi return (error); 142030fdd8aSTomohiro Kusumi } 143