Exemplo n.º 1
0
Arquivo: device.c Projeto: DonCN/haiku
/**
 * ntfs_cluster_write - write ntfs clusters
 * @vol:	volume to write to
 * @lcn:	starting logical cluster number
 * @count:	number of clusters to write
 * @b:		data buffer to write to disk
 *
 * Write @count ntfs clusters starting at logical cluster number @lcn from
 * buffer @b to volume @vol. Return the number of clusters written or -1 on
 * error, with errno set to the error code.
 */
s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn,
		const s64 count, const void *b)
{
	s64 bw;

	if (!vol || lcn < 0 || count < 0) {
		errno = EINVAL;
		return -1;
	}
	if (vol->nr_clusters < lcn + count) {
		errno = ESPIPE;
		ntfs_log_perror("Trying to write outside of volume "
				"(%lld < %lld)", (long long)vol->nr_clusters,
			        (long long)lcn + count);
		return -1;
	}
	if (!NVolReadOnly(vol))
		bw = ntfs_pwrite(vol->dev, lcn << vol->cluster_size_bits,
				count << vol->cluster_size_bits, b);
	else
		bw = count << vol->cluster_size_bits;
	if (bw < 0) {
		ntfs_log_perror("Error writing cluster(s)");
		return bw;
	}
	return bw >> vol->cluster_size_bits;
}
Exemplo n.º 2
0
Arquivo: device.c Projeto: DonCN/haiku
/**
 * ntfs_mst_pwrite - multi sector transfer (mst) positioned write
 * @dev:	device to write to
 * @pos:	position in file descriptor to write to
 * @count:	number of blocks to write
 * @bksize:	size of each block that needs mst protecting
 * @b:		data buffer to write to disk
 *
 * Multi sector transfer (mst) positioned write. This function will write
 * @count blocks of size @bksize bytes each from data buffer @b to the device
 * @dev at position @pos.
 *
 * On success, return the number of successfully written blocks. If this number
 * is lower than @count this means that the write has been interrupted or that
 * an error was encountered during the write so that the write is partial. 0
 * means nothing was written (also return 0 when @count or @bksize are 0).
 *
 * On error and nothing has been written, return -1 with errno set
 * appropriately to the return code of either seek, write, or set
 * to EINVAL in case of invalid arguments.
 *
 * NOTE: We mst protect the data, write it, then mst deprotect it using a quick
 * deprotect algorithm (no checking). This saves us from making a copy before
 * the write and at the same time causes the usn to be incremented in the
 * buffer. This conceptually fits in better with the idea that cached data is
 * always deprotected and protection is performed when the data is actually
 * going to hit the disk and the cache is immediately deprotected again
 * simulating an mst read on the written data. This way cache coherency is
 * achieved.
 */
s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
		const u32 bksize, void *b)
{
	s64 written, i;

	if (count < 0 || bksize % NTFS_BLOCK_SIZE) {
		errno = EINVAL;
		return -1;
	}
	if (!count)
		return 0;
	/* Prepare data for writing. */
	for (i = 0; i < count; ++i) {
		int err;

		err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)
				((u8*)b + i * bksize), bksize);
		if (err < 0) {
			/* Abort write at this position. */
			if (!i)
				return err;
			count = i;
			break;
		}
	}
	/* Write the prepared data. */
	written = ntfs_pwrite(dev, pos, count * bksize, b);
	/* Quickly deprotect the data again. */
	for (i = 0; i < count; ++i)
		ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)b + i * bksize));
	if (written <= 0)
		return written;
	/* Finally, return the number of complete blocks written. */
	return written / bksize;
}
Exemplo n.º 3
0
static int ntfs_inner_zero(ntfs_attr *na, runlist_element *rl)
{
	ntfs_volume *vol;
	char *buf;
	runlist_element *zrl;
	s64 cofs;
	s64 pos;
	s64 zeroed;
	int err;

	err = 0;
	vol = na->ni->vol;
	buf = (char*)malloc(vol->cluster_size);
	if (buf) {
		memset(buf, 0, vol->cluster_size);
		zrl = rl;
		pos = zrl->vcn << vol->cluster_size_bits;
		while (zrl->length
	 	    && !err
	    	    && (pos < na->initialized_size)) {
			for (cofs=0; cofs<zrl->length && !err; cofs++) {
				zeroed = ntfs_pwrite(vol->dev,
					(rl->lcn + cofs)
						<< vol->cluster_size_bits,
					vol->cluster_size, buf);
				if (zeroed != vol->cluster_size) {
					ntfs_log_error("Failed to zero at "
						"offset %lld\n",
						(long long)pos);
					errno = EIO;
					err = -1;
				}
				pos += vol->cluster_size;
			}
			zrl++;
			pos = zrl->vcn << vol->cluster_size_bits;
		}
		free(buf);
	} else {
		ntfs_log_error("Failed to allocate memory\n");
		errno = ENOSPC;
		err = -1;
	}
	return (err);
}
Exemplo n.º 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);
}