1/* 2 * volume_id - reads filesystem label and uuid 3 * 4 * Copyright (C) 2004 Andre Masella <andre@masella.no-ip.org> 5 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation version 2 of the License. 10 */ 11 12#ifndef _GNU_SOURCE 13#define _GNU_SOURCE 1 14#endif 15 16#ifdef HAVE_CONFIG_H 17# include <config.h> 18#endif 19 20#include <stdio.h> 21#include <stdlib.h> 22#include <unistd.h> 23#include <string.h> 24#include <errno.h> 25#include <ctype.h> 26 27#include "libvolume_id.h" 28#include "util.h" 29 30 31struct ocfs1_super_block_header { 32 uint32_t minor_version; 33 uint32_t major_version; 34 uint8_t signature[128]; 35 uint8_t mount_point[128]; 36 uint64_t serial_num; 37 uint64_t device_size; 38 uint64_t start_off; 39 uint64_t bitmap_off; 40 uint64_t publ_off; 41 uint64_t vote_off; 42 uint64_t root_bitmap_off; 43 uint64_t data_start_off; 44 uint64_t root_bitmap_size; 45 uint64_t root_off; 46 uint64_t root_size; 47 uint64_t cluster_size; 48 uint64_t num_nodes; 49 uint64_t num_clusters; 50 uint64_t dir_node_size; 51 uint64_t file_node_size; 52 uint64_t internal_off; 53 uint64_t node_cfg_off; 54 uint64_t node_cfg_size; 55 uint64_t new_cfg_off; 56 uint32_t prot_bits; 57 int32_t excl_mount; 58} PACKED; 59 60struct ocfs1_super_block_label { 61 struct ocfs1_disk_lock { 62 uint32_t curr_master; 63 uint8_t file_lock; 64 uint8_t compat_pad[3]; 65 uint64_t last_write_time; 66 uint64_t last_read_time; 67 uint32_t writer_node_num; 68 uint32_t reader_node_num; 69 uint64_t oin_node_map; 70 uint64_t dlock_seq_num; 71 } PACKED disk_lock; 72 uint8_t label[64]; 73 uint16_t label_len; 74 uint8_t vol_id[16]; 75 uint16_t vol_id_len; 76 uint8_t cluster_name[64]; 77 uint16_t cluster_name_len; 78} PACKED; 79 80struct ocfs2_super_block { 81 uint8_t i_signature[8]; 82 uint32_t i_generation; 83 int16_t i_suballoc_slot; 84 uint16_t i_suballoc_bit; 85 uint32_t i_reserved0; 86 uint32_t i_clusters; 87 uint32_t i_uid; 88 uint32_t i_gid; 89 uint64_t i_size; 90 uint16_t i_mode; 91 uint16_t i_links_count; 92 uint32_t i_flags; 93 uint64_t i_atime; 94 uint64_t i_ctime; 95 uint64_t i_mtime; 96 uint64_t i_dtime; 97 uint64_t i_blkno; 98 uint64_t i_last_eb_blk; 99 uint32_t i_fs_generation; 100 uint32_t i_atime_nsec; 101 uint32_t i_ctime_nsec; 102 uint32_t i_mtime_nsec; 103 uint64_t i_reserved1[9]; 104 uint64_t i_pad1; 105 uint16_t s_major_rev_level; 106 uint16_t s_minor_rev_level; 107 uint16_t s_mnt_count; 108 int16_t s_max_mnt_count; 109 uint16_t s_state; 110 uint16_t s_errors; 111 uint32_t s_checkinterval; 112 uint64_t s_lastcheck; 113 uint32_t s_creator_os; 114 uint32_t s_feature_compat; 115 uint32_t s_feature_incompat; 116 uint32_t s_feature_ro_compat; 117 uint64_t s_root_blkno; 118 uint64_t s_system_dir_blkno; 119 uint32_t s_blocksize_bits; 120 uint32_t s_clustersize_bits; 121 uint16_t s_max_slots; 122 uint16_t s_reserved1; 123 uint32_t s_reserved2; 124 uint64_t s_first_cluster_group; 125 uint8_t s_label[64]; 126 uint8_t s_uuid[16]; 127} PACKED; 128 129int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size) 130{ 131 const uint8_t *buf; 132 struct ocfs1_super_block_header *osh; 133 struct ocfs1_super_block_label *osl; 134 135 info("probing at offset 0x%llx", (unsigned long long) off); 136 137 buf = volume_id_get_buffer(id, off, 0x200); 138 if (buf == NULL) 139 return -1; 140 141 osh = (struct ocfs1_super_block_header *) buf; 142 if (memcmp(osh->signature, "OracleCFS", 9) != 0) 143 return -1; 144 snprintf(id->type_version, sizeof(id->type_version)-1, 145 "%u.%u", osh->major_version, osh->minor_version); 146 147 dbg("found OracleCFS signature, now reading label"); 148 buf = volume_id_get_buffer(id, off + 0x200, 0x200); 149 if (buf == NULL) 150 return -1; 151 152 osl = (struct ocfs1_super_block_label *) buf; 153 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); 154 if (osl->label_len <= 64) { 155 volume_id_set_label_raw(id, osl->label, 64); 156 volume_id_set_label_string(id, osl->label, 64); 157 } 158 if (osl->vol_id_len == 16) 159 volume_id_set_uuid(id, osl->vol_id, 0, UUID_DCE); 160 id->type = "ocfs"; 161 return 0; 162} 163 164#define OCFS2_MAX_BLOCKSIZE 0x1000 165#define OCFS2_SUPER_BLOCK_BLKNO 2 166 167int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size) 168{ 169 const uint8_t *buf; 170 struct ocfs2_super_block *os; 171 size_t blksize; 172 173 info("probing at offset 0x%llx", (unsigned long long) off); 174 175 for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) { 176 buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200); 177 if (buf == NULL) 178 return -1; 179 180 os = (struct ocfs2_super_block *) buf; 181 if (memcmp(os->i_signature, "OCFSV2", 6) != 0) 182 continue; 183 184 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); 185 volume_id_set_label_raw(id, os->s_label, 64); 186 volume_id_set_label_string(id, os->s_label, 64); 187 volume_id_set_uuid(id, os->s_uuid, 0, UUID_DCE); 188 snprintf(id->type_version, sizeof(id->type_version)-1, 189 "%u.%u", os->s_major_rev_level, os->s_minor_rev_level); 190 id->type = "ocfs2"; 191 return 0; 192 } 193 return -1; 194} 195