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#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