]> err.no Git - util-linux/commitdiff
blkid: add HTFS
authorKarel Zak <kzak@redhat.com>
Mon, 13 Oct 2008 10:16:28 +0000 (12:16 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 11 Feb 2009 22:21:46 +0000 (23:21 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libs/blkid/src/probe.c
libs/blkid/src/probers/Makefile.am
libs/blkid/src/probers/ntfs.c [new file with mode: 0644]
libs/blkid/src/probers/probers.h

index ee59c2c7449a93175e6ed764fc45a7c57e2c58bf..3ea81052b48d30be35b413fef84a33f91da3756e 100644 (file)
@@ -65,7 +65,8 @@ static const struct blkid_idinfo *idinfos[] =
        &reiser4_idinfo,
        &jbd_idinfo,
        &hfsplus_idinfo,
-       &hfs_idinfo
+       &hfs_idinfo,
+       &ntfs_idinfo
 };
 
 #ifndef ARRAY_SIZE
index 67a68183898ac5846bb77f325cb792082e046229..f19a82eef87032e50241c16603edc67f6f782d59 100644 (file)
@@ -24,6 +24,7 @@ libprobers_a_SOURCES =        probers.h \
                        ocfs.c \
                        reiserfs.c \
                        romfs.c \
+                       ntfs.c \
                        hfs.c
 
 all-local: $(lib_LIBRARIES)
diff --git a/libs/blkid/src/probers/ntfs.c b/libs/blkid/src/probers/ntfs.c
new file mode 100644 (file)
index 0000000..5802c5c
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "blkidP.h"
+
+struct ntfs_super_block {
+       uint8_t         jump[3];
+       uint8_t         oem_id[8];
+       uint8_t         bios_parameter_block[25];
+       uint16_t        unused[2];
+       uint64_t        number_of_sectors;
+       uint64_t        mft_cluster_location;
+       uint64_t        mft_mirror_cluster_location;
+       int8_t          cluster_per_mft_record;
+       uint8_t         reserved1[3];
+       int8_t          cluster_per_index_record;
+       uint8_t         reserved2[3];
+       uint64_t        volume_serial;
+       uint16_t        checksum;
+};
+
+struct master_file_table_record {
+       uint32_t        magic;
+       uint16_t        usa_ofs;
+       uint16_t        usa_count;
+       uint64_t        lsn;
+       uint16_t        sequence_number;
+       uint16_t        link_count;
+       uint16_t        attrs_offset;
+       uint16_t        flags;
+       uint32_t        bytes_in_use;
+       uint32_t        bytes_allocated;
+} __attribute__((__packed__));
+
+struct file_attribute {
+       uint32_t        type;
+       uint32_t        len;
+       uint8_t         non_resident;
+       uint8_t         name_len;
+       uint16_t        name_offset;
+       uint16_t        flags;
+       uint16_t        instance;
+       uint32_t        value_len;
+       uint16_t        value_offset;
+} __attribute__((__packed__));
+
+#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(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       struct ntfs_super_block *ns;
+       struct master_file_table_record *mft;
+       struct file_attribute *attr;
+       unsigned char   label_str[129], *cp;
+       int             bytes_per_sector, sectors_per_cluster;
+       int             mft_record_size, attr_off, attr_len;
+       unsigned int    i, attr_type, val_len;
+       int             val_off;
+       uint64_t                nr_clusters;
+       blkid_loff_t off;
+       unsigned char *buf_mft, *val;
+
+       ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
+       if (!ns)
+               return -1;
+
+       bytes_per_sector = ns->bios_parameter_block[0] +
+               (ns->bios_parameter_block[1]  << 8);
+       sectors_per_cluster = ns->bios_parameter_block[2];
+
+       if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
+               return 1;
+
+       if (ns->cluster_per_mft_record < 0)
+               mft_record_size = 1 << (0 - ns->cluster_per_mft_record);
+       else
+               mft_record_size = ns->cluster_per_mft_record *
+                       sectors_per_cluster * bytes_per_sector;
+       nr_clusters = le64_to_cpu(ns->number_of_sectors) / sectors_per_cluster;
+
+       if ((le64_to_cpu(ns->mft_cluster_location) > nr_clusters) ||
+           (le64_to_cpu(ns->mft_mirror_cluster_location) > nr_clusters))
+               return 1;
+
+       off = le64_to_cpu(ns->mft_mirror_cluster_location) *
+               bytes_per_sector * sectors_per_cluster;
+
+       buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
+       if (!buf_mft)
+               return 1;
+
+       if (memcmp(buf_mft, "FILE", 4))
+               return 1;
+
+       off = le64_to_cpu(ns->mft_cluster_location) * bytes_per_sector *
+               sectors_per_cluster;
+
+       buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
+       if (!buf_mft)
+               return 1;
+
+       if (memcmp(buf_mft, "FILE", 4))
+               return 1;
+
+       off += MFT_RECORD_VOLUME * mft_record_size;
+
+       buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
+       if (!buf_mft)
+               return 1;
+
+       if (memcmp(buf_mft, "FILE", 4))
+               return 1;
+
+       mft = (struct master_file_table_record *) buf_mft;
+
+       attr_off = le16_to_cpu(mft->attrs_offset);
+       label_str[0] = 0;
+
+       while (1) {
+               attr = (struct file_attribute *) (buf_mft + attr_off);
+               attr_len = le16_to_cpu(attr->len);
+               attr_type = le32_to_cpu(attr->type);
+               val_off = le16_to_cpu(attr->value_offset);
+               val_len = le32_to_cpu(attr->value_len);
+
+               attr_off += attr_len;
+
+               if ((attr_off > mft_record_size) ||
+                   (attr_len == 0))
+                       break;
+
+               if (attr_type == MFT_RECORD_ATTR_END)
+                       break;
+
+               if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
+                       if (val_len > sizeof(label_str))
+                               val_len = sizeof(label_str)-1;
+
+                       for (i=0, cp=label_str; i < val_len; i+=2,cp++) {
+                               val = ((uint8_t *) attr) + val_off + i;
+                               *cp = val[0];
+                               if (val[1])
+                                       *cp = '?';
+                       }
+                       *cp = 0;
+               }
+       }
+
+       blkid_probe_sprintf_uuid(pr,
+                       (unsigned char *) &ns->volume_serial,
+                       sizeof(ns->volume_serial),
+                       "%016" PRIX64, le64_to_cpu(ns->volume_serial));
+       if (label_str[0])
+               blkid_probe_set_label(pr, label_str, strlen((char *)label_str));
+       return 0;
+}
+
+
+const struct blkid_idinfo ntfs_idinfo =
+{
+       .name           = "ntfs",
+       .usage          = BLKID_USAGE_FILESYSTEM,
+       .probefunc      = probe_ntfs,
+       .magics         =
+       {
+               { .magic = "NTFS    ", .len = 8, .sboff = 3 },
+               { NULL }
+       }
+};
+
index 4a44a22e1891bf699079108e48356e5270e60a6e..35180e6a4d6bfee1a7626142224780904765528d 100644 (file)
@@ -45,6 +45,7 @@ extern const struct blkid_idinfo reiser_idinfo;
 extern const struct blkid_idinfo reiser4_idinfo;
 extern const struct blkid_idinfo hfs_idinfo;
 extern const struct blkid_idinfo hfsplus_idinfo;
+extern const struct blkid_idinfo ntfs_idinfo;
 
 
 #endif /* _BLKID_PROBE_H */