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