chiark / gitweb /
[PATCH] update udev_volume_id
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Sat, 26 Jun 2004 08:18:21 +0000 (01:18 -0700)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:36:21 +0000 (21:36 -0700)
volume_id is now able to read NTFS labels. Not very exciting, but we
keep up to date with the version in HAL. Also __packed__ was needed for
the structs, cause the gcc 3.4 compiled version was no longer working
properly.

extras/volume_id/volume_id.c
extras/volume_id/volume_id.h

index dcc341c4dd89caff1635ea1215db00069acb0317..ac7e76b9d4740aa6b3f919a48866b4a72eceed4e 100644 (file)
@@ -7,7 +7,7 @@
  *     the e2fsprogs. This is a simple straightforward implementation for
  *     reading the label strings of only the most common filesystems.
  *     If you need a full featured library with attribute caching, support for
  *     the e2fsprogs. This is a simple straightforward implementation for
  *     reading the label strings of only the most common filesystems.
  *     If you need a full featured library with attribute caching, support for
- *     much more partition/media types or non-root data access, you may have
+ *     much more partition/media types or non-root disk access, you may have
  *     a look at:
  *             http://e2fsprogs.sourceforge.net.
  *
  *     a look at:
  *             http://e2fsprogs.sourceforge.net.
  *
  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
                           (((__u32)(x) & 0x0000ff00u) <<  8) | \
                           (((__u32)(x) & 0x000000ffu) << 24))
 
                           (((__u32)(x) & 0x0000ff00u) <<  8) | \
                           (((__u32)(x) & 0x000000ffu) << 24))
 
+#define bswap64(x) (__u64)((((__u64)(x) & 0xff00000000000000u) >> 56) | \
+                          (((__u64)(x) & 0x00ff000000000000u) >> 40) | \
+                          (((__u64)(x) & 0x0000ff0000000000u) >> 24) | \
+                          (((__u64)(x) & 0x000000ff00000000u) >>  8) | \
+                          (((__u64)(x) & 0x00000000ff000000u) <<  8) | \
+                          (((__u64)(x) & 0x0000000000ff0000u) << 24) | \
+                          (((__u64)(x) & 0x000000000000ff00u) << 40) | \
+                          (((__u64)(x) & 0x00000000000000ffu) << 56))
+
 #if (__BYTE_ORDER == __LITTLE_ENDIAN) 
 #define le16_to_cpu(x) (x)
 #define le32_to_cpu(x) (x)
 #if (__BYTE_ORDER == __LITTLE_ENDIAN) 
 #define le16_to_cpu(x) (x)
 #define le32_to_cpu(x) (x)
+#define le64_to_cpu(x) (x)
 #elif (__BYTE_ORDER == __BIG_ENDIAN)
 #define le16_to_cpu(x) bswap16(x)
 #define le32_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)
 #endif
 
 /* size of superblock buffer, reiser block is at 64k */
 #endif
 
 /* size of superblock buffer, reiser block is at 64k */
 #define SEEK_BUFFER_SIZE                       0x800
 
 
 #define SEEK_BUFFER_SIZE                       0x800
 
 
-static void set_label_raw(struct volume_id *id, char *buf, int count)
+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;
 }
 
 {
        memcpy(id->label_raw, buf, count);
        id->label_raw_len = count;
 }
 
-static void set_label_string(struct volume_id *id, char *buf, int count)
+static void set_label_string(struct volume_id *id,
+                            const __u8 *buf, unsigned int count)
 {
 {
-       int i;
+       unsigned int i;
 
        memcpy(id->label_string, buf, count);
 
 
        memcpy(id->label_string, buf, count);
 
@@ -90,9 +107,42 @@ static void set_label_string(struct volume_id *id, char *buf, int count)
        id->label_string[i+1] = '\0';
 }
 
        id->label_string[i+1] = '\0';
 }
 
-static void set_uuid(struct volume_id *id, unsigned char *buf, int count)
+#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 <= count-2; 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_string[j] = '\0';
+                       break;
+               } else if (c < 0x80) {
+                       id->label_string[j++] = (__u8) c;
+               } else if (c < 0x800) {
+                       id->label_string[j++] = (__u8) (0xc0 | (c >> 6));
+                       id->label_string[j++] = (__u8) (0x80 | (c & 0x3f));
+               } else {
+                       id->label_string[j++] = (__u8) (0xe0 | (c >> 12));
+                       id->label_string[j++] = (__u8) (0x80 | ((c >> 6) & 0x3f));
+                       id->label_string[j++] = (__u8) (0x80 | (c & 0x3f));
+               }
+       }
+}
+
+static void set_uuid(struct volume_id *id,
+                    const __u8 *buf, unsigned int count)
 {
 {
-       int i;
+       unsigned int i;
 
        memcpy(id->uuid, buf, count);
 
 
        memcpy(id->uuid, buf, count);
 
@@ -121,9 +171,10 @@ set:
        }
 }
 
        }
 }
 
-static char *get_buffer(struct volume_id *id, size_t off, size_t len)
+static __u8 *get_buffer(struct volume_id *id,
+                       unsigned long off, unsigned int len)
 {
 {
-       size_t buf_len;
+       unsigned int buf_len;
 
        /* check if requested area fits in superblock buffer */
        if (off + len <= SB_BUFFER_SIZE) {
 
        /* check if requested area fits in superblock buffer */
        if (off + len <= SB_BUFFER_SIZE) {
@@ -135,8 +186,8 @@ static char *get_buffer(struct volume_id *id, size_t off, size_t len)
 
                /* check if we need to read */
                if ((off + len) > id->sbbuf_len) {
 
                /* check if we need to read */
                if ((off + len) > id->sbbuf_len) {
-                       dbg("read sbbuf len:0x%x", off + len);
-                       lseek(id->fd, 0, SEEK_SET);
+                       dbg("read sbbuf len:0x%lx", off + len);
+                       lseek64(id->fd, 0, SEEK_SET);
                        buf_len = read(id->fd, id->sbbuf, off + len);
                        id->sbbuf_len = buf_len;
                        if (buf_len < off + len)
                        buf_len = read(id->fd, id->sbbuf, off + len);
                        id->sbbuf_len = buf_len;
                        if (buf_len < off + len)
@@ -158,9 +209,10 @@ static char *get_buffer(struct volume_id *id, size_t off, size_t len)
                /* check if we need to read */
                if ((off < id->seekbuf_off) ||
                    ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
                /* check if we need to read */
                if ((off < id->seekbuf_off) ||
                    ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
-                       dbg("read seekbuf off:0x%x len:0x%x", off, len);
-                       lseek(id->fd, off, SEEK_SET);
+                       dbg("read seekbuf off:0x%lx len:0x%x", off, len);
+                       lseek64(id->fd, off, SEEK_SET);
                        buf_len = read(id->fd, id->seekbuf, len);
                        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)
                        id->seekbuf_off = off;
                        id->seekbuf_len = buf_len;
                        if (buf_len < len)
@@ -191,23 +243,23 @@ static void free_buffer(struct volume_id *id)
 static int probe_ext(struct volume_id *id)
 {
        struct ext2_super_block {
 static int probe_ext(struct volume_id *id)
 {
        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];
-               unsigned char   magic[2];
-               __u16           state;
-               __u32           dummy5[8];
-               __u32           feature_compat;
-               __u32           feature_incompat;
-               __u32           feature_ro_compat;
-               unsigned char   uuid[16];
-               char            volume_name[16];
-       } *es;
+               __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, EXT_SUPERBLOCK_OFFSET, 0x200);
 
        es = (struct ext2_super_block *)
             get_buffer(id, EXT_SUPERBLOCK_OFFSET, 0x200);
@@ -239,20 +291,20 @@ static int probe_ext(struct volume_id *id)
 static int probe_reiser(struct volume_id *id)
 {
        struct reiser_super_block {
 static int probe_reiser(struct volume_id *id)
 {
        struct reiser_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];
-               unsigned char   magic[12];
-               __u32           dummy4[5];
-               unsigned char   uuid[16];
-               char            label[16];
-       } *rs;
+               __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 reiser_super_block *)
             get_buffer(id, REISER_SUPERBLOCK_OFFSET, 0x200);
 
        rs = (struct reiser_super_block *)
             get_buffer(id, REISER_SUPERBLOCK_OFFSET, 0x200);
@@ -288,19 +340,19 @@ found:
 static int probe_xfs(struct volume_id *id)
 {
        struct xfs_super_block {
 static int probe_xfs(struct volume_id *id)
 {
        struct xfs_super_block {
-               unsigned char   magic[4];
-               __u32           blocksize;
-               __u64           dblocks;
-               __u64           rblocks;
-               __u32           dummy1[2];
-               unsigned char   uuid[16];
-               __u32           dummy2[15];
-               char            fname[12];
-               __u32           dummy3[2];
-               __u64           icount;
-               __u64           ifree;
-               __u64           fdblocks;
-       } *xs;
+               __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, 0, 0x200);
        if (xs == NULL)
 
        xs = (struct xfs_super_block *) get_buffer(id, 0, 0x200);
        if (xs == NULL)
@@ -323,17 +375,17 @@ static int probe_xfs(struct volume_id *id)
 static int probe_jfs(struct volume_id *id)
 {
        struct jfs_super_block {
 static int probe_jfs(struct volume_id *id)
 {
        struct jfs_super_block {
-               unsigned char   magic[4];
-               __u32           version;
-               __u64           size;
-               __u32           bsize;
-               __u32           dummy1;
-               __u32           pbsize;
-               __u32           dummy2[27];
-               unsigned char   uuid[16];
-               unsigned char   label[16];
-               unsigned char   loguuid[16];
-       } *js;
+               __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, JFS_SUPERBLOCK_OFFSET, 0x200);
 
        js = (struct jfs_super_block *)
             get_buffer(id, JFS_SUPERBLOCK_OFFSET, 0x200);
@@ -356,34 +408,34 @@ static int probe_jfs(struct volume_id *id)
 static int probe_vfat(struct volume_id *id)
 {
        struct vfat_super_block {
 static int probe_vfat(struct volume_id *id)
 {
        struct vfat_super_block {
-               unsigned char   ignored[3];
-               unsigned char   sysid[8];
-               unsigned char   sector_size[2];
-               __u8            cluster_size;
-               __u16           reserved;
-               __u8            fats;
-               unsigned char   dir_entries[2];
-               unsigned char   sectors[2];
-               unsigned char   media;
-               __u16           fat_length;
-               __u16           secs_track;
-               __u16           heads;
-               __u32           hidden;
-               __u32           total_sect;
-               __u32           fat32_length;
-               __u16           flags;
-               __u8            version[2];
-               __u32           root_cluster;
-               __u16           insfo_sector;
-               __u16           backup_boot;
-               __u16           reserved2[6];
-               unsigned char   unknown[3];
-               unsigned char   serno[4];
-               char            label[11];
-               unsigned char   magic[8];
-               unsigned char   dummy2[164];
-               unsigned char   pmagic[2];
-       } *vs;
+               __u8    ignored[3];
+               __u8    sysid[8];
+               __u8    sector_size[2];
+               __u8    cluster_size;
+               __u16   reserved;
+               __u8    fats;
+               __u8    dir_entries[2];
+               __u8    sectors[2];
+               __u8    media;
+               __u16   fat_length;
+               __u16   secs_track;
+               __u16   heads;
+               __u32   hidden;
+               __u32   total_sect;
+               __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__)) *vs;
 
        vs = (struct vfat_super_block *) get_buffer(id, 0, 0x200);
        if (vs == NULL)
 
        vs = (struct vfat_super_block *) get_buffer(id, 0, 0x200);
        if (vs == NULL)
@@ -409,27 +461,27 @@ found:
 static int probe_msdos(struct volume_id *id)
 {
        struct msdos_super_block {
 static int probe_msdos(struct volume_id *id)
 {
        struct msdos_super_block {
-               unsigned char   ignored[3];
-               unsigned char   sysid[8];
-               unsigned char   sector_size[2];
-               __u8            cluster_size;
-               __u16           reserved;
-               __u8            fats;
-               unsigned char   dir_entries[2];
-               unsigned char   sectors[2];
-               unsigned char   media;
-               __u16           fat_length;
-               __u16           secs_track;
-               __u16           heads;
-               __u32           hidden;
-               __u32           total_sect;
-               unsigned char   unknown[3];
-               unsigned char   serno[4];
-               char            label[11];
-               unsigned char   magic[8];
-               unsigned char   dummy2[192];
-               unsigned char   pmagic[2];
-       } *ms;
+               __u8    ignored[3];
+               __u8    sysid[8];
+               __u8    sector_size[2];
+               __u8    cluster_size;
+               __u16   reserved;
+               __u8    fats;
+               __u8    dir_entries[2];
+               __u8    sectors[2];
+               __u8    media;
+               __u16   fat_length;
+               __u16   secs_track;
+               __u16   heads;
+               __u32   hidden;
+               __u32   total_sect;
+               __u8    unknown[3];
+               __u8    serno[4];
+               __u8    label[11];
+               __u8    magic[8];
+               __u8    dummy2[192];
+               __u8    pmagic[2];
+       } __attribute__((__packed__)) *ms;
 
        ms = (struct msdos_super_block *) get_buffer(id, 0, 0x200);
        if (ms == NULL)
 
        ms = (struct msdos_super_block *) get_buffer(id, 0, 0x200);
        if (ms == NULL)
@@ -459,45 +511,43 @@ static int probe_udf(struct volume_id *id)
 {
        struct volume_descriptor {
                struct descriptor_tag {
 {
        struct volume_descriptor {
                struct descriptor_tag {
-                       __u16           id;
-                       __u16           version;
-                       unsigned char   checksum;
-                       unsigned char   reserved;
-                       __u16           serial;
-                       __u16           crc;
-                       __u16           crc_len;
-                       __u32           location;
-               } 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 {
                union {
                        struct anchor_descriptor {
-                               __u32           length;
-                               __u32           location;
-                       } anchor;
+                               __u32   length;
+                               __u32   location;
+                       } __attribute__((__packed__)) anchor;
                        struct primary_descriptor {
                        struct primary_descriptor {
-                               __u32           seq_num;
-                               __u32           desc_num;
+                               __u32   seq_num;
+                               __u32   desc_num;
                                struct dstring {
                                struct dstring {
-                                       char            clen;
-                                       char            c[31];
-                               } ident;
-                       } primary;
-               } type;
-       } *vd;
+                                       __u8    clen;
+                                       __u8    c[31];
+                               } __attribute__((__packed__)) ident;
+                       } __attribute__((__packed__)) primary;
+               } __attribute__((__packed__)) type;
+       } __attribute__((__packed__)) *vd;
 
        struct volume_structure_descriptor {
 
        struct volume_structure_descriptor {
-               unsigned char   type;
-               char            id[5];
-               unsigned char   version;
+               __u8    type;
+               __u8    id[5];
+               __u8    version;
        } *vsd;
 
        } *vsd;
 
-       size_t bs;
-       size_t b;
-       int type;
-       int count;
-       int loc;
-       int clen;
-       int i,j;
-       int c;
+       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, UDF_VSD_OFFSET, 0x200);
 
        vsd = (struct volume_structure_descriptor *)
              get_buffer(id, UDF_VSD_OFFSET, 0x200);
@@ -594,29 +644,10 @@ pvd:
 
        clen = vd->type.primary.ident.clen;
        dbg("label string charsize=%i bit", clen);
 
        clen = vd->type.primary.ident.clen;
        dbg("label string charsize=%i bit", clen);
-       if (clen == 8) {
+       if (clen == 8) 
                set_label_string(id, vd->type.primary.ident.c, 31);
                set_label_string(id, vd->type.primary.ident.c, 31);
-       } else if (clen == 16) {
-               /* convert unicode OSTA dstring to UTF-8 */
-               j = 0;
-               for (i = 0; i < 32; i += 2) {
-                       c = (vd->type.primary.ident.c[i] << 8) |
-                           vd->type.primary.ident.c[i+1];
-                       if (c == 0) {
-                               id->label_string[j] = '\0';
-                               break;
-                       }else if (c < 0x80U) {
-                               id->label_string[j++] = (char) c;
-                       } else if (c < 0x800U) {
-                               id->label_string[j++] = (char) (0xc0 | (c >> 6));
-                               id->label_string[j++] = (char) (0x80 | (c & 0x3f));
-                       } else {
-                               id->label_string[j++] = (char) (0xe0 | (c >> 12));
-                               id->label_string[j++] = (char) (0x80 | ((c >> 6) & 0x3f));
-                               id->label_string[j++] = (char) (0x80 | (c & 0x3f));
-                       }
-               }
-       }
+       else if (clen == 16)
+               set_label_unicode16(id, vd->type.primary.ident.c, BE,31);
 
 found:
        id->fs_type = UDF;
 
 found:
        id->fs_type = UDF;
@@ -630,20 +661,20 @@ static int probe_iso9660(struct volume_id *id)
 {
        union iso_super_block {
                struct iso_header {
 {
        union iso_super_block {
                struct iso_header {
-                       unsigned char   type;
-                       char            id[5];
-                       unsigned char   version;
-                       unsigned char   unused1;
-                       char            system_id[32];
-                       char            volume_id[32];
-               } iso;
+                       __u8    type;
+                       __u8    id[5];
+                       __u8    version;
+                       __u8    unused1;
+                       __u8            system_id[32];
+                       __u8            volume_id[32];
+               } __attribute__((__packed__)) iso;
                struct hs_header {
                struct hs_header {
-                       char            foo[8];
-                       unsigned char   type;
-                       char            id[4];
-                       unsigned char   version;
-               } hs;
-       } *is;
+                       __u8    foo[8];
+                       __u8    type;
+                       __u8    id[4];
+                       __u8    version;
+               } __attribute__((__packed__)) hs;
+       } __attribute__((__packed__)) *is;
 
        is = (union iso_super_block *)
             get_buffer(id, ISO_SUPERBLOCK_OFFSET, 0x200);
 
        is = (union iso_super_block *)
             get_buffer(id, ISO_SUPERBLOCK_OFFSET, 0x200);
@@ -666,12 +697,73 @@ found:
        return 0;
 }
 
        return 0;
 }
 
+#define MFT_RECORD_VOLUME                      3
+#define MFT_RECORD_ATTR_VOLUME_NAME            0x60u
+#define MFT_RECORD_ATTR_OBJECT_ID              0x40u
+#define MFT_RECORD_ATTR_END                    0xffffffffu
 static int probe_ntfs(struct volume_id *id)
 {
        struct ntfs_super_block {
 static int probe_ntfs(struct volume_id *id)
 {
        struct ntfs_super_block {
-               char jump[3];
-               char oem_id[4];
-       } *ns;
+               __u8    jump[3];
+               __u8    oem_id[8];
+               struct bios_param_block {
+                       __u16   bytes_per_sector;
+                       __u8    sectors_per_cluster;
+                       __u16   reserved_sectors;
+                       __u8    fats;
+                       __u16   root_entries;
+                       __u16   sectors;
+                       __u8    media_type;             /* 0xf8 = hard disk */
+                       __u16   sectors_per_fat;
+                       __u16   sectors_per_track;
+                       __u16   heads;
+                       __u32   hidden_sectors;
+                       __u32   large_sectors;
+               } __attribute__((__packed__)) bpb;
+               __u8 unused[4];
+               __u64   number_of_sectors;
+               __u64   mft_cluster_location;
+               __u64   mft_mirror_cluster_location;
+               __s8    cluster_per_mft_record;
+       } __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;
+
+       unsigned int    sector_size;
+       unsigned int    cluster_size;
+       unsigned long   mft_cluster;
+       unsigned long   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, 0, 0x200);
        if (ns == NULL)
 
        ns = (struct ntfs_super_block *) get_buffer(id, 0, 0x200);
        if (ns == NULL)
@@ -680,6 +772,78 @@ static int probe_ntfs(struct volume_id *id)
        if (strncmp(ns->oem_id, "NTFS", 4) != 0)
                return -1;
 
        if (strncmp(ns->oem_id, "NTFS", 4) != 0)
                return -1;
 
+       sector_size = le16_to_cpu(ns->bpb.bytes_per_sector);
+       cluster_size = ns->bpb.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  %li", mft_cluster);
+       dbg("mftoffset  0x%lx", 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, 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[0] = '%c' %03d, 0x%02x", mftr->magic[0], mftr->magic[0], mftr->magic[0]);
+       dbg("mftr->magic[1] = '%c' %03d, 0x%02x", mftr->magic[1], mftr->magic[1], mftr->magic[1]);
+       dbg("mftr->magic[2] = '%c' %03d, 0x%02x", mftr->magic[2], mftr->magic[2], mftr->magic[2]);
+       dbg("mftr->magic[3] = '%c' %03d, 0x%02x", mftr->magic[3], mftr->magic[3], 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);
+
+               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_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);
+               }
+
+               if (attr_type == MFT_RECORD_ATTR_OBJECT_ID) {
+                       dbg("found uuid");
+                       val = &((__u8 *) attr)[val_off];
+                       set_uuid(id, val, 16);
+               }
+
+               if (attr_len == 0)
+                       break;
+               attr_off += attr_len;
+               if (attr_off >= mft_record_size)
+                       break;
+       }
+
+found:
        id->fs_type = NTFS;
        id->fs_name = "ntfs";
 
        id->fs_type = NTFS;
        id->fs_name = "ntfs";
 
@@ -689,8 +853,8 @@ static int probe_ntfs(struct volume_id *id)
 #define LARGEST_PAGESIZE                       0x4000
 static int probe_swap(struct volume_id *id)
 {
 #define LARGEST_PAGESIZE                       0x4000
 static int probe_swap(struct volume_id *id)
 {
-       char *sig;
-       size_t page;
+       const __u8 *sig;
+       unsigned int page;
 
        /* huhh, the swap signature is on the end of the PAGE_SIZE */
        for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
 
        /* huhh, the swap signature is on the end of the PAGE_SIZE */
        for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
@@ -836,7 +1000,7 @@ struct volume_id *volume_id_open_node(const char *path)
 struct volume_id *volume_id_open_dev_t(dev_t devt)
 {
        struct volume_id *id;
 struct volume_id *volume_id_open_dev_t(dev_t devt)
 {
        struct volume_id *id;
-       char tmp_node[VOLUME_ID_PATH_MAX];
+       __u8 tmp_node[VOLUME_ID_PATH_MAX];
 
        snprintf(tmp_node, VOLUME_ID_PATH_MAX,
                 "/tmp/volume-%u-%u-%u", getpid(), major(devt), minor(devt));
 
        snprintf(tmp_node, VOLUME_ID_PATH_MAX,
                 "/tmp/volume-%u-%u-%u", getpid(), major(devt), minor(devt));
index 2f20244c7c7de615a7cf8e4169c5870429149438..a939743dc1ec8330367e841a4bf871b6f17a13ef 100644 (file)
@@ -21,9 +21,9 @@
 #ifndef _VOLUME_ID_H_
 #define _VOLUME_ID_H_
 
 #ifndef _VOLUME_ID_H_
 #define _VOLUME_ID_H_
 
-#define VOLUME_ID_VERSION              002
+#define VOLUME_ID_VERSION              004
 
 
-#define VOLUME_ID_LABEL_SIZE           32
+#define VOLUME_ID_LABEL_SIZE           64
 #define VOLUME_ID_UUID_SIZE            16
 #define VOLUME_ID_UUID_STRING_SIZE     37
 #define VOLUME_ID_PATH_MAX             255
 #define VOLUME_ID_UUID_SIZE            16
 #define VOLUME_ID_UUID_STRING_SIZE     37
 #define VOLUME_ID_PATH_MAX             255
@@ -45,19 +45,19 @@ enum filesystem_type {
 };
 
 struct volume_id {
 };
 
 struct volume_id {
-       char            label_raw[VOLUME_ID_LABEL_SIZE];
-       size_t          label_raw_len;
+       unsigned char   label_raw[VOLUME_ID_LABEL_SIZE];
+       unsigned int    label_raw_len;
        char            label_string[VOLUME_ID_LABEL_SIZE+1];
        unsigned char   uuid[VOLUME_ID_UUID_SIZE];
        char            uuid_string[VOLUME_ID_UUID_STRING_SIZE];
        enum            filesystem_type fs_type;
        char            *fs_name;
        int             fd;
        char            label_string[VOLUME_ID_LABEL_SIZE+1];
        unsigned char   uuid[VOLUME_ID_UUID_SIZE];
        char            uuid_string[VOLUME_ID_UUID_STRING_SIZE];
        enum            filesystem_type fs_type;
        char            *fs_name;
        int             fd;
-       char            *sbbuf;
-       size_t          sbbuf_len;
-       char            *seekbuf;
-       size_t          seekbuf_off;
-       size_t          seekbuf_len;
+       unsigned char   *sbbuf;
+       unsigned int    sbbuf_len;
+       unsigned char   *seekbuf;
+       unsigned int    seekbuf_off;
+       unsigned int    seekbuf_len;
        int             fd_close;
 };
 
        int             fd_close;
 };