]> err.no Git - util-linux/commitdiff
blkid: add UDF support
authorKarel Zak <kzak@redhat.com>
Tue, 4 Nov 2008 09:50:14 +0000 (10:50 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 11 Feb 2009 22:21:46 +0000 (23:21 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libs/blkid/src/probe.c
libs/blkid/src/probers/Makefile.am
libs/blkid/src/probers/probers.h
libs/blkid/src/probers/udf.c [new file with mode: 0644]

index 5b7fe6fa70ac890d500a7498444751592ea967a1..fcd7f61b13e73e11346a5b1ec6a4bf75eb475aeb 100644 (file)
@@ -68,6 +68,7 @@ static const struct blkid_idinfo *idinfos[] =
        &hfs_idinfo,
        &ntfs_idinfo,
        &iso9660_idinfo,
+       &udf_idinfo,
        &lvm2_idinfo
 };
 
index 62c31fa7aa5b89e7df38337d5632eea822dad4c6..b59ec313a260c21e127e97e3767c069693e97459 100644 (file)
@@ -27,6 +27,7 @@ libprobers_a_SOURCES =        probers.h \
                        ntfs.c \
                        hfs.c \
                        iso9660.c \
+                       udf.c \
                        lvm.c
 
 all-local: $(lib_LIBRARIES)
index ae6df7e636a77201bddd6fecda6713e6da92e292..c50e0b5b3e0c5d99063a1bbaebf55e8891b51f66 100644 (file)
@@ -47,6 +47,7 @@ extern const struct blkid_idinfo hfs_idinfo;
 extern const struct blkid_idinfo hfsplus_idinfo;
 extern const struct blkid_idinfo ntfs_idinfo;
 extern const struct blkid_idinfo iso9660_idinfo;
+extern const struct blkid_idinfo udf_idinfo;
 extern const struct blkid_idinfo lvm2_idinfo;
 
 #endif /* _BLKID_PROBE_H */
diff --git a/libs/blkid/src/probers/udf.c b/libs/blkid/src/probers/udf.c
new file mode 100644 (file)
index 0000000..ef34bb8
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "blkidP.h"
+
+struct volume_descriptor {
+       struct descriptor_tag {
+               uint16_t        id;
+               uint16_t        version;
+               uint8_t         checksum;
+               uint8_t         reserved;
+               uint16_t        serial;
+               uint16_t        crc;
+               uint16_t        crc_len;
+               uint32_t        location;
+       } tag;
+       union {
+               struct anchor_descriptor {
+                       uint32_t        length;
+                       uint32_t        location;
+               } anchor;
+               struct primary_descriptor {
+                       uint32_t        seq_num;
+                       uint32_t        desc_num;
+                       struct dstring {
+                               uint8_t clen;
+                               uint8_t c[31];
+                       } ident;
+               } primary;
+       } type;
+};
+
+struct volume_structure_descriptor {
+       uint8_t         type;
+       uint8_t         id[5];
+       uint8_t         version;
+} PACKED;
+
+#define UDF_VSD_OFFSET                 0x8000
+
+static int probe_udf(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       struct volume_descriptor *vd;
+       struct volume_structure_descriptor *vsd;
+       unsigned int bs;
+       unsigned int b;
+       unsigned int type;
+       unsigned int count;
+       unsigned int loc;
+
+       /* search Volume Sequence Descriptor (VSD) to get the logical
+        * block size of the volume */
+       for (bs = 0x800; bs < 0x8000; bs += 0x800) {
+               vsd = (struct volume_structure_descriptor *)
+                       blkid_probe_get_buffer(pr,
+                                       UDF_VSD_OFFSET + bs,
+                                       sizeof(*vsd));
+               if (!vsd)
+                       return 1;
+               if (vsd->id[0] != '\0')
+                       goto nsr;
+       }
+       return -1;
+
+nsr:
+       /* search the list of VSDs for a NSR descriptor */
+       for (b = 0; b < 64; b++) {
+               vsd = (struct volume_structure_descriptor *)
+                       blkid_probe_get_buffer(pr,
+                                       UDF_VSD_OFFSET + (b * bs),
+                                       sizeof(*vsd));
+               if (!vsd)
+                       return -1;
+               if (vsd->id[0] == '\0')
+                       return -1;
+               if (memcmp(vsd->id, "NSR02", 5) == 0)
+                       goto anchor;
+               if (memcmp(vsd->id, "NSR03", 5) == 0)
+                       goto anchor;
+       }
+       return -1;
+
+anchor:
+       /* read Anchor Volume Descriptor (AVDP) */
+       vd = (struct volume_descriptor *)
+               blkid_probe_get_buffer(pr, 256 * bs, sizeof(*vd));
+       if (!vd)
+               return -1;
+
+       type = le16_to_cpu(vd->tag.id);
+       if (type != 2) /* TAG_ID_AVDP */
+               return 0;
+
+       /* get desriptor list address and block count */
+       count = le32_to_cpu(vd->type.anchor.length) / bs;
+       loc = le32_to_cpu(vd->type.anchor.location);
+
+       /* pick the primary descriptor from the list */
+       for (b = 0; b < count; b++) {
+               vd = (struct volume_descriptor *)
+                       blkid_probe_get_buffer(pr, (loc + b) * bs, sizeof(*vd));
+               if (!vd)
+                       return -1;
+
+               type = le16_to_cpu(vd->tag.id);
+               if (type == 0)
+                       break;
+               if (le32_to_cpu(vd->tag.location) != loc + b)
+                       break;
+               if (type == 1) { /* TAG_ID_PVD */
+                       uint8_t clen = vd->type.primary.ident.clen;
+
+                       if (clen == 8)
+                               blkid_probe_set_label(pr,
+                                               vd->type.primary.ident.c, 31);
+                       else if (clen == 16)
+                               blkid_probe_set_utf8label(pr,
+                                               vd->type.primary.ident.c,
+                                               31, BLKID_ENC_UTF16BE);
+               }
+       }
+
+       return 0;
+}
+
+
+const struct blkid_idinfo udf_idinfo =
+{
+       .name           = "udf",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_udf,
+       .magics         =
+       {
+               { .magic = "BEA01", .len = 5, .kboff = 32, .sboff = 1 },
+               { .magic = "BOOT2", .len = 5, .kboff = 32, .sboff = 1 },
+               { .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
+               { .magic = "CDW02", .len = 5, .kboff = 32, .sboff = 1 },
+               { .magic = "NSR02", .len = 5, .kboff = 32, .sboff = 1 },
+               { .magic = "NSR03", .len = 5, .kboff = 32, .sboff = 1 },
+               { .magic = "TEA01", .len = 5, .kboff = 32, .sboff = 1 },
+               { NULL }
+       }
+};