Beispiel #1
0
/**
 * ntfs_mst_pread - multi sector transfer (mst) positioned read
 * @dev:	device to read from
 * @pos:	position in file descriptor to read from
 * @count:	number of blocks to read
 * @bksize:	size of each block that needs mst deprotecting
 * @b:		output data buffer
 *
 * Multi sector transfer (mst) positioned read. This function will read @count
 * blocks of size @bksize bytes each from device @dev at position @pos into the
 * the data buffer @b.
 *
 * On success, return the number of successfully read blocks. If this number is
 * lower than @count this means that we have reached end of file, that the read
 * was interrupted, or that an error was encountered during the read so that
 * the read is partial. 0 means end of file or nothing was read (also return 0
 * when @count or @bksize are 0).
 *
 * On error and nothing was read, return -1 with errno set appropriately to the
 * return code of either seek, read, or set to EINVAL in case of invalid
 * arguments.
 *
 * NOTE: If an incomplete multi sector transfer has been detected the magic
 * will have been changed to magic_BAAD but no error will be returned. Thus it
 * is possible that we return count blocks as being read but that any number
 * (between zero and count!) of these blocks is actually subject to a multi
 * sector transfer error. This should be detected by the caller by checking for
 * the magic being "BAAD".
 */
s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count,
		const u32 bksize, void *b)
{
	s64 br, i;

	if (bksize & (bksize - 1) || bksize % NTFS_BLOCK_SIZE) {
		errno = EINVAL;
		return -1;
	}
	/* Do the read. */
	br = ntfs_pread(dev, pos, count * bksize, b);
	if (br < 0)
		return br;
	/*
	 * Apply fixups to successfully read data, disregarding any errors
	 * returned from the MST fixup function. This is because we want to
	 * fixup everything possible and we rely on the fact that the "BAAD"
	 * magic will be detected later on.
	 */
	count = br / bksize;
	for (i = 0; i < count; ++i)
		ntfs_mst_post_read_fixup((NTFS_RECORD*)
				((u8*)b + i * bksize), bksize);
	/* Finally, return the number of complete blocks read. */
	return count;
}
Beispiel #2
0
static int print_serial(ntfs_volume *vol)
{
	NTFS_BOOT_SECTOR *bs; /* full boot sectors */
	int res;

	res = -1;
	bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
	if (bs
	    && (ntfs_pread(vol->dev, 0,
			vol->sector_size, bs) == vol->sector_size)) {
		ntfs_log_info("Serial number : %016llx\n",
			(long long)le64_to_cpu(bs->volume_serial_number));
		res = 0;
		free(bs);
	}
	if (res)
		ntfs_log_info("Error getting the serial number\n");
	return (res);
}
Beispiel #3
0
/**
 * ntfs_cluster_read - read ntfs clusters
 * @vol:	volume to read from
 * @lcn:	starting logical cluster number
 * @count:	number of clusters to read
 * @b:		output data buffer
 *
 * Read @count ntfs clusters starting at logical cluster number @lcn from
 * volume @vol into buffer @b. Return number of clusters read or -1 on error,
 * with errno set to the error code.
 */
s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, const s64 count,
		void *b)
{
	s64 br;

	if (!vol || lcn < 0 || count < 0) {
		errno = EINVAL;
		return -1;
	}
	if (vol->nr_clusters < lcn + count) {
		errno = ESPIPE;
		return -1;
	}
	br = ntfs_pread(vol->dev, lcn << vol->cluster_size_bits,
			count << vol->cluster_size_bits, b);
	if (br < 0) {
		ntfs_log_perror("Error reading cluster(s)");
		return br;
	}
	return br >> vol->cluster_size_bits;
}
Beispiel #4
0
static int change_serial(ntfs_volume *vol, u64 sector, le64 serial_number,
			NTFS_BOOT_SECTOR *bs, NTFS_BOOT_SECTOR *oldbs)
{
	int res;
	le64 mask;
	BOOL same;

	res = -1;
        if ((ntfs_pread(vol->dev, sector << vol->sector_size_bits,
			vol->sector_size, bs) == vol->sector_size)) {
		same = TRUE;
		if (!sector)
				/* save the real bootsector */
			memcpy(oldbs, bs, vol->sector_size);
		else
				/* backup bootsector must be similar */
			same = !memcmp(oldbs, bs, vol->sector_size);
		if (same) {
			if (opts.new_serial & 2)
				bs->volume_serial_number = serial_number;
			else {
				mask = const_cpu_to_le64(~0x0ffffffffULL);
				bs->volume_serial_number
				    = (serial_number & mask)
					| (bs->volume_serial_number & ~mask);
			}
			if (opts.noaction
			    || (ntfs_pwrite(vol->dev,
				sector << vol->sector_size_bits,
				vol->sector_size, bs) == vol->sector_size)) {
				res = 0;
			}
		} else {
			ntfs_log_info("* Warning : the backup boot sector"
				" does not match (leaving unchanged)\n");
			res = 0;
		}
	}
	return (res);
}
Beispiel #5
0
/**
 * Return: 0 ok, 1 error.
 *
 * todo: may we use ntfs_boot_sector_is_ntfs() instead?
 *	It already does the checks but will not be able to fix anything.
 */
static BOOL verify_boot_sector(struct ntfs_device *dev, ntfs_volume *rawvol)
{
	u8 buf[512];
	NTFS_BOOT_SECTOR *ntfs_boot = (NTFS_BOOT_SECTOR *)&buf;
	//u32 bytes_per_cluster;

	current_mft_record = 9;

	if (ntfs_pread(dev, 0, sizeof(buf), buf) != sizeof(buf)) {
		check_failed("Failed to read boot sector.\n");
		return 1;
	}

	if ((buf[0]!=0xeb) ||
			((buf[1]!=0x52) && (buf[1]!=0x5b)) ||
			(buf[2]!=0x90)) {
		check_failed("Boot sector: Bad jump.\n");
	}
	if (ntfs_boot->oem_id != magicNTFS) {
		check_failed("Boot sector: Bad NTFS magic.\n");
	}
	bytes_per_sector = le16_to_cpu(ntfs_boot->bpb.bytes_per_sector);
	if (!bytes_per_sector) {
		check_failed("Boot sector: Bytes per sector is 0.\n");
	}
	if (bytes_per_sector%512) {
		check_failed("Boot sector: Bytes per sector is not a multiple"
					" of 512.\n");
	}
	sectors_per_cluster = ntfs_boot->bpb.sectors_per_cluster;

	// todo: if partition, query bios and match heads/tracks? */

	// Initialize some values into rawvol. We will need those later.
	rawvol->dev = dev;
	ntfs_boot_sector_parse(rawvol, (NTFS_BOOT_SECTOR *)buf);

	return 0;
}
Beispiel #6
0
/**
 * Load the runlist of the <attr_type> attribute.
 *
 * Return NULL if an error.
 * The caller is responsible on freeing the allocated memory if the result is not NULL.
 *
 * Set size_of_file_record to some reasonable size when in doubt (the Windows default is 1024.)
 *
 * attr_type must be little endian.
 *
 * This function has code duplication with check_file_record() and
 * check_attr_record() but its goal is to be less strict. Thus the
 * duplicated checks are the minimal required for not crashing.
 *
 * Assumes dev is open.
 */
static runlist *load_runlist(ntfs_volume *rawvol, s64 offset_to_file_record, u32 attr_type, u32 size_of_file_record)
{
	u8 *buf;
	u16 attrs_offset;
	u32 length;
	ATTR_RECORD *attr_rec;
	
	if (size_of_file_record<22) // offset to attrs_offset
		return NULL;

	buf = (u8*)ntfs_malloc(size_of_file_record);
	if (!buf)
		return NULL;

	if (ntfs_pread(rawvol->dev, offset_to_file_record, size_of_file_record, buf) !=
			size_of_file_record) {
		check_failed("Failed to read file record at offset %lld (0x%llx).\n",
					(long long)offset_to_file_record,
					(long long)offset_to_file_record);
		return NULL;
	}

	attrs_offset = le16_to_cpu(((MFT_RECORD*)buf)->attrs_offset);
	// first attribute must be after the header.
	if (attrs_offset<42) {
		check_failed("First attribute must be after the header (%u).\n", (int)attrs_offset);
	}
	attr_rec = (ATTR_RECORD *)(buf + attrs_offset);
	//printf("uv1.\n");

	while ((u8*)attr_rec<=buf+size_of_file_record-4) {

		//printf("Attr type: 0x%x.\n", attr_rec->type);
		// Check attribute record. (Only what is in the buffer)
		if (attr_rec->type==AT_END) {
			check_failed("Attribute 0x%x not found in file record at offset %lld (0x%llx).\n", (int)le32_to_cpu(attr_rec->type),
					(long long)offset_to_file_record,
					(long long)offset_to_file_record);
			return NULL;
		}
		if ((u8*)attr_rec>buf+size_of_file_record-8) {
			// not AT_END yet no room for the length field.
			check_failed("Attribute 0x%x is not AT_END, yet no "
					"room for the length field.\n",
					(int)le32_to_cpu(attr_rec->type));
			return NULL;
		}

		length = le32_to_cpu(attr_rec->length);

		// Check that this attribute does not overflow the mft_record
		if ((u8*)attr_rec+length >= buf+size_of_file_record) {
			check_failed("Attribute (0x%x) is larger than FILE record at offset %lld (0x%llx).\n",
					(int)le32_to_cpu(attr_rec->type),
					(long long)offset_to_file_record,
					(long long)offset_to_file_record);
			return NULL;
		}
		// todo: what ATTRIBUTE_LIST (0x20)?

		if (attr_rec->type==attr_type) {
			// Eurika!

			// ntfs_mapping_pairs_decompress only use two values from vol. Just fake it.
			// todo: it will also use vol->major_ver if defined(DEBUG). But only for printing purposes.

			// Assume ntfs_boot_sector_parse() was called.
			return ntfs_mapping_pairs_decompress(rawvol, attr_rec, NULL);
		}

		attr_rec = (ATTR_RECORD*)((u8*)attr_rec+length);
	}
	// If we got here, there was an overflow.
	check_failed("file record corrupted at offset %lld (0x%llx).\n",
			(long long)offset_to_file_record,
			(long long)offset_to_file_record);
	return NULL;
}