* ldm - Support for Windows Logical Disk Manager (Dynamic Disks)
*
* Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
- * Copyright (c) 2001-2004 Anton Altaparmakov
+ * Copyright (c) 2001-2007 Anton Altaparmakov
* Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
*
- * Documentation is available at http://linux-ntfs.sf.net/ldm
+ * Documentation is available at http://www.linux-ntfs.org/content/view/19/37/
*
* This program 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
#include "check.h"
#include "msdos.h"
-typedef enum {
- FALSE = 0,
- TRUE = 1
-} BOOL;
-
/**
* ldm_debug/info/error/crit - Output an error message
* @f: A printf format string containing the message
printk ("%s%s(): %s\n", level, function, buf);
}
-
/**
* ldm_parse_hexbyte - Convert a ASCII hex number to a byte
* @src: Pointer to at least 2 characters to convert.
*
* N.B. The GUID need not be NULL terminated.
*
- * Return: TRUE @dest contains binary GUID
- * FALSE @dest contents are undefined
+ * Return: 'true' @dest contains binary GUID
+ * 'false' @dest contents are undefined
*/
-static BOOL ldm_parse_guid (const u8 *src, u8 *dest)
+static bool ldm_parse_guid (const u8 *src, u8 *dest)
{
static const int size[] = { 4, 2, 2, 2, 6 };
int i, j, v;
if (src[8] != '-' || src[13] != '-' ||
src[18] != '-' || src[23] != '-')
- return FALSE;
+ return false;
for (j = 0; j < 5; j++, src++)
for (i = 0; i < size[j]; i++, src+=2, *dest++ = v)
if ((v = ldm_parse_hexbyte (src)) < 0)
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
-
/**
* ldm_parse_privhead - Read the LDM Database PRIVHEAD structure
* @data: Raw database PRIVHEAD structure loaded from the device
* This parses the LDM database PRIVHEAD structure supplied in @data and
* sets up the in-memory privhead structure @ph with the obtained information.
*
- * Return: TRUE @ph contains the PRIVHEAD data
- * FALSE @ph contents are undefined
+ * Return: 'true' @ph contains the PRIVHEAD data
+ * 'false' @ph contents are undefined
*/
-static BOOL ldm_parse_privhead (const u8 *data, struct privhead *ph)
+static bool ldm_parse_privhead(const u8 *data, struct privhead *ph)
{
- BUG_ON (!data || !ph);
+ bool is_vista = false;
- if (MAGIC_PRIVHEAD != BE64 (data)) {
- ldm_error ("Cannot find PRIVHEAD structure. LDM database is"
+ BUG_ON(!data || !ph);
+ if (MAGIC_PRIVHEAD != BE64(data)) {
+ ldm_error("Cannot find PRIVHEAD structure. LDM database is"
" corrupt. Aborting.");
- return FALSE;
+ return false;
}
-
- ph->ver_major = BE16 (data + 0x000C);
- ph->ver_minor = BE16 (data + 0x000E);
- ph->logical_disk_start = BE64 (data + 0x011B);
- ph->logical_disk_size = BE64 (data + 0x0123);
- ph->config_start = BE64 (data + 0x012B);
- ph->config_size = BE64 (data + 0x0133);
-
- if ((ph->ver_major != 2) || (ph->ver_minor != 11)) {
- ldm_error ("Expected PRIVHEAD version %d.%d, got %d.%d."
- " Aborting.", 2, 11, ph->ver_major, ph->ver_minor);
- return FALSE;
+ ph->ver_major = BE16(data + 0x000C);
+ ph->ver_minor = BE16(data + 0x000E);
+ ph->logical_disk_start = BE64(data + 0x011B);
+ ph->logical_disk_size = BE64(data + 0x0123);
+ ph->config_start = BE64(data + 0x012B);
+ ph->config_size = BE64(data + 0x0133);
+ /* Version 2.11 is Win2k/XP and version 2.12 is Vista. */
+ if (ph->ver_major == 2 && ph->ver_minor == 12)
+ is_vista = true;
+ if (!is_vista && (ph->ver_major != 2 || ph->ver_minor != 11)) {
+ ldm_error("Expected PRIVHEAD version 2.11 or 2.12, got %d.%d."
+ " Aborting.", ph->ver_major, ph->ver_minor);
+ return false;
}
+ ldm_debug("PRIVHEAD version %d.%d (Windows %s).", ph->ver_major,
+ ph->ver_minor, is_vista ? "Vista" : "2000/XP");
if (ph->config_size != LDM_DB_SIZE) { /* 1 MiB in sectors. */
- /* Warn the user and continue, carefully */
- ldm_info ("Database is normally %u bytes, it claims to "
+ /* Warn the user and continue, carefully. */
+ ldm_info("Database is normally %u bytes, it claims to "
"be %llu bytes.", LDM_DB_SIZE,
- (unsigned long long)ph->config_size );
+ (unsigned long long)ph->config_size);
}
- if ((ph->logical_disk_size == 0) ||
- (ph->logical_disk_start + ph->logical_disk_size > ph->config_start)) {
- ldm_error ("PRIVHEAD disk size doesn't match real disk size");
- return FALSE;
+ if ((ph->logical_disk_size == 0) || (ph->logical_disk_start +
+ ph->logical_disk_size > ph->config_start)) {
+ ldm_error("PRIVHEAD disk size doesn't match real disk size");
+ return false;
}
-
- if (!ldm_parse_guid (data + 0x0030, ph->disk_id)) {
- ldm_error ("PRIVHEAD contains an invalid GUID.");
- return FALSE;
+ if (!ldm_parse_guid(data + 0x0030, ph->disk_id)) {
+ ldm_error("PRIVHEAD contains an invalid GUID.");
+ return false;
}
-
- ldm_debug ("Parsed PRIVHEAD successfully.");
- return TRUE;
+ ldm_debug("Parsed PRIVHEAD successfully.");
+ return true;
}
/**
*
* N.B. The *_start and *_size values returned in @toc are not range-checked.
*
- * Return: TRUE @toc contains the TOCBLOCK data
- * FALSE @toc contents are undefined
+ * Return: 'true' @toc contains the TOCBLOCK data
+ * 'false' @toc contents are undefined
*/
-static BOOL ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
+static bool ldm_parse_tocblock (const u8 *data, struct tocblock *toc)
{
BUG_ON (!data || !toc);
if (MAGIC_TOCBLOCK != BE64 (data)) {
ldm_crit ("Cannot find TOCBLOCK, database may be corrupt.");
- return FALSE;
+ return false;
}
strncpy (toc->bitmap1_name, data + 0x24, sizeof (toc->bitmap1_name));
toc->bitmap1_name[sizeof (toc->bitmap1_name) - 1] = 0;
sizeof (toc->bitmap1_name)) != 0) {
ldm_crit ("TOCBLOCK's first bitmap is '%s', should be '%s'.",
TOC_BITMAP1, toc->bitmap1_name);
- return FALSE;
+ return false;
}
strncpy (toc->bitmap2_name, data + 0x46, sizeof (toc->bitmap2_name));
toc->bitmap2_name[sizeof (toc->bitmap2_name) - 1] = 0;
sizeof (toc->bitmap2_name)) != 0) {
ldm_crit ("TOCBLOCK's second bitmap is '%s', should be '%s'.",
TOC_BITMAP2, toc->bitmap2_name);
- return FALSE;
+ return false;
}
ldm_debug ("Parsed TOCBLOCK successfully.");
- return TRUE;
+ return true;
}
/**
*
* N.B. The *_start, *_size and *_seq values will be range-checked later.
*
- * Return: TRUE @vm contains VMDB info
- * FALSE @vm contents are undefined
+ * Return: 'true' @vm contains VMDB info
+ * 'false' @vm contents are undefined
*/
-static BOOL ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
+static bool ldm_parse_vmdb (const u8 *data, struct vmdb *vm)
{
BUG_ON (!data || !vm);
if (MAGIC_VMDB != BE32 (data)) {
ldm_crit ("Cannot find the VMDB, database may be corrupt.");
- return FALSE;
+ return false;
}
vm->ver_major = BE16 (data + 0x12);
if ((vm->ver_major != 4) || (vm->ver_minor != 10)) {
ldm_error ("Expected VMDB version %d.%d, got %d.%d. "
"Aborting.", 4, 10, vm->ver_major, vm->ver_minor);
- return FALSE;
+ return false;
}
vm->vblk_size = BE32 (data + 0x08);
vm->last_vblk_seq = BE32 (data + 0x04);
ldm_debug ("Parsed VMDB successfully.");
- return TRUE;
+ return true;
}
/**
*
* This compares the two privhead structures @ph1 and @ph2.
*
- * Return: TRUE Identical
- * FALSE Different
+ * Return: 'true' Identical
+ * 'false' Different
*/
-static BOOL ldm_compare_privheads (const struct privhead *ph1,
+static bool ldm_compare_privheads (const struct privhead *ph1,
const struct privhead *ph2)
{
BUG_ON (!ph1 || !ph2);
*
* This compares the two tocblock structures @toc1 and @toc2.
*
- * Return: TRUE Identical
- * FALSE Different
+ * Return: 'true' Identical
+ * 'false' Different
*/
-static BOOL ldm_compare_tocblocks (const struct tocblock *toc1,
+static bool ldm_compare_tocblocks (const struct tocblock *toc1,
const struct tocblock *toc2)
{
BUG_ON (!toc1 || !toc2);
* the configuration area (the database). The values are range-checked against
* @hd, which contains the real size of the disk.
*
- * Return: TRUE Success
- * FALSE Error
+ * Return: 'true' Success
+ * 'false' Error
*/
-static BOOL ldm_validate_privheads (struct block_device *bdev,
+static bool ldm_validate_privheads (struct block_device *bdev,
struct privhead *ph1)
{
static const int off[3] = { OFF_PRIV1, OFF_PRIV2, OFF_PRIV3 };
struct privhead *ph[3] = { ph1 };
Sector sect;
u8 *data;
- BOOL result = FALSE;
+ bool result = false;
long num_sects;
int i;
goto out;
}*/
ldm_debug ("Validated PRIVHEADs successfully.");
- result = TRUE;
+ result = true;
out:
kfree (ph[1]);
kfree (ph[2]);
*
* The offsets and sizes of the configs are range-checked against a privhead.
*
- * Return: TRUE @toc1 contains validated TOCBLOCK info
- * FALSE @toc1 contents are undefined
+ * Return: 'true' @toc1 contains validated TOCBLOCK info
+ * 'false' @toc1 contents are undefined
*/
-static BOOL ldm_validate_tocblocks (struct block_device *bdev,
+static bool ldm_validate_tocblocks(struct block_device *bdev,
unsigned long base, struct ldmdb *ldb)
{
static const int off[4] = { OFF_TOCB1, OFF_TOCB2, OFF_TOCB3, OFF_TOCB4};
struct privhead *ph;
Sector sect;
u8 *data;
- BOOL result = FALSE;
- int i;
+ int i, nr_tbs;
+ bool result = false;
- BUG_ON (!bdev || !ldb);
-
- ph = &ldb->ph;
+ BUG_ON(!bdev || !ldb);
+ ph = &ldb->ph;
tb[0] = &ldb->toc;
- tb[1] = kmalloc (sizeof (*tb[1]), GFP_KERNEL);
- tb[2] = kmalloc (sizeof (*tb[2]), GFP_KERNEL);
- tb[3] = kmalloc (sizeof (*tb[3]), GFP_KERNEL);
- if (!tb[1] || !tb[2] || !tb[3]) {
- ldm_crit ("Out of memory.");
- goto out;
+ tb[1] = kmalloc(sizeof(*tb[1]) * 3, GFP_KERNEL);
+ if (!tb[1]) {
+ ldm_crit("Out of memory.");
+ goto err;
}
-
- for (i = 0; i < 4; i++) /* Read and parse all four toc's. */
- {
- data = read_dev_sector (bdev, base + off[i], §);
+ tb[2] = (struct tocblock*)((u8*)tb[1] + sizeof(*tb[1]));
+ tb[3] = (struct tocblock*)((u8*)tb[2] + sizeof(*tb[2]));
+ /*
+ * Try to read and parse all four TOCBLOCKs.
+ *
+ * Windows Vista LDM v2.12 does not always have all four TOCBLOCKs so
+ * skip any that fail as long as we get at least one valid TOCBLOCK.
+ */
+ for (nr_tbs = i = 0; i < 4; i++) {
+ data = read_dev_sector(bdev, base + off[i], §);
if (!data) {
- ldm_crit ("Disk read failed.");
- goto out;
+ ldm_error("Disk read failed for TOCBLOCK %d.", i);
+ continue;
}
- result = ldm_parse_tocblock (data, tb[i]);
- put_dev_sector (sect);
- if (!result)
- goto out; /* Already logged */
+ if (ldm_parse_tocblock(data, tb[nr_tbs]))
+ nr_tbs++;
+ put_dev_sector(sect);
}
-
- /* Range check the toc against a privhead. */
+ if (!nr_tbs) {
+ ldm_crit("Failed to find a valid TOCBLOCK.");
+ goto err;
+ }
+ /* Range check the TOCBLOCK against a privhead. */
if (((tb[0]->bitmap1_start + tb[0]->bitmap1_size) > ph->config_size) ||
- ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) > ph->config_size)) {
- ldm_crit ("The bitmaps are out of range. Giving up.");
- goto out;
+ ((tb[0]->bitmap2_start + tb[0]->bitmap2_size) >
+ ph->config_size)) {
+ ldm_crit("The bitmaps are out of range. Giving up.");
+ goto err;
}
-
- if (!ldm_compare_tocblocks (tb[0], tb[1]) || /* Compare all tocs. */
- !ldm_compare_tocblocks (tb[0], tb[2]) ||
- !ldm_compare_tocblocks (tb[0], tb[3])) {
- ldm_crit ("The TOCBLOCKs don't match.");
- goto out;
+ /* Compare all loaded TOCBLOCKs. */
+ for (i = 1; i < nr_tbs; i++) {
+ if (!ldm_compare_tocblocks(tb[0], tb[i])) {
+ ldm_crit("TOCBLOCKs 0 and %d do not match.", i);
+ goto err;
+ }
}
-
- ldm_debug ("Validated TOCBLOCKs successfully.");
- result = TRUE;
-out:
- kfree (tb[1]);
- kfree (tb[2]);
- kfree (tb[3]);
+ ldm_debug("Validated %d TOCBLOCKs successfully.", nr_tbs);
+ result = true;
+err:
+ kfree(tb[1]);
return result;
}
* Find the vmdb of the LDM Database stored on @bdev and return the parsed
* information in @ldb.
*
- * Return: TRUE @ldb contains validated VBDB info
- * FALSE @ldb contents are undefined
+ * Return: 'true' @ldb contains validated VBDB info
+ * 'false' @ldb contents are undefined
*/
-static BOOL ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
+static bool ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
struct ldmdb *ldb)
{
Sector sect;
u8 *data;
- BOOL result = FALSE;
+ bool result = false;
struct vmdb *vm;
struct tocblock *toc;
data = read_dev_sector (bdev, base + OFF_VMDB, §);
if (!data) {
ldm_crit ("Disk read failed.");
- return FALSE;
+ return false;
}
if (!ldm_parse_vmdb (data, vm))
goto out;
}
- result = TRUE;
+ result = true;
out:
put_dev_sector (sect);
return result;
* only likely to happen if the underlying device is strange. If that IS
* the case we should return zero to let someone else try.
*
- * Return: TRUE @bdev is a dynamic disk
- * FALSE @bdev is not a dynamic disk, or an error occurred
+ * Return: 'true' @bdev is a dynamic disk
+ * 'false' @bdev is not a dynamic disk, or an error occurred
*/
-static BOOL ldm_validate_partition_table (struct block_device *bdev)
+static bool ldm_validate_partition_table (struct block_device *bdev)
{
Sector sect;
u8 *data;
struct partition *p;
int i;
- BOOL result = FALSE;
+ bool result = false;
BUG_ON (!bdev);
data = read_dev_sector (bdev, 0, §);
if (!data) {
ldm_crit ("Disk read failed.");
- return FALSE;
+ return false;
}
if (*(__le16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
p = (struct partition*)(data + 0x01BE);
for (i = 0; i < 4; i++, p++)
- if (SYS_IND (p) == WIN2K_DYNAMIC_PARTITION) {
- result = TRUE;
+ if (SYS_IND (p) == LDM_PARTITION) {
+ result = true;
break;
}
* N.B. This function creates the partitions in the order it finds partition
* objects in the linked list.
*
- * Return: TRUE Partition created
- * FALSE Error, probably a range checking problem
+ * Return: 'true' Partition created
+ * 'false' Error, probably a range checking problem
*/
-static BOOL ldm_create_data_partitions (struct parsed_partitions *pp,
+static bool ldm_create_data_partitions (struct parsed_partitions *pp,
const struct ldmdb *ldb)
{
struct list_head *item;
disk = ldm_get_disk_objid (ldb);
if (!disk) {
ldm_crit ("Can't find the ID of this disk in the database.");
- return FALSE;
+ return false;
}
printk (" [LDM]");
}
printk ("\n");
- return TRUE;
+ return true;
}
* Return: -1 Error, the calculated offset exceeded the size of the buffer
* n OK, a range-checked offset into buffer
*/
-static int ldm_relative (const u8 *buffer, int buflen, int base, int offset)
+static int ldm_relative(const u8 *buffer, int buflen, int base, int offset)
{
base += offset;
- if ((!buffer) || (offset < 0) || (base > buflen))
+ if (!buffer || offset < 0 || base > buflen) {
+ if (!buffer)
+ ldm_error("!buffer");
+ if (offset < 0)
+ ldm_error("offset (%d) < 0", offset);
+ if (base > buflen)
+ ldm_error("base (%d) > buflen (%d)", base, buflen);
return -1;
- if ((base + buffer[base]) >= buflen)
+ }
+ if (base + buffer[base] >= buflen) {
+ ldm_error("base (%d) + buffer[base] (%d) >= buflen (%d)", base,
+ buffer[base], buflen);
return -1;
-
+ }
return buffer[base] + offset + 1;
}
*
* Read a raw VBLK Component object (version 3) into a vblk structure.
*
- * Return: TRUE @vb contains a Component VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a Component VBLK
+ * 'false' @vb contents are not defined
*/
-static BOOL ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_cmp3 (const u8 *buffer, int buflen, struct vblk *vb)
{
int r_objid, r_name, r_vstate, r_child, r_parent, r_stripe, r_cols, len;
struct vblk_comp *comp;
len = r_parent;
}
if (len < 0)
- return FALSE;
+ return false;
len += VBLK_SIZE_CMP3;
if (len != BE32 (buffer + 0x14))
- return FALSE;
+ return false;
comp = &vb->vblk.comp;
ldm_get_vstr (buffer + 0x18 + r_name, comp->state,
comp->parent_id = ldm_get_vnum (buffer + 0x2D + r_child);
comp->chunksize = r_stripe ? ldm_get_vnum (buffer+r_parent+0x2E) : 0;
- return TRUE;
+ return true;
}
/**
*
* Read a raw VBLK Disk Group object (version 3) into a vblk structure.
*
- * Return: TRUE @vb contains a Disk Group VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a Disk Group VBLK
+ * 'false' @vb contents are not defined
*/
static int ldm_parse_dgr3 (const u8 *buffer, int buflen, struct vblk *vb)
{
len = r_diskid;
}
if (len < 0)
- return FALSE;
+ return false;
len += VBLK_SIZE_DGR3;
if (len != BE32 (buffer + 0x14))
- return FALSE;
+ return false;
dgrp = &vb->vblk.dgrp;
ldm_get_vstr (buffer + 0x18 + r_name, dgrp->disk_id,
sizeof (dgrp->disk_id));
- return TRUE;
+ return true;
}
/**
*
* Read a raw VBLK Disk Group object (version 4) into a vblk structure.
*
- * Return: TRUE @vb contains a Disk Group VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a Disk Group VBLK
+ * 'false' @vb contents are not defined
*/
-static BOOL ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_dgr4 (const u8 *buffer, int buflen, struct vblk *vb)
{
char buf[64];
int r_objid, r_name, r_id1, r_id2, len;
len = r_name;
}
if (len < 0)
- return FALSE;
+ return false;
len += VBLK_SIZE_DGR4;
if (len != BE32 (buffer + 0x14))
- return FALSE;
+ return false;
dgrp = &vb->vblk.dgrp;
ldm_get_vstr (buffer + 0x18 + r_objid, buf, sizeof (buf));
- return TRUE;
+ return true;
}
/**
*
* Read a raw VBLK Disk object (version 3) into a vblk structure.
*
- * Return: TRUE @vb contains a Disk VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a Disk VBLK
+ * 'false' @vb contents are not defined
*/
-static BOOL ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_dsk3 (const u8 *buffer, int buflen, struct vblk *vb)
{
int r_objid, r_name, r_diskid, r_altname, len;
struct vblk_disk *disk;
r_altname = ldm_relative (buffer, buflen, 0x18, r_diskid);
len = r_altname;
if (len < 0)
- return FALSE;
+ return false;
len += VBLK_SIZE_DSK3;
if (len != BE32 (buffer + 0x14))
- return FALSE;
+ return false;
disk = &vb->vblk.disk;
ldm_get_vstr (buffer + 0x18 + r_diskid, disk->alt_name,
sizeof (disk->alt_name));
if (!ldm_parse_guid (buffer + 0x19 + r_name, disk->disk_id))
- return FALSE;
+ return false;
- return TRUE;
+ return true;
}
/**
*
* Read a raw VBLK Disk object (version 4) into a vblk structure.
*
- * Return: TRUE @vb contains a Disk VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a Disk VBLK
+ * 'false' @vb contents are not defined
*/
-static BOOL ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_dsk4 (const u8 *buffer, int buflen, struct vblk *vb)
{
int r_objid, r_name, len;
struct vblk_disk *disk;
r_name = ldm_relative (buffer, buflen, 0x18, r_objid);
len = r_name;
if (len < 0)
- return FALSE;
+ return false;
len += VBLK_SIZE_DSK4;
if (len != BE32 (buffer + 0x14))
- return FALSE;
+ return false;
disk = &vb->vblk.disk;
memcpy (disk->disk_id, buffer + 0x18 + r_name, GUID_SIZE);
- return TRUE;
+ return true;
}
/**
*
* Read a raw VBLK Partition object (version 3) into a vblk structure.
*
- * Return: TRUE @vb contains a Partition VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a Partition VBLK
+ * 'false' @vb contents are not defined
*/
-static BOOL ldm_parse_prt3 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb)
{
int r_objid, r_name, r_size, r_parent, r_diskid, r_index, len;
struct vblk_part *part;
- BUG_ON (!buffer || !vb);
-
- r_objid = ldm_relative (buffer, buflen, 0x18, 0);
- r_name = ldm_relative (buffer, buflen, 0x18, r_objid);
- r_size = ldm_relative (buffer, buflen, 0x34, r_name);
- r_parent = ldm_relative (buffer, buflen, 0x34, r_size);
- r_diskid = ldm_relative (buffer, buflen, 0x34, r_parent);
-
+ BUG_ON(!buffer || !vb);
+ r_objid = ldm_relative(buffer, buflen, 0x18, 0);
+ if (r_objid < 0) {
+ ldm_error("r_objid %d < 0", r_objid);
+ return false;
+ }
+ r_name = ldm_relative(buffer, buflen, 0x18, r_objid);
+ if (r_name < 0) {
+ ldm_error("r_name %d < 0", r_name);
+ return false;
+ }
+ r_size = ldm_relative(buffer, buflen, 0x34, r_name);
+ if (r_size < 0) {
+ ldm_error("r_size %d < 0", r_size);
+ return false;
+ }
+ r_parent = ldm_relative(buffer, buflen, 0x34, r_size);
+ if (r_parent < 0) {
+ ldm_error("r_parent %d < 0", r_parent);
+ return false;
+ }
+ r_diskid = ldm_relative(buffer, buflen, 0x34, r_parent);
+ if (r_diskid < 0) {
+ ldm_error("r_diskid %d < 0", r_diskid);
+ return false;
+ }
if (buffer[0x12] & VBLK_FLAG_PART_INDEX) {
- r_index = ldm_relative (buffer, buflen, 0x34, r_diskid);
+ r_index = ldm_relative(buffer, buflen, 0x34, r_diskid);
+ if (r_index < 0) {
+ ldm_error("r_index %d < 0", r_index);
+ return false;
+ }
len = r_index;
} else {
r_index = 0;
len = r_diskid;
}
- if (len < 0)
- return FALSE;
-
+ if (len < 0) {
+ ldm_error("len %d < 0", len);
+ return false;
+ }
len += VBLK_SIZE_PRT3;
- if (len != BE32 (buffer + 0x14))
- return FALSE;
-
+ if (len > BE32(buffer + 0x14)) {
+ ldm_error("len %d > BE32(buffer + 0x14) %d", len,
+ BE32(buffer + 0x14));
+ return false;
+ }
part = &vb->vblk.part;
- part->start = BE64 (buffer + 0x24 + r_name);
- part->volume_offset = BE64 (buffer + 0x2C + r_name);
- part->size = ldm_get_vnum (buffer + 0x34 + r_name);
- part->parent_id = ldm_get_vnum (buffer + 0x34 + r_size);
- part->disk_id = ldm_get_vnum (buffer + 0x34 + r_parent);
+ part->start = BE64(buffer + 0x24 + r_name);
+ part->volume_offset = BE64(buffer + 0x2C + r_name);
+ part->size = ldm_get_vnum(buffer + 0x34 + r_name);
+ part->parent_id = ldm_get_vnum(buffer + 0x34 + r_size);
+ part->disk_id = ldm_get_vnum(buffer + 0x34 + r_parent);
if (vb->flags & VBLK_FLAG_PART_INDEX)
part->partnum = buffer[0x35 + r_diskid];
else
part->partnum = 0;
-
- return TRUE;
+ return true;
}
/**
*
* Read a raw VBLK Volume object (version 5) into a vblk structure.
*
- * Return: TRUE @vb contains a Volume VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a Volume VBLK
+ * 'false' @vb contents are not defined
*/
-static BOOL ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb)
+static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb)
{
- int r_objid, r_name, r_vtype, r_child, r_size, r_id1, r_id2, r_size2;
- int r_drive, len;
+ int r_objid, r_name, r_vtype, r_disable_drive_letter, r_child, r_size;
+ int r_id1, r_id2, r_size2, r_drive, len;
struct vblk_volu *volu;
- BUG_ON (!buffer || !vb);
-
- r_objid = ldm_relative (buffer, buflen, 0x18, 0);
- r_name = ldm_relative (buffer, buflen, 0x18, r_objid);
- r_vtype = ldm_relative (buffer, buflen, 0x18, r_name);
- r_child = ldm_relative (buffer, buflen, 0x2E, r_vtype);
- r_size = ldm_relative (buffer, buflen, 0x3E, r_child);
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_ID1)
- r_id1 = ldm_relative (buffer, buflen, 0x53, r_size);
- else
+ BUG_ON(!buffer || !vb);
+ r_objid = ldm_relative(buffer, buflen, 0x18, 0);
+ if (r_objid < 0) {
+ ldm_error("r_objid %d < 0", r_objid);
+ return false;
+ }
+ r_name = ldm_relative(buffer, buflen, 0x18, r_objid);
+ if (r_name < 0) {
+ ldm_error("r_name %d < 0", r_name);
+ return false;
+ }
+ r_vtype = ldm_relative(buffer, buflen, 0x18, r_name);
+ if (r_vtype < 0) {
+ ldm_error("r_vtype %d < 0", r_vtype);
+ return false;
+ }
+ r_disable_drive_letter = ldm_relative(buffer, buflen, 0x18, r_vtype);
+ if (r_disable_drive_letter < 0) {
+ ldm_error("r_disable_drive_letter %d < 0",
+ r_disable_drive_letter);
+ return false;
+ }
+ r_child = ldm_relative(buffer, buflen, 0x2D, r_disable_drive_letter);
+ if (r_child < 0) {
+ ldm_error("r_child %d < 0", r_child);
+ return false;
+ }
+ r_size = ldm_relative(buffer, buflen, 0x3D, r_child);
+ if (r_size < 0) {
+ ldm_error("r_size %d < 0", r_size);
+ return false;
+ }
+ if (buffer[0x12] & VBLK_FLAG_VOLU_ID1) {
+ r_id1 = ldm_relative(buffer, buflen, 0x52, r_size);
+ if (r_id1 < 0) {
+ ldm_error("r_id1 %d < 0", r_id1);
+ return false;
+ }
+ } else
r_id1 = r_size;
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_ID2)
- r_id2 = ldm_relative (buffer, buflen, 0x53, r_id1);
- else
+ if (buffer[0x12] & VBLK_FLAG_VOLU_ID2) {
+ r_id2 = ldm_relative(buffer, buflen, 0x52, r_id1);
+ if (r_id2 < 0) {
+ ldm_error("r_id2 %d < 0", r_id2);
+ return false;
+ }
+ } else
r_id2 = r_id1;
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE)
- r_size2 = ldm_relative (buffer, buflen, 0x53, r_id2);
- else
+ if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE) {
+ r_size2 = ldm_relative(buffer, buflen, 0x52, r_id2);
+ if (r_size2 < 0) {
+ ldm_error("r_size2 %d < 0", r_size2);
+ return false;
+ }
+ } else
r_size2 = r_id2;
-
- if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE)
- r_drive = ldm_relative (buffer, buflen, 0x53, r_size2);
- else
+ if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
+ r_drive = ldm_relative(buffer, buflen, 0x52, r_size2);
+ if (r_drive < 0) {
+ ldm_error("r_drive %d < 0", r_drive);
+ return false;
+ }
+ } else
r_drive = r_size2;
-
len = r_drive;
- if (len < 0)
- return FALSE;
-
+ if (len < 0) {
+ ldm_error("len %d < 0", len);
+ return false;
+ }
len += VBLK_SIZE_VOL5;
- if (len != BE32 (buffer + 0x14))
- return FALSE;
-
+ if (len > BE32(buffer + 0x14)) {
+ ldm_error("len %d > BE32(buffer + 0x14) %d", len,
+ BE32(buffer + 0x14));
+ return false;
+ }
volu = &vb->vblk.volu;
-
- ldm_get_vstr (buffer + 0x18 + r_name, volu->volume_type,
- sizeof (volu->volume_type));
- memcpy (volu->volume_state, buffer + 0x19 + r_vtype,
- sizeof (volu->volume_state));
- volu->size = ldm_get_vnum (buffer + 0x3E + r_child);
- volu->partition_type = buffer[0x42 + r_size];
- memcpy (volu->guid, buffer + 0x43 + r_size, sizeof (volu->guid));
+ ldm_get_vstr(buffer + 0x18 + r_name, volu->volume_type,
+ sizeof(volu->volume_type));
+ memcpy(volu->volume_state, buffer + 0x18 + r_disable_drive_letter,
+ sizeof(volu->volume_state));
+ volu->size = ldm_get_vnum(buffer + 0x3D + r_child);
+ volu->partition_type = buffer[0x41 + r_size];
+ memcpy(volu->guid, buffer + 0x42 + r_size, sizeof(volu->guid));
if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) {
- ldm_get_vstr (buffer + 0x53 + r_size, volu->drive_hint,
- sizeof (volu->drive_hint));
+ ldm_get_vstr(buffer + 0x52 + r_size, volu->drive_hint,
+ sizeof(volu->drive_hint));
}
- return TRUE;
+ return true;
}
/**
* information common to all VBLK types, then delegates the rest of the work to
* helper functions: ldm_parse_*.
*
- * Return: TRUE @vb contains a VBLK
- * FALSE @vb contents are not defined
+ * Return: 'true' @vb contains a VBLK
+ * 'false' @vb contents are not defined
*/
-static BOOL ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb)
+static bool ldm_parse_vblk (const u8 *buf, int len, struct vblk *vb)
{
- BOOL result = FALSE;
+ bool result = false;
int r_objid;
BUG_ON (!buf || !vb);
r_objid = ldm_relative (buf, len, 0x18, 0);
if (r_objid < 0) {
ldm_error ("VBLK header is corrupt.");
- return FALSE;
+ return false;
}
vb->flags = buf[0x12];
*
* N.B. This function does not check the validity of the VBLKs.
*
- * Return: TRUE The VBLK was added
- * FALSE An error occurred
+ * Return: 'true' The VBLK was added
+ * 'false' An error occurred
*/
-static BOOL ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
+static bool ldm_ldmdb_add (u8 *data, int len, struct ldmdb *ldb)
{
struct vblk *vb;
struct list_head *item;
vb = kmalloc (sizeof (*vb), GFP_KERNEL);
if (!vb) {
ldm_crit ("Out of memory.");
- return FALSE;
+ return false;
}
if (!ldm_parse_vblk (data, len, vb)) {
kfree(vb);
- return FALSE; /* Already logged */
+ return false; /* Already logged */
}
/* Put vblk into the correct list. */
if ((v->vblk.part.disk_id == vb->vblk.part.disk_id) &&
(v->vblk.part.start > vb->vblk.part.start)) {
list_add_tail (&vb->list, &v->list);
- return TRUE;
+ return true;
}
}
list_add_tail (&vb->list, &ldb->v_part);
break;
}
- return TRUE;
+ return true;
}
/**
* Fragmented VBLKs may not be consecutive in the database, so they are placed
* in a list so they can be pieced together later.
*
- * Return: TRUE Success, the VBLK was added to the list
- * FALSE Error, a problem occurred
+ * Return: 'true' Success, the VBLK was added to the list
+ * 'false' Error, a problem occurred
*/
-static BOOL ldm_frag_add (const u8 *data, int size, struct list_head *frags)
+static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
{
struct frag *f;
struct list_head *item;
num = BE16 (data + 0x0E);
if ((num < 1) || (num > 4)) {
ldm_error ("A VBLK claims to have %d parts.", num);
- return FALSE;
+ return false;
}
list_for_each (item, frags) {
f = kmalloc (sizeof (*f) + size*num, GFP_KERNEL);
if (!f) {
ldm_crit ("Out of memory.");
- return FALSE;
+ return false;
}
f->group = group;
if (f->map & (1 << rec)) {
ldm_error ("Duplicate VBLK, part %d.", rec);
f->map &= 0x7F; /* Mark the group as broken */
- return FALSE;
+ return false;
}
f->map |= (1 << rec);
}
memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
- return TRUE;
+ return true;
}
/**
* Now that all the fragmented VBLKs have been collected, they must be added to
* the database for later use.
*
- * Return: TRUE All the fragments we added successfully
- * FALSE One or more of the fragments we invalid
+ * Return: 'true' All the fragments we added successfully
+ * 'false' One or more of the fragments we invalid
*/
-static BOOL ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
+static bool ldm_frag_commit (struct list_head *frags, struct ldmdb *ldb)
{
struct frag *f;
struct list_head *item;
if (f->map != 0xFF) {
ldm_error ("VBLK group %d is incomplete (0x%02x).",
f->group, f->map);
- return FALSE;
+ return false;
}
if (!ldm_ldmdb_add (f->data, f->num*ldb->vm.vblk_size, ldb))
- return FALSE; /* Already logged */
+ return false; /* Already logged */
}
- return TRUE;
+ return true;
}
/**
* To use the information from the VBLKs, they need to be read from the disk,
* unpacked and validated. We cache them in @ldb according to their type.
*
- * Return: TRUE All the VBLKs were read successfully
- * FALSE An error occurred
+ * Return: 'true' All the VBLKs were read successfully
+ * 'false' An error occurred
*/
-static BOOL ldm_get_vblks (struct block_device *bdev, unsigned long base,
+static bool ldm_get_vblks (struct block_device *bdev, unsigned long base,
struct ldmdb *ldb)
{
int size, perbuf, skip, finish, s, v, recs;
u8 *data = NULL;
Sector sect;
- BOOL result = FALSE;
+ bool result = false;
LIST_HEAD (frags);
BUG_ON (!bdev || !ldb);
kfree (ldb);
return result;
}
-