/* size of superblock buffer, reiserfs block is at 64k */
#define SB_BUFFER_SIZE 0x11000
/* size of seek buffer 4k */
-#define SEEK_BUFFER_SIZE 0x1000
+#define SEEK_BUFFER_SIZE 0x10000
static void set_label_raw(struct volume_id *id,
return &(id->sbbuf[off]);
} else {
- if (len > SEEK_BUFFER_SIZE)
- len = SEEK_BUFFER_SIZE;
+ if (len > SEEK_BUFFER_SIZE) {
+ dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
+ return NULL;
+ }
/* get seek buffer */
if (id->seekbuf == NULL) {
}
/* check if we need to read */
- if ((off < id->seekbuf_off) ||
- ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
+ 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;
dbg("got 0x%x (%i) bytes", buf_len, buf_len);
id->seekbuf_off = off;
id->seekbuf_len = buf_len;
- if (buf_len < 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]);
}
}
+#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)
p->partition_type_raw = part[i].sys_ind;
if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
- dbg("to many partitions");
+ dbg("too many partitions");
next = 0;
}
}
#define FAT12_MAX 0xff5
#define FAT16_MAX 0xfff5
-#define FAT_ATTR_VOLUME 0x08
+#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 {
__u16 dir_entries;
__u32 sect_count;
__u16 reserved;
- __u16 fat_size;
+ __u32 fat_size;
__u32 root_cluster;
__u32 dir_size;
__u32 cluster_count;
/* 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;
dir = (struct vfat_dir_entry*) buf;
- for (i = 0; i <= root_dir_entries; i++) {
+ for (i = 0; i < root_dir_entries; i++) {
/* end marker */
if (dir[i].name[0] == 0x00) {
dbg("end of dir");
}
/* empty entry */
- if (dir[i].name[0] == 0xe5)
+ if (dir[i].name[0] == FAT_ENTRY_FREE)
continue;
- if (dir[i].attr == FAT_ATTR_VOLUME) {
- dbg("found ATTR_VOLUME id in root dir");
+ /* 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);
count = buf_size / sizeof(struct vfat_dir_entry);
dbg("expected entries 0x%x", count);
- for (i = 0; i <= count; i++) {
+ for (i = 0; i < count; i++) {
/* end marker */
if (dir[i].name[0] == 0x00) {
dbg("end of dir");
}
/* empty entry */
- if (dir[i].name[0] == 0xe5)
+ 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) {
- dbg("found ATTR_VOLUME id in root dir");
+ 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("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) {
+ } 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);
}
}
#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 {
return -1;
if (strncmp(is->iso.id, "CD001", 5) == 0) {
- set_label_raw(id, is->iso.volume_id, 32);
- set_label_string(id, is->iso.volume_id, 32);
+ 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)
#define LARGEST_PAGESIZE 0x4000
static int probe_swap(struct volume_id *id, __u64 off)
{
- const __u8 *sig;
+ 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;
- /* huhh, the swap signature is on the end of the PAGE_SIZE */
+ /* the swap signature is at the end of the PAGE_SIZE */
for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
- sig = get_buffer(id, off + page-10, 10);
- if (sig == NULL)
+ buf = get_buffer(id, off + page-10, 10);
+ if (buf == NULL)
return -1;
- if (strncmp(sig, "SWAP-SPACE", 10) == 0) {
+ if (strncmp(buf, "SWAP-SPACE", 10) == 0) {
strcpy(id->type_version, "1");
goto found;
}
- if (strncmp(sig, "SWAPSPACE2", 10) == 0) {
+
+ 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;
}
}
{
int rc;
+ dbg("called with size=0x%llx", size);
+
if (id == NULL)
return -EINVAL;
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_lvm2(id, off);
if (rc == 0)
break;
-
- /* signature in the first block, only small buffer needed */
- rc = probe_msdos_part_table(id, off);
- if (rc == 0)
- break;
- rc = probe_ntfs(id, off);
+ 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;
if (rc == 0)
break;
rc = probe_ufs(id, off);
+ if (rc == 0)
+ break;
+ rc = probe_ntfs(id, off);
if (rc == 0)
break;
struct volume_id *id;
int fd;
- fd = open(path, O_RDONLY | O_NONBLOCK);
+ fd = open(path, O_RDONLY);
if (fd < 0) {
dbg("unable to open '%s'", path);
return NULL;