mirror of
https://github.com/systemd/systemd.git
synced 2024-12-26 03:22:00 +03:00
[PATCH] update udev_volume_id
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.
This commit is contained in:
parent
062db23d5e
commit
b99f344fde
@ -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
|
||||
* 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.
|
||||
*
|
||||
@ -26,6 +26,10 @@
|
||||
* 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>
|
||||
@ -55,12 +59,23 @@
|
||||
(((__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)
|
||||
#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)
|
||||
#define le64_to_cpu(x) bswap64(x)
|
||||
#endif
|
||||
|
||||
/* size of superblock buffer, reiser block is at 64k */
|
||||
@ -69,15 +84,17 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -90,9 +107,42 @@ static void set_label_string(struct volume_id *id, char *buf, int count)
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
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)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
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) {
|
||||
@ -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) {
|
||||
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)
|
||||
@ -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))) {
|
||||
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);
|
||||
dbg("got 0x%x (%i) bytes", buf_len, buf_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 {
|
||||
__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);
|
||||
@ -239,20 +291,20 @@ static int probe_ext(struct volume_id *id)
|
||||
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);
|
||||
@ -288,19 +340,19 @@ found:
|
||||
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)
|
||||
@ -323,17 +375,17 @@ static int probe_xfs(struct volume_id *id)
|
||||
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);
|
||||
@ -356,34 +408,34 @@ static int probe_jfs(struct volume_id *id)
|
||||
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)
|
||||
@ -409,27 +461,27 @@ found:
|
||||
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)
|
||||
@ -459,45 +511,43 @@ static int probe_udf(struct volume_id *id)
|
||||
{
|
||||
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 {
|
||||
__u32 length;
|
||||
__u32 location;
|
||||
} anchor;
|
||||
__u32 length;
|
||||
__u32 location;
|
||||
} __attribute__((__packed__)) anchor;
|
||||
struct primary_descriptor {
|
||||
__u32 seq_num;
|
||||
__u32 desc_num;
|
||||
__u32 seq_num;
|
||||
__u32 desc_num;
|
||||
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 {
|
||||
unsigned char type;
|
||||
char id[5];
|
||||
unsigned char version;
|
||||
__u8 type;
|
||||
__u8 id[5];
|
||||
__u8 version;
|
||||
} *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);
|
||||
@ -594,29 +644,10 @@ pvd:
|
||||
|
||||
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);
|
||||
} 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;
|
||||
@ -630,20 +661,20 @@ static int probe_iso9660(struct volume_id *id)
|
||||
{
|
||||
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 {
|
||||
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);
|
||||
@ -666,12 +697,73 @@ found:
|
||||
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 {
|
||||
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)
|
||||
@ -680,6 +772,78 @@ static int probe_ntfs(struct volume_id *id)
|
||||
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";
|
||||
|
||||
@ -689,8 +853,8 @@ static int probe_ntfs(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) {
|
||||
@ -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;
|
||||
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));
|
||||
|
@ -21,9 +21,9 @@
|
||||
#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
|
||||
@ -45,19 +45,19 @@ enum filesystem_type {
|
||||
};
|
||||
|
||||
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 *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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user