busybox/util-linux/volume_id/udf.c
<<
>>
Prefs
   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//config:config FEATURE_VOLUMEID_UDF
  21//config:       bool "udf filesystem"
  22//config:       default y
  23//config:       depends on VOLUMEID
  24
  25//kbuild:lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o
  26
  27#include "volume_id_internal.h"
  28
  29struct volume_descriptor {
  30        struct descriptor_tag {
  31                uint16_t        id;
  32                uint16_t        version;
  33                uint8_t         checksum;
  34                uint8_t         reserved;
  35                uint16_t        serial;
  36                uint16_t        crc;
  37                uint16_t        crc_len;
  38                uint32_t        location;
  39        } PACKED tag;
  40        union {
  41                struct anchor_descriptor {
  42                        uint32_t        length;
  43                        uint32_t        location;
  44                } PACKED anchor;
  45                struct primary_descriptor {
  46                        uint32_t        seq_num;
  47                        uint32_t        desc_num;
  48                        struct dstring {
  49                                uint8_t clen;
  50                                uint8_t c[31];
  51                        } PACKED ident;
  52                } PACKED primary;
  53        } PACKED type;
  54} PACKED;
  55
  56struct volume_structure_descriptor {
  57        uint8_t         type;
  58        uint8_t         id[5];
  59        uint8_t         version;
  60} PACKED;
  61
  62#define UDF_VSD_OFFSET                  0x8000
  63
  64int FAST_FUNC volume_id_probe_udf(struct volume_id *id /*,uint64_t off*/)
  65{
  66#define off ((uint64_t)0)
  67        struct volume_descriptor *vd;
  68        struct volume_structure_descriptor *vsd;
  69        unsigned bs;
  70        unsigned b;
  71        unsigned type;
  72        unsigned count;
  73        unsigned loc;
  74        unsigned clen;
  75
  76        dbg("probing at offset 0x%llx", (unsigned long long) off);
  77
  78        vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
  79        if (vsd == NULL)
  80                return -1;
  81
  82        if (memcmp(vsd->id, "NSR02", 5) == 0)
  83                goto blocksize;
  84        if (memcmp(vsd->id, "NSR03", 5) == 0)
  85                goto blocksize;
  86        if (memcmp(vsd->id, "BEA01", 5) == 0)
  87                goto blocksize;
  88        if (memcmp(vsd->id, "BOOT2", 5) == 0)
  89                goto blocksize;
  90        if (memcmp(vsd->id, "CD001", 5) == 0)
  91                goto blocksize;
  92        if (memcmp(vsd->id, "CDW02", 5) == 0)
  93                goto blocksize;
  94        if (memcmp(vsd->id, "TEA03", 5) == 0)
  95                goto blocksize;
  96        return -1;
  97
  98blocksize:
  99        /* search the next VSD to get the logical block size of the volume */
 100        for (bs = 0x800; bs < 0x8000; bs += 0x800) {
 101                vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
 102                if (vsd == NULL)
 103                        return -1;
 104                dbg("test for blocksize: 0x%x", bs);
 105                if (vsd->id[0] != '\0')
 106                        goto nsr;
 107        }
 108        return -1;
 109
 110nsr:
 111        /* search the list of VSDs for a NSR descriptor */
 112        for (b = 0; b < 64; b++) {
 113                vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
 114                if (vsd == NULL)
 115                        return -1;
 116
 117                dbg("vsd: %c%c%c%c%c",
 118                        vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
 119
 120                if (vsd->id[0] == '\0')
 121                        return -1;
 122                if (memcmp(vsd->id, "NSR02", 5) == 0)
 123                        goto anchor;
 124                if (memcmp(vsd->id, "NSR03", 5) == 0)
 125                        goto anchor;
 126        }
 127        return -1;
 128
 129anchor:
 130        /* read anchor volume descriptor */
 131        vd = volume_id_get_buffer(id, off + (256 * bs), 0x200);
 132        if (vd == NULL)
 133                return -1;
 134
 135        type = le16_to_cpu(vd->tag.id);
 136        if (type != 2) /* TAG_ID_AVDP */
 137                goto found;
 138
 139        /* get descriptor list address and block count */
 140        count = le32_to_cpu(vd->type.anchor.length) / bs;
 141        loc = le32_to_cpu(vd->type.anchor.location);
 142        dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
 143
 144        /* pick the primary descriptor from the list */
 145        for (b = 0; b < count; b++) {
 146                vd = volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200);
 147                if (vd == NULL)
 148                        return -1;
 149
 150                type = le16_to_cpu(vd->tag.id);
 151                dbg("descriptor type %i", type);
 152
 153                /* check validity */
 154                if (type == 0)
 155                        goto found;
 156                if (le32_to_cpu(vd->tag.location) != loc + b)
 157                        goto found;
 158
 159                if (type == 1) /* TAG_ID_PVD */
 160                        goto pvd;
 161        }
 162        goto found;
 163
 164 pvd:
 165//      volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32);
 166
 167        clen = vd->type.primary.ident.clen;
 168        dbg("label string charsize=%i bit", clen);
 169        if (clen == 8)
 170                volume_id_set_label_string(id, vd->type.primary.ident.c, 31);
 171        else if (clen == 16)
 172                volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE, 31);
 173
 174 found:
 175//      volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
 176        IF_FEATURE_BLKID_TYPE(id->type = "udf";)
 177        return 0;
 178}
 179