]> err.no Git - systemd/commitdiff
[PATCH] udev_volume_id: new version of volume_id
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Mon, 31 Jan 2005 04:28:44 +0000 (05:28 +0100)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 06:24:19 +0000 (23:24 -0700)
Every filesystem has its own subdirectory.
The IBM dasd label reading is included into volume_id.

42 files changed:
extras/volume_id/Makefile
extras/volume_id/udev_volume_id.c
extras/volume_id/volume_id.c [deleted file]
extras/volume_id/volume_id/dasd/dasd.c [moved from extras/volume_id/dasdlabel.c with 88% similarity]
extras/volume_id/volume_id/dasd/dasd.h [moved from extras/volume_id/dasdlabel.h with 87% similarity]
extras/volume_id/volume_id/ext/ext.c [new file with mode: 0644]
extras/volume_id/volume_id/ext/ext.h [new file with mode: 0644]
extras/volume_id/volume_id/fat/fat.c [new file with mode: 0644]
extras/volume_id/volume_id/fat/fat.h [new file with mode: 0644]
extras/volume_id/volume_id/hfs/hfs.c [new file with mode: 0644]
extras/volume_id/volume_id/hfs/hfs.h [new file with mode: 0644]
extras/volume_id/volume_id/highpoint/highpoint.c [new file with mode: 0644]
extras/volume_id/volume_id/highpoint/highpoint.h [new file with mode: 0644]
extras/volume_id/volume_id/iso9660/iso9660.c [new file with mode: 0644]
extras/volume_id/volume_id/iso9660/iso9660.h [new file with mode: 0644]
extras/volume_id/volume_id/jfs/jfs.c [new file with mode: 0644]
extras/volume_id/volume_id/jfs/jfs.h [new file with mode: 0644]
extras/volume_id/volume_id/linux_raid/linux_raid.c [new file with mode: 0644]
extras/volume_id/volume_id/linux_raid/linux_raid.h [new file with mode: 0644]
extras/volume_id/volume_id/linux_swap/linux_swap.c [new file with mode: 0644]
extras/volume_id/volume_id/linux_swap/linux_swap.h [new file with mode: 0644]
extras/volume_id/volume_id/logging.h [moved from extras/volume_id/volume_id_logging.h with 77% similarity]
extras/volume_id/volume_id/lvm/lvm.c [new file with mode: 0644]
extras/volume_id/volume_id/lvm/lvm.h [new file with mode: 0644]
extras/volume_id/volume_id/mac/mac.c [new file with mode: 0644]
extras/volume_id/volume_id/mac/mac.h [new file with mode: 0644]
extras/volume_id/volume_id/msdos/msdos.c [new file with mode: 0644]
extras/volume_id/volume_id/msdos/msdos.h [new file with mode: 0644]
extras/volume_id/volume_id/ntfs/ntfs.c [new file with mode: 0644]
extras/volume_id/volume_id/ntfs/ntfs.h [new file with mode: 0644]
extras/volume_id/volume_id/reiserfs/reiserfs.c [new file with mode: 0644]
extras/volume_id/volume_id/reiserfs/reiserfs.h [new file with mode: 0644]
extras/volume_id/volume_id/udf/udf.c [new file with mode: 0644]
extras/volume_id/volume_id/udf/udf.h [new file with mode: 0644]
extras/volume_id/volume_id/ufs/ufs.c [new file with mode: 0644]
extras/volume_id/volume_id/ufs/ufs.h [new file with mode: 0644]
extras/volume_id/volume_id/util.c [new file with mode: 0644]
extras/volume_id/volume_id/util.h [new file with mode: 0644]
extras/volume_id/volume_id/volume_id.c [new file with mode: 0644]
extras/volume_id/volume_id/volume_id.h [moved from extras/volume_id/volume_id.h with 70% similarity]
extras/volume_id/volume_id/xfs/xfs.c [new file with mode: 0644]
extras/volume_id/volume_id/xfs/xfs.h [new file with mode: 0644]

index 5c8adb065be9c1091872c7b940fe690e4eaa0f01..f0c15b8fecd4a50090519bccbe3792b8ca298b0e 100644 (file)
@@ -33,8 +33,50 @@ override CFLAGS+=-Wall -fno-builtin -Wchar-subscripts \
 
 override CFLAGS+=-D_FILE_OFFSET_BITS=64
 
-OBJS = volume_id.o udev_volume_id.o dasdlabel.o $(SYSFS)
-HEADERS = volume_id.h dasdlabel.h
+VOLUME_ID_OBJS=                                        \
+       volume_id/ext/ext.o                     \
+       volume_id/fat/fat.o                     \
+       volume_id/hfs/hfs.o                     \
+       volume_id/highpoint/highpoint.o         \
+       volume_id/iso9660/iso9660.o             \
+       volume_id/jfs/jfs.o                     \
+       volume_id/linux_raid/linux_raid.o       \
+       volume_id/linux_swap/linux_swap.o       \
+       volume_id/lvm/lvm.o                     \
+       volume_id/mac/mac.o                     \
+       volume_id/msdos/msdos.o                 \
+       volume_id/ntfs/ntfs.o                   \
+       volume_id/reiserfs/reiserfs.o           \
+       volume_id/udf/udf.o                     \
+       volume_id/ufs/ufs.o                     \
+       volume_id/xfs/xfs.o                     \
+       volume_id/dasd/dasd.o                   \
+       volume_id/volume_id.o                   \
+       volume_id/util.o
+
+VOLUME_ID_HEADERS=                             \
+       volume_id/ext/ext.h                     \
+       volume_id/fat/fat.h                     \
+       volume_id/hfs/hfs.h                     \
+       volume_id/highpoint/highpoint.h         \
+       volume_id/iso9660/iso9660.h             \
+       volume_id/jfs/jfs.h                     \
+       volume_id/linux_raid/linux_raid.h       \
+       volume_id/linux_swap/linux_swap.h       \
+       volume_id/lvm/lvm.h                     \
+       volume_id/mac/mac.h                     \
+       volume_id/msdos/msdos.h                 \
+       volume_id/ntfs/ntfs.h                   \
+       volume_id/reiserfs/reiserfs.h           \
+       volume_id/udf/udf.h                     \
+       volume_id/ufs/ufs.h                     \
+       volume_id/xfs/xfs.h                     \
+       volume_id/dasd/dasd.h                   \
+       volume_id/volume_id.h                   \
+       volume_id/util.h
+
+OBJS = udev_volume_id.o $(VOLUME_ID_OBJS) $(SYSFS)
+HEADERS = $(VOLUME_ID_HEADERS)
 
 $(OBJS): $(HEADERS)
 
@@ -54,4 +96,3 @@ install: all
 
 uninstall:
        - rm $(DESTDIR)$(sbindir)/$(PROG)
-
index 7b6985680414837457996c4a298be3a930487c43..915c1c411739a073b91a10a44c7260244e4f1719 100644 (file)
@@ -31,8 +31,8 @@
 #include "../../libsysfs/sysfs/libsysfs.h"
 #include "../../udev_utils.h"
 #include "../../logging.h"
-#include "volume_id.h"
-#include "dasdlabel.h"
+#include "volume_id/volume_id.h"
+#include "volume_id/dasd/dasd.h"
 
 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
 
@@ -74,26 +74,6 @@ static struct volume_id *open_classdev(struct sysfs_class_device *class_dev)
        return vid;
 }
 
-static char *usage_id_name(enum volume_id_usage usage)
-{
-       switch(usage) {
-       case VOLUME_ID_UNUSED:
-               return "unused";
-       case VOLUME_ID_UNPROBED:
-               return "unprobed";
-       case VOLUME_ID_OTHER:
-               return "other";
-       case VOLUME_ID_PARTITIONTABLE:
-               return "partitiontable";
-       case VOLUME_ID_FILESYSTEM:
-               return "filesystem";
-       case VOLUME_ID_RAID:
-               return "raid";
-       default:
-               return "unknown type_id";
-       }
-}
-
 int main(int argc, char *argv[])
 {
        const char help[] = "usage: udev_volume_id [-t|-l|-u|-d]\n"
@@ -111,7 +91,6 @@ int main(int argc, char *argv[])
        char *devpath;
        char probe = 'p';
        char print = 'a';
-       char dasd_label[7];
        static char name[VOLUME_ID_LABEL_SIZE];
        int len, i, j;
        unsigned long long size;
@@ -177,7 +156,7 @@ int main(int argc, char *argv[])
                if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0)
                        size = 0;
 
-               if (volume_id_probe(vid, VOLUME_ID_ALL, 0, size) == 0)
+               if (volume_id_probe_all(vid, 0, size) == 0)
                        goto print;
                break;
        case 'd' :
@@ -190,12 +169,8 @@ int main(int argc, char *argv[])
                if (vid == NULL)
                        goto exit;
 
-               if (probe_ibm_partition(vid->fd, dasd_label) == 0) {
-                       vid->type = "dasd";
-                       strncpy(vid->label, dasd_label, 6);
-                       vid->label[6] = '\0';
+               if (probe_ibm_partition(vid) == 0)
                        goto print;
-               }
                break;
        }
 
@@ -247,7 +222,7 @@ print:
                printf("%s\n", vid->uuid);
                break;
        case 'a':
-               printf("F:%s\n", usage_id_name(vid->usage_id));
+               printf("F:%s\n", vid->usage);
                printf("T:%s\n", vid->type);
                printf("V:%s\n", vid->type_version);
                printf("L:%s\n", vid->label);
diff --git a/extras/volume_id/volume_id.c b/extras/volume_id/volume_id.c
deleted file mode 100644 (file)
index 3bf7886..0000000
+++ /dev/null
@@ -1,2305 +0,0 @@
-/*
- * volume_id - reads filesystem label and uuid
- *
- * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
- *
- *     The superblock structs are taken from the linux kernel sources
- *     and the libblkid living inside the e2fsprogs. This is a simple
- *     straightforward implementation for reading the label strings of the
- *     most common filesystems.
- *
- *     This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU Lesser General Public
- *     License as published by the Free Software Foundation; either
- *     version 2.1 of the License, or (at your option) any later version.
- *
- *     This library 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
- *     Lesser General Public License for more details.
- *
- *     You should have received a copy of the GNU Lesser General Public
- *     License along with this library; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#endif
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <asm/types.h>
-
-#include "volume_id.h"
-#include "volume_id_logging.h"
-
-#define bswap16(x) (__u16)((((__u16)(x) & 0x00ffu) << 8) | \
-                          (((__u16)(x) & 0xff00u) >> 8))
-
-#define bswap32(x) (__u32)((((__u32)(x) & 0xff000000u) >> 24) | \
-                          (((__u32)(x) & 0x00ff0000u) >>  8) | \
-                          (((__u32)(x) & 0x0000ff00u) <<  8) | \
-                          (((__u32)(x) & 0x000000ffu) << 24))
-
-#define bswap64(x) (__u64)((((__u64)(x) & 0xff00000000000000ull) >> 56) | \
-                          (((__u64)(x) & 0x00ff000000000000ull) >> 40) | \
-                          (((__u64)(x) & 0x0000ff0000000000ull) >> 24) | \
-                          (((__u64)(x) & 0x000000ff00000000ull) >>  8) | \
-                          (((__u64)(x) & 0x00000000ff000000ull) <<  8) | \
-                          (((__u64)(x) & 0x0000000000ff0000ull) << 24) | \
-                          (((__u64)(x) & 0x000000000000ff00ull) << 40) | \
-                          (((__u64)(x) & 0x00000000000000ffull) << 56))
-
-#if (__BYTE_ORDER == __LITTLE_ENDIAN)
-#define le16_to_cpu(x) (x)
-#define le32_to_cpu(x) (x)
-#define le64_to_cpu(x) (x)
-#define be16_to_cpu(x) bswap16(x)
-#define be32_to_cpu(x) bswap32(x)
-#elif (__BYTE_ORDER == __BIG_ENDIAN)
-#define le16_to_cpu(x) bswap16(x)
-#define le32_to_cpu(x) bswap32(x)
-#define le64_to_cpu(x) bswap64(x)
-#define be16_to_cpu(x) (x)
-#define be32_to_cpu(x) (x)
-#endif
-
-/* size of superblock buffer, reiserfs block is at 64k */
-#define SB_BUFFER_SIZE                         0x11000
-/* size of seek buffer 4k */
-#define SEEK_BUFFER_SIZE                       0x10000
-
-
-static void set_label_raw(struct volume_id *id,
-                         const __u8 *buf, unsigned int count)
-{
-       memcpy(id->label_raw, buf, count);
-       id->label_raw_len = count;
-}
-
-static void set_label_string(struct volume_id *id,
-                            const __u8 *buf, unsigned int count)
-{
-       unsigned int i;
-
-       memcpy(id->label, buf, count);
-
-       /* remove trailing whitespace */
-       i = strnlen(id->label, count);
-       while (i--) {
-               if (! isspace(id->label[i]))
-                       break;
-       }
-       id->label[i+1] = '\0';
-}
-
-#define LE             0
-#define BE             1
-static void set_label_unicode16(struct volume_id *id,
-                               const __u8 *buf,
-                               unsigned int endianess,
-                               unsigned int count)
-{
-       unsigned int i, j;
-       __u16 c;
-
-       j = 0;
-       for (i = 0; i + 2 <= count; i += 2) {
-               if (endianess == LE)
-                       c = (buf[i+1] << 8) | buf[i];
-               else
-                       c = (buf[i] << 8) | buf[i+1];
-               if (c == 0) {
-                       id->label[j] = '\0';
-                       break;
-               } else if (c < 0x80) {
-                       id->label[j++] = (__u8) c;
-               } else if (c < 0x800) {
-                       id->label[j++] = (__u8) (0xc0 | (c >> 6));
-                       id->label[j++] = (__u8) (0x80 | (c & 0x3f));
-               } else {
-                       id->label[j++] = (__u8) (0xe0 | (c >> 12));
-                       id->label[j++] = (__u8) (0x80 | ((c >> 6) & 0x3f));
-                       id->label[j++] = (__u8) (0x80 | (c & 0x3f));
-               }
-       }
-}
-
-enum uuid_format {
-       UUID_DCE,
-       UUID_DOS,
-       UUID_NTFS,
-       UUID_HFS,
-};
-
-static void set_uuid(struct volume_id *id, const __u8 *buf, enum uuid_format format)
-{
-       unsigned int i;
-       unsigned int count = 0;
-
-       switch(format) {
-       case UUID_DOS:
-               count = 4;
-               break;
-       case UUID_NTFS:
-       case UUID_HFS:
-               count = 8;
-               break;
-       case UUID_DCE:
-               count = 16;
-       }
-       memcpy(id->uuid_raw, buf, count);
-
-       /* if set, create string in the same format, the native platform uses */
-       for (i = 0; i < count; i++)
-               if (buf[i] != 0)
-                       goto set;
-       return;
-
-set:
-       switch(format) {
-       case UUID_DOS:
-               sprintf(id->uuid, "%02X%02X-%02X%02X",
-                       buf[3], buf[2], buf[1], buf[0]);
-               break;
-       case UUID_NTFS:
-               sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
-                       buf[7], buf[6], buf[5], buf[4],
-                       buf[3], buf[2], buf[1], buf[0]);
-               break;
-       case UUID_HFS:
-               sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
-                       buf[0], buf[1], buf[2], buf[3],
-                       buf[4], buf[5], buf[6], buf[7]);
-               break;
-       case UUID_DCE:
-               sprintf(id->uuid,
-                       "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-                       buf[0], buf[1], buf[2], buf[3],
-                       buf[4], buf[5],
-                       buf[6], buf[7],
-                       buf[8], buf[9],
-                       buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]);
-               break;
-       }
-}
-
-static __u8 *get_buffer(struct volume_id *id, __u64 off, unsigned int len)
-{
-       unsigned int buf_len;
-
-       dbg("get buffer off 0x%llx, len 0x%x", off, len);
-       /* check if requested area fits in superblock buffer */
-       if (off + len <= SB_BUFFER_SIZE) {
-               if (id->sbbuf == NULL) {
-                       id->sbbuf = malloc(SB_BUFFER_SIZE);
-                       if (id->sbbuf == NULL)
-                               return NULL;
-               }
-
-               /* check if we need to read */
-               if ((off + len) > id->sbbuf_len) {
-                       dbg("read sbbuf len:0x%llx", off + len);
-                       lseek(id->fd, 0, SEEK_SET);
-                       buf_len = read(id->fd, id->sbbuf, off + len);
-                       dbg("got 0x%x (%i) bytes", buf_len, buf_len);
-                       id->sbbuf_len = buf_len;
-                       if (buf_len < off + len)
-                               return NULL;
-               }
-
-               return &(id->sbbuf[off]);
-       } else {
-               if (len > SEEK_BUFFER_SIZE) {
-                       dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
-                       return NULL;
-               }
-
-               /* get seek buffer */
-               if (id->seekbuf == NULL) {
-                       id->seekbuf = malloc(SEEK_BUFFER_SIZE);
-                       if (id->seekbuf == NULL)
-                               return NULL;
-               }
-
-               /* check if we need to read */
-               if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
-                       dbg("read seekbuf off:0x%llx len:0x%x", off, len);
-                       if (lseek(id->fd, off, SEEK_SET) == -1)
-                               return NULL;
-                       buf_len = read(id->fd, id->seekbuf, len);
-                       dbg("got 0x%x (%i) bytes", buf_len, buf_len);
-                       id->seekbuf_off = off;
-                       id->seekbuf_len = buf_len;
-                       if (buf_len < len) {
-                               dbg("requested 0x%x bytes, got only 0x%x bytes", len, buf_len);
-                               return NULL;
-                       }
-               }
-
-               return &(id->seekbuf[off - id->seekbuf_off]);
-       }
-}
-
-static void free_buffer(struct volume_id *id)
-{
-       if (id->sbbuf != NULL) {
-               free(id->sbbuf);
-               id->sbbuf = NULL;
-               id->sbbuf_len = 0;
-       }
-       if (id->seekbuf != NULL) {
-               free(id->seekbuf);
-               id->seekbuf = NULL;
-               id->seekbuf_len = 0;
-       }
-}
-
-#define HPT37X_CONFIG_OFF              0x1200
-#define HPT37X_MAGIC_OK                        0x5a7816f0
-#define HPT37X_MAGIC_BAD               0x5a7816fd
-static int probe_highpoint_ataraid(struct volume_id *id, __u64 off)
-{
-       struct hpt37x {
-               __u8    filler1[32];
-               __u32   magic;
-               __u32   magic_0;
-               __u32   magic_1;
-       } __attribute__((packed)) *hpt;
-
-       const __u8 *buf;
-
-       buf = get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
-       if (buf == NULL)
-               return -1;
-
-       hpt = (struct hpt37x *) buf;
-
-       if (hpt->magic != HPT37X_MAGIC_OK && hpt->magic != HPT37X_MAGIC_BAD)
-               return -1;
-
-       id->usage_id = VOLUME_ID_RAID;
-       id->type_id = VOLUME_ID_HPTRAID;
-       id->type = "hpt_ataraid_member";
-
-       return 0;
-}
-
-#define LVM1_SB_OFF                    0x400
-#define LVM1_MAGIC                     "HM"
-static int probe_lvm1(struct volume_id *id, __u64 off)
-{
-       struct lvm2_super_block {
-               __u8    id[2];
-       } __attribute__((packed)) *lvm;
-
-       const __u8 *buf;
-
-       buf = get_buffer(id, off + LVM1_SB_OFF, 0x800);
-       if (buf == NULL)
-               return -1;
-
-       lvm = (struct lvm2_super_block *) buf;
-
-       if (strncmp(lvm->id, LVM1_MAGIC, 2) != 0)
-               return -1;
-
-       id->usage_id = VOLUME_ID_RAID;
-       id->type_id = VOLUME_ID_LVM1;
-       id->type = "LVM1_member";
-
-       return 0;
-}
-
-#define LVM2_LABEL_ID                  "LABELONE"
-#define LVM2LABEL_SCAN_SECTORS         4
-static int probe_lvm2(struct volume_id *id, __u64 off)
-{
-       struct lvm2_super_block {
-               __u8    id[8];
-               __u64   sector_xl;
-               __u32   crc_xl;
-               __u32   offset_xl;
-               __u8    type[8];
-       } __attribute__((packed)) *lvm;
-
-       const __u8 *buf;
-       unsigned int soff;
-
-       buf = get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200);
-       if (buf == NULL)
-               return -1;
-
-
-       for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
-               lvm = (struct lvm2_super_block *) &buf[soff];
-
-               if (strncmp(lvm->id, LVM2_LABEL_ID, 8) == 0)
-                       goto found;
-       }
-
-       return -1;
-
-found:
-       strncpy(id->type_version, lvm->type, 8);
-       id->usage_id = VOLUME_ID_RAID;
-       id->type_id = VOLUME_ID_LVM2;
-       id->type = "LVM2_member";
-
-       return 0;
-}
-
-#define MD_RESERVED_BYTES              0x10000
-#define MD_MAGIC                       0xa92b4efc
-static int probe_linux_raid(struct volume_id *id, __u64 off, __u64 size)
-{
-       struct mdp_super_block {
-               __u32   md_magic;
-               __u32   major_version;
-               __u32   minor_version;
-               __u32   patch_version;
-               __u32   gvalid_words;
-               __u32   set_uuid0;
-               __u32   ctime;
-               __u32   level;
-               __u32   size;
-               __u32   nr_disks;
-               __u32   raid_disks;
-               __u32   md_minor;
-               __u32   not_persistent;
-               __u32   set_uuid1;
-               __u32   set_uuid2;
-               __u32   set_uuid3;
-       } __attribute__((packed)) *mdp;
-
-       const __u8 *buf;
-       __u64 sboff;
-       __u8 uuid[16];
-
-       if (size < 0x10000)
-               return -1;
-
-       sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
-       buf = get_buffer(id, off + sboff, 0x800);
-       if (buf == NULL)
-               return -1;
-
-       mdp = (struct mdp_super_block *) buf;
-
-       if (le32_to_cpu(mdp->md_magic) != MD_MAGIC)
-               return -1;
-
-       memcpy(uuid, &mdp->set_uuid0, 4);
-       memcpy(&uuid[4], &mdp->set_uuid1, 12);
-       set_uuid(id, uuid, UUID_DCE);
-
-       snprintf(id->type_version, VOLUME_ID_FORMAT_SIZE-1, "%u.%u.%u",
-                le32_to_cpu(mdp->major_version),
-                le32_to_cpu(mdp->minor_version),
-                le32_to_cpu(mdp->patch_version));
-
-       dbg("found raid signature");
-       id->usage_id = VOLUME_ID_RAID;
-       id->type = "linux_raid_member";
-
-       return 0;
-}
-
-#define MSDOS_MAGIC                    "\x55\xaa"
-#define MSDOS_PARTTABLE_OFFSET         0x1be
-#define MSDOS_SIG_OFF                  0x1fe
-#define BSIZE                          0x200
-#define DOS_EXTENDED_PARTITION         0x05
-#define LINUX_EXTENDED_PARTITION       0x85
-#define WIN98_EXTENDED_PARTITION       0x0f
-#define LINUX_RAID_PARTITION           0xfd
-#define is_extended(type) \
-       (type == DOS_EXTENDED_PARTITION ||      \
-        type == WIN98_EXTENDED_PARTITION ||    \
-        type == LINUX_EXTENDED_PARTITION)
-#define is_raid(type) \
-       (type == LINUX_RAID_PARTITION)
-static int probe_msdos_part_table(struct volume_id *id, __u64 off)
-{
-       struct msdos_partition_entry {
-               __u8    boot_ind;
-               __u8    head;
-               __u8    sector;
-               __u8    cyl;
-               __u8    sys_ind;
-               __u8    end_head;
-               __u8    end_sector;
-               __u8    end_cyl;
-               __u32   start_sect;
-               __u32   nr_sects;
-       } __attribute__((packed)) *part;
-
-       const __u8 *buf;
-       int i;
-       __u64 poff;
-       __u64 plen;
-       __u64 extended = 0;
-       __u64 current;
-       __u64 next;
-       int limit;
-       int empty = 1;
-       struct volume_id_partition *p;
-
-       buf = get_buffer(id, off, 0x200);
-       if (buf == NULL)
-               return -1;
-
-       if (strncmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
-               return -1;
-
-       /* check flags on all entries for a valid partition table */
-       part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
-       for (i = 0; i < 4; i++) {
-               if (part[i].boot_ind != 0 &&
-                   part[i].boot_ind != 0x80)
-                       return -1;
-
-               if (le32_to_cpu(part[i].nr_sects) != 0)
-                       empty = 0;
-       }
-       if (empty == 1)
-               return -1;
-
-       if (id->partitions != NULL)
-               free(id->partitions);
-       id->partitions = malloc(VOLUME_ID_PARTITIONS_MAX *
-                               sizeof(struct volume_id_partition));
-       if (id->partitions == NULL)
-               return -1;
-       memset(id->partitions, 0x00,
-              VOLUME_ID_PARTITIONS_MAX * sizeof(struct volume_id_partition));
-
-       for (i = 0; i < 4; i++) {
-               poff = (__u64) le32_to_cpu(part[i].start_sect) * BSIZE;
-               plen = (__u64) le32_to_cpu(part[i].nr_sects) * BSIZE;
-
-               if (plen == 0)
-                       continue;
-
-               p = &id->partitions[i];
-
-               p->partition_type_raw = part[i].sys_ind;
-
-               if (is_extended(part[i].sys_ind)) {
-                       dbg("found extended partition at 0x%llx", poff);
-                       p->usage_id = VOLUME_ID_PARTITIONTABLE;
-                       p->type_id = VOLUME_ID_MSDOSEXTENDED;
-                       p->type = "msdos_extended_partition";
-                       if (extended == 0)
-                               extended = off + poff;
-               } else {
-                       dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
-                           part[i].sys_ind, poff, plen);
-
-                       if (is_raid(part[i].sys_ind))
-                               p->usage_id = VOLUME_ID_RAID;
-                       else
-                               p->usage_id = VOLUME_ID_UNPROBED;
-               }
-
-               p->off = off + poff;
-               p->len = plen;
-               id->partition_count = i+1;
-       }
-
-       next = extended;
-       current = extended;
-       limit = 50;
-
-       /* follow extended partition chain and add data partitions */
-       while (next != 0) {
-               if (limit-- == 0) {
-                       dbg("extended chain limit reached");
-                       break;
-               }
-
-               buf = get_buffer(id, current, 0x200);
-               if (buf == NULL)
-                       break;
-
-               part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
-
-               if (strncmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
-                       break;
-
-               next = 0;
-
-               for (i = 0; i < 4; i++) {
-                       poff = (__u64) le32_to_cpu(part[i].start_sect) * BSIZE;
-                       plen = (__u64) le32_to_cpu(part[i].nr_sects) * BSIZE;
-
-                       if (plen == 0)
-                               continue;
-
-                       if (is_extended(part[i].sys_ind)) {
-                               dbg("found extended partition at 0x%llx", poff);
-                               if (next == 0)
-                                       next = extended + poff;
-                       } else {
-                               dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
-                                       part[i].sys_ind, poff, plen);
-
-                               /* we always start at the 5th entry */
-                               while (id->partition_count < 4)
-                                       id->partitions[id->partition_count++].usage_id =
-                                               VOLUME_ID_UNUSED;
-
-                               p = &id->partitions[id->partition_count];
-
-                               if (is_raid(part[i].sys_ind))
-                                       p->usage_id = VOLUME_ID_RAID;
-                               else
-                                       p->usage_id = VOLUME_ID_UNPROBED;
-
-                               p->off = current + poff;
-                               p->len = plen;
-                               id->partition_count++;
-
-                               p->partition_type_raw = part[i].sys_ind;
-
-                               if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
-                                       dbg("too many partitions");
-                                       next = 0;
-                               }
-                       }
-               }
-
-               current = next;
-       }
-
-       id->usage_id = VOLUME_ID_PARTITIONTABLE;
-       id->type_id = VOLUME_ID_MSDOSPARTTABLE;
-       id->type = "msdos_partition_table";
-
-       return 0;
-}
-
-#define EXT3_FEATURE_COMPAT_HAS_JOURNAL                0x00000004
-#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x00000008
-#define EXT_SUPERBLOCK_OFFSET                  0x400
-static int probe_ext(struct volume_id *id, __u64 off)
-{
-       struct ext2_super_block {
-               __u32   inodes_count;
-               __u32   blocks_count;
-               __u32   r_blocks_count;
-               __u32   free_blocks_count;
-               __u32   free_inodes_count;
-               __u32   first_data_block;
-               __u32   log_block_size;
-               __u32   dummy3[7];
-               __u8    magic[2];
-               __u16   state;
-               __u32   dummy5[8];
-               __u32   feature_compat;
-               __u32   feature_incompat;
-               __u32   feature_ro_compat;
-               __u8    uuid[16];
-               __u8    volume_name[16];
-       } __attribute__((__packed__)) *es;
-
-       es = (struct ext2_super_block *)
-            get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
-       if (es == NULL)
-               return -1;
-
-       if (es->magic[0] != 0123 ||
-           es->magic[1] != 0357)
-               return -1;
-
-       set_label_raw(id, es->volume_name, 16);
-       set_label_string(id, es->volume_name, 16);
-       set_uuid(id, es->uuid, UUID_DCE);
-
-       if ((le32_to_cpu(es->feature_compat) &
-            EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) {
-               id->usage_id = VOLUME_ID_FILESYSTEM;
-               id->type_id = VOLUME_ID_EXT3;
-               id->type = "ext3";
-       } else {
-               id->usage_id = VOLUME_ID_FILESYSTEM;
-               id->type_id = VOLUME_ID_EXT2;
-               id->type = "ext2";
-       }
-
-       return 0;
-}
-
-#define REISERFS1_SUPERBLOCK_OFFSET            0x2000
-#define REISERFS_SUPERBLOCK_OFFSET             0x10000
-static int probe_reiserfs(struct volume_id *id, __u64 off)
-{
-       struct reiserfs_super_block {
-               __u32   blocks_count;
-               __u32   free_blocks;
-               __u32   root_block;
-               __u32   journal_block;
-               __u32   journal_dev;
-               __u32   orig_journal_size;
-               __u32   dummy2[5];
-               __u16   blocksize;
-               __u16   dummy3[3];
-               __u8    magic[12];
-               __u32   dummy4[5];
-               __u8    uuid[16];
-               __u8    label[16];
-       } __attribute__((__packed__)) *rs;
-
-       rs = (struct reiserfs_super_block *)
-            get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
-       if (rs == NULL)
-               return -1;
-
-       if (strncmp(rs->magic, "ReIsEr2Fs", 9) == 0) {
-               strcpy(id->type_version, "3.6");
-               goto found;
-       }
-
-       if (strncmp(rs->magic, "ReIsEr3Fs", 9) == 0) {
-               strcpy(id->type_version, "JR");
-               goto found;
-       }
-
-       rs = (struct reiserfs_super_block *)
-            get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
-       if (rs == NULL)
-               return -1;
-
-       if (strncmp(rs->magic, "ReIsErFs", 8) == 0) {
-               strcpy(id->type_version, "3.5");
-               goto found;
-       }
-
-       return -1;
-
-found:
-       set_label_raw(id, rs->label, 16);
-       set_label_string(id, rs->label, 16);
-       set_uuid(id, rs->uuid, UUID_DCE);
-
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_REISERFS;
-       id->type = "reiserfs";
-
-       return 0;
-}
-
-static int probe_xfs(struct volume_id *id, __u64 off)
-{
-       struct xfs_super_block {
-               __u8    magic[4];
-               __u32   blocksize;
-               __u64   dblocks;
-               __u64   rblocks;
-               __u32   dummy1[2];
-               __u8    uuid[16];
-               __u32   dummy2[15];
-               __u8    fname[12];
-               __u32   dummy3[2];
-               __u64   icount;
-               __u64   ifree;
-               __u64   fdblocks;
-       } __attribute__((__packed__)) *xs;
-
-       xs = (struct xfs_super_block *) get_buffer(id, off, 0x200);
-       if (xs == NULL)
-               return -1;
-
-       if (strncmp(xs->magic, "XFSB", 4) != 0)
-               return -1;
-
-       set_label_raw(id, xs->fname, 12);
-       set_label_string(id, xs->fname, 12);
-       set_uuid(id, xs->uuid, UUID_DCE);
-
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_XFS;
-       id->type = "xfs";
-
-       return 0;
-}
-
-#define JFS_SUPERBLOCK_OFFSET                  0x8000
-static int probe_jfs(struct volume_id *id, __u64 off)
-{
-       struct jfs_super_block {
-               __u8    magic[4];
-               __u32   version;
-               __u64   size;
-               __u32   bsize;
-               __u32   dummy1;
-               __u32   pbsize;
-               __u32   dummy2[27];
-               __u8    uuid[16];
-               __u8    label[16];
-               __u8    loguuid[16];
-       } __attribute__((__packed__)) *js;
-
-       js = (struct jfs_super_block *)
-            get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
-       if (js == NULL)
-               return -1;
-
-       if (strncmp(js->magic, "JFS1", 4) != 0)
-               return -1;
-
-       set_label_raw(id, js->label, 16);
-       set_label_string(id, js->label, 16);
-       set_uuid(id, js->uuid, UUID_DCE);
-
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_JFS;
-       id->type = "jfs";
-
-       return 0;
-}
-
-#define FAT12_MAX                      0xff5
-#define FAT16_MAX                      0xfff5
-#define FAT_ATTR_VOLUME_ID             0x08
-#define FAT_ATTR_DIR                   0x10
-#define FAT_ATTR_LONG_NAME             0x0f
-#define FAT_ATTR_MASK                  0x3f
-#define FAT_ENTRY_FREE                 0xe5
-static int probe_vfat(struct volume_id *id, __u64 off)
-{
-       struct vfat_super_block {
-               __u8    boot_jump[3];
-               __u8    sysid[8];
-               __u16   sector_size;
-               __u8    sectors_per_cluster;
-               __u16   reserved;
-               __u8    fats;
-               __u16   dir_entries;
-               __u16   sectors;
-               __u8    media;
-               __u16   fat_length;
-               __u16   secs_track;
-               __u16   heads;
-               __u32   hidden;
-               __u32   total_sect;
-               union {
-                       struct fat_super_block {
-                               __u8    unknown[3];
-                               __u8    serno[4];
-                               __u8    label[11];
-                               __u8    magic[8];
-                               __u8    dummy2[192];
-                               __u8    pmagic[2];
-                       } __attribute__((__packed__)) fat;
-                       struct fat32_super_block {
-                               __u32   fat32_length;
-                               __u16   flags;
-                               __u8    version[2];
-                               __u32   root_cluster;
-                               __u16   insfo_sector;
-                               __u16   backup_boot;
-                               __u16   reserved2[6];
-                               __u8    unknown[3];
-                               __u8    serno[4];
-                               __u8    label[11];
-                               __u8    magic[8];
-                               __u8    dummy2[164];
-                               __u8    pmagic[2];
-                       } __attribute__((__packed__)) fat32;
-               } __attribute__((__packed__)) type;
-       } __attribute__((__packed__)) *vs;
-
-       struct vfat_dir_entry {
-               __u8    name[11];
-               __u8    attr;
-               __u16   time_creat;
-               __u16   date_creat;
-               __u16   time_acc;
-               __u16   date_acc;
-               __u16   cluster_high;
-               __u16   time_write;
-               __u16   date_write;
-               __u16   cluster_low;
-               __u32   size;
-       } __attribute__((__packed__)) *dir;
-
-       __u16 sector_size;
-       __u16 dir_entries;
-       __u32 sect_count;
-       __u16 reserved;
-       __u32 fat_size;
-       __u32 root_cluster;
-       __u32 dir_size;
-       __u32 cluster_count;
-       __u32 fat_length;
-       __u64 root_start;
-       __u32 start_data_sect;
-       __u16 root_dir_entries;
-       __u8 *buf;
-       __u32 buf_size;
-       __u8 *label = NULL;
-       __u32 next;
-       int maxloop;
-       int i;
-
-       vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
-       if (vs == NULL)
-               return -1;
-
-       /* believe only that's fat, don't trust the version
-        * the cluster_count will tell us
-        */
-       if (strncmp(vs->sysid, "NTFS", 4) == 0)
-               return -1;
-
-       if (strncmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
-               goto valid;
-
-       if (strncmp(vs->type.fat32.magic, "FAT32   ", 8) == 0)
-               goto valid;
-
-       if (strncmp(vs->type.fat.magic, "FAT16   ", 8) == 0)
-               goto valid;
-
-       if (strncmp(vs->type.fat.magic, "MSDOS", 5) == 0)
-               goto valid;
-
-       if (strncmp(vs->type.fat.magic, "FAT12   ", 8) == 0)
-               goto valid;
-
-       /*
-        * There are old floppies out there without a magic, so we check
-        * for well known values and guess if it's a fat volume
-        */
-
-       /* boot jump address check */
-       if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
-            vs->boot_jump[0] != 0xe9)
-               return -1;
-
-       /* heads check */
-       if (vs->heads == 0)
-               return -1;
-
-       /* cluster size check*/ 
-       if (vs->sectors_per_cluster == 0 ||
-           (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
-               return -1;
-
-       /* media check */
-       if (vs->media < 0xf8 && vs->media != 0xf0)
-               return -1;
-
-       /* fat count*/
-       if (vs->fats != 2)
-               return -1;
-
-valid:
-       /* sector size check */
-       sector_size = le16_to_cpu(vs->sector_size);
-       if (sector_size != 0x200 && sector_size != 0x400 &&
-           sector_size != 0x800 && sector_size != 0x1000)
-               return -1;
-
-       dbg("sector_size 0x%x", sector_size);
-       dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
-
-       dir_entries = le16_to_cpu(vs->dir_entries);
-       reserved = le16_to_cpu(vs->reserved);
-       dbg("reserved 0x%x", reserved);
-
-       sect_count = le16_to_cpu(vs->sectors);
-       if (sect_count == 0)
-               sect_count = le32_to_cpu(vs->total_sect);
-       dbg("sect_count 0x%x", sect_count);
-
-       fat_length = le16_to_cpu(vs->fat_length);
-       if (fat_length == 0)
-               fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
-       dbg("fat_length 0x%x", fat_length);
-
-       fat_size = fat_length * vs->fats;
-       dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
-                       (sector_size-1)) / sector_size;
-       dbg("dir_size 0x%x", dir_size);
-
-       cluster_count = sect_count - (reserved + fat_size + dir_size);
-       cluster_count /= vs->sectors_per_cluster;
-       dbg("cluster_count 0x%x", cluster_count);
-
-       if (cluster_count < FAT12_MAX) {
-               strcpy(id->type_version, "FAT12");
-       } else if (cluster_count < FAT16_MAX) {
-               strcpy(id->type_version, "FAT16");
-       } else {
-               strcpy(id->type_version, "FAT32");
-               goto fat32;
-       }
-
-       /* the label may be an attribute in the root directory */
-       root_start = (reserved + fat_size) * sector_size;
-       dbg("root dir start 0x%llx", root_start);
-       root_dir_entries = le16_to_cpu(vs->dir_entries);
-       dbg("expected entries 0x%x", root_dir_entries);
-
-       buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
-       buf = get_buffer(id, off + root_start, buf_size);
-       if (buf == NULL)
-               goto found;
-
-       dir = (struct vfat_dir_entry*) buf;
-
-       for (i = 0; i < root_dir_entries; i++) {
-               /* end marker */
-               if (dir[i].name[0] == 0x00) {
-                       dbg("end of dir");
-                       break;
-               }
-
-               /* empty entry */
-               if (dir[i].name[0] == FAT_ENTRY_FREE)
-                       continue;
-
-               /* long name */
-               if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
-                       continue;
-
-               if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
-                       /* labels do not have file data */
-                       if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
-                               continue;
-
-                       dbg("found ATTR_VOLUME_ID id in root dir");
-                       label = dir[i].name;
-                       break;
-               }
-
-               dbg("skip dir entry");
-       }
-
-       vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
-       if (vs == NULL)
-               return -1;
-
-       if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
-               set_label_raw(id, label, 11);
-               set_label_string(id, label, 11);
-       } else if (strncmp(vs->type.fat.label, "NO NAME    ", 11) != 0) {
-               set_label_raw(id, vs->type.fat.label, 11);
-               set_label_string(id, vs->type.fat.label, 11);
-       }
-       set_uuid(id, vs->type.fat.serno, UUID_DOS);
-       goto found;
-
-fat32:
-       /* FAT32 root dir is a cluster chain like any other directory */
-       buf_size = vs->sectors_per_cluster * sector_size;
-       root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
-       dbg("root dir cluster %u", root_cluster);
-       start_data_sect = reserved + fat_size;
-
-       next = root_cluster;
-       maxloop = 100;
-       while (--maxloop) {
-               __u32 next_sect_off;
-               __u64 next_off;
-               __u64 fat_entry_off;
-               int count;
-
-               dbg("next cluster %u", next);
-               next_sect_off = (next - 2) * vs->sectors_per_cluster;
-               next_off = (start_data_sect + next_sect_off) * sector_size;
-               dbg("cluster offset 0x%llx", next_off);
-
-               /* get cluster */
-               buf = get_buffer(id, off + next_off, buf_size);
-               if (buf == NULL)
-                       goto found;
-
-               dir = (struct vfat_dir_entry*) buf;
-               count = buf_size / sizeof(struct vfat_dir_entry);
-               dbg("expected entries 0x%x", count);
-
-               for (i = 0; i < count; i++) {
-                       /* end marker */
-                       if (dir[i].name[0] == 0x00) {
-                               dbg("end of dir");
-                               goto fat32_label;
-                       }
-
-                       /* empty entry */
-                       if (dir[i].name[0] == FAT_ENTRY_FREE)
-                               continue;
-
-                       /* long name */
-                       if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
-                               continue;
-
-                       if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
-                               /* labels do not have file data */
-                               if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
-                                       continue;
-
-                               dbg("found ATTR_VOLUME_ID id in root dir");
-                               label = dir[i].name;
-                               goto fat32_label;
-                       }
-
-                       dbg("skip dir entry");
-               }
-
-               /* get FAT entry */
-               fat_entry_off = (reserved * sector_size) + (next * sizeof(__u32));
-               buf = get_buffer(id, off + fat_entry_off, buf_size);
-               if (buf == NULL)
-                       goto found;
-
-               /* set next cluster */
-               next = le32_to_cpu(*((__u32 *) buf) & 0x0fffffff);
-               if (next == 0)
-                       break;
-       }
-       if (maxloop == 0)
-               dbg("reached maximum follow count of root cluster chain, give up");
-
-fat32_label:
-       vs = (struct vfat_super_block *) get_buffer(id, off, 0x200);
-       if (vs == NULL)
-               return -1;
-
-       if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
-               set_label_raw(id, label, 11);
-               set_label_string(id, label, 11);
-       } else if (strncmp(vs->type.fat32.label, "NO NAME    ", 11) != 0) {
-               set_label_raw(id, vs->type.fat32.label, 11);
-               set_label_string(id, vs->type.fat32.label, 11);
-       }
-       set_uuid(id, vs->type.fat32.serno, UUID_DOS);
-
-found:
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_VFAT;
-       id->type = "vfat";
-
-       return 0;
-}
-
-#define UDF_VSD_OFFSET                 0x8000
-static int probe_udf(struct volume_id *id, __u64 off)
-{
-       struct volume_descriptor {
-               struct descriptor_tag {
-                       __u16   id;
-                       __u16   version;
-                       __u8    checksum;
-                       __u8    reserved;
-                       __u16   serial;
-                       __u16   crc;
-                       __u16   crc_len;
-                       __u32   location;
-               } __attribute__((__packed__)) tag;
-               union {
-                       struct anchor_descriptor {
-                               __u32   length;
-                               __u32   location;
-                       } __attribute__((__packed__)) anchor;
-                       struct primary_descriptor {
-                               __u32   seq_num;
-                               __u32   desc_num;
-                               struct dstring {
-                                       __u8    clen;
-                                       __u8    c[31];
-                               } __attribute__((__packed__)) ident;
-                       } __attribute__((__packed__)) primary;
-               } __attribute__((__packed__)) type;
-       } __attribute__((__packed__)) *vd;
-
-       struct volume_structure_descriptor {
-               __u8    type;
-               __u8    id[5];
-               __u8    version;
-       } *vsd;
-
-       unsigned int bs;
-       unsigned int b;
-       unsigned int type;
-       unsigned int count;
-       unsigned int loc;
-       unsigned int clen;
-
-       vsd = (struct volume_structure_descriptor *)
-             get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
-       if (vsd == NULL)
-               return -1;
-
-       if (strncmp(vsd->id, "NSR02", 5) == 0)
-               goto blocksize;
-       if (strncmp(vsd->id, "NSR03", 5) == 0)
-               goto blocksize;
-       if (strncmp(vsd->id, "BEA01", 5) == 0)
-               goto blocksize;
-       if (strncmp(vsd->id, "BOOT2", 5) == 0)
-               goto blocksize;
-       if (strncmp(vsd->id, "CD001", 5) == 0)
-               goto blocksize;
-       if (strncmp(vsd->id, "CDW02", 5) == 0)
-               goto blocksize;
-       if (strncmp(vsd->id, "TEA03", 5) == 0)
-               goto blocksize;
-       return -1;
-
-blocksize:
-       /* search the next VSD to get the logical block size of the volume */
-       for (bs = 0x800; bs < 0x8000; bs += 0x800) {
-               vsd = (struct volume_structure_descriptor *)
-                     get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
-               if (vsd == NULL)
-                       return -1;
-               dbg("test for blocksize: 0x%x", bs);
-               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 *)
-                     get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
-               if (vsd == NULL)
-                       return -1;
-
-               dbg("vsd: %c%c%c%c%c",
-                   vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
-
-               if (vsd->id[0] == '\0')
-                       return -1;
-               if (strncmp(vsd->id, "NSR02", 5) == 0)
-                       goto anchor;
-               if (strncmp(vsd->id, "NSR03", 5) == 0)
-                       goto anchor;
-       }
-       return -1;
-
-anchor:
-       /* read anchor volume descriptor */
-       vd = (struct volume_descriptor *)
-               get_buffer(id, off + (256 * bs), 0x200);
-       if (vd == NULL)
-               return -1;
-
-       type = le16_to_cpu(vd->tag.id);
-       if (type != 2) /* TAG_ID_AVDP */
-               goto found;
-
-       /* get desriptor list address and block count */
-       count = le32_to_cpu(vd->type.anchor.length) / bs;
-       loc = le32_to_cpu(vd->type.anchor.location);
-       dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
-
-       /* pick the primary descriptor from the list */
-       for (b = 0; b < count; b++) {
-               vd = (struct volume_descriptor *)
-                    get_buffer(id, off + ((loc + b) * bs), 0x200);
-               if (vd == NULL)
-                       return -1;
-
-               type = le16_to_cpu(vd->tag.id);
-               dbg("descriptor type %i", type);
-
-               /* check validity */
-               if (type == 0)
-                       goto found;
-               if (le32_to_cpu(vd->tag.location) != loc + b)
-                       goto found;
-
-               if (type == 1) /* TAG_ID_PVD */
-                       goto pvd;
-       }
-       goto found;
-
-pvd:
-       set_label_raw(id, &(vd->type.primary.ident.clen), 32);
-
-       clen = vd->type.primary.ident.clen;
-       dbg("label string charsize=%i bit", clen);
-       if (clen == 8)
-               set_label_string(id, vd->type.primary.ident.c, 31);
-       else if (clen == 16)
-               set_label_unicode16(id, vd->type.primary.ident.c, BE,31);
-
-found:
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_UDF;
-       id->type = "udf";
-
-       return 0;
-}
-
-#define ISO_SUPERBLOCK_OFFSET          0x8000
-#define ISO_SECTOR_SIZE                        0x800
-#define ISO_VD_OFFSET                  (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
-#define ISO_VD_PRIMARY                 0x1
-#define ISO_VD_SUPPLEMENTARY           0x2
-#define ISO_VD_END                     0xff
-#define ISO_VD_MAX                     16
-static int probe_iso9660(struct volume_id *id, __u64 off)
-{
-       union iso_super_block {
-               struct iso_header {
-                       __u8    type;
-                       __u8    id[5];
-                       __u8    version;
-                       __u8    unused1;
-                       __u8            system_id[32];
-                       __u8            volume_id[32];
-               } __attribute__((__packed__)) iso;
-               struct hs_header {
-                       __u8    foo[8];
-                       __u8    type;
-                       __u8    id[4];
-                       __u8    version;
-               } __attribute__((__packed__)) hs;
-       } __attribute__((__packed__)) *is;
-
-       is = (union iso_super_block *)
-            get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
-       if (is == NULL)
-               return -1;
-
-       if (strncmp(is->iso.id, "CD001", 5) == 0) {
-               char root_label[VOLUME_ID_LABEL_SIZE+1];
-               int vd_offset;
-               int i;
-               int found_svd;
-
-               memset(root_label, 0, sizeof(root_label));
-               strncpy(root_label, is->iso.volume_id, sizeof(root_label)-1);
-
-               found_svd = 0;
-               vd_offset = ISO_VD_OFFSET;
-               for (i = 0; i < ISO_VD_MAX; i++) {
-                       is = (union iso_super_block *) 
-                            get_buffer (id, off + vd_offset, 0x200);
-                       if (is == NULL || is->iso.type == ISO_VD_END)
-                               break;
-                       if (is->iso.type == ISO_VD_SUPPLEMENTARY) {
-                               dbg("found ISO supplementary VD at offset 0x%llx", off + vd_offset);
-                               set_label_raw(id, is->iso.volume_id, 32);
-                               set_label_unicode16(id, is->iso.volume_id, BE, 32);
-                               found_svd = 1;
-                               break;
-                       }
-                       vd_offset += ISO_SECTOR_SIZE;
-               }
-
-               if (!found_svd ||
-                   (found_svd && !strncmp(root_label, id->label, 16)))
-               {
-                       set_label_raw(id, root_label, 32);
-                       set_label_string(id, root_label, 32);
-               }
-               goto found;
-       }
-       if (strncmp(is->hs.id, "CDROM", 5) == 0)
-               goto found;
-       return -1;
-
-found:
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_ISO9660;
-       id->type = "iso9660";
-
-       return 0;
-}
-
-#define UFS_MAGIC                      0x00011954
-#define UFS2_MAGIC                     0x19540119
-#define UFS_MAGIC_FEA                  0x00195612
-#define UFS_MAGIC_LFN                  0x00095014
-
-
-static int probe_ufs(struct volume_id *id, __u64 off)
-{
-       struct ufs_super_block {
-               __u32   fs_link;
-               __u32   fs_rlink;
-               __u32   fs_sblkno;
-               __u32   fs_cblkno;
-               __u32   fs_iblkno;
-               __u32   fs_dblkno;
-               __u32   fs_cgoffset;
-               __u32   fs_cgmask;
-               __u32   fs_time;
-               __u32   fs_size;
-               __u32   fs_dsize;
-               __u32   fs_ncg; 
-               __u32   fs_bsize;
-               __u32   fs_fsize;
-               __u32   fs_frag;
-               __u32   fs_minfree;
-               __u32   fs_rotdelay;
-               __u32   fs_rps; 
-               __u32   fs_bmask;
-               __u32   fs_fmask;
-               __u32   fs_bshift;
-               __u32   fs_fshift;
-               __u32   fs_maxcontig;
-               __u32   fs_maxbpg;
-               __u32   fs_fragshift;
-               __u32   fs_fsbtodb;
-               __u32   fs_sbsize;
-               __u32   fs_csmask;
-               __u32   fs_csshift;
-               __u32   fs_nindir;
-               __u32   fs_inopb;
-               __u32   fs_nspf;
-               __u32   fs_optim;
-               __u32   fs_npsect_state;
-               __u32   fs_interleave;
-               __u32   fs_trackskew;
-               __u32   fs_id[2];
-               __u32   fs_csaddr;
-               __u32   fs_cssize;
-               __u32   fs_cgsize;
-               __u32   fs_ntrak;
-               __u32   fs_nsect;
-               __u32   fs_spc; 
-               __u32   fs_ncyl;
-               __u32   fs_cpg;
-               __u32   fs_ipg;
-               __u32   fs_fpg;
-               struct ufs_csum {
-                       __u32   cs_ndir;
-                       __u32   cs_nbfree;
-                       __u32   cs_nifree;
-                       __u32   cs_nffree;
-               } __attribute__((__packed__)) fs_cstotal;
-               __s8    fs_fmod;
-               __s8    fs_clean;
-               __s8    fs_ronly;
-               __s8    fs_flags;
-               union {
-                       struct {
-                               __s8    fs_fsmnt[512];
-                               __u32   fs_cgrotor;
-                               __u32   fs_csp[31];
-                               __u32   fs_maxcluster;
-                               __u32   fs_cpc;
-                               __u16   fs_opostbl[16][8];
-                       } __attribute__((__packed__)) fs_u1;
-                       struct {
-                               __s8  fs_fsmnt[468];
-                               __u8   fs_volname[32];
-                               __u64  fs_swuid;
-                               __s32  fs_pad;
-                               __u32   fs_cgrotor;
-                               __u32   fs_ocsp[28];
-                               __u32   fs_contigdirs;
-                               __u32   fs_csp; 
-                               __u32   fs_maxcluster;
-                               __u32   fs_active;
-                               __s32   fs_old_cpc;
-                               __s32   fs_maxbsize;
-                               __s64   fs_sparecon64[17];
-                               __s64   fs_sblockloc;
-                               struct  ufs2_csum_total {
-                                       __u64   cs_ndir;
-                                       __u64   cs_nbfree;
-                                       __u64   cs_nifree;
-                                       __u64   cs_nffree;
-                                       __u64   cs_numclusters;
-                                       __u64   cs_spare[3];
-                               } __attribute__((__packed__)) fs_cstotal;
-                               struct  ufs_timeval {
-                                       __s32   tv_sec;
-                                       __s32   tv_usec;
-                               } __attribute__((__packed__)) fs_time;
-                               __s64    fs_size;
-                               __s64    fs_dsize;
-                               __u64    fs_csaddr;
-                               __s64    fs_pendingblocks;
-                               __s32    fs_pendinginodes;
-                       } __attribute__((__packed__)) fs_u2;
-               }  fs_u11;
-               union {
-                       struct {
-                               __s32   fs_sparecon[53];
-                               __s32   fs_reclaim;
-                               __s32   fs_sparecon2[1];
-                               __s32   fs_state;
-                               __u32   fs_qbmask[2];
-                               __u32   fs_qfmask[2];
-                       } __attribute__((__packed__)) fs_sun;
-                       struct {
-                               __s32   fs_sparecon[53];
-                               __s32   fs_reclaim;
-                               __s32   fs_sparecon2[1];
-                               __u32   fs_npsect;
-                               __u32   fs_qbmask[2];
-                               __u32   fs_qfmask[2];
-                       } __attribute__((__packed__)) fs_sunx86;
-                       struct {
-                               __s32   fs_sparecon[50];
-                               __s32   fs_contigsumsize;
-                               __s32   fs_maxsymlinklen;
-                               __s32   fs_inodefmt;
-                               __u32   fs_maxfilesize[2];
-                               __u32   fs_qbmask[2];
-                               __u32   fs_qfmask[2];
-                               __s32   fs_state;
-                       } __attribute__((__packed__)) fs_44;
-               } fs_u2;
-               __s32   fs_postblformat;
-               __s32   fs_nrpos;
-               __s32   fs_postbloff;
-               __s32   fs_rotbloff;
-               __u32   fs_magic;
-               __u8    fs_space[1];
-       } __attribute__((__packed__)) *ufs;
-
-       __u32   magic;
-       int     i;
-       int     offsets[] = {0, 8, 64, 256, -1};
-
-       for (i = 0; offsets[i] >= 0; i++) {     
-               ufs = (struct ufs_super_block *)
-                       get_buffer(id, off + (offsets[i] * 0x400), 0x800);
-               if (ufs == NULL)
-                       return -1;
-
-               dbg("offset 0x%x", offsets[i] * 0x400);
-               magic = be32_to_cpu(ufs->fs_magic);
-               if ((magic == UFS_MAGIC) ||
-                   (magic == UFS2_MAGIC) ||
-                   (magic == UFS_MAGIC_FEA) ||
-                   (magic == UFS_MAGIC_LFN)) {
-                       dbg("magic 0x%08x(be)", magic);
-                       goto found;
-               }
-               magic = le32_to_cpu(ufs->fs_magic);
-               if ((magic == UFS_MAGIC) ||
-                   (magic == UFS2_MAGIC) ||
-                   (magic == UFS_MAGIC_FEA) ||
-                   (magic == UFS_MAGIC_LFN)) {
-                       dbg("magic 0x%08x(le)", magic);
-                       goto found;
-               }
-       }
-       return -1;
-
-found:
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_UFS;
-       id->type = "ufs";
-
-       return 0;
-}
-
-static int probe_mac_partition_map(struct volume_id *id, __u64 off)
-{
-       struct mac_driver_desc {
-               __u8    signature[2];
-               __u16   block_size;
-               __u32   block_count;
-       } __attribute__((__packed__)) *driver;
-
-       struct mac_partition {
-               __u8    signature[2];
-               __u16   res1;
-               __u32   map_count;
-               __u32   start_block;
-               __u32   block_count;
-               __u8    name[32];
-               __u8    type[32];
-       } __attribute__((__packed__)) *part;
-
-       const __u8 *buf;
-
-       buf = get_buffer(id, off, 0x200);
-       if (buf == NULL)
-               return -1;
-
-       part = (struct mac_partition *) buf;
-       if ((strncmp(part->signature, "PM", 2) == 0) &&
-           (strncmp(part->type, "Apple_partition_map", 19) == 0)) {
-               /* linux creates an own subdevice for the map
-                * just return the type if the drive header is missing */
-               id->usage_id = VOLUME_ID_PARTITIONTABLE;
-               id->type_id = VOLUME_ID_MACPARTMAP;
-               id->type = "mac_partition_map";
-               return 0;
-       }
-
-       driver = (struct mac_driver_desc *) buf;
-       if (strncmp(driver->signature, "ER", 2) == 0) {
-               /* we are on a main device, like a CD
-                * just try to probe the first partition from the map */
-               unsigned int bsize = be16_to_cpu(driver->block_size);
-               int part_count;
-               int i;
-
-               /* get first entry of partition table */
-               buf = get_buffer(id, off +  bsize, 0x200);
-               if (buf == NULL)
-                       return -1;
-
-               part = (struct mac_partition *) buf;
-               if (strncmp(part->signature, "PM", 2) != 0)
-                       return -1;
-
-               part_count = be32_to_cpu(part->map_count);
-               dbg("expecting %d partition entries", part_count);
-
-               if (id->partitions != NULL)
-                       free(id->partitions);
-               id->partitions =
-                       malloc(part_count * sizeof(struct volume_id_partition));
-               if (id->partitions == NULL)
-                       return -1;
-               memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
-
-               id->partition_count = part_count;
-
-               for (i = 0; i < part_count; i++) {
-                       __u64 poff;
-                       __u64 plen;
-
-                       buf = get_buffer(id, off + ((i+1) * bsize), 0x200);
-                       if (buf == NULL)
-                               return -1;
-
-                       part = (struct mac_partition *) buf;
-                       if (strncmp(part->signature, "PM", 2) != 0)
-                               return -1;
-
-                       poff = be32_to_cpu(part->start_block) * bsize;
-                       plen = be32_to_cpu(part->block_count) * bsize;
-                       dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
-                           part->type, poff, plen);
-
-                       id->partitions[i].off = poff;
-                       id->partitions[i].len = plen;
-
-                       if (strncmp(part->type, "Apple_Free", 10) == 0) {
-                               id->partitions[i].usage_id = VOLUME_ID_UNUSED;
-                       } else if (strncmp(part->type, "Apple_partition_map", 19) == 0) {
-                               id->partitions[i].usage_id = VOLUME_ID_PARTITIONTABLE;
-                               id->partitions[i].type_id = VOLUME_ID_MACPARTMAP;
-                       } else {
-                               id->partitions[i].usage_id = VOLUME_ID_UNPROBED;
-                       }
-               }
-               id->usage_id = VOLUME_ID_PARTITIONTABLE;
-               id->type_id = VOLUME_ID_MACPARTMAP;
-               id->type = "mac_partition_map";
-               return 0;
-       }
-
-       return -1;
-}
-
-#define HFS_SUPERBLOCK_OFFSET          0x400
-#define HFS_NODE_LEAF                  0xff
-#define HFSPLUS_POR_CNID               1
-#define HFSPLUS_EXTENT_COUNT           8
-static int probe_hfs_hfsplus(struct volume_id *id, __u64 off)
-{
-       struct hfs_finder_info{
-               __u32   boot_folder;
-               __u32   start_app;
-               __u32   open_folder;
-               __u32   os9_folder;
-               __u32   reserved;
-               __u32   osx_folder;
-               __u8    id[8];
-       } __attribute__((__packed__));
-
-       struct hfs_mdb {
-               __u8    signature[2];
-               __u32   cr_date;
-               __u32   ls_Mod;
-               __u16   atrb;
-               __u16   nm_fls;
-               __u16   vbm_st;
-               __u16   alloc_ptr;
-               __u16   nm_al_blks;
-               __u32   al_blk_size;
-               __u32   clp_size;
-               __u16   al_bl_st;
-               __u32   nxt_cnid;
-               __u16   free_bks;
-               __u8    label_len;
-               __u8    label[27];
-               __u32   vol_bkup;
-               __u16   vol_seq_num;
-               __u32   wr_cnt;
-               __u32   xt_clump_size;
-               __u32   ct_clump_size;
-               __u16   num_root_dirs;
-               __u32   file_count;
-               __u32   dir_count;
-               struct hfs_finder_info finder_info;
-               __u8    embed_sig[2];
-               __u16   embed_startblock;
-               __u16   embed_blockcount;
-       } __attribute__((__packed__)) *hfs;
-
-       struct hfsplus_bnode_descriptor {
-               __u32   next;
-               __u32   prev;
-               __u8    type;
-               __u8    height;
-               __u16   num_recs;
-               __u16   reserved;
-       } __attribute__((__packed__));
-
-       struct hfsplus_bheader_record {
-               __u16   depth;
-               __u32   root;
-               __u32   leaf_count;
-               __u32   leaf_head;
-               __u32   leaf_tail;
-               __u16   node_size;
-       } __attribute__((__packed__));
-
-       struct hfsplus_catalog_key {
-               __u16   key_len;
-               __u32   parent_id;
-               __u16   unicode_len;
-               __u8    unicode[255 * 2];
-       } __attribute__((__packed__));
-
-       struct hfsplus_extent {
-               __u32 start_block;
-               __u32 block_count;
-       } __attribute__((__packed__));
-
-       struct hfsplus_fork {
-               __u64 total_size;
-               __u32 clump_size;
-               __u32 total_blocks;
-               struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
-       } __attribute__((__packed__));
-
-       struct hfsplus_vol_header {
-               __u8    signature[2];
-               __u16   version;
-               __u32   attributes;
-               __u32   last_mount_vers;
-               __u32   reserved;
-               __u32   create_date;
-               __u32   modify_date;
-               __u32   backup_date;
-               __u32   checked_date;
-               __u32   file_count;
-               __u32   folder_count;
-               __u32   blocksize;
-               __u32   total_blocks;
-               __u32   free_blocks;
-               __u32   next_alloc;
-               __u32   rsrc_clump_sz;
-               __u32   data_clump_sz;
-               __u32   next_cnid;
-               __u32   write_count;
-               __u64   encodings_bmp;
-               struct hfs_finder_info finder_info;
-               struct hfsplus_fork alloc_file;
-               struct hfsplus_fork ext_file;
-               struct hfsplus_fork cat_file;
-               struct hfsplus_fork attr_file;
-               struct hfsplus_fork start_file;
-       } __attribute__((__packed__)) *hfsplus;
-
-       unsigned int blocksize;
-       unsigned int cat_block;
-       unsigned int ext_block_start;
-       unsigned int ext_block_count;
-       int ext;
-       unsigned int leaf_node_head;
-       unsigned int leaf_node_count;
-       unsigned int leaf_node_size;
-       unsigned int leaf_block;
-       __u64 leaf_off;
-       unsigned int alloc_block_size;
-       unsigned int alloc_first_block;
-       unsigned int embed_first_block;
-       unsigned int record_count;
-       struct hfsplus_bnode_descriptor *descr;
-       struct hfsplus_bheader_record *bnode;
-       struct hfsplus_catalog_key *key;
-       unsigned int    label_len;
-       struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
-       const __u8 *buf;
-
-       buf = get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
-       if (buf == NULL)
-                return -1;
-
-       hfs = (struct hfs_mdb *) buf;
-       if (strncmp(hfs->signature, "BD", 2) != 0)
-               goto checkplus;
-
-       /* it may be just a hfs wrapper for hfs+ */
-       if (strncmp(hfs->embed_sig, "H+", 2) == 0) {
-               alloc_block_size = be32_to_cpu(hfs->al_blk_size);
-               dbg("alloc_block_size 0x%x", alloc_block_size);
-
-               alloc_first_block = be16_to_cpu(hfs->al_bl_st);
-               dbg("alloc_first_block 0x%x", alloc_first_block);
-
-               embed_first_block = be16_to_cpu(hfs->embed_startblock);
-               dbg("embed_first_block 0x%x", embed_first_block);
-
-               off += (alloc_first_block * 512) +
-                      (embed_first_block * alloc_block_size);
-               dbg("hfs wrapped hfs+ found at offset 0x%llx", off);
-
-               buf = get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
-               if (buf == NULL)
-                       return -1;
-               goto checkplus;
-       }
-
-       if (hfs->label_len > 0 && hfs->label_len < 28) {
-               set_label_raw(id, hfs->label, hfs->label_len);
-               set_label_string(id, hfs->label, hfs->label_len) ;
-       }
-
-       set_uuid(id, hfs->finder_info.id, UUID_HFS);
-
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_HFS;
-       id->type = "hfs";
-
-       return 0;
-
-checkplus:
-       hfsplus = (struct hfsplus_vol_header *) buf;
-       if (strncmp(hfsplus->signature, "H+", 2) == 0)
-               goto hfsplus;
-       if (strncmp(hfsplus->signature, "HX", 2) == 0)
-               goto hfsplus;
-       return -1;
-
-hfsplus:
-       set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
-
-       blocksize = be32_to_cpu(hfsplus->blocksize);
-       dbg("blocksize %u", blocksize);
-
-       memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
-       cat_block = be32_to_cpu(extents[0].start_block);
-       dbg("catalog start block 0x%x", cat_block);
-
-       buf = get_buffer(id, off + (cat_block * blocksize), 0x2000);
-       if (buf == NULL)
-               goto found;
-
-       bnode = (struct hfsplus_bheader_record *)
-               &buf[sizeof(struct hfsplus_bnode_descriptor)];
-
-       leaf_node_head = be32_to_cpu(bnode->leaf_head);
-       dbg("catalog leaf node 0x%x", leaf_node_head);
-
-       leaf_node_size = be16_to_cpu(bnode->node_size);
-       dbg("leaf node size 0x%x", leaf_node_size);
-
-       leaf_node_count = be32_to_cpu(bnode->leaf_count);
-       dbg("leaf node count 0x%x", leaf_node_count);
-       if (leaf_node_count == 0)
-               goto found;
-
-       leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
-
-       /* get physical location */
-       for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
-               ext_block_start = be32_to_cpu(extents[ext].start_block);
-               ext_block_count = be32_to_cpu(extents[ext].block_count);
-               dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
-
-               if (ext_block_count == 0)
-                       goto found;
-
-               /* this is our extent */
-               if (leaf_block < ext_block_count)
-                       break;
-
-               leaf_block -= ext_block_count;
-       }
-       if (ext == HFSPLUS_EXTENT_COUNT)
-               goto found;
-       dbg("found block in extent %i", ext);
-
-       leaf_off = (ext_block_start + leaf_block) * blocksize;
-
-       buf = get_buffer(id, off + leaf_off, leaf_node_size);
-       if (buf == NULL)
-               goto found;
-
-       descr = (struct hfsplus_bnode_descriptor *) buf;
-       dbg("descriptor type 0x%x", descr->type);
-
-       record_count = be16_to_cpu(descr->num_recs);
-       dbg("number of records %u", record_count);
-       if (record_count == 0)
-               goto found;
-
-       if (descr->type != HFS_NODE_LEAF)
-               goto found;
-
-       key = (struct hfsplus_catalog_key *)
-               &buf[sizeof(struct hfsplus_bnode_descriptor)];
-
-       dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
-       if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
-               goto found;
-
-       label_len = be16_to_cpu(key->unicode_len) * 2;
-       dbg("label unicode16 len %i", label_len);
-       set_label_raw(id, key->unicode, label_len);
-       set_label_unicode16(id, key->unicode, BE, label_len);
-
-found:
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_HFSPLUS;
-       id->type = "hfsplus";
-
-       return 0;
-}
-
-#define MFT_RECORD_VOLUME                      3
-#define MFT_RECORD_ATTR_VOLUME_NAME            0x60
-#define MFT_RECORD_ATTR_VOLUME_INFO            0x70
-#define MFT_RECORD_ATTR_OBJECT_ID              0x40
-#define MFT_RECORD_ATTR_END                    0xffffffffu
-static int probe_ntfs(struct volume_id *id, __u64 off)
-{
-       struct ntfs_super_block {
-               __u8    jump[3];
-               __u8    oem_id[8];
-               __u16   bytes_per_sector;
-               __u8    sectors_per_cluster;
-               __u16   reserved_sectors;
-               __u8    fats;
-               __u16   root_entries;
-               __u16   sectors;
-               __u8    media_type;
-               __u16   sectors_per_fat;
-               __u16   sectors_per_track;
-               __u16   heads;
-               __u32   hidden_sectors;
-               __u32   large_sectors;
-               __u16   unused[2];
-               __u64   number_of_sectors;
-               __u64   mft_cluster_location;
-               __u64   mft_mirror_cluster_location;
-               __s8    cluster_per_mft_record;
-               __u8    reserved1[3];
-               __s8    cluster_per_index_record;
-               __u8    reserved2[3];
-               __u8    volume_serial[8];
-               __u16   checksum;
-       } __attribute__((__packed__)) *ns;
-
-       struct master_file_table_record {
-               __u8    magic[4];
-               __u16   usa_ofs;
-               __u16   usa_count;
-               __u64   lsn;
-               __u16   sequence_number;
-               __u16   link_count;
-               __u16   attrs_offset;
-               __u16   flags;
-               __u32   bytes_in_use;
-               __u32   bytes_allocated;
-       } __attribute__((__packed__)) *mftr;
-
-       struct file_attribute {
-               __u32   type;
-               __u32   len;
-               __u8    non_resident;
-               __u8    name_len;
-               __u16   name_offset;
-               __u16   flags;
-               __u16   instance;
-               __u32   value_len;
-               __u16   value_offset;
-       } __attribute__((__packed__)) *attr;
-
-       struct volume_info {
-               __u64 reserved;
-               __u8 major_ver;
-               __u8 minor_ver;
-       } __attribute__((__packed__)) *info;
-
-       unsigned int sector_size;
-       unsigned int cluster_size;
-       __u64 mft_cluster;
-       __u64 mft_off;
-       unsigned int mft_record_size;
-       unsigned int attr_type;
-       unsigned int attr_off;
-       unsigned int attr_len;
-       unsigned int val_off;
-       unsigned int val_len;
-       const __u8 *buf;
-       const __u8 *val;
-
-       ns = (struct ntfs_super_block *) get_buffer(id, off, 0x200);
-       if (ns == NULL)
-               return -1;
-
-       if (strncmp(ns->oem_id, "NTFS", 4) != 0)
-               return -1;
-
-       set_uuid(id, ns->volume_serial, UUID_NTFS);
-
-       sector_size = le16_to_cpu(ns->bytes_per_sector);
-       cluster_size = ns->sectors_per_cluster * sector_size;
-       mft_cluster = le64_to_cpu(ns->mft_cluster_location);
-       mft_off = mft_cluster * cluster_size;
-
-       if (ns->cluster_per_mft_record < 0)
-               /* size = -log2(mft_record_size); normally 1024 Bytes */
-               mft_record_size = 1 << -ns->cluster_per_mft_record;
-       else
-               mft_record_size = ns->cluster_per_mft_record * cluster_size;
-
-       dbg("sectorsize  0x%x", sector_size);
-       dbg("clustersize 0x%x", cluster_size);
-       dbg("mftcluster  %lli", mft_cluster);
-       dbg("mftoffset  0x%llx", mft_off);
-       dbg("cluster per mft_record  %i", ns->cluster_per_mft_record);
-       dbg("mft record size  %i", mft_record_size);
-
-       buf = get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
-                        mft_record_size);
-       if (buf == NULL)
-               goto found;
-
-       mftr = (struct master_file_table_record*) buf;
-
-       dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
-       if (strncmp(mftr->magic, "FILE", 4) != 0)
-               goto found;
-
-       attr_off = le16_to_cpu(mftr->attrs_offset);
-       dbg("file $Volume's attributes are at offset %i", attr_off);
-
-       while (1) {
-               attr = (struct file_attribute*) &buf[attr_off];
-               attr_type = le32_to_cpu(attr->type);
-               attr_len = le16_to_cpu(attr->len);
-               val_off = le16_to_cpu(attr->value_offset);
-               val_len = le32_to_cpu(attr->value_len);
-               attr_off += attr_len;
-
-               if (attr_len == 0)
-                       break;
-
-               if (attr_off >= mft_record_size)
-                       break;
-
-               if (attr_type == MFT_RECORD_ATTR_END)
-                       break;
-
-               dbg("found attribute type 0x%x, len %i, at offset %i",
-                   attr_type, attr_len, attr_off);
-
-               if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
-                       dbg("found info, len %i", val_len);
-                       info = (struct volume_info*) (((__u8 *) attr) + val_off);
-                       snprintf(id->type_version, VOLUME_ID_FORMAT_SIZE-1,
-                                "%u.%u", info->major_ver, info->minor_ver);
-               }
-
-               if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
-                       dbg("found label, len %i", val_len);
-                       if (val_len > VOLUME_ID_LABEL_SIZE)
-                               val_len = VOLUME_ID_LABEL_SIZE;
-
-                       val = ((__u8 *) attr) + val_off;
-                       set_label_raw(id, val, val_len);
-                       set_label_unicode16(id, val, LE, val_len);
-               }
-       }
-
-found:
-       id->usage_id = VOLUME_ID_FILESYSTEM;
-       id->type_id = VOLUME_ID_NTFS;
-       id->type = "ntfs";
-
-       return 0;
-}
-
-#define LARGEST_PAGESIZE                       0x4000
-static int probe_swap(struct volume_id *id, __u64 off)
-{
-       struct swap_header_v1_2 {
-               __u8    bootbits[1024];
-               __u32   version;
-               __u32   last_page;
-               __u32   nr_badpages;
-               __u8    uuid[16];
-               __u8    volume_name[16];
-       } __attribute__((__packed__)) *sw;
-
-       const __u8 *buf;
-       unsigned int page;
-
-       /* the swap signature is at the end of the PAGE_SIZE */
-       for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
-                       buf = get_buffer(id, off + page-10, 10);
-                       if (buf == NULL)
-                               return -1;
-
-                       if (strncmp(buf, "SWAP-SPACE", 10) == 0) {
-                               strcpy(id->type_version, "1");
-                               goto found;
-                       }
-
-                       if (strncmp(buf, "SWAPSPACE2", 10) == 0) {
-                               sw = (struct swap_header_v1_2 *) get_buffer(id, off, sizeof(struct swap_header_v1_2));
-                               if (sw == NULL)
-                                       return -1;
-                               strcpy(id->type_version, "2");
-                               set_label_raw(id, sw->volume_name, 16);
-                               set_label_string(id, sw->volume_name, 16);
-                               set_uuid(id, sw->uuid, UUID_DCE);
-                               goto found;
-                       }
-       }
-       return -1;
-
-found:
-       id->usage_id = VOLUME_ID_OTHER;
-       id->type_id = VOLUME_ID_SWAP;
-       id->type = "swap";
-
-       return 0;
-}
-
-/* probe volume for filesystem type and try to read label+uuid */
-int volume_id_probe(struct volume_id *id,
-                   enum volume_id_type type,
-                   unsigned long long off,
-                   unsigned long long size)
-{
-       int rc;
-
-       dbg("called with size=0x%llx", size);
-
-       if (id == NULL)
-               return -EINVAL;
-
-       switch (type) {
-       case VOLUME_ID_MSDOSPARTTABLE:
-               rc = probe_msdos_part_table(id, off);
-               break;
-       case VOLUME_ID_EXT3:
-       case VOLUME_ID_EXT2:
-               rc = probe_ext(id, off);
-               break;
-       case VOLUME_ID_REISERFS:
-               rc = probe_reiserfs(id, off);
-               break;
-       case VOLUME_ID_XFS:
-               rc = probe_xfs(id, off);
-               break;
-       case VOLUME_ID_JFS:
-               rc = probe_jfs(id, off);
-               break;
-       case VOLUME_ID_VFAT:
-               rc = probe_vfat(id, off);
-               break;
-       case VOLUME_ID_UDF:
-               rc = probe_udf(id, off);
-               break;
-       case VOLUME_ID_ISO9660:
-               rc = probe_iso9660(id, off);
-               break;
-       case VOLUME_ID_MACPARTMAP:
-               rc = probe_mac_partition_map(id, off);
-               break;
-       case VOLUME_ID_HFS:
-       case VOLUME_ID_HFSPLUS:
-               rc = probe_hfs_hfsplus(id, off);
-               break;
-       case VOLUME_ID_UFS:
-               rc = probe_ufs(id, off);
-               break;
-       case VOLUME_ID_NTFS:
-               rc = probe_ntfs(id, off);
-               break;
-       case VOLUME_ID_SWAP:
-               rc = probe_swap(id, off);
-               break;
-       case VOLUME_ID_LINUX_RAID:
-               rc = probe_linux_raid(id, off, size);
-               break;
-       case VOLUME_ID_LVM1:
-               rc = probe_lvm1(id, off);
-               break;
-       case VOLUME_ID_LVM2:
-               rc = probe_lvm2(id, off);
-               break;
-       case VOLUME_ID_HPTRAID:
-               rc = probe_highpoint_ataraid(id, off);
-               break;
-       case VOLUME_ID_ALL:
-       default:
-               /* probe for raid first, cause fs probes may be successful on raid members */
-               rc = probe_linux_raid(id, off, size);
-               if (rc == 0)
-                       break;
-               rc = probe_lvm1(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_lvm2(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_highpoint_ataraid(id, off);
-               if (rc == 0)
-                       break;
-
-               /* signature in the first block, only small buffer needed */
-               rc = probe_vfat(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_mac_partition_map(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_xfs(id, off);
-               if (rc == 0)
-                       break;
-
-               /* fill buffer with maximum */
-               get_buffer(id, 0, SB_BUFFER_SIZE);
-
-               rc = probe_swap(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_ext(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_reiserfs(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_jfs(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_udf(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_iso9660(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_hfs_hfsplus(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_ufs(id, off);
-               if (rc == 0)
-                       break;
-               rc = probe_ntfs(id, off);
-               if (rc == 0)
-                       break;
-
-               rc = -1;
-       }
-
-       /* If the filestystem in recognized, we free the allocated buffers,
-          otherwise they will stay in place for the possible next probe call */
-       if (rc == 0)
-               free_buffer(id);
-
-       return rc;
-}
-
-/* open volume by already open file descriptor */
-struct volume_id *volume_id_open_fd(int fd)
-{
-       struct volume_id *id;
-
-       id = malloc(sizeof(struct volume_id));
-       if (id == NULL)
-               return NULL;
-       memset(id, 0x00, sizeof(struct volume_id));
-
-       id->fd = fd;
-
-       return id;
-}
-
-/* open volume by device node */
-struct volume_id *volume_id_open_node(const char *path)
-{
-       struct volume_id *id;
-       int fd;
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0) {
-               dbg("unable to open '%s'", path);
-               return NULL;
-       }
-
-       id = volume_id_open_fd(fd);
-       if (id == NULL)
-               return NULL;
-
-       /* close fd on device close */
-       id->fd_close = 1;
-
-       return id;
-}
-
-/* open volume by major/minor */
-struct volume_id *volume_id_open_dev_t(dev_t devt)
-{
-       struct volume_id *id;
-       __u8 tmp_node[VOLUME_ID_PATH_MAX];
-
-       snprintf(tmp_node, VOLUME_ID_PATH_MAX,
-                "/tmp/volume-%u-%u-%u", getpid(), major(devt), minor(devt));
-       tmp_node[VOLUME_ID_PATH_MAX] = '\0';
-
-       /* create tempory node to open the block device */
-       unlink(tmp_node);
-       if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
-               return NULL;
-
-       id = volume_id_open_node(tmp_node);
-
-       unlink(tmp_node);
-
-       return id;
-}
-
-/* free allocated volume info */
-void volume_id_close(struct volume_id *id)
-{
-       if (id == NULL)
-               return;
-
-       if (id->fd_close != 0)
-               close(id->fd);
-
-       free_buffer(id);
-
-       if (id->partitions != NULL)
-               free(id->partitions);
-
-       free(id);
-}
similarity index 88%
rename from extras/volume_id/dasdlabel.c
rename to extras/volume_id/volume_id/dasd/dasd.c
index cbbe88179d4467e55adee534dd5a85ca7df788dd..6f045fe32693b99f7b14f74b8284219f23f68247 100644 (file)
  *
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <asm/types.h>
 
-#include "dasdlabel.h"
+#include "../volume_id.h"
+#include "../util.h"
+#include "dasd.h"
 
 static unsigned char EBCtoASC[256] =
 {
@@ -100,7 +110,7 @@ static unsigned char EBCtoASC[256] =
        0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
 };
 
-static void vtoc_ebcdic_dec (unsigned char *source, unsigned char *target, int l) 
+static void vtoc_ebcdic_dec (const unsigned char *source, unsigned char *target, int l) 
 {
        int i;
 
@@ -150,29 +160,35 @@ typedef struct dasd_information_t {
 #define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,dasd_information_t)
 #define BLKSSZGET _IO(0x12,104)
 
-int probe_ibm_partition(int fd, char *out)
+int probe_ibm_partition(struct volume_id *id)
 {
        int blocksize;
        dasd_information_t info;
-       char name[7] = {0,};
-       unsigned char data[16];
+       __u8 *data;
+       __u8 *label_raw;
+       unsigned char name[7];
 
-       if (ioctl(fd, BIODASDINFO, (unsigned long)&info) != 0)
+       if (ioctl(id->fd, BIODASDINFO, &info) != 0)
                return -1;
 
-       if (ioctl(fd, BLKSSZGET, (unsigned long)&blocksize))
+       if (ioctl(id->fd, BLKSSZGET, &blocksize) != 0)
                return -1;
 
-       lseek(fd, info.label_block * blocksize, SEEK_SET);
-       if (read(fd, &data, 16) != 16)
+       data = volume_id_get_buffer(id, info.label_block * blocksize, 16);
+       if (data == NULL)
                return -1;
 
        if ((!info.FBA_layout) && (!strcmp(info.type, "ECKD")))
-               strncpy(name, data + 8, 6);
+               label_raw = &data[8];
        else
-               strncpy(name, data + 4, 6);
-
-       vtoc_ebcdic_dec(name, out, 6);
+               label_raw = &data[4];
+
+       name[6] = '\0';
+       volume_id_set_usage(id, VOLUME_ID_DISKLABEL);
+       id->type = "dasd";
+       volume_id_set_label_raw(id, label_raw, 6);
+       vtoc_ebcdic_dec(label_raw, name, 6);
+       volume_id_set_label_string(id, name, 6);
 
        return 0;
 }
similarity index 87%
rename from extras/volume_id/dasdlabel.h
rename to extras/volume_id/volume_id/dasd/dasd.h
index 1501d3ff890a9f2bd248a8c0bb46a5a0e48ff044..eba73f1af003ef91457a7f42f2dc242d734a695a 100644 (file)
@@ -18,9 +18,9 @@
  *
  */
 
-#ifndef _DASDLABEL_H_
-#define _DASDLABEL_H_
+#ifndef _VOLUME_ID_DASDLABEL_
+#define _VOLUME_ID_DASDLABEL_
 
-extern int probe_ibm_partition(int fd, char *out);
+extern int probe_ibm_partition(struct volume_id *id);
 
 #endif
diff --git a/extras/volume_id/volume_id/ext/ext.c b/extras/volume_id/volume_id/ext/ext.c
new file mode 100644 (file)
index 0000000..50ffa85
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../util.h"
+#include "../logging.h"
+#include "ext.h"
+
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL                0x00000004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV      0x00000008
+#define EXT_SUPERBLOCK_OFFSET                  0x400
+
+int volume_id_probe_ext(struct volume_id *id, __u64 off)
+{
+       struct ext2_super_block {
+               __u32   inodes_count;
+               __u32   blocks_count;
+               __u32   r_blocks_count;
+               __u32   free_blocks_count;
+               __u32   free_inodes_count;
+               __u32   first_data_block;
+               __u32   log_block_size;
+               __u32   dummy3[7];
+               __u8    magic[2];
+               __u16   state;
+               __u32   dummy5[8];
+               __u32   feature_compat;
+               __u32   feature_incompat;
+               __u32   feature_ro_compat;
+               __u8    uuid[16];
+               __u8    volume_name[16];
+       } __attribute__((__packed__)) *es;
+
+       es = (struct ext2_super_block *) volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
+       if (es == NULL)
+               return -1;
+
+       if (es->magic[0] != 0123 ||
+           es->magic[1] != 0357)
+               return -1;
+
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       volume_id_set_label_raw(id, es->volume_name, 16);
+       volume_id_set_label_string(id, es->volume_name, 16);
+       volume_id_set_uuid(id, es->uuid, UUID_DCE);
+
+       if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0)
+               id->type = "ext3";
+       else
+               id->type = "ext2";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/ext/ext.h b/extras/volume_id/volume_id/ext/ext.h
new file mode 100644 (file)
index 0000000..6b9b858
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_EXT_
+#define _VOLUME_ID_EXT_
+
+extern int volume_id_probe_ext(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/fat/fat.c b/extras/volume_id/volume_id/fat/fat.c
new file mode 100644 (file)
index 0000000..e6f0107
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "fat.h"
+
+#define FAT12_MAX                      0xff5
+#define FAT16_MAX                      0xfff5
+#define FAT_ATTR_VOLUME_ID             0x08
+#define FAT_ATTR_DIR                   0x10
+#define FAT_ATTR_LONG_NAME             0x0f
+#define FAT_ATTR_MASK                  0x3f
+#define FAT_ENTRY_FREE                 0xe5
+
+struct vfat_super_block {
+       __u8    boot_jump[3];
+       __u8    sysid[8];
+       __u16   sector_size;
+       __u8    sectors_per_cluster;
+       __u16   reserved;
+       __u8    fats;
+       __u16   dir_entries;
+       __u16   sectors;
+       __u8    media;
+       __u16   fat_length;
+       __u16   secs_track;
+       __u16   heads;
+       __u32   hidden;
+       __u32   total_sect;
+       union {
+               struct fat_super_block {
+                       __u8    unknown[3];
+                       __u8    serno[4];
+                       __u8    label[11];
+                       __u8    magic[8];
+                       __u8    dummy2[192];
+                       __u8    pmagic[2];
+               } __attribute__((__packed__)) fat;
+               struct fat32_super_block {
+                       __u32   fat32_length;
+                       __u16   flags;
+                       __u8    version[2];
+                       __u32   root_cluster;
+                       __u16   insfo_sector;
+                       __u16   backup_boot;
+                       __u16   reserved2[6];
+                       __u8    unknown[3];
+                       __u8    serno[4];
+                       __u8    label[11];
+                       __u8    magic[8];
+                       __u8    dummy2[164];
+                       __u8    pmagic[2];
+               } __attribute__((__packed__)) fat32;
+       } __attribute__((__packed__)) type;
+} __attribute__((__packed__));
+
+struct vfat_dir_entry {
+       __u8    name[11];
+       __u8    attr;
+       __u16   time_creat;
+       __u16   date_creat;
+       __u16   time_acc;
+       __u16   date_acc;
+       __u16   cluster_high;
+       __u16   time_write;
+       __u16   date_write;
+       __u16   cluster_low;
+       __u32   size;
+} __attribute__((__packed__));
+
+static char *get_attr_volume_id(struct vfat_dir_entry *dir, unsigned int count)
+{
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               /* end marker */
+               if (dir[i].name[0] == 0x00) {
+                       dbg("end of dir");
+                       break;
+               }
+
+               /* empty entry */
+               if (dir[i].name[0] == FAT_ENTRY_FREE)
+                       continue;
+
+               /* long name */
+               if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
+                       continue;
+
+               if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
+                       /* labels do not have file data */
+                       if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
+                               continue;
+
+                       dbg("found ATTR_VOLUME_ID id in root dir");
+                       return dir[i].name;
+               }
+
+               dbg("skip dir entry");
+       }
+
+       return NULL;
+}
+
+int volume_id_probe_vfat(struct volume_id *id, __u64 off)
+{
+       struct vfat_super_block *vs;
+       struct vfat_dir_entry *dir;
+       __u16 sector_size;
+       __u16 dir_entries;
+       __u32 sect_count;
+       __u16 reserved;
+       __u32 fat_size;
+       __u32 root_cluster;
+       __u32 dir_size;
+       __u32 cluster_count;
+       __u32 fat_length;
+       __u64 root_start;
+       __u32 start_data_sect;
+       __u16 root_dir_entries;
+       __u8 *buf;
+       __u32 buf_size;
+       __u8 *label = NULL;
+       __u32 next;
+       int maxloop;
+
+       vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
+       if (vs == NULL)
+               return -1;
+
+       /* believe only that's fat, don't trust the version
+        * the cluster_count will tell us
+        */
+       if (strncmp(vs->sysid, "NTFS", 4) == 0)
+               return -1;
+
+       if (strncmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
+               goto valid;
+
+       if (strncmp(vs->type.fat32.magic, "FAT32   ", 8) == 0)
+               goto valid;
+
+       if (strncmp(vs->type.fat.magic, "FAT16   ", 8) == 0)
+               goto valid;
+
+       if (strncmp(vs->type.fat.magic, "MSDOS", 5) == 0)
+               goto valid;
+
+       if (strncmp(vs->type.fat.magic, "FAT12   ", 8) == 0)
+               goto valid;
+
+       /*
+        * There are old floppies out there without a magic, so we check
+        * for well known values and guess if it's a fat volume
+        */
+
+       /* boot jump address check */
+       if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
+            vs->boot_jump[0] != 0xe9)
+               return -1;
+
+       /* heads check */
+       if (vs->heads == 0)
+               return -1;
+
+       /* cluster size check*/ 
+       if (vs->sectors_per_cluster == 0 ||
+           (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
+               return -1;
+
+       /* media check */
+       if (vs->media < 0xf8 && vs->media != 0xf0)
+               return -1;
+
+       /* fat count*/
+       if (vs->fats != 2)
+               return -1;
+
+valid:
+       /* sector size check */
+       sector_size = le16_to_cpu(vs->sector_size);
+       if (sector_size != 0x200 && sector_size != 0x400 &&
+           sector_size != 0x800 && sector_size != 0x1000)
+               return -1;
+
+       dbg("sector_size 0x%x", sector_size);
+       dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
+
+       dir_entries = le16_to_cpu(vs->dir_entries);
+       reserved = le16_to_cpu(vs->reserved);
+       dbg("reserved 0x%x", reserved);
+
+       sect_count = le16_to_cpu(vs->sectors);
+       if (sect_count == 0)
+               sect_count = le32_to_cpu(vs->total_sect);
+       dbg("sect_count 0x%x", sect_count);
+
+       fat_length = le16_to_cpu(vs->fat_length);
+       if (fat_length == 0)
+               fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
+       dbg("fat_length 0x%x", fat_length);
+
+       fat_size = fat_length * vs->fats;
+       dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
+                       (sector_size-1)) / sector_size;
+       dbg("dir_size 0x%x", dir_size);
+
+       cluster_count = sect_count - (reserved + fat_size + dir_size);
+       cluster_count /= vs->sectors_per_cluster;
+       dbg("cluster_count 0x%x", cluster_count);
+
+       if (cluster_count < FAT12_MAX) {
+               strcpy(id->type_version, "FAT12");
+       } else if (cluster_count < FAT16_MAX) {
+               strcpy(id->type_version, "FAT16");
+       } else {
+               strcpy(id->type_version, "FAT32");
+               goto fat32;
+       }
+
+       /* the label may be an attribute in the root directory */
+       root_start = (reserved + fat_size) * sector_size;
+       dbg("root dir start 0x%llx", root_start);
+       root_dir_entries = le16_to_cpu(vs->dir_entries);
+       dbg("expected entries 0x%x", root_dir_entries);
+
+       buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
+       buf = volume_id_get_buffer(id, off + root_start, buf_size);
+       if (buf == NULL)
+               goto found;
+
+       dir = (struct vfat_dir_entry*) buf;
+
+       label = get_attr_volume_id(dir, root_dir_entries);
+
+       vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
+       if (vs == NULL)
+               return -1;
+
+       if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
+               volume_id_set_label_raw(id, label, 11);
+               volume_id_set_label_string(id, label, 11);
+       } else if (strncmp(vs->type.fat.label, "NO NAME    ", 11) != 0) {
+               volume_id_set_label_raw(id, vs->type.fat.label, 11);
+               volume_id_set_label_string(id, vs->type.fat.label, 11);
+       }
+       volume_id_set_uuid(id, vs->type.fat.serno, UUID_DOS);
+       goto found;
+
+fat32:
+       /* FAT32 root dir is a cluster chain like any other directory */
+       buf_size = vs->sectors_per_cluster * sector_size;
+       root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
+       dbg("root dir cluster %u", root_cluster);
+       start_data_sect = reserved + fat_size;
+
+       next = root_cluster;
+       maxloop = 100;
+       while (--maxloop) {
+               __u32 next_sect_off;
+               __u64 next_off;
+               __u64 fat_entry_off;
+               int count;
+
+               dbg("next cluster %u", next);
+               next_sect_off = (next - 2) * vs->sectors_per_cluster;
+               next_off = (start_data_sect + next_sect_off) * sector_size;
+               dbg("cluster offset 0x%llx", next_off);
+
+               /* get cluster */
+               buf = volume_id_get_buffer(id, off + next_off, buf_size);
+               if (buf == NULL)
+                       goto found;
+
+               dir = (struct vfat_dir_entry*) buf;
+               count = buf_size / sizeof(struct vfat_dir_entry);
+               dbg("expected entries 0x%x", count);
+
+               label = get_attr_volume_id(dir, count);
+               if (label)
+                       break;
+
+               /* get FAT entry */
+               fat_entry_off = (reserved * sector_size) + (next * sizeof(__u32));
+               buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size);
+               if (buf == NULL)
+                       goto found;
+
+               /* set next cluster */
+               next = le32_to_cpu(*((__u32 *) buf) & 0x0fffffff);
+               if (next == 0)
+                       break;
+       }
+       if (maxloop == 0)
+               dbg("reached maximum follow count of root cluster chain, give up");
+
+       vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
+       if (vs == NULL)
+               return -1;
+
+       if (label != NULL && strncmp(label, "NO NAME    ", 11) != 0) {
+               volume_id_set_label_raw(id, label, 11);
+               volume_id_set_label_string(id, label, 11);
+       } else if (strncmp(vs->type.fat32.label, "NO NAME    ", 11) != 0) {
+               volume_id_set_label_raw(id, vs->type.fat32.label, 11);
+               volume_id_set_label_string(id, vs->type.fat32.label, 11);
+       }
+       volume_id_set_uuid(id, vs->type.fat32.serno, UUID_DOS);
+
+found:
+       volume_id_set_usage(id, VOLUME_ID_DISKLABEL);
+       id->type = "vfat";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/fat/fat.h b/extras/volume_id/volume_id/fat/fat.h
new file mode 100644 (file)
index 0000000..51ad94d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_FAT_
+#define _VOLUME_ID_FAT_
+
+extern int volume_id_probe_vfat(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/hfs/hfs.c b/extras/volume_id/volume_id/hfs/hfs.c
new file mode 100644 (file)
index 0000000..638aaba
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "hfs.h"
+
+#define HFS_SUPERBLOCK_OFFSET          0x400
+#define HFS_NODE_LEAF                  0xff
+#define HFSPLUS_POR_CNID               1
+#define HFSPLUS_EXTENT_COUNT           8
+
+int volume_id_probe_hfs_hfsplus(struct volume_id *id, __u64 off)
+{
+       struct hfs_finder_info{
+               __u32   boot_folder;
+               __u32   start_app;
+               __u32   open_folder;
+               __u32   os9_folder;
+               __u32   reserved;
+               __u32   osx_folder;
+               __u8    id[8];
+       } __attribute__((__packed__));
+
+       struct hfs_mdb {
+               __u8    signature[2];
+               __u32   cr_date;
+               __u32   ls_Mod;
+               __u16   atrb;
+               __u16   nm_fls;
+               __u16   vbm_st;
+               __u16   alloc_ptr;
+               __u16   nm_al_blks;
+               __u32   al_blk_size;
+               __u32   clp_size;
+               __u16   al_bl_st;
+               __u32   nxt_cnid;
+               __u16   free_bks;
+               __u8    label_len;
+               __u8    label[27];
+               __u32   vol_bkup;
+               __u16   vol_seq_num;
+               __u32   wr_cnt;
+               __u32   xt_clump_size;
+               __u32   ct_clump_size;
+               __u16   num_root_dirs;
+               __u32   file_count;
+               __u32   dir_count;
+               struct hfs_finder_info finder_info;
+               __u8    embed_sig[2];
+               __u16   embed_startblock;
+               __u16   embed_blockcount;
+       } __attribute__((__packed__)) *hfs;
+
+       struct hfsplus_bnode_descriptor {
+               __u32   next;
+               __u32   prev;
+               __u8    type;
+               __u8    height;
+               __u16   num_recs;
+               __u16   reserved;
+       } __attribute__((__packed__));
+
+       struct hfsplus_bheader_record {
+               __u16   depth;
+               __u32   root;
+               __u32   leaf_count;
+               __u32   leaf_head;
+               __u32   leaf_tail;
+               __u16   node_size;
+       } __attribute__((__packed__));
+
+       struct hfsplus_catalog_key {
+               __u16   key_len;
+               __u32   parent_id;
+               __u16   unicode_len;
+               __u8    unicode[255 * 2];
+       } __attribute__((__packed__));
+
+       struct hfsplus_extent {
+               __u32 start_block;
+               __u32 block_count;
+       } __attribute__((__packed__));
+
+       struct hfsplus_fork {
+               __u64 total_size;
+               __u32 clump_size;
+               __u32 total_blocks;
+               struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
+       } __attribute__((__packed__));
+
+       struct hfsplus_vol_header {
+               __u8    signature[2];
+               __u16   version;
+               __u32   attributes;
+               __u32   last_mount_vers;
+               __u32   reserved;
+               __u32   create_date;
+               __u32   modify_date;
+               __u32   backup_date;
+               __u32   checked_date;
+               __u32   file_count;
+               __u32   folder_count;
+               __u32   blocksize;
+               __u32   total_blocks;
+               __u32   free_blocks;
+               __u32   next_alloc;
+               __u32   rsrc_clump_sz;
+               __u32   data_clump_sz;
+               __u32   next_cnid;
+               __u32   write_count;
+               __u64   encodings_bmp;
+               struct hfs_finder_info finder_info;
+               struct hfsplus_fork alloc_file;
+               struct hfsplus_fork ext_file;
+               struct hfsplus_fork cat_file;
+               struct hfsplus_fork attr_file;
+               struct hfsplus_fork start_file;
+       } __attribute__((__packed__)) *hfsplus;
+
+       unsigned int blocksize;
+       unsigned int cat_block;
+       unsigned int ext_block_start;
+       unsigned int ext_block_count;
+       int ext;
+       unsigned int leaf_node_head;
+       unsigned int leaf_node_count;
+       unsigned int leaf_node_size;
+       unsigned int leaf_block;
+       __u64 leaf_off;
+       unsigned int alloc_block_size;
+       unsigned int alloc_first_block;
+       unsigned int embed_first_block;
+       unsigned int record_count;
+       struct hfsplus_bnode_descriptor *descr;
+       struct hfsplus_bheader_record *bnode;
+       struct hfsplus_catalog_key *key;
+       unsigned int    label_len;
+       struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
+       const __u8 *buf;
+
+       buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
+       if (buf == NULL)
+                return -1;
+
+       hfs = (struct hfs_mdb *) buf;
+       if (strncmp(hfs->signature, "BD", 2) != 0)
+               goto checkplus;
+
+       /* it may be just a hfs wrapper for hfs+ */
+       if (strncmp(hfs->embed_sig, "H+", 2) == 0) {
+               alloc_block_size = be32_to_cpu(hfs->al_blk_size);
+               dbg("alloc_block_size 0x%x", alloc_block_size);
+
+               alloc_first_block = be16_to_cpu(hfs->al_bl_st);
+               dbg("alloc_first_block 0x%x", alloc_first_block);
+
+               embed_first_block = be16_to_cpu(hfs->embed_startblock);
+               dbg("embed_first_block 0x%x", embed_first_block);
+
+               off += (alloc_first_block * 512) +
+                      (embed_first_block * alloc_block_size);
+               dbg("hfs wrapped hfs+ found at offset 0x%llx", off);
+
+               buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
+               if (buf == NULL)
+                       return -1;
+               goto checkplus;
+       }
+
+       if (hfs->label_len > 0 && hfs->label_len < 28) {
+               volume_id_set_label_raw(id, hfs->label, hfs->label_len);
+               volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
+       }
+
+       volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS);
+
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "hfs";
+
+       return 0;
+
+checkplus:
+       hfsplus = (struct hfsplus_vol_header *) buf;
+       if (strncmp(hfsplus->signature, "H+", 2) == 0)
+               goto hfsplus;
+       if (strncmp(hfsplus->signature, "HX", 2) == 0)
+               goto hfsplus;
+       return -1;
+
+hfsplus:
+       volume_id_set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
+
+       blocksize = be32_to_cpu(hfsplus->blocksize);
+       dbg("blocksize %u", blocksize);
+
+       memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
+       cat_block = be32_to_cpu(extents[0].start_block);
+       dbg("catalog start block 0x%x", cat_block);
+
+       buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000);
+       if (buf == NULL)
+               goto found;
+
+       bnode = (struct hfsplus_bheader_record *)
+               &buf[sizeof(struct hfsplus_bnode_descriptor)];
+
+       leaf_node_head = be32_to_cpu(bnode->leaf_head);
+       dbg("catalog leaf node 0x%x", leaf_node_head);
+
+       leaf_node_size = be16_to_cpu(bnode->node_size);
+       dbg("leaf node size 0x%x", leaf_node_size);
+
+       leaf_node_count = be32_to_cpu(bnode->leaf_count);
+       dbg("leaf node count 0x%x", leaf_node_count);
+       if (leaf_node_count == 0)
+               goto found;
+
+       leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
+
+       /* get physical location */
+       for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
+               ext_block_start = be32_to_cpu(extents[ext].start_block);
+               ext_block_count = be32_to_cpu(extents[ext].block_count);
+               dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
+
+               if (ext_block_count == 0)
+                       goto found;
+
+               /* this is our extent */
+               if (leaf_block < ext_block_count)
+                       break;
+
+               leaf_block -= ext_block_count;
+       }
+       if (ext == HFSPLUS_EXTENT_COUNT)
+               goto found;
+       dbg("found block in extent %i", ext);
+
+       leaf_off = (ext_block_start + leaf_block) * blocksize;
+
+       buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size);
+       if (buf == NULL)
+               goto found;
+
+       descr = (struct hfsplus_bnode_descriptor *) buf;
+       dbg("descriptor type 0x%x", descr->type);
+
+       record_count = be16_to_cpu(descr->num_recs);
+       dbg("number of records %u", record_count);
+       if (record_count == 0)
+               goto found;
+
+       if (descr->type != HFS_NODE_LEAF)
+               goto found;
+
+       key = (struct hfsplus_catalog_key *)
+               &buf[sizeof(struct hfsplus_bnode_descriptor)];
+
+       dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
+       if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
+               goto found;
+
+       label_len = be16_to_cpu(key->unicode_len) * 2;
+       dbg("label unicode16 len %i", label_len);
+       volume_id_set_label_raw(id, key->unicode, label_len);
+       volume_id_set_label_unicode16(id, key->unicode, BE, label_len);
+
+found:
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "hfsplus";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/hfs/hfs.h b/extras/volume_id/volume_id/hfs/hfs.h
new file mode 100644 (file)
index 0000000..b23ccd3
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_HFS_
+#define _VOLUME_ID_HFS_
+
+extern int volume_id_probe_hfs_hfsplus(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/highpoint/highpoint.c b/extras/volume_id/volume_id/highpoint/highpoint.c
new file mode 100644 (file)
index 0000000..3236d6b
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "highpoint.h"
+
+#define HPT37X_CONFIG_OFF              0x1200
+#define HPT37X_MAGIC_OK                        0x5a7816f0
+#define HPT37X_MAGIC_BAD               0x5a7816fd
+
+int volume_id_probe_highpoint_ataraid(struct volume_id *id, __u64 off)
+{
+       struct hpt37x {
+               __u8    filler1[32];
+               __u32   magic;
+               __u32   magic_0;
+               __u32   magic_1;
+       } __attribute__((packed)) *hpt;
+
+       const __u8 *buf;
+
+       buf = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
+       if (buf == NULL)
+               return -1;
+
+       hpt = (struct hpt37x *) buf;
+
+       if (hpt->magic != HPT37X_MAGIC_OK && hpt->magic != HPT37X_MAGIC_BAD)
+               return -1;
+
+       volume_id_set_usage(id, VOLUME_ID_RAID);
+       id->type = "hpt_ataraid_member";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/highpoint/highpoint.h b/extras/volume_id/volume_id/highpoint/highpoint.h
new file mode 100644 (file)
index 0000000..5a5614a
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_HIGHPOINT_
+#define _VOLUME_ID_HIGHPOINT_
+
+extern int volume_id_probe_highpoint_ataraid(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/iso9660/iso9660.c b/extras/volume_id/volume_id/iso9660/iso9660.c
new file mode 100644 (file)
index 0000000..6af9e8b
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "iso9660.h"
+
+#define ISO_SUPERBLOCK_OFFSET          0x8000
+#define ISO_SECTOR_SIZE                        0x800
+#define ISO_VD_OFFSET                  (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
+#define ISO_VD_PRIMARY                 0x1
+#define ISO_VD_SUPPLEMENTARY           0x2
+#define ISO_VD_END                     0xff
+#define ISO_VD_MAX                     16
+
+int volume_id_probe_iso9660(struct volume_id *id, __u64 off)
+{
+       union iso_super_block {
+               struct iso_header {
+                       __u8    type;
+                       __u8    id[5];
+                       __u8    version;
+                       __u8    unused1;
+                       __u8            system_id[32];
+                       __u8            volume_id[32];
+               } __attribute__((__packed__)) iso;
+               struct hs_header {
+                       __u8    foo[8];
+                       __u8    type;
+                       __u8    id[4];
+                       __u8    version;
+               } __attribute__((__packed__)) hs;
+       } __attribute__((__packed__)) *is;
+
+       is = (union iso_super_block *) volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
+       if (is == NULL)
+               return -1;
+
+       if (strncmp(is->iso.id, "CD001", 5) == 0) {
+               char root_label[VOLUME_ID_LABEL_SIZE+1];
+               int vd_offset;
+               int i;
+               int found_svd;
+
+               memset(root_label, 0, sizeof(root_label));
+               strncpy(root_label, is->iso.volume_id, sizeof(root_label)-1);
+
+               found_svd = 0;
+               vd_offset = ISO_VD_OFFSET;
+               for (i = 0; i < ISO_VD_MAX; i++) {
+                       is = (union iso_super_block *) volume_id_get_buffer(id, off + vd_offset, 0x200);
+                       if (is == NULL || is->iso.type == ISO_VD_END)
+                               break;
+                       if (is->iso.type == ISO_VD_SUPPLEMENTARY) {
+                               dbg("found ISO supplementary VD at offset 0x%llx", off + vd_offset);
+                               volume_id_set_label_raw(id, is->iso.volume_id, 32);
+                               volume_id_set_label_unicode16(id, is->iso.volume_id, BE, 32);
+                               found_svd = 1;
+                               break;
+                       }
+                       vd_offset += ISO_SECTOR_SIZE;
+               }
+
+               if (!found_svd ||
+                   (found_svd && !strncmp(root_label, id->label, 16)))
+               {
+                       volume_id_set_label_raw(id, root_label, 32);
+                       volume_id_set_label_string(id, root_label, 32);
+               }
+               goto found;
+       }
+       if (strncmp(is->hs.id, "CDROM", 5) == 0)
+               goto found;
+       return -1;
+
+found:
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "iso9660";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/iso9660/iso9660.h b/extras/volume_id/volume_id/iso9660/iso9660.h
new file mode 100644 (file)
index 0000000..c187e25
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_ISO9660_
+#define _VOLUME_ID_ISO9660_
+
+extern int volume_id_probe_iso9660(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/jfs/jfs.c b/extras/volume_id/volume_id/jfs/jfs.c
new file mode 100644 (file)
index 0000000..3e7e9d6
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "jfs.h"
+
+#define JFS_SUPERBLOCK_OFFSET                  0x8000
+
+int volume_id_probe_jfs(struct volume_id *id, __u64 off)
+{
+       struct jfs_super_block {
+               __u8    magic[4];
+               __u32   version;
+               __u64   size;
+               __u32   bsize;
+               __u32   dummy1;
+               __u32   pbsize;
+               __u32   dummy2[27];
+               __u8    uuid[16];
+               __u8    label[16];
+               __u8    loguuid[16];
+       } __attribute__((__packed__)) *js;
+
+       js = (struct jfs_super_block *) volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
+       if (js == NULL)
+               return -1;
+
+       if (strncmp(js->magic, "JFS1", 4) != 0)
+               return -1;
+
+       volume_id_set_label_raw(id, js->label, 16);
+       volume_id_set_label_string(id, js->label, 16);
+       volume_id_set_uuid(id, js->uuid, UUID_DCE);
+
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "jfs";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/jfs/jfs.h b/extras/volume_id/volume_id/jfs/jfs.h
new file mode 100644 (file)
index 0000000..28c48ff
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_JFS_
+#define _VOLUME_ID_JFS_
+
+extern int volume_id_probe_jfs(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/linux_raid/linux_raid.c b/extras/volume_id/volume_id/linux_raid/linux_raid.c
new file mode 100644 (file)
index 0000000..b55c6ca
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "linux_raid.h"
+
+#define MD_RESERVED_BYTES              0x10000
+#define MD_MAGIC                       0xa92b4efc
+
+int volume_id_probe_linux_raid(struct volume_id *id, __u64 off, __u64 size)
+{
+       struct mdp_super_block {
+               __u32   md_magic;
+               __u32   major_version;
+               __u32   minor_version;
+               __u32   patch_version;
+               __u32   gvalid_words;
+               __u32   set_uuid0;
+               __u32   ctime;
+               __u32   level;
+               __u32   size;
+               __u32   nr_disks;
+               __u32   raid_disks;
+               __u32   md_minor;
+               __u32   not_persistent;
+               __u32   set_uuid1;
+               __u32   set_uuid2;
+               __u32   set_uuid3;
+       } __attribute__((packed)) *mdp;
+
+       const __u8 *buf;
+       __u64 sboff;
+       __u8 uuid[16];
+
+       if (size < 0x10000)
+               return -1;
+
+       sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
+       buf = volume_id_get_buffer(id, off + sboff, 0x800);
+       if (buf == NULL)
+               return -1;
+
+       mdp = (struct mdp_super_block *) buf;
+
+       if (le32_to_cpu(mdp->md_magic) != MD_MAGIC)
+               return -1;
+
+       memcpy(uuid, &mdp->set_uuid0, 4);
+       memcpy(&uuid[4], &mdp->set_uuid1, 12);
+       volume_id_set_uuid(id, uuid, UUID_DCE);
+
+       snprintf(id->type_version, VOLUME_ID_FORMAT_SIZE-1, "%u.%u.%u",
+                le32_to_cpu(mdp->major_version),
+                le32_to_cpu(mdp->minor_version),
+                le32_to_cpu(mdp->patch_version));
+
+       dbg("found raid signature");
+       volume_id_set_usage(id, VOLUME_ID_RAID);
+       id->type = "linux_raid_member";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/linux_raid/linux_raid.h b/extras/volume_id/volume_id/linux_raid/linux_raid.h
new file mode 100644 (file)
index 0000000..0aaaaa6
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_LINUX_RAID_
+#define _VOLUME_ID_LINUX_RAID_
+
+extern int volume_id_probe_linux_raid(struct volume_id *id, __u64 off, __u64 size);
+
+#endif
diff --git a/extras/volume_id/volume_id/linux_swap/linux_swap.c b/extras/volume_id/volume_id/linux_swap/linux_swap.c
new file mode 100644 (file)
index 0000000..7ca4976
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "linux_swap.h"
+
+#define LARGEST_PAGESIZE                       0x4000
+
+int volume_id_probe_linux_swap(struct volume_id *id, __u64 off)
+{
+       struct swap_header_v1_2 {
+               __u8    bootbits[1024];
+               __u32   version;
+               __u32   last_page;
+               __u32   nr_badpages;
+               __u8    uuid[16];
+               __u8    volume_name[16];
+       } __attribute__((__packed__)) *sw;
+
+       const __u8 *buf;
+       unsigned int page;
+
+       /* the swap signature is at the end of the PAGE_SIZE */
+       for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
+                       buf = volume_id_get_buffer(id, off + page-10, 10);
+                       if (buf == NULL)
+                               return -1;
+
+                       if (strncmp(buf, "SWAP-SPACE", 10) == 0) {
+                               strcpy(id->type_version, "1");
+                               goto found;
+                       }
+
+                       if (strncmp(buf, "SWAPSPACE2", 10) == 0) {
+                               sw = (struct swap_header_v1_2 *) volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2));
+                               if (sw == NULL)
+                                       return -1;
+                               strcpy(id->type_version, "2");
+                               volume_id_set_label_raw(id, sw->volume_name, 16);
+                               volume_id_set_label_string(id, sw->volume_name, 16);
+                               volume_id_set_uuid(id, sw->uuid, UUID_DCE);
+                               goto found;
+                       }
+       }
+       return -1;
+
+found:
+       volume_id_set_usage(id, VOLUME_ID_OTHER);
+       id->type = "swap";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/linux_swap/linux_swap.h b/extras/volume_id/volume_id/linux_swap/linux_swap.h
new file mode 100644 (file)
index 0000000..5de0f93
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_LINUX_SWAP_
+#define _VOLUME_ID_LINUX_SWAP_
+
+extern int volume_id_probe_linux_swap(struct volume_id *id, __u64 off);
+
+#endif
similarity index 77%
rename from extras/volume_id/volume_id_logging.h
rename to extras/volume_id/volume_id/logging.h
index e978ce197c5b61b7400f5a6499f1a04d7bdb49a8..c81dc5756737817921692b9975f0f9024d151e73 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * volume_id_logging - this file is used to map the dbg() function
- *                     to the host logging facility
+ *                     to the user's logging facility
  *
  */
 
@@ -15,7 +15,7 @@
 #include <config.h>
 #endif
 
-/* just use the udev version*/
+/* just use the udev version */
 #include "../../logging.h"
 
 #endif /* _VOLUME_ID_LOGGING_H_ */
diff --git a/extras/volume_id/volume_id/lvm/lvm.c b/extras/volume_id/volume_id/lvm/lvm.c
new file mode 100644 (file)
index 0000000..d95b6bf
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "lvm.h"
+
+#define LVM1_SB_OFF                    0x400
+#define LVM1_MAGIC                     "HM"
+
+int volume_id_probe_lvm1(struct volume_id *id, __u64 off)
+{
+       struct lvm2_super_block {
+               __u8    id[2];
+       } __attribute__((packed)) *lvm;
+
+       const __u8 *buf;
+
+       buf = volume_id_get_buffer(id, off + LVM1_SB_OFF, 0x800);
+       if (buf == NULL)
+               return -1;
+
+       lvm = (struct lvm2_super_block *) buf;
+
+       if (strncmp(lvm->id, LVM1_MAGIC, 2) != 0)
+               return -1;
+
+       volume_id_set_usage(id, VOLUME_ID_RAID);
+       id->type = "LVM1_member";
+
+       return 0;
+}
+
+#define LVM2_LABEL_ID                  "LABELONE"
+#define LVM2LABEL_SCAN_SECTORS         4
+
+int volume_id_probe_lvm2(struct volume_id *id, __u64 off)
+{
+       struct lvm2_super_block {
+               __u8    id[8];
+               __u64   sector_xl;
+               __u32   crc_xl;
+               __u32   offset_xl;
+               __u8    type[8];
+       } __attribute__((packed)) *lvm;
+
+       const __u8 *buf;
+       unsigned int soff;
+
+       buf = volume_id_get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200);
+       if (buf == NULL)
+               return -1;
+
+
+       for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
+               lvm = (struct lvm2_super_block *) &buf[soff];
+
+               if (strncmp(lvm->id, LVM2_LABEL_ID, 8) == 0)
+                       goto found;
+       }
+
+       return -1;
+
+found:
+       strncpy(id->type_version, lvm->type, 8);
+       volume_id_set_usage(id, VOLUME_ID_RAID);
+       id->type = "LVM2_member";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/lvm/lvm.h b/extras/volume_id/volume_id/lvm/lvm.h
new file mode 100644 (file)
index 0000000..2e44cda
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_LVM_
+#define _VOLUME_ID_LVM_
+
+extern int volume_id_probe_lvm1(struct volume_id *id, __u64 off);
+extern int volume_id_probe_lvm2(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/mac/mac.c b/extras/volume_id/volume_id/mac/mac.c
new file mode 100644 (file)
index 0000000..7265b28
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "mac.h"
+
+int volume_id_probe_mac_partition_map(struct volume_id *id, __u64 off)
+{
+       struct mac_driver_desc {
+               __u8    signature[2];
+               __u16   block_size;
+               __u32   block_count;
+       } __attribute__((__packed__)) *driver;
+
+       struct mac_partition {
+               __u8    signature[2];
+               __u16   res1;
+               __u32   map_count;
+               __u32   start_block;
+               __u32   block_count;
+               __u8    name[32];
+               __u8    type[32];
+       } __attribute__((__packed__)) *part;
+
+       const __u8 *buf;
+
+       buf = volume_id_get_buffer(id, off, 0x200);
+       if (buf == NULL)
+               return -1;
+
+       part = (struct mac_partition *) buf;
+       if ((strncmp(part->signature, "PM", 2) == 0) &&
+           (strncmp(part->type, "Apple_partition_map", 19) == 0)) {
+               /* linux creates an own subdevice for the map
+                * just return the type if the drive header is missing */
+               volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
+               id->type = "mac_partition_map";
+               return 0;
+       }
+
+       driver = (struct mac_driver_desc *) buf;
+       if (strncmp(driver->signature, "ER", 2) == 0) {
+               /* we are on a main device, like a CD
+                * just try to probe the first partition from the map */
+               unsigned int bsize = be16_to_cpu(driver->block_size);
+               int part_count;
+               int i;
+
+               /* get first entry of partition table */
+               buf = volume_id_get_buffer(id, off +  bsize, 0x200);
+               if (buf == NULL)
+                       return -1;
+
+               part = (struct mac_partition *) buf;
+               if (strncmp(part->signature, "PM", 2) != 0)
+                       return -1;
+
+               part_count = be32_to_cpu(part->map_count);
+               dbg("expecting %d partition entries", part_count);
+
+               if (id->partitions != NULL)
+                       free(id->partitions);
+               id->partitions =
+                       malloc(part_count * sizeof(struct volume_id_partition));
+               if (id->partitions == NULL)
+                       return -1;
+               memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
+
+               id->partition_count = part_count;
+
+               for (i = 0; i < part_count; i++) {
+                       __u64 poff;
+                       __u64 plen;
+
+                       buf = volume_id_get_buffer(id, off + ((i+1) * bsize), 0x200);
+                       if (buf == NULL)
+                               return -1;
+
+                       part = (struct mac_partition *) buf;
+                       if (strncmp(part->signature, "PM", 2) != 0)
+                               return -1;
+
+                       poff = be32_to_cpu(part->start_block) * bsize;
+                       plen = be32_to_cpu(part->block_count) * bsize;
+                       dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
+                           part->type, poff, plen);
+
+                       id->partitions[i].off = poff;
+                       id->partitions[i].len = plen;
+
+                       if (strncmp(part->type, "Apple_Free", 10) == 0) {
+                               volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNUSED);
+                       } else if (strncmp(part->type, "Apple_partition_map", 19) == 0) {
+                               volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_PARTITIONTABLE);
+                       } else {
+                               volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNPROBED);
+                       }
+               }
+               volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
+               id->type = "mac_partition_map";
+               return 0;
+       }
+
+       return -1;
+}
diff --git a/extras/volume_id/volume_id/mac/mac.h b/extras/volume_id/volume_id/mac/mac.h
new file mode 100644 (file)
index 0000000..888c1c5
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_MAC_
+#define _VOLUME_ID_MAC_
+
+extern int volume_id_probe_mac_partition_map(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/msdos/msdos.c b/extras/volume_id/volume_id/msdos/msdos.c
new file mode 100644 (file)
index 0000000..915c1b2
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "msdos.h"
+
+#define MSDOS_MAGIC                    "\x55\xaa"
+#define MSDOS_PARTTABLE_OFFSET         0x1be
+#define MSDOS_SIG_OFF                  0x1fe
+#define BSIZE                          0x200
+#define DOS_EXTENDED_PARTITION         0x05
+#define LINUX_EXTENDED_PARTITION       0x85
+#define WIN98_EXTENDED_PARTITION       0x0f
+#define LINUX_RAID_PARTITION           0xfd
+#define is_extended(type) \
+       (type == DOS_EXTENDED_PARTITION ||      \
+        type == WIN98_EXTENDED_PARTITION ||    \
+        type == LINUX_EXTENDED_PARTITION)
+#define is_raid(type) \
+       (type == LINUX_RAID_PARTITION)
+
+int volume_id_probe_msdos_part_table(struct volume_id *id, __u64 off)
+{
+       struct msdos_partition_entry {
+               __u8    boot_ind;
+               __u8    head;
+               __u8    sector;
+               __u8    cyl;
+               __u8    sys_ind;
+               __u8    end_head;
+               __u8    end_sector;
+               __u8    end_cyl;
+               __u32   start_sect;
+               __u32   nr_sects;
+       } __attribute__((packed)) *part;
+
+       const __u8 *buf;
+       int i;
+       __u64 poff;
+       __u64 plen;
+       __u64 extended = 0;
+       __u64 current;
+       __u64 next;
+       int limit;
+       int empty = 1;
+       struct volume_id_partition *p;
+
+       buf = volume_id_get_buffer(id, off, 0x200);
+       if (buf == NULL)
+               return -1;
+
+       if (strncmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
+               return -1;
+
+       /* check flags on all entries for a valid partition table */
+       part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
+       for (i = 0; i < 4; i++) {
+               if (part[i].boot_ind != 0 &&
+                   part[i].boot_ind != 0x80)
+                       return -1;
+
+               if (le32_to_cpu(part[i].nr_sects) != 0)
+                       empty = 0;
+       }
+       if (empty == 1)
+               return -1;
+
+       if (id->partitions != NULL)
+               free(id->partitions);
+       id->partitions = malloc(VOLUME_ID_PARTITIONS_MAX *
+                               sizeof(struct volume_id_partition));
+       if (id->partitions == NULL)
+               return -1;
+       memset(id->partitions, 0x00,
+              VOLUME_ID_PARTITIONS_MAX * sizeof(struct volume_id_partition));
+
+       for (i = 0; i < 4; i++) {
+               poff = (__u64) le32_to_cpu(part[i].start_sect) * BSIZE;
+               plen = (__u64) le32_to_cpu(part[i].nr_sects) * BSIZE;
+
+               if (plen == 0)
+                       continue;
+
+               p = &id->partitions[i];
+
+               p->partition_type_raw = part[i].sys_ind;
+
+               if (is_extended(part[i].sys_ind)) {
+                       dbg("found extended partition at 0x%llx", poff);
+                       volume_id_set_usage_part(p, VOLUME_ID_PARTITIONTABLE);
+                       p->type = "msdos_extended_partition";
+                       if (extended == 0)
+                               extended = off + poff;
+               } else {
+                       dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
+                           part[i].sys_ind, poff, plen);
+
+                       if (is_raid(part[i].sys_ind))
+                               volume_id_set_usage_part(p, VOLUME_ID_RAID);
+                       else
+                               volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
+               }
+
+               p->off = off + poff;
+               p->len = plen;
+               id->partition_count = i+1;
+       }
+
+       next = extended;
+       current = extended;
+       limit = 50;
+
+       /* follow extended partition chain and add data partitions */
+       while (next != 0) {
+               if (limit-- == 0) {
+                       dbg("extended chain limit reached");
+                       break;
+               }
+
+               buf = volume_id_get_buffer(id, current, 0x200);
+               if (buf == NULL)
+                       break;
+
+               part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
+
+               if (strncmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
+                       break;
+
+               next = 0;
+
+               for (i = 0; i < 4; i++) {
+                       poff = (__u64) le32_to_cpu(part[i].start_sect) * BSIZE;
+                       plen = (__u64) le32_to_cpu(part[i].nr_sects) * BSIZE;
+
+                       if (plen == 0)
+                               continue;
+
+                       if (is_extended(part[i].sys_ind)) {
+                               dbg("found extended partition at 0x%llx", poff);
+                               if (next == 0)
+                                       next = extended + poff;
+                       } else {
+                               dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
+                                       part[i].sys_ind, poff, plen);
+
+                               /* we always start at the 5th entry */
+                               while (id->partition_count < 4)
+                                       volume_id_set_usage_part(&id->partitions[id->partition_count++], VOLUME_ID_UNUSED);
+
+                               p = &id->partitions[id->partition_count];
+
+                               if (is_raid(part[i].sys_ind))
+                                       volume_id_set_usage_part(p, VOLUME_ID_RAID);
+                               else
+                                       volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
+
+                               p->off = current + poff;
+                               p->len = plen;
+                               id->partition_count++;
+
+                               p->partition_type_raw = part[i].sys_ind;
+
+                               if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
+                                       dbg("too many partitions");
+                                       next = 0;
+                               }
+                       }
+               }
+
+               current = next;
+       }
+
+       volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
+       id->type = "msdos_partition_table";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/msdos/msdos.h b/extras/volume_id/volume_id/msdos/msdos.h
new file mode 100644 (file)
index 0000000..55185c0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_MSDOS_
+#define _VOLUME_ID_MSDOS_
+
+extern int volume_id_probe_msdos_part_table(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/ntfs/ntfs.c b/extras/volume_id/volume_id/ntfs/ntfs.c
new file mode 100644 (file)
index 0000000..4e1f508
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "ntfs.h"
+
+#define MFT_RECORD_VOLUME                      3
+#define MFT_RECORD_ATTR_VOLUME_NAME            0x60
+#define MFT_RECORD_ATTR_VOLUME_INFO            0x70
+#define MFT_RECORD_ATTR_OBJECT_ID              0x40
+#define MFT_RECORD_ATTR_END                    0xffffffffu
+
+int volume_id_probe_ntfs(struct volume_id *id, __u64 off)
+{
+       struct ntfs_super_block {
+               __u8    jump[3];
+               __u8    oem_id[8];
+               __u16   bytes_per_sector;
+               __u8    sectors_per_cluster;
+               __u16   reserved_sectors;
+               __u8    fats;
+               __u16   root_entries;
+               __u16   sectors;
+               __u8    media_type;
+               __u16   sectors_per_fat;
+               __u16   sectors_per_track;
+               __u16   heads;
+               __u32   hidden_sectors;
+               __u32   large_sectors;
+               __u16   unused[2];
+               __u64   number_of_sectors;
+               __u64   mft_cluster_location;
+               __u64   mft_mirror_cluster_location;
+               __s8    cluster_per_mft_record;
+               __u8    reserved1[3];
+               __s8    cluster_per_index_record;
+               __u8    reserved2[3];
+               __u8    volume_serial[8];
+               __u16   checksum;
+       } __attribute__((__packed__)) *ns;
+
+       struct master_file_table_record {
+               __u8    magic[4];
+               __u16   usa_ofs;
+               __u16   usa_count;
+               __u64   lsn;
+               __u16   sequence_number;
+               __u16   link_count;
+               __u16   attrs_offset;
+               __u16   flags;
+               __u32   bytes_in_use;
+               __u32   bytes_allocated;
+       } __attribute__((__packed__)) *mftr;
+
+       struct file_attribute {
+               __u32   type;
+               __u32   len;
+               __u8    non_resident;
+               __u8    name_len;
+               __u16   name_offset;
+               __u16   flags;
+               __u16   instance;
+               __u32   value_len;
+               __u16   value_offset;
+       } __attribute__((__packed__)) *attr;
+
+       struct volume_info {
+               __u64 reserved;
+               __u8 major_ver;
+               __u8 minor_ver;
+       } __attribute__((__packed__)) *info;
+
+       unsigned int sector_size;
+       unsigned int cluster_size;
+       __u64 mft_cluster;
+       __u64 mft_off;
+       unsigned int mft_record_size;
+       unsigned int attr_type;
+       unsigned int attr_off;
+       unsigned int attr_len;
+       unsigned int val_off;
+       unsigned int val_len;
+       const __u8 *buf;
+       const __u8 *val;
+
+       ns = (struct ntfs_super_block *) volume_id_get_buffer(id, off, 0x200);
+       if (ns == NULL)
+               return -1;
+
+       if (strncmp(ns->oem_id, "NTFS", 4) != 0)
+               return -1;
+
+       volume_id_set_uuid(id, ns->volume_serial, UUID_NTFS);
+
+       sector_size = le16_to_cpu(ns->bytes_per_sector);
+       cluster_size = ns->sectors_per_cluster * sector_size;
+       mft_cluster = le64_to_cpu(ns->mft_cluster_location);
+       mft_off = mft_cluster * cluster_size;
+
+       if (ns->cluster_per_mft_record < 0)
+               /* size = -log2(mft_record_size); normally 1024 Bytes */
+               mft_record_size = 1 << -ns->cluster_per_mft_record;
+       else
+               mft_record_size = ns->cluster_per_mft_record * cluster_size;
+
+       dbg("sectorsize  0x%x", sector_size);
+       dbg("clustersize 0x%x", cluster_size);
+       dbg("mftcluster  %lli", mft_cluster);
+       dbg("mftoffset  0x%llx", mft_off);
+       dbg("cluster per mft_record  %i", ns->cluster_per_mft_record);
+       dbg("mft record size  %i", mft_record_size);
+
+       buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
+                        mft_record_size);
+       if (buf == NULL)
+               goto found;
+
+       mftr = (struct master_file_table_record*) buf;
+
+       dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
+       if (strncmp(mftr->magic, "FILE", 4) != 0)
+               goto found;
+
+       attr_off = le16_to_cpu(mftr->attrs_offset);
+       dbg("file $Volume's attributes are at offset %i", attr_off);
+
+       while (1) {
+               attr = (struct file_attribute*) &buf[attr_off];
+               attr_type = le32_to_cpu(attr->type);
+               attr_len = le16_to_cpu(attr->len);
+               val_off = le16_to_cpu(attr->value_offset);
+               val_len = le32_to_cpu(attr->value_len);
+               attr_off += attr_len;
+
+               if (attr_len == 0)
+                       break;
+
+               if (attr_off >= mft_record_size)
+                       break;
+
+               if (attr_type == MFT_RECORD_ATTR_END)
+                       break;
+
+               dbg("found attribute type 0x%x, len %i, at offset %i",
+                   attr_type, attr_len, attr_off);
+
+               if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
+                       dbg("found info, len %i", val_len);
+                       info = (struct volume_info*) (((__u8 *) attr) + val_off);
+                       snprintf(id->type_version, VOLUME_ID_FORMAT_SIZE-1,
+                                "%u.%u", info->major_ver, info->minor_ver);
+               }
+
+               if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
+                       dbg("found label, len %i", val_len);
+                       if (val_len > VOLUME_ID_LABEL_SIZE)
+                               val_len = VOLUME_ID_LABEL_SIZE;
+
+                       val = ((__u8 *) attr) + val_off;
+                       volume_id_set_label_raw(id, val, val_len);
+                       volume_id_set_label_unicode16(id, val, LE, val_len);
+               }
+       }
+
+found:
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "ntfs";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/ntfs/ntfs.h b/extras/volume_id/volume_id/ntfs/ntfs.h
new file mode 100644 (file)
index 0000000..63b1161
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_NTFS_
+#define _VOLUME_ID_NTFS_
+
+extern int volume_id_probe_ntfs(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/reiserfs/reiserfs.c b/extras/volume_id/volume_id/reiserfs/reiserfs.c
new file mode 100644 (file)
index 0000000..8fd8b51
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "reiserfs.h"
+
+#define REISERFS1_SUPERBLOCK_OFFSET            0x2000
+#define REISERFS_SUPERBLOCK_OFFSET             0x10000
+
+int volume_id_probe_reiserfs(struct volume_id *id, __u64 off)
+{
+       struct reiserfs_super_block {
+               __u32   blocks_count;
+               __u32   free_blocks;
+               __u32   root_block;
+               __u32   journal_block;
+               __u32   journal_dev;
+               __u32   orig_journal_size;
+               __u32   dummy2[5];
+               __u16   blocksize;
+               __u16   dummy3[3];
+               __u8    magic[12];
+               __u32   dummy4[5];
+               __u8    uuid[16];
+               __u8    label[16];
+       } __attribute__((__packed__)) *rs;
+
+       rs = (struct reiserfs_super_block *) volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
+       if (rs == NULL)
+               return -1;
+
+       if (strncmp(rs->magic, "ReIsEr2Fs", 9) == 0) {
+               strcpy(id->type_version, "3.6");
+               goto found;
+       }
+
+       if (strncmp(rs->magic, "ReIsEr3Fs", 9) == 0) {
+               strcpy(id->type_version, "JR");
+               goto found;
+       }
+
+       rs = (struct reiserfs_super_block *) volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
+       if (rs == NULL)
+               return -1;
+
+       if (strncmp(rs->magic, "ReIsErFs", 8) == 0) {
+               strcpy(id->type_version, "3.5");
+               goto found;
+       }
+
+       return -1;
+
+found:
+       volume_id_set_label_raw(id, rs->label, 16);
+       volume_id_set_label_string(id, rs->label, 16);
+       volume_id_set_uuid(id, rs->uuid, UUID_DCE);
+
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "reiserfs";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/reiserfs/reiserfs.h b/extras/volume_id/volume_id/reiserfs/reiserfs.h
new file mode 100644 (file)
index 0000000..14f0945
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_REISERFS_
+#define _VOLUME_ID_REISERFS_
+
+extern int volume_id_probe_reiserfs(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/udf/udf.c b/extras/volume_id/volume_id/udf/udf.c
new file mode 100644 (file)
index 0000000..b91e3cc
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "udf.h"
+
+#define UDF_VSD_OFFSET                 0x8000
+
+int volume_id_probe_udf(struct volume_id *id, __u64 off)
+{
+       struct volume_descriptor {
+               struct descriptor_tag {
+                       __u16   id;
+                       __u16   version;
+                       __u8    checksum;
+                       __u8    reserved;
+                       __u16   serial;
+                       __u16   crc;
+                       __u16   crc_len;
+                       __u32   location;
+               } __attribute__((__packed__)) tag;
+               union {
+                       struct anchor_descriptor {
+                               __u32   length;
+                               __u32   location;
+                       } __attribute__((__packed__)) anchor;
+                       struct primary_descriptor {
+                               __u32   seq_num;
+                               __u32   desc_num;
+                               struct dstring {
+                                       __u8    clen;
+                                       __u8    c[31];
+                               } __attribute__((__packed__)) ident;
+                       } __attribute__((__packed__)) primary;
+               } __attribute__((__packed__)) type;
+       } __attribute__((__packed__)) *vd;
+
+       struct volume_structure_descriptor {
+               __u8    type;
+               __u8    id[5];
+               __u8    version;
+       } *vsd;
+
+       unsigned int bs;
+       unsigned int b;
+       unsigned int type;
+       unsigned int count;
+       unsigned int loc;
+       unsigned int clen;
+
+       vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
+       if (vsd == NULL)
+               return -1;
+
+       if (strncmp(vsd->id, "NSR02", 5) == 0)
+               goto blocksize;
+       if (strncmp(vsd->id, "NSR03", 5) == 0)
+               goto blocksize;
+       if (strncmp(vsd->id, "BEA01", 5) == 0)
+               goto blocksize;
+       if (strncmp(vsd->id, "BOOT2", 5) == 0)
+               goto blocksize;
+       if (strncmp(vsd->id, "CD001", 5) == 0)
+               goto blocksize;
+       if (strncmp(vsd->id, "CDW02", 5) == 0)
+               goto blocksize;
+       if (strncmp(vsd->id, "TEA03", 5) == 0)
+               goto blocksize;
+       return -1;
+
+blocksize:
+       /* search the next VSD to get the logical block size of the volume */
+       for (bs = 0x800; bs < 0x8000; bs += 0x800) {
+               vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
+               if (vsd == NULL)
+                       return -1;
+               dbg("test for blocksize: 0x%x", bs);
+               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 *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
+               if (vsd == NULL)
+                       return -1;
+
+               dbg("vsd: %c%c%c%c%c",
+                   vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
+
+               if (vsd->id[0] == '\0')
+                       return -1;
+               if (strncmp(vsd->id, "NSR02", 5) == 0)
+                       goto anchor;
+               if (strncmp(vsd->id, "NSR03", 5) == 0)
+                       goto anchor;
+       }
+       return -1;
+
+anchor:
+       /* read anchor volume descriptor */
+       vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + (256 * bs), 0x200);
+       if (vd == NULL)
+               return -1;
+
+       type = le16_to_cpu(vd->tag.id);
+       if (type != 2) /* TAG_ID_AVDP */
+               goto found;
+
+       /* get desriptor list address and block count */
+       count = le32_to_cpu(vd->type.anchor.length) / bs;
+       loc = le32_to_cpu(vd->type.anchor.location);
+       dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
+
+       /* pick the primary descriptor from the list */
+       for (b = 0; b < count; b++) {
+               vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200);
+               if (vd == NULL)
+                       return -1;
+
+               type = le16_to_cpu(vd->tag.id);
+               dbg("descriptor type %i", type);
+
+               /* check validity */
+               if (type == 0)
+                       goto found;
+               if (le32_to_cpu(vd->tag.location) != loc + b)
+                       goto found;
+
+               if (type == 1) /* TAG_ID_PVD */
+                       goto pvd;
+       }
+       goto found;
+
+pvd:
+       volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32);
+
+       clen = vd->type.primary.ident.clen;
+       dbg("label string charsize=%i bit", clen);
+       if (clen == 8)
+               volume_id_set_label_string(id, vd->type.primary.ident.c, 31);
+       else if (clen == 16)
+               volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE,31);
+
+found:
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "udf";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/udf/udf.h b/extras/volume_id/volume_id/udf/udf.h
new file mode 100644 (file)
index 0000000..b112e46
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_UDF_
+#define _VOLUME_ID_UDF_
+
+extern int volume_id_probe_udf(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/ufs/ufs.c b/extras/volume_id/volume_id/ufs/ufs.c
new file mode 100644 (file)
index 0000000..bab1d4c
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "ufs.h"
+
+#define UFS_MAGIC                      0x00011954
+#define UFS2_MAGIC                     0x19540119
+#define UFS_MAGIC_FEA                  0x00195612
+#define UFS_MAGIC_LFN                  0x00095014
+
+int volume_id_probe_ufs(struct volume_id *id, __u64 off)
+{
+       struct ufs_super_block {
+               __u32   fs_link;
+               __u32   fs_rlink;
+               __u32   fs_sblkno;
+               __u32   fs_cblkno;
+               __u32   fs_iblkno;
+               __u32   fs_dblkno;
+               __u32   fs_cgoffset;
+               __u32   fs_cgmask;
+               __u32   fs_time;
+               __u32   fs_size;
+               __u32   fs_dsize;
+               __u32   fs_ncg; 
+               __u32   fs_bsize;
+               __u32   fs_fsize;
+               __u32   fs_frag;
+               __u32   fs_minfree;
+               __u32   fs_rotdelay;
+               __u32   fs_rps; 
+               __u32   fs_bmask;
+               __u32   fs_fmask;
+               __u32   fs_bshift;
+               __u32   fs_fshift;
+               __u32   fs_maxcontig;
+               __u32   fs_maxbpg;
+               __u32   fs_fragshift;
+               __u32   fs_fsbtodb;
+               __u32   fs_sbsize;
+               __u32   fs_csmask;
+               __u32   fs_csshift;
+               __u32   fs_nindir;
+               __u32   fs_inopb;
+               __u32   fs_nspf;
+               __u32   fs_optim;
+               __u32   fs_npsect_state;
+               __u32   fs_interleave;
+               __u32   fs_trackskew;
+               __u32   fs_id[2];
+               __u32   fs_csaddr;
+               __u32   fs_cssize;
+               __u32   fs_cgsize;
+               __u32   fs_ntrak;
+               __u32   fs_nsect;
+               __u32   fs_spc; 
+               __u32   fs_ncyl;
+               __u32   fs_cpg;
+               __u32   fs_ipg;
+               __u32   fs_fpg;
+               struct ufs_csum {
+                       __u32   cs_ndir;
+                       __u32   cs_nbfree;
+                       __u32   cs_nifree;
+                       __u32   cs_nffree;
+               } __attribute__((__packed__)) fs_cstotal;
+               __s8    fs_fmod;
+               __s8    fs_clean;
+               __s8    fs_ronly;
+               __s8    fs_flags;
+               union {
+                       struct {
+                               __s8    fs_fsmnt[512];
+                               __u32   fs_cgrotor;
+                               __u32   fs_csp[31];
+                               __u32   fs_maxcluster;
+                               __u32   fs_cpc;
+                               __u16   fs_opostbl[16][8];
+                       } __attribute__((__packed__)) fs_u1;
+                       struct {
+                               __s8  fs_fsmnt[468];
+                               __u8   fs_volname[32];
+                               __u64  fs_swuid;
+                               __s32  fs_pad;
+                               __u32   fs_cgrotor;
+                               __u32   fs_ocsp[28];
+                               __u32   fs_contigdirs;
+                               __u32   fs_csp; 
+                               __u32   fs_maxcluster;
+                               __u32   fs_active;
+                               __s32   fs_old_cpc;
+                               __s32   fs_maxbsize;
+                               __s64   fs_sparecon64[17];
+                               __s64   fs_sblockloc;
+                               struct  ufs2_csum_total {
+                                       __u64   cs_ndir;
+                                       __u64   cs_nbfree;
+                                       __u64   cs_nifree;
+                                       __u64   cs_nffree;
+                                       __u64   cs_numclusters;
+                                       __u64   cs_spare[3];
+                               } __attribute__((__packed__)) fs_cstotal;
+                               struct  ufs_timeval {
+                                       __s32   tv_sec;
+                                       __s32   tv_usec;
+                               } __attribute__((__packed__)) fs_time;
+                               __s64    fs_size;
+                               __s64    fs_dsize;
+                               __u64    fs_csaddr;
+                               __s64    fs_pendingblocks;
+                               __s32    fs_pendinginodes;
+                       } __attribute__((__packed__)) fs_u2;
+               }  fs_u11;
+               union {
+                       struct {
+                               __s32   fs_sparecon[53];
+                               __s32   fs_reclaim;
+                               __s32   fs_sparecon2[1];
+                               __s32   fs_state;
+                               __u32   fs_qbmask[2];
+                               __u32   fs_qfmask[2];
+                       } __attribute__((__packed__)) fs_sun;
+                       struct {
+                               __s32   fs_sparecon[53];
+                               __s32   fs_reclaim;
+                               __s32   fs_sparecon2[1];
+                               __u32   fs_npsect;
+                               __u32   fs_qbmask[2];
+                               __u32   fs_qfmask[2];
+                       } __attribute__((__packed__)) fs_sunx86;
+                       struct {
+                               __s32   fs_sparecon[50];
+                               __s32   fs_contigsumsize;
+                               __s32   fs_maxsymlinklen;
+                               __s32   fs_inodefmt;
+                               __u32   fs_maxfilesize[2];
+                               __u32   fs_qbmask[2];
+                               __u32   fs_qfmask[2];
+                               __s32   fs_state;
+                       } __attribute__((__packed__)) fs_44;
+               } fs_u2;
+               __s32   fs_postblformat;
+               __s32   fs_nrpos;
+               __s32   fs_postbloff;
+               __s32   fs_rotbloff;
+               __u32   fs_magic;
+               __u8    fs_space[1];
+       } __attribute__((__packed__)) *ufs;
+
+       __u32   magic;
+       int     i;
+       int     offsets[] = {0, 8, 64, 256, -1};
+
+       for (i = 0; offsets[i] >= 0; i++) {     
+               ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
+               if (ufs == NULL)
+                       return -1;
+
+               dbg("offset 0x%x", offsets[i] * 0x400);
+               magic = be32_to_cpu(ufs->fs_magic);
+               if ((magic == UFS_MAGIC) ||
+                   (magic == UFS2_MAGIC) ||
+                   (magic == UFS_MAGIC_FEA) ||
+                   (magic == UFS_MAGIC_LFN)) {
+                       dbg("magic 0x%08x(be)", magic);
+                       goto found;
+               }
+               magic = le32_to_cpu(ufs->fs_magic);
+               if ((magic == UFS_MAGIC) ||
+                   (magic == UFS2_MAGIC) ||
+                   (magic == UFS_MAGIC_FEA) ||
+                   (magic == UFS_MAGIC_LFN)) {
+                       dbg("magic 0x%08x(le)", magic);
+                       goto found;
+               }
+       }
+       return -1;
+
+found:
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "ufs";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/ufs/ufs.h b/extras/volume_id/volume_id/ufs/ufs.h
new file mode 100644 (file)
index 0000000..82b4e1d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_UFS_
+#define _VOLUME_ID_UFS_
+
+extern int volume_id_probe_ufs(struct volume_id *id, __u64 off);
+
+#endif
diff --git a/extras/volume_id/volume_id/util.c b/extras/volume_id/volume_id/util.c
new file mode 100644 (file)
index 0000000..0cd2ead
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <asm/types.h>
+
+#include "volume_id.h"
+#include "logging.h"
+#include "util.h"
+
+static char *usage_to_string(enum volume_id_usage usage_id)
+{
+       switch (usage_id) {
+       case VOLUME_ID_FILESYSTEM:
+               return "filesystem";
+       case VOLUME_ID_PARTITIONTABLE:
+               return "partitiontable";
+       case VOLUME_ID_OTHER:
+               return "other";
+       case VOLUME_ID_RAID:
+               return "raid";
+       case VOLUME_ID_DISKLABEL:
+               return "disklabel";
+       case VOLUME_ID_UNPROBED:
+               return "unprobed";
+       case VOLUME_ID_UNUSED:
+               return "unused";
+       }
+       return NULL;
+}
+
+void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id)
+{
+       part->usage_id = usage_id;
+       part->usage = usage_to_string(usage_id);
+}
+
+void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id)
+{
+       id->usage_id = usage_id;
+       id->usage = usage_to_string(usage_id);
+}
+
+void volume_id_set_label_raw(struct volume_id *id, const __u8 *buf, unsigned int count)
+{
+       memcpy(id->label_raw, buf, count);
+       id->label_raw_len = count;
+}
+
+void volume_id_set_label_string(struct volume_id *id, const __u8 *buf, unsigned int count)
+{
+       unsigned int i;
+
+       memcpy(id->label, buf, count);
+
+       /* remove trailing whitespace */
+       i = strnlen(id->label, count);
+       while (i--) {
+               if (!isspace(id->label[i]))
+                       break;
+       }
+       id->label[i+1] = '\0';
+}
+
+void volume_id_set_label_unicode16(struct volume_id *id, const __u8 *buf, enum endian endianess, unsigned int count)
+{
+       unsigned int i, j;
+       __u16 c;
+
+       j = 0;
+       for (i = 0; i + 2 <= count; i += 2) {
+               if (endianess == LE)
+                       c = (buf[i+1] << 8) | buf[i];
+               else
+                       c = (buf[i] << 8) | buf[i+1];
+               if (c == 0) {
+                       id->label[j] = '\0';
+                       break;
+               } else if (c < 0x80) {
+                       id->label[j++] = (__u8) c;
+               } else if (c < 0x800) {
+                       id->label[j++] = (__u8) (0xc0 | (c >> 6));
+                       id->label[j++] = (__u8) (0x80 | (c & 0x3f));
+               } else {
+                       id->label[j++] = (__u8) (0xe0 | (c >> 12));
+                       id->label[j++] = (__u8) (0x80 | ((c >> 6) & 0x3f));
+                       id->label[j++] = (__u8) (0x80 | (c & 0x3f));
+               }
+       }
+}
+
+void volume_id_set_uuid(struct volume_id *id, const __u8 *buf, enum uuid_format format)
+{
+       unsigned int i;
+       unsigned int count = 0;
+
+       switch(format) {
+       case UUID_DOS:
+               count = 4;
+               break;
+       case UUID_NTFS:
+       case UUID_HFS:
+               count = 8;
+               break;
+       case UUID_DCE:
+               count = 16;
+       }
+       memcpy(id->uuid_raw, buf, count);
+
+       /* if set, create string in the same format, the native platform uses */
+       for (i = 0; i < count; i++)
+               if (buf[i] != 0)
+                       goto set;
+       return;
+
+set:
+       switch(format) {
+       case UUID_DOS:
+               sprintf(id->uuid, "%02X%02X-%02X%02X",
+                       buf[3], buf[2], buf[1], buf[0]);
+               break;
+       case UUID_NTFS:
+               sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
+                       buf[7], buf[6], buf[5], buf[4],
+                       buf[3], buf[2], buf[1], buf[0]);
+               break;
+       case UUID_HFS:
+               sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
+                       buf[0], buf[1], buf[2], buf[3],
+                       buf[4], buf[5], buf[6], buf[7]);
+               break;
+       case UUID_DCE:
+               sprintf(id->uuid,
+                       "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                       buf[0], buf[1], buf[2], buf[3],
+                       buf[4], buf[5],
+                       buf[6], buf[7],
+                       buf[8], buf[9],
+                       buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]);
+               break;
+       }
+}
+
+__u8 *volume_id_get_buffer(struct volume_id *id, __u64 off, unsigned int len)
+{
+       unsigned int buf_len;
+
+       dbg("get buffer off 0x%llx(%llu), len 0x%x", off, off, len);
+       /* check if requested area fits in superblock buffer */
+       if (off + len <= SB_BUFFER_SIZE) {
+               if (id->sbbuf == NULL) {
+                       id->sbbuf = malloc(SB_BUFFER_SIZE);
+                       if (id->sbbuf == NULL)
+                               return NULL;
+               }
+
+               /* check if we need to read */
+               if ((off + len) > id->sbbuf_len) {
+                       dbg("read sbbuf len:0x%llx", off + len);
+                       lseek(id->fd, 0, SEEK_SET);
+                       buf_len = read(id->fd, id->sbbuf, off + len);
+                       dbg("got 0x%x (%i) bytes", buf_len, buf_len);
+                       id->sbbuf_len = buf_len;
+                       if (buf_len < off + len)
+                               return NULL;
+               }
+
+               return &(id->sbbuf[off]);
+       } else {
+               if (len > SEEK_BUFFER_SIZE) {
+                       dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
+                       return NULL;
+               }
+
+               /* get seek buffer */
+               if (id->seekbuf == NULL) {
+                       id->seekbuf = malloc(SEEK_BUFFER_SIZE);
+                       if (id->seekbuf == NULL)
+                               return NULL;
+               }
+
+               /* check if we need to read */
+               if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
+                       dbg("read seekbuf off:0x%llx len:0x%x", off, len);
+                       if (lseek(id->fd, off, SEEK_SET) == -1)
+                               return NULL;
+                       buf_len = read(id->fd, id->seekbuf, len);
+                       dbg("got 0x%x (%i) bytes", buf_len, buf_len);
+                       id->seekbuf_off = off;
+                       id->seekbuf_len = buf_len;
+                       if (buf_len < len) {
+                               dbg("requested 0x%x bytes, got only 0x%x bytes", len, buf_len);
+                               return NULL;
+                       }
+               }
+
+               return &(id->seekbuf[off - id->seekbuf_off]);
+       }
+}
+
+void volume_id_free_buffer(struct volume_id *id)
+{
+       if (id->sbbuf != NULL) {
+               free(id->sbbuf);
+               id->sbbuf = NULL;
+               id->sbbuf_len = 0;
+       }
+       if (id->seekbuf != NULL) {
+               free(id->seekbuf);
+               id->seekbuf = NULL;
+               id->seekbuf_len = 0;
+       }
+}
diff --git a/extras/volume_id/volume_id/util.h b/extras/volume_id/volume_id/util.h
new file mode 100644 (file)
index 0000000..e5cd63e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_UTIL_
+#define _VOLUME_ID_UTIL_
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+/* size of superblock buffer, reiserfs block is at 64k */
+#define SB_BUFFER_SIZE                         0x11000
+/* size of seek buffer, FAT cluster is 32k max */
+#define SEEK_BUFFER_SIZE                       0x10000
+
+/* probe volume for all known filesystems in specific order */
+#define bswap16(x) (__u16)((((__u16)(x) & 0x00ffu) << 8) | \
+                          (((__u16)(x) & 0xff00u) >> 8))
+
+#define bswap32(x) (__u32)((((__u32)(x) & 0xff000000u) >> 24) | \
+                          (((__u32)(x) & 0x00ff0000u) >>  8) | \
+                          (((__u32)(x) & 0x0000ff00u) <<  8) | \
+                          (((__u32)(x) & 0x000000ffu) << 24))
+
+#define bswap64(x) (__u64)((((__u64)(x) & 0xff00000000000000ull) >> 56) | \
+                          (((__u64)(x) & 0x00ff000000000000ull) >> 40) | \
+                          (((__u64)(x) & 0x0000ff0000000000ull) >> 24) | \
+                          (((__u64)(x) & 0x000000ff00000000ull) >>  8) | \
+                          (((__u64)(x) & 0x00000000ff000000ull) <<  8) | \
+                          (((__u64)(x) & 0x0000000000ff0000ull) << 24) | \
+                          (((__u64)(x) & 0x000000000000ff00ull) << 40) | \
+                          (((__u64)(x) & 0x00000000000000ffull) << 56))
+
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+#define le16_to_cpu(x) (x)
+#define le32_to_cpu(x) (x)
+#define le64_to_cpu(x) (x)
+#define be16_to_cpu(x) bswap16(x)
+#define be32_to_cpu(x) bswap32(x)
+#elif (__BYTE_ORDER == __BIG_ENDIAN)
+#define le16_to_cpu(x) bswap16(x)
+#define le32_to_cpu(x) bswap32(x)
+#define le64_to_cpu(x) bswap64(x)
+#define be16_to_cpu(x) (x)
+#define be32_to_cpu(x) (x)
+#endif
+
+enum uuid_format {
+       UUID_DCE,
+       UUID_DOS,
+       UUID_NTFS,
+       UUID_HFS,
+};
+
+enum endian {
+       LE = 0,
+       BE = 1
+};
+
+extern void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id);
+extern void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id);
+extern void volume_id_set_label_raw(struct volume_id *id, const __u8 *buf, unsigned int count);
+extern void volume_id_set_label_string(struct volume_id *id, const __u8 *buf, unsigned int count);
+extern void volume_id_set_label_unicode16(struct volume_id *id, const __u8 *buf, enum endian endianess, unsigned int count);
+extern void volume_id_set_uuid(struct volume_id *id, const __u8 *buf, enum uuid_format format);
+extern __u8 *volume_id_get_buffer(struct volume_id *id, __u64 off, unsigned int len);
+extern void volume_id_free_buffer(struct volume_id *id);
+
+#endif /* _VOLUME_ID_UTIL_ */
+
diff --git a/extras/volume_id/volume_id/volume_id.c b/extras/volume_id/volume_id/volume_id.c
new file mode 100644 (file)
index 0000000..e1d4b1c
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <asm/types.h>
+
+#include "volume_id.h"
+#include "logging.h"
+#include "util.h"
+
+#include "ext/ext.h"
+#include "reiserfs/reiserfs.h"
+#include "fat/fat.h"
+#include "hfs/hfs.h"
+#include "jfs/jfs.h"
+#include "xfs/xfs.h"
+#include "ufs/ufs.h"
+#include "ntfs/ntfs.h"
+#include "iso9660/iso9660.h"
+#include "udf/udf.h"
+#include "highpoint/highpoint.h"
+#include "linux_swap/linux_swap.h"
+#include "linux_raid/linux_raid.h"
+#include "lvm/lvm.h"
+#include "mac/mac.h"
+#include "msdos/msdos.h"
+
+int volume_id_probe_all(struct volume_id *id, unsigned long long off, unsigned long long size)
+{
+       if (id == NULL)
+               return -EINVAL;
+
+       /* probe for raid first, cause fs probes may be successful on raid members */
+       if (volume_id_probe_linux_raid(id, off, size) == 0)
+               goto exit;
+
+       if (volume_id_probe_lvm1(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_lvm2(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_highpoint_ataraid(id, off) == 0)
+               goto exit;
+
+       /* signature in the first block, only small buffer needed */
+       if (volume_id_probe_vfat(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_mac_partition_map(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_xfs(id, off) == 0)
+               goto exit;
+
+       /* fill buffer with maximum */
+       volume_id_get_buffer(id, 0, SB_BUFFER_SIZE);
+
+       if (volume_id_probe_linux_swap(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_ext(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_reiserfs(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_jfs(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_udf(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_iso9660(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_hfs_hfsplus(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_ufs(id, off) == 0)
+               goto exit;
+
+       if (volume_id_probe_ntfs(id, off)  == 0)
+               goto exit;
+
+       return -1;
+
+exit:
+       /* If the filestystem in recognized, we free the allocated buffers,
+          otherwise they will stay in place for the possible next probe call */
+       volume_id_free_buffer(id);
+
+       return 0;
+}
+
+/* open volume by already open file descriptor */
+struct volume_id *volume_id_open_fd(int fd)
+{
+       struct volume_id *id;
+
+       id = malloc(sizeof(struct volume_id));
+       if (id == NULL)
+               return NULL;
+       memset(id, 0x00, sizeof(struct volume_id));
+
+       id->fd = fd;
+
+       return id;
+}
+
+/* open volume by device node */
+struct volume_id *volume_id_open_node(const char *path)
+{
+       struct volume_id *id;
+       int fd;
+
+       fd = open(path, O_RDONLY);
+       if (fd < 0) {
+               dbg("unable to open '%s'", path);
+               return NULL;
+       }
+
+       id = volume_id_open_fd(fd);
+       if (id == NULL)
+               return NULL;
+
+       /* close fd on device close */
+       id->fd_close = 1;
+
+       return id;
+}
+
+/* open volume by major/minor */
+struct volume_id *volume_id_open_dev_t(dev_t devt)
+{
+       struct volume_id *id;
+       __u8 tmp_node[VOLUME_ID_PATH_MAX];
+
+       snprintf(tmp_node, VOLUME_ID_PATH_MAX,
+                "/dev/.volume_id-%u-%u-%u", getpid(), major(devt), minor(devt));
+       tmp_node[VOLUME_ID_PATH_MAX] = '\0';
+
+       /* create tempory node to open the block device */
+       unlink(tmp_node);
+       if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
+               return NULL;
+
+       id = volume_id_open_node(tmp_node);
+
+       unlink(tmp_node);
+
+       return id;
+}
+
+void volume_id_close(struct volume_id *id)
+{
+       if (id == NULL)
+               return;
+
+       if (id->fd_close != 0)
+               close(id->fd);
+
+       volume_id_free_buffer(id);
+
+       if (id->partitions != NULL)
+               free(id->partitions);
+
+       free(id);
+}
similarity index 70%
rename from extras/volume_id/volume_id.h
rename to extras/volume_id/volume_id/volume_id.h
index 9d66b196b7b41424c54fd40346c1c8388f4e9831..6c25a243c3fde2c1071a5151429e2c1cb4139b2e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * volume_id - reads partition label and uuid
  *
- * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
  *
  *     This library is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,7 @@
 #ifndef _VOLUME_ID_H_
 #define _VOLUME_ID_H_
 
-#define VOLUME_ID_VERSION              28
+#define VOLUME_ID_VERSION              31
 
 #define VOLUME_ID_LABEL_SIZE           64
 #define VOLUME_ID_UUID_SIZE            16
@@ -37,35 +37,12 @@ enum volume_id_usage {
        VOLUME_ID_FILESYSTEM,
        VOLUME_ID_PARTITIONTABLE,
        VOLUME_ID_RAID,
-};
-
-enum volume_id_type {
-       VOLUME_ID_ALL,
-       VOLUME_ID_MSDOSPARTTABLE,
-       VOLUME_ID_MSDOSEXTENDED,
-       VOLUME_ID_SWAP,
-       VOLUME_ID_EXT2,
-       VOLUME_ID_EXT3,
-       VOLUME_ID_REISERFS,
-       VOLUME_ID_XFS,
-       VOLUME_ID_JFS,
-       VOLUME_ID_VFAT,
-       VOLUME_ID_UDF,
-       VOLUME_ID_ISO9660,
-       VOLUME_ID_NTFS,
-       VOLUME_ID_MACPARTMAP,
-       VOLUME_ID_HFS,
-       VOLUME_ID_HFSPLUS,
-       VOLUME_ID_UFS,
-       VOLUME_ID_LINUX_RAID,
-       VOLUME_ID_LVM1,
-       VOLUME_ID_LVM2,
-       VOLUME_ID_HPTRAID,
+       VOLUME_ID_DISKLABEL,
 };
 
 struct volume_id_partition {
        enum            volume_id_usage usage_id;
-       enum            volume_id_type type_id;
+       char            *usage;
        char            *type;
        unsigned long long off;
        unsigned long long len;
@@ -79,11 +56,13 @@ struct volume_id {
        unsigned char   uuid_raw[VOLUME_ID_UUID_SIZE];
        char            uuid[VOLUME_ID_UUID_STRING_SIZE];
        enum            volume_id_usage usage_id;
-       enum            volume_id_type type_id;
+       char            *usage;
        char            *type;
        char            type_version[VOLUME_ID_FORMAT_SIZE];
+
        struct volume_id_partition *partitions;
        unsigned int    partition_count;
+
        int             fd;
        unsigned char   *sbbuf;
        unsigned int    sbbuf_len;
@@ -93,20 +72,10 @@ struct volume_id {
        int             fd_close;
 };
 
-/* open volume by already open file descriptor */
 extern struct volume_id *volume_id_open_fd(int fd);
-
-/* open volume by device node */
 extern struct volume_id *volume_id_open_node(const char *path);
-
-/* open volume by major/minor */
 extern struct volume_id *volume_id_open_dev_t(dev_t devt);
-
-/* probe volume for filesystem type and try to read label/uuid */
-extern int volume_id_probe(struct volume_id *id, enum volume_id_type type,
-                          unsigned long long off, unsigned long long size);
-
-/* free allocated device info */
+extern int volume_id_probe_all(struct volume_id *id, unsigned long long off, unsigned long long size);
 extern void volume_id_close(struct volume_id *id);
 
 #endif
diff --git a/extras/volume_id/volume_id/xfs/xfs.c b/extras/volume_id/volume_id/xfs/xfs.c
new file mode 100644 (file)
index 0000000..b73f565
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "../volume_id.h"
+#include "../logging.h"
+#include "../util.h"
+#include "xfs.h"
+
+int volume_id_probe_xfs(struct volume_id *id, __u64 off)
+{
+       struct xfs_super_block {
+               __u8    magic[4];
+               __u32   blocksize;
+               __u64   dblocks;
+               __u64   rblocks;
+               __u32   dummy1[2];
+               __u8    uuid[16];
+               __u32   dummy2[15];
+               __u8    fname[12];
+               __u32   dummy3[2];
+               __u64   icount;
+               __u64   ifree;
+               __u64   fdblocks;
+       } __attribute__((__packed__)) *xs;
+
+       xs = (struct xfs_super_block *) volume_id_get_buffer(id, off, 0x200);
+       if (xs == NULL)
+               return -1;
+
+       if (strncmp(xs->magic, "XFSB", 4) != 0)
+               return -1;
+
+       volume_id_set_label_raw(id, xs->fname, 12);
+       volume_id_set_label_string(id, xs->fname, 12);
+       volume_id_set_uuid(id, xs->uuid, UUID_DCE);
+
+       volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
+       id->type = "xfs";
+
+       return 0;
+}
diff --git a/extras/volume_id/volume_id/xfs/xfs.h b/extras/volume_id/volume_id/xfs/xfs.h
new file mode 100644 (file)
index 0000000..76b1725
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *     This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     This library 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
+ *     Lesser General Public License for more details.
+ *
+ *     You should have received a copy of the GNU Lesser General Public
+ *     License along with this library; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID__
+#define _VOLUME_ID__
+
+extern int volume_id_probe_xfs(struct volume_id *id, __u64 off);
+
+#endif