Initial revision
							parent
							
								
									a7a6c5cfe5
								
							
						
					
					
						commit
						010e735129
					
				|  | @ -1,217 +0,0 @@ | |||
| /*
 | ||||
|  * compress.c - Compressed attribute handling code. Part of the Linux-NTFS | ||||
|  *		project. | ||||
|  * | ||||
|  * Copyright (c) 2004 Anton Altaparmakov | ||||
|  * | ||||
|  * This program/include file 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 Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program/include file is distributed in the hope that it will be | ||||
|  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty | ||||
|  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program (in the main directory of the Linux-NTFS | ||||
|  * distribution in the file COPYING); if not, write to the Free Software | ||||
|  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include "attrib.h" | ||||
| #include "debug.h" | ||||
| #include "volume.h" | ||||
| #include "types.h" | ||||
| #include "layout.h" | ||||
| #include "runlist.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * ntfs_compressed_attr_pread - read from a compressed attribute | ||||
|  * @na:		ntfs attribute to read from | ||||
|  * @pos:	byte position in the attribute to begin reading from | ||||
|  * @count:	number of bytes to read | ||||
|  * @b:		output data buffer | ||||
|  * | ||||
|  * NOTE:  You probably want to be using attrib.c::ntfs_attr_pread() instead. | ||||
|  * | ||||
|  * This function will read @count bytes starting at offset @pos from the | ||||
|  * compressed ntfs attribute @na into the data buffer @b. | ||||
|  * | ||||
|  * On success, return the number of successfully read bytes.  If this number | ||||
|  * is lower than @count this means that the read reached end of file 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 is 0). | ||||
|  * | ||||
|  * On error and nothing has been read, return -1 with errno set appropriately | ||||
|  * to the return code of ntfs_pread(), or to EINVAL in case of invalid | ||||
|  * arguments. | ||||
|  */ | ||||
| s64 ntfs_compressed_attr_pread(ntfs_attr *na, const s64 pos, s64 count, | ||||
| 		void *b) | ||||
| { | ||||
| 	s64 br, to_read, ofs, total, total2; | ||||
| 	u64 cb_size_mask; | ||||
| 	VCN start_vcn, end_vcn; | ||||
| 	ntfs_volume *vol; | ||||
| 	runlist_element *rl; | ||||
| 	u8 *ntfs_compression_buffer, *ntfs_uncompressed_buffer; | ||||
| 	u8 *cb, *cb_pos, *cb_end; | ||||
| 	u32 cb_size; | ||||
| 	unsigned int nr_cbs, cb_clusters; | ||||
| 
 | ||||
| 	Dprintf("%s(): Entering for inode 0x%Lx, attr 0x%x, pos 0x%Lx, " | ||||
| 			"count 0x%Lx.\n", __FUNCTION__, | ||||
| 			(unsigned long long)na->ni->mft_no, na->type, | ||||
| 			(long long)pos, (long long)count); | ||||
| 	if (!na || !NAttrCompressed(na) || !na->ni || !na->ni->vol || !b || | ||||
| 			pos < 0 || count < 0) { | ||||
| 		errno = EINVAL; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/*
 | ||||
| 	 * Encrypted attributes are not supported.  We return access denied, | ||||
| 	 * which is what Windows NT4 does, too. | ||||
| 	 */ | ||||
| 	if (NAttrEncrypted(na)) { | ||||
| 		errno = EACCES; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	if (!count) | ||||
| 		return 0; | ||||
| 	/* Truncate reads beyond end of attribute. */ | ||||
| 	if (pos + count > na->data_size) { | ||||
| 		if (pos >= na->data_size) | ||||
| 			return 0; | ||||
| 		count = na->data_size - pos; | ||||
| 	} | ||||
| 	/* If it is a resident attribute, simply use ntfs_attr_pread(). */ | ||||
| 	if (!NAttrNonResident(na)) | ||||
| 		return ntfs_attr_pread(na, pos, count, b); | ||||
| 	total = total2 = 0; | ||||
| 	/* Zero out reads beyond initialized size. */ | ||||
| 	if (pos + count > na->initialized_size) { | ||||
| 		if (pos >= na->initialized_size) { | ||||
| 			memset(b, 0, count); | ||||
| 			return count; | ||||
| 		} | ||||
| 		total2 = pos + count - na->initialized_size; | ||||
| 		count -= total2; | ||||
| 		memset((u8*)b + count, 0, total2); | ||||
| 	} | ||||
| 	vol = na->ni->vol; | ||||
| 	cb_size = na->compression_block_size; | ||||
| 	cb_size_mask = cb_size - 1UL; | ||||
| 	cb_clusters = na->compression_block_clusters; | ||||
| 	/* Need a temporary buffer for each loaded compression block. */ | ||||
| 	ntfs_compression_buffer = malloc(cb_size); | ||||
| 	if (!ntfs_compression_buffer) | ||||
| 		return -1; | ||||
| 	/* Need a temporary buffer for each uncompressed block. */ | ||||
| 	ntfs_uncompressed_buffer = malloc(cb_size); | ||||
| 	if (!ntfs_uncompressed_buffer) { | ||||
| 		int eo = errno; | ||||
| 		free(ntfs_compression_buffer); | ||||
| 		errno = eo; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/*
 | ||||
| 	 * The first vcn in the first compression block (cb) which we need to | ||||
| 	 * decompress. | ||||
| 	 */ | ||||
| 	start_vcn = (pos & ~cb_size_mask) >> vol->cluster_size_bits; | ||||
| 	/*
 | ||||
| 	 * The first vcn in the cb after the last cb which we need to | ||||
| 	 * decompress. | ||||
| 	 */ | ||||
| 	end_vcn = ((pos + count + cb_size - 1) & ~cb_size_mask) >> | ||||
| 			vol->cluster_size_bits; | ||||
| 	/* Number of compression blocks (cbs) in the wanted vcn range. */ | ||||
| 	nr_cbs = (end_vcn - start_vcn) << vol->cluster_size_bits >> | ||||
| 			na->compression_block_size_bits; | ||||
| do_next_cb: | ||||
| 	nr_cbs--; | ||||
| 	cb_pos = cb = ntfs_compression_buffer; | ||||
| 	cb_end = cb + cb_size; | ||||
| 
 | ||||
| // FIXME: I am here... (AIA)
 | ||||
| 
 | ||||
| 	free(ntfs_compression_buffer); | ||||
| 	free(ntfs_uncompressed_buffer); | ||||
| 	errno = ENOTSUP; | ||||
| 	return -1; | ||||
| 
 | ||||
| 	/* Find the runlist element containing the vcn. */ | ||||
| 	rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits); | ||||
| 	if (!rl) { | ||||
| 		/*
 | ||||
| 		 * If the vcn is not present it is an out of bounds read. | ||||
| 		 * However, we already truncated the read to the data_size, | ||||
| 		 * so getting this here is an error. | ||||
| 		 */ | ||||
| 		if (errno == ENOENT) | ||||
| 			errno = EIO; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/*
 | ||||
| 	 * Gather the requested data into the linear destination buffer. Note, | ||||
| 	 * a partial final vcn is taken care of by the @count capping of read | ||||
| 	 * length. | ||||
| 	 */ | ||||
| 	ofs = pos - (rl->vcn << vol->cluster_size_bits); | ||||
| 	for (; count; rl++, ofs = 0) { | ||||
| 		if (!rl->length) | ||||
| 			goto rl_err_out; | ||||
| 		if (rl->lcn < (LCN)0) { | ||||
| 			if (rl->lcn != (LCN)LCN_HOLE) | ||||
| 				goto rl_err_out; | ||||
| 			/* It is a hole, just zero the matching @b range. */ | ||||
| 			to_read = min(count, (rl->length << | ||||
| 					vol->cluster_size_bits) - ofs); | ||||
| 			memset(b, 0, to_read); | ||||
| 			/* Update progress counters. */ | ||||
| 			total += to_read; | ||||
| 			count -= to_read; | ||||
| 			(u8*)b += to_read; | ||||
| 			continue; | ||||
| 		} | ||||
| 		/* It is a real lcn, read it into @dst. */ | ||||
| 		to_read = min(count, (rl->length << vol->cluster_size_bits) - | ||||
| 				ofs); | ||||
| retry: | ||||
| 		Dprintf("%s(): Reading 0x%Lx bytes from vcn 0x%Lx, lcn 0x%Lx, " | ||||
| 				"ofs 0x%Lx.\n", __FUNCTION__, to_read, | ||||
| 				rl->vcn, rl->lcn, ofs); | ||||
| 		br = ntfs_pread(vol->dev, (rl->lcn << vol->cluster_size_bits) + | ||||
| 				ofs, to_read, b); | ||||
| 		/* If everything ok, update progress counters and continue. */ | ||||
| 		if (br > 0) { | ||||
| 			total += br; | ||||
| 			count -= br; | ||||
| 			(u8*)b += br; | ||||
| 			continue; | ||||
| 		} | ||||
| 		/* If the syscall was interrupted, try again. */ | ||||
| 		if (br == (s64)-1 && errno == EINTR) | ||||
| 			goto retry; | ||||
| 		if (total) | ||||
| 			return total; | ||||
| 		if (!br) | ||||
| 			errno = EIO; | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* Finally, return the number of bytes read. */ | ||||
| 	return total + total2; | ||||
| rl_err_out: | ||||
| 	if (total) | ||||
| 		return total; | ||||
| 	errno = EIO; | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue