]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Add more paranoid NTFS probing and fetch UUID and LABEL information
authorTheodore Ts'o <tytso@mit.edu>
Tue, 19 Jun 2007 07:29:47 +0000 (03:29 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 19 Jun 2007 07:29:47 +0000 (03:29 -0400)
Hopefully this addresses false positives by the blkid library when
detecting NTFS partitions.

Addresses Launchpad Bug: #110138

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
lib/blkid/ChangeLog
lib/blkid/probe.c
lib/blkid/probe.h

index 28e0cbd46116e93e81a881f11a7bb5583fb97e7b..d2de7b9c05fee8ab3feb3c962ea3d4e42d88da1f 100644 (file)
@@ -1,3 +1,10 @@
+2007-06-19  Theodore Tso  <tytso@mit.edu>
+
+       * probe.c (probe_ntfs): Add probe function which is more paranoid
+               about checking for a valid NTFS partition, and which sets
+               the UUID and LABEL information.  (Addresses Launchpad Bug
+               #110138)
+
 2007-05-23  Theodore Tso  <tytso@mit.edu>
 
        * getsize.c (main), read.c (parse_dev), tst_types.c (main): Fix
index 3f0829cc6ddda234d0c3e1d35b96ee4cee3736e2..211c8bd4c03e32ed092149b73bbcacd407154f54 100644 (file)
@@ -46,7 +46,7 @@ static int figure_label_len(const unsigned char *label, int len)
 }
 
 static unsigned char *get_buffer(struct blkid_probe *pr, 
-                         unsigned off, size_t len)
+                         blkid_loff_t off, size_t len)
 {
        ssize_t         ret_read;
        unsigned char   *newbuf;
@@ -74,7 +74,7 @@ static unsigned char *get_buffer(struct blkid_probe *pr,
                        pr->buf = newbuf;
                        pr->buf_max = len;
                }
-               if (lseek(pr->fd, off, SEEK_SET) < 0)
+               if (blkid_llseek(pr->fd, off, SEEK_SET) < 0)
                        return NULL;
                ret_read = read(pr->fd, pr->buf, len);
                if (ret_read != (ssize_t) len)
@@ -398,6 +398,111 @@ static int probe_fat_nomagic(struct blkid_probe *probe,
        return probe_fat(probe, id, buf);
 }
 
+static int probe_ntfs(struct blkid_probe *probe,
+                     struct blkid_magic *id __BLKID_ATTR((unused)), 
+                     unsigned char *buf)
+{
+       struct ntfs_super_block *ns;
+       struct master_file_table_record *mft;
+       struct file_attribute *attr;
+       char            uuid_str[17], 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;
+       __u64           nr_clusters;
+       blkid_loff_t off;
+       unsigned char *buf_mft, *val;
+
+       ns = (struct ntfs_super_block *) buf;
+
+       bytes_per_sector = ns->bios_parameter_block[0] +
+               (ns->bios_parameter_block[1]  << 8);
+       sectors_per_cluster = ns->bios_parameter_block[2];
+
+       if (ns->cluster_per_mft_record < 0)
+               mft_record_size = 1 << - ns->cluster_per_mft_record;
+       else
+               mft_record_size = ns->cluster_per_mft_record * 
+                       sectors_per_cluster * bytes_per_sector;
+       nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster;
+
+       if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) ||
+           (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters))
+               return 1;
+
+       off = blkid_le64(ns->mft_mirror_cluster_location) * 
+               bytes_per_sector * sectors_per_cluster;
+
+       buf_mft = get_buffer(probe, off, mft_record_size);
+       if (!buf_mft)
+               return 1;
+
+       if (memcmp(buf_mft, "FILE", 4))
+               return 1;
+
+       off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector * 
+               sectors_per_cluster;
+
+       buf_mft = get_buffer(probe, 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 = get_buffer(probe, 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 = blkid_le16(mft->attrs_offset);
+       label_str[0] = 0;
+       
+       while (1) {
+               attr = (struct file_attribute *) (buf_mft + attr_off);
+               attr_len = blkid_le16(attr->len);
+               attr_type = blkid_le32(attr->type);
+               val_off = blkid_le16(attr->value_offset);
+               val_len = blkid_le32(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 = ((__u8 *) attr) + val_off + i;
+                               *cp = val[0];
+                               if (val[1])
+                                       *cp = '?';
+                       }
+                       *cp = 0;
+               }
+       }
+
+       sprintf(uuid_str, "%llX", blkid_le64(ns->volume_serial));
+       blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
+       if (label_str[0])
+               blkid_set_tag(probe->dev, "LABEL", label_str, 0);
+       return 0;
+}
+
+
 static int probe_xfs(struct blkid_probe *probe,
                     struct blkid_magic *id __BLKID_ATTR((unused)), 
                     unsigned char *buf)
@@ -709,7 +814,7 @@ static int probe_gfs2(struct blkid_probe *probe,
 static struct blkid_magic type_array[] = {
 /*  type     kboff   sboff len  magic                  probe */
   { "oracleasm", 0,    32,  8, "ORCLDISK",             probe_oracleasm },
-  { "ntfs",      0,      3,  8, "NTFS    ",             0 },
+  { "ntfs",     0,      3,  8, "NTFS    ",             probe_ntfs },
   { "jbd",      1,   0x38,  2, "\123\357",             probe_jbd },
   { "ext3",     1,   0x38,  2, "\123\357",             probe_ext3 },
   { "ext2",     1,   0x38,  2, "\123\357",             probe_ext2 },
index 88bf3116c8cd0e9ef98ba10791d9eaf61310751d..f22fb2ecefcfeebfad5b9305c0294cbeca8d610f 100644 (file)
@@ -393,6 +393,53 @@ struct gfs2_sb {
        /* In gfs1, quota and license dinodes followed */
 };
 
+struct ntfs_super_block {
+       __u8    jump[3];
+       __u8    oem_id[8];
+       __u8    bios_parameter_block[25];
+       __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];
+       __u64   volume_serial;
+       __u16   checksum;
+};
+
+struct master_file_table_record {
+       __u32   magic;
+       __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__));
+
+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__));
+
+#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
+
 /*
  * Byte swap functions
  */