⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 runlist.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
			 * -1. So if either is found give us a message so we			 * can investigate it further!			 */			if (vol->major_ver < 3) {				if (deltaxcn == (LCN)-1)					ntfs_log_debug("lcn delta == -1\n");				if (lcn == (LCN)-1)					ntfs_log_debug("lcn == -1\n");			}#endif			/* Check lcn is not below -1. */			if (lcn < (LCN)-1) {				ntfs_log_debug("Invalid LCN < -1 in mapping pairs "						"array.\n");				goto err_out;			}			/* Enter the current lcn into the runlist element. */			rl[rlpos].lcn = lcn;		}		/* Get to the next runlist element. */		rlpos++;		/* Increment the buffer position to the next mapping pair. */		buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;	}	if (buf >= attr_end)		goto io_error;	/*	 * If there is a highest_vcn specified, it must be equal to the final	 * vcn in the runlist - 1, or something has gone badly wrong.	 */	deltaxcn = sle64_to_cpu(attr->highest_vcn);	if (deltaxcn && vcn - 1 != deltaxcn) {mpa_err:		ntfs_log_debug("Corrupt mapping pairs array in non-resident "				"attribute.\n");		goto err_out;	}	/* Setup not mapped runlist element if this is the base extent. */	if (!attr->lowest_vcn) {		VCN max_cluster;		max_cluster = ((sle64_to_cpu(attr->allocated_size) +				vol->cluster_size - 1) >>				vol->cluster_size_bits) - 1;		/*		 * A highest_vcn of zero means this is a single extent		 * attribute so simply terminate the runlist with LCN_ENOENT).		 */		if (deltaxcn) {			/*			 * If there is a difference between the highest_vcn and			 * the highest cluster, the runlist is either corrupt			 * or, more likely, there are more extents following			 * this one.			 */			if (deltaxcn < max_cluster) {				ntfs_log_debug("More extents to follow; deltaxcn = "						"0x%llx, max_cluster = 0x%llx\n",						(long long)deltaxcn,						(long long)max_cluster);				rl[rlpos].vcn = vcn;				vcn += rl[rlpos].length = max_cluster - deltaxcn;				rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;				rlpos++;			} else if (deltaxcn > max_cluster) {				ntfs_log_debug("Corrupt attribute. deltaxcn = "						"0x%llx, max_cluster = 0x%llx\n",						(long long)deltaxcn,						(long long)max_cluster);				goto mpa_err;			}		}		rl[rlpos].lcn = (LCN)LCN_ENOENT;	} else /* Not the base extent. There may be more extents to follow. */		rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;	/* Setup terminating runlist element. */	rl[rlpos].vcn = vcn;	rl[rlpos].length = (s64)0;	/* If no existing runlist was specified, we are done. */	if (!old_rl) {		ntfs_log_debug("Mapping pairs array successfully decompressed:\n");		ntfs_debug_runlist_dump(rl);		return rl;	}	/* Now combine the new and old runlists checking for overlaps. */	old_rl = ntfs_runlists_merge(old_rl, rl);	if (old_rl)		return old_rl;	err = errno;	free(rl);	ntfs_log_debug("Failed to merge runlists.\n");	errno = err;	return NULL;io_error:	ntfs_log_debug("Corrupt attribute.\n");err_out:	free(rl);	errno = EIO;	return NULL;}/** * ntfs_rl_vcn_to_lcn - convert a vcn into a lcn given a runlist * @rl:		runlist to use for conversion * @vcn:	vcn to convert * * Convert the virtual cluster number @vcn of an attribute into a logical * cluster number (lcn) of a device using the runlist @rl to map vcns to their * corresponding lcns. * * Since lcns must be >= 0, we use negative return values with special meaning: * * Return value			Meaning / Description * ================================================== *  -1 = LCN_HOLE		Hole / not allocated on disk. *  -2 = LCN_RL_NOT_MAPPED	This is part of the runlist which has not been *				inserted into the runlist yet. *  -3 = LCN_ENOENT		There is no such vcn in the attribute. *  -4 = LCN_EINVAL		Input parameter error. */LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn){	int i;	if (vcn < (VCN)0)		return (LCN)LCN_EINVAL;	/*	 * If rl is NULL, assume that we have found an unmapped runlist. The	 * caller can then attempt to map it and fail appropriately if	 * necessary.	 */	if (!rl)		return (LCN)LCN_RL_NOT_MAPPED;	/* Catch out of lower bounds vcn. */	if (vcn < rl[0].vcn)		return (LCN)LCN_ENOENT;	for (i = 0; rl[i].length; i++) {		if (vcn < rl[i+1].vcn) {			if (rl[i].lcn >= (LCN)0)				return rl[i].lcn + (vcn - rl[i].vcn);			return rl[i].lcn;		}	}	/*	 * The terminator element is setup to the correct value, i.e. one of	 * LCN_HOLE, LCN_RL_NOT_MAPPED, or LCN_ENOENT.	 */	if (rl[i].lcn < (LCN)0)		return rl[i].lcn;	/* Just in case... We could replace this with BUG() some day. */	return (LCN)LCN_ENOENT;}/** * ntfs_rl_pread - gather read from disk * @vol:	ntfs volume to read from * @rl:		runlist specifying where to read the data from * @pos:	byte position within runlist @rl at which to begin the read * @count:	number of bytes to read * @b:		data buffer into which to read from disk * * This function will read @count bytes from the volume @vol to the data buffer * @b gathering the data as specified by the runlist @rl. The read begins at * offset @pos into the runlist @rl. * * 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 * 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. * * NOTE: If we encounter EOF while reading we return EIO because we assume that * the run list must point to valid locations within the ntfs volume. */s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl,		const s64 pos, s64 count, void *b){	s64 bytes_read, to_read, ofs, total;	int err = EIO;	if (!vol || !rl || pos < 0 || count < 0) {		errno = EINVAL;		return -1;	}	if (!count)		return count;	/* Seek in @rl to the run containing @pos. */	for (ofs = 0; rl->length && (ofs + (rl->length <<			vol->cluster_size_bits) <= pos); rl++)		ofs += (rl->length << vol->cluster_size_bits);	/* Offset in the run at which to begin reading. */	ofs = pos - ofs;	for (total = 0LL; 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 fill buffer @b with zeroes. */			to_read = min(count, (rl->length <<					vol->cluster_size_bits) - ofs);			memset(b, 0, to_read);			/* Update counters and proceed with next run. */			total += to_read;			count -= to_read;			b = (u8*)b + to_read;			continue;		}		/* It is a real lcn, read it from the volume. */		to_read = min(count, (rl->length << vol->cluster_size_bits) -				ofs);retry:		bytes_read = ntfs_pread(vol->dev, (rl->lcn <<				vol->cluster_size_bits) + ofs, to_read, b);		/* If everything ok, update progress counters and continue. */		if (bytes_read > 0) {			total += bytes_read;			count -= bytes_read;			b = (u8*)b + bytes_read;			continue;		}		/* If the syscall was interrupted, try again. */		if (bytes_read == (s64)-1 && errno == EINTR)			goto retry;		if (bytes_read == (s64)-1)			err = errno;		goto rl_err_out;	}	/* Finally, return the number of bytes read. */	return total;rl_err_out:	if (total)		return total;	errno = err;	return -1;}/** * ntfs_rl_pwrite - scatter write to disk * @vol:	ntfs volume to write to * @rl:		runlist specifying where to write the data to * @pos:	byte position within runlist @rl at which to begin the write * @count:	number of bytes to write * @b:		data buffer to write to disk * * This function will write @count bytes from data buffer @b to the volume @vol * scattering the data as specified by the runlist @rl. The write begins at * offset @pos into the runlist @rl. * * On success, return the number of successfully written bytes. If this number * is lower than @count this means that the write has been interrupted in * flight 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 is 0). * * On error and nothing has been written, return -1 with errno set * appropriately to the return code of ntfs_pwrite(), or to to EINVAL in case * of invalid arguments. */s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl,		const s64 pos, s64 count, void *b){	s64 written, to_write, ofs, total;	int err = EIO;	if (!vol || !rl || pos < 0 || count < 0) {		errno = EINVAL;		return -1;	}	if (!count)		return count;	/* Seek in @rl to the run containing @pos. */	for (ofs = 0; rl->length && (ofs + (rl->length <<			vol->cluster_size_bits) <= pos); rl++)		ofs += (rl->length << vol->cluster_size_bits);	/* Offset in the run at which to begin writing. */	ofs = pos - ofs;	for (total = 0LL; count; rl++, ofs = 0) {		if (!rl->length)			goto rl_err_out;		if (rl->lcn < (LCN)0) {			s64 t;			int cnt;			if (rl->lcn != (LCN)LCN_HOLE)				goto rl_err_out;			/*			 * It is a hole. Check if the buffer is zero in this			 * region and if not abort with error.			 */			to_write = min(count, (rl->length <<					vol->cluster_size_bits) - ofs);			written = to_write / sizeof(unsigned long);			for (t = 0; t < written; t++) {				if (((unsigned long*)b)[t])					goto rl_err_out;			}			cnt = to_write & (sizeof(unsigned long) - 1);			if (cnt) {				int i;				u8 *b2;				b2 = (u8*)b + (to_write &						~(sizeof(unsigned long) - 1));				for (i = 0; i < cnt; i++) {					if (b2[i])						goto rl_err_out;				}			}			/*			 * The buffer region is zero, update progress counters			 * and proceed with next run.			 */			total += to_write;			count -= to_write;			b = (u8*)b + to_write;			continue;		}		/* It is a real lcn, write it to the volume. */		to_write = min(count, (rl->length << vol->cluster_size_bits) -				ofs);retry:		if (!NVolReadOnly(vol))			written = ntfs_pwrite(vol->dev, (rl->lcn <<					vol->cluster_size_bits) + ofs,					to_write, b);		else			written = to_write;		/* If everything ok, update progress counters and continue. */		if (written > 0) {			total += written;			count -= written;			b = (u8*)b + written;			continue;		}		/* If the syscall was interrupted, try again. */		if (written == (s64)-1 && errno == EINTR)			goto retry;		if (written == (s64)-1)			err = errno;		goto rl_err_out;	}	/* Finally, return the number of bytes written. */	return total;rl_err_out:	if (total)		return total;	errno = err;	return -1;}/** * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number * @n:		number for which to get the number of bytes for * * Return the number of bytes required to store @n unambiguously as * a signed number. * * This is used in the context of the mapping pairs array to determine how * many bytes will be needed in the array to store a given logical cluster * number (lcn) or a specific run length. * * Return the number of bytes written. This function cannot fail. */__inline__ int ntfs_get_nr_significant_bytes(const s64 n){	s64 l = n;	int i;	s8 j;	i = 0;	do {		l >>= 8;		i++;	} while (l != 0LL && l != -1LL);	j = (n >> 8 * (i - 1)) & 0xff;	/* If the sign bit is wrong, we need an extra byte. */	if ((n < 0LL && j >= 0) || (n > 0LL && j < 0))		i++;	return i;}/** * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array * @vol:	ntfs volume (needed for the ntfs version) * @rl:		runlist for which to determine the size of the mapping pairs * @start_vcn:	vcn at which to start the mapping pairs array * * Walk the runlist @rl and calculate the size in bytes of the mapping pairs * array corresponding to the runlist @rl, starting at vcn @start_vcn.  This * for example allows us to allocate a buffer of the right size when building * the mapping pairs array. * * If @rl is NULL, just return 1 (for the single terminator byte). * * Return the calculated size in bytes on success.  On error, return -1 with * errno set to the error code.  The following error codes are defined: *	EINVAL	- Run list contains unmapped elements. Make sure to only pass *		  fully mapped runlists to this function. *		- @start_vcn is invalid. *	EIO	- The runlist is corrupt. */int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,		const runlist_element *rl, const VCN start_vcn){	LCN prev_lcn;	int rls;	if (start_vcn < 0) {		ntfs_log_trace("start_vcn %lld (should be >= 0)\n",				(long long) start_vcn);		errno = EINVAL;		return -1;	}	if (!rl) {		if (start_vcn) {			ntfs_log_trace("rl NULL, start_vcn %lld (should be > 0)\n",					(long long) start_vcn);			errno = EINVAL;			return -1;		}		return 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -