1/* 2 * volume_id - reads filesystem label and uuid 3 * 4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the 8 * Free Software Foundation version 2 of the License. 9 */ 10 11#ifndef _GNU_SOURCE 12#define _GNU_SOURCE 1 13#endif 14 15#ifdef HAVE_CONFIG_H 16# include <config.h> 17#endif 18 19#include <stdio.h> 20#include <stdlib.h> 21#include <unistd.h> 22#include <string.h> 23#include <errno.h> 24#include <ctype.h> 25 26#include "libvolume_id.h" 27#include "util.h" 28 29struct ufs_super_block { 30 uint32_t fs_link; 31 uint32_t fs_rlink; 32 uint32_t fs_sblkno; 33 uint32_t fs_cblkno; 34 uint32_t fs_iblkno; 35 uint32_t fs_dblkno; 36 uint32_t fs_cgoffset; 37 uint32_t fs_cgmask; 38 uint32_t fs_time; 39 uint32_t fs_size; 40 uint32_t fs_dsize; 41 uint32_t fs_ncg; 42 uint32_t fs_bsize; 43 uint32_t fs_fsize; 44 uint32_t fs_frag; 45 uint32_t fs_minfree; 46 uint32_t fs_rotdelay; 47 uint32_t fs_rps; 48 uint32_t fs_bmask; 49 uint32_t fs_fmask; 50 uint32_t fs_bshift; 51 uint32_t fs_fshift; 52 uint32_t fs_maxcontig; 53 uint32_t fs_maxbpg; 54 uint32_t fs_fragshift; 55 uint32_t fs_fsbtodb; 56 uint32_t fs_sbsize; 57 uint32_t fs_csmask; 58 uint32_t fs_csshift; 59 uint32_t fs_nindir; 60 uint32_t fs_inopb; 61 uint32_t fs_nspf; 62 uint32_t fs_optim; 63 uint32_t fs_npsect_state; 64 uint32_t fs_interleave; 65 uint32_t fs_trackskew; 66 uint32_t fs_id[2]; 67 uint32_t fs_csaddr; 68 uint32_t fs_cssize; 69 uint32_t fs_cgsize; 70 uint32_t fs_ntrak; 71 uint32_t fs_nsect; 72 uint32_t fs_spc; 73 uint32_t fs_ncyl; 74 uint32_t fs_cpg; 75 uint32_t fs_ipg; 76 uint32_t fs_fpg; 77 struct ufs_csum { 78 uint32_t cs_ndir; 79 uint32_t cs_nbfree; 80 uint32_t cs_nifree; 81 uint32_t cs_nffree; 82 } PACKED fs_cstotal; 83 int8_t fs_fmod; 84 int8_t fs_clean; 85 int8_t fs_ronly; 86 int8_t fs_flags; 87 union { 88 struct { 89 int8_t fs_fsmnt[512]; 90 uint32_t fs_cgrotor; 91 uint32_t fs_csp[31]; 92 uint32_t fs_maxcluster; 93 uint32_t fs_cpc; 94 uint16_t fs_opostbl[16][8]; 95 } PACKED fs_u1; 96 struct { 97 int8_t fs_fsmnt[468]; 98 uint8_t fs_volname[32]; 99 uint64_t fs_swuid; 100 int32_t fs_pad; 101 uint32_t fs_cgrotor; 102 uint32_t fs_ocsp[28]; 103 uint32_t fs_contigdirs; 104 uint32_t fs_csp; 105 uint32_t fs_maxcluster; 106 uint32_t fs_active; 107 int32_t fs_old_cpc; 108 int32_t fs_maxbsize; 109 int64_t fs_sparecon64[17]; 110 int64_t fs_sblockloc; 111 struct ufs2_csum_total { 112 uint64_t cs_ndir; 113 uint64_t cs_nbfree; 114 uint64_t cs_nifree; 115 uint64_t cs_nffree; 116 uint64_t cs_numclusters; 117 uint64_t cs_spare[3]; 118 } PACKED fs_cstotal; 119 struct ufs_timeval { 120 int32_t tv_sec; 121 int32_t tv_usec; 122 } PACKED fs_time; 123 int64_t fs_size; 124 int64_t fs_dsize; 125 uint64_t fs_csaddr; 126 int64_t fs_pendingblocks; 127 int32_t fs_pendinginodes; 128 } PACKED fs_u2; 129 } fs_u11; 130 union { 131 struct { 132 int32_t fs_sparecon[53]; 133 int32_t fs_reclaim; 134 int32_t fs_sparecon2[1]; 135 int32_t fs_state; 136 uint32_t fs_qbmask[2]; 137 uint32_t fs_qfmask[2]; 138 } PACKED fs_sun; 139 struct { 140 int32_t fs_sparecon[53]; 141 int32_t fs_reclaim; 142 int32_t fs_sparecon2[1]; 143 uint32_t fs_npsect; 144 uint32_t fs_qbmask[2]; 145 uint32_t fs_qfmask[2]; 146 } PACKED fs_sunx86; 147 struct { 148 int32_t fs_sparecon[50]; 149 int32_t fs_contigsumsize; 150 int32_t fs_maxsymlinklen; 151 int32_t fs_inodefmt; 152 uint32_t fs_maxfilesize[2]; 153 uint32_t fs_qbmask[2]; 154 uint32_t fs_qfmask[2]; 155 int32_t fs_state; 156 } PACKED fs_44; 157 } fs_u2; 158 int32_t fs_postblformat; 159 int32_t fs_nrpos; 160 int32_t fs_postbloff; 161 int32_t fs_rotbloff; 162 uint32_t fs_magic; 163 uint8_t fs_space[1]; 164} PACKED; 165 166#define UFS_MAGIC 0x00011954 167#define UFS2_MAGIC 0x19540119 168#define UFS_MAGIC_FEA 0x00195612 169#define UFS_MAGIC_LFN 0x00095014 170 171int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size) 172{ 173 uint32_t magic; 174 int i; 175 struct ufs_super_block *ufs; 176 int offsets[] = {0, 8, 64, 256, -1}; 177 178 info("probing at offset 0x%llx", (unsigned long long) off); 179 180 for (i = 0; offsets[i] >= 0; i++) { 181 ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800); 182 if (ufs == NULL) 183 return -1; 184 185 dbg("offset 0x%x", offsets[i] * 0x400); 186 magic = be32_to_cpu(ufs->fs_magic); 187 if ((magic == UFS_MAGIC) || 188 (magic == UFS2_MAGIC) || 189 (magic == UFS_MAGIC_FEA) || 190 (magic == UFS_MAGIC_LFN)) { 191 dbg("magic 0x%08x(be)", magic); 192 goto found; 193 } 194 magic = le32_to_cpu(ufs->fs_magic); 195 if ((magic == UFS_MAGIC) || 196 (magic == UFS2_MAGIC) || 197 (magic == UFS_MAGIC_FEA) || 198 (magic == UFS_MAGIC_LFN)) { 199 dbg("magic 0x%08x(le)", magic); 200 goto found; 201 } 202 } 203 return -1; 204 205found: 206 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); 207 id->type = "ufs"; 208 switch (magic) { 209 case UFS_MAGIC: 210 strcpy(id->type_version, "1"); 211 break; 212 case UFS2_MAGIC: 213 strcpy(id->type_version, "2"); 214 volume_id_set_label_raw(id, ufs->fs_u11.fs_u2.fs_volname, 32); 215 volume_id_set_label_string(id, ufs->fs_u11.fs_u2.fs_volname, 32); 216 break; 217 default: 218 break; 219 } 220 221 return 0; 222} 223