1/* 2 * volume_id - reads filesystem label and uuid 3 * 4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#include "volume_id_internal.h" 22 23struct volume_descriptor { 24 struct descriptor_tag { 25 uint16_t id; 26 uint16_t version; 27 uint8_t checksum; 28 uint8_t reserved; 29 uint16_t serial; 30 uint16_t crc; 31 uint16_t crc_len; 32 uint32_t location; 33 } PACKED tag; 34 union { 35 struct anchor_descriptor { 36 uint32_t length; 37 uint32_t location; 38 } PACKED anchor; 39 struct primary_descriptor { 40 uint32_t seq_num; 41 uint32_t desc_num; 42 struct dstring { 43 uint8_t clen; 44 uint8_t c[31]; 45 } PACKED ident; 46 } PACKED primary; 47 } PACKED type; 48} PACKED; 49 50struct volume_structure_descriptor { 51 uint8_t type; 52 uint8_t id[5]; 53 uint8_t version; 54} PACKED; 55 56#define UDF_VSD_OFFSET 0x8000 57 58int FAST_FUNC volume_id_probe_udf(struct volume_id *id /*,uint64_t off*/) 59{ 60#define off ((uint64_t)0) 61 struct volume_descriptor *vd; 62 struct volume_structure_descriptor *vsd; 63 unsigned bs; 64 unsigned b; 65 unsigned type; 66 unsigned count; 67 unsigned loc; 68 unsigned clen; 69 70 dbg("probing at offset 0x%llx", (unsigned long long) off); 71 72 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200); 73 if (vsd == NULL) 74 return -1; 75 76 if (memcmp(vsd->id, "NSR02", 5) == 0) 77 goto blocksize; 78 if (memcmp(vsd->id, "NSR03", 5) == 0) 79 goto blocksize; 80 if (memcmp(vsd->id, "BEA01", 5) == 0) 81 goto blocksize; 82 if (memcmp(vsd->id, "BOOT2", 5) == 0) 83 goto blocksize; 84 if (memcmp(vsd->id, "CD001", 5) == 0) 85 goto blocksize; 86 if (memcmp(vsd->id, "CDW02", 5) == 0) 87 goto blocksize; 88 if (memcmp(vsd->id, "TEA03", 5) == 0) 89 goto blocksize; 90 return -1; 91 92blocksize: 93 /* search the next VSD to get the logical block size of the volume */ 94 for (bs = 0x800; bs < 0x8000; bs += 0x800) { 95 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800); 96 if (vsd == NULL) 97 return -1; 98 dbg("test for blocksize: 0x%x", bs); 99 if (vsd->id[0] != '\0') 100 goto nsr; 101 } 102 return -1; 103 104nsr: 105 /* search the list of VSDs for a NSR descriptor */ 106 for (b = 0; b < 64; b++) { 107 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800); 108 if (vsd == NULL) 109 return -1; 110 111 dbg("vsd: %c%c%c%c%c", 112 vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]); 113 114 if (vsd->id[0] == '\0') 115 return -1; 116 if (memcmp(vsd->id, "NSR02", 5) == 0) 117 goto anchor; 118 if (memcmp(vsd->id, "NSR03", 5) == 0) 119 goto anchor; 120 } 121 return -1; 122 123anchor: 124 /* read anchor volume descriptor */ 125 vd = volume_id_get_buffer(id, off + (256 * bs), 0x200); 126 if (vd == NULL) 127 return -1; 128 129 type = le16_to_cpu(vd->tag.id); 130 if (type != 2) /* TAG_ID_AVDP */ 131 goto found; 132 133 /* get desriptor list address and block count */ 134 count = le32_to_cpu(vd->type.anchor.length) / bs; 135 loc = le32_to_cpu(vd->type.anchor.location); 136 dbg("0x%x descriptors starting at logical secor 0x%x", count, loc); 137 138 /* pick the primary descriptor from the list */ 139 for (b = 0; b < count; b++) { 140 vd = volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200); 141 if (vd == NULL) 142 return -1; 143 144 type = le16_to_cpu(vd->tag.id); 145 dbg("descriptor type %i", type); 146 147 /* check validity */ 148 if (type == 0) 149 goto found; 150 if (le32_to_cpu(vd->tag.location) != loc + b) 151 goto found; 152 153 if (type == 1) /* TAG_ID_PVD */ 154 goto pvd; 155 } 156 goto found; 157 158 pvd: 159// volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32); 160 161 clen = vd->type.primary.ident.clen; 162 dbg("label string charsize=%i bit", clen); 163 if (clen == 8) 164 volume_id_set_label_string(id, vd->type.primary.ident.c, 31); 165 else if (clen == 16) 166 volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE, 31); 167 168 found: 169// volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); 170// id->type = "udf"; 171 172 return 0; 173} 174