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

📄 runlist.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	/* Skip to runlist element containing @start_vcn. */	while (rl->length && start_vcn >= rl[1].vcn)		rl++;	if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) {		errno = EINVAL;		return -1;	}	prev_lcn = 0;	/* Always need the terminating zero byte. */	rls = 1;	/* Do the first partial run if present. */	if (start_vcn > rl->vcn) {		s64 delta;		/* We know rl->length != 0 already. */		if (rl->length < 0 || rl->lcn < LCN_HOLE)			goto err_out;		delta = start_vcn - rl->vcn;		/* Header byte + length. */		rls += 1 + ntfs_get_nr_significant_bytes(rl->length - delta);		/*		 * If the logical cluster number (lcn) denotes a hole and we		 * are on NTFS 3.0+, we don't store it at all, i.e. we need		 * zero space. On earlier NTFS versions we just store the lcn.		 * Note: this assumes that on NTFS 1.2-, holes are stored with		 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).		 */		if (rl->lcn >= 0 || vol->major_ver < 3) {			prev_lcn = rl->lcn;			if (rl->lcn >= 0)				prev_lcn += delta;			/* Change in lcn. */			rls += ntfs_get_nr_significant_bytes(prev_lcn);		}		/* Go to next runlist element. */		rl++;	}	/* Do the full runs. */	for (; rl->length; rl++) {		if (rl->length < 0 || rl->lcn < LCN_HOLE)			goto err_out;		/* Header byte + length. */		rls += 1 + ntfs_get_nr_significant_bytes(rl->length);		/*		 * If the logical cluster number (lcn) denotes a hole and we		 * are on NTFS 3.0+, we don't store it at all, i.e. we need		 * zero space. On earlier NTFS versions we just store the lcn.		 * Note: this assumes that on NTFS 1.2-, holes are stored with		 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).		 */		if (rl->lcn >= 0 || vol->major_ver < 3) {			/* Change in lcn. */			rls += ntfs_get_nr_significant_bytes(rl->lcn -					prev_lcn);			prev_lcn = rl->lcn;		}	}	return rls;err_out:	if (rl->lcn == LCN_RL_NOT_MAPPED)		errno = EINVAL;	else		errno = EIO;	return -1;}/** * ntfs_write_significant_bytes - write the significant bytes of a number * @dst:	destination buffer to write to * @dst_max:	pointer to last byte of destination buffer for bounds checking * @n:		number whose significant bytes to write * * Store in @dst, the minimum bytes of the number @n which are required to * identify @n unambiguously as a signed number, taking care not to exceed * @dest_max, the maximum position within @dst to which we are allowed to * write. * * This is used when building the mapping pairs array of a runlist to compress * a given logical cluster number (lcn) or a specific run length to the minimum * size possible. * * Return the number of bytes written on success. On error, i.e. the * destination buffer @dst is too small, return -1 with errno set ENOSPC. */__inline__ int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max,		const s64 n){	s64 l = n;	int i;	s8 j;	i = 0;	do {		if (dst > dst_max)			goto err_out;		*dst++ = l & 0xffLL;		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) {		if (dst > dst_max)			goto err_out;		i++;		*dst = (u8)-1;	} else if (n > 0LL && j < 0) {		if (dst > dst_max)			goto err_out;		i++;		*dst = 0;	}	return i;err_out:	errno = ENOSPC;	return -1;}/** * ntfs_mapping_pairs_build - build the mapping pairs array from a runlist * @vol:	ntfs volume (needed for the ntfs version) * @dst:	destination buffer to which to write the mapping pairs array * @dst_len:	size of destination buffer @dst in bytes * @rl:		runlist for which to build the mapping pairs array * @start_vcn:	vcn at which to start the mapping pairs array * @stop_vcn:	first vcn outside destination buffer on success or ENOSPC error * * Create the mapping pairs array from the runlist @rl, starting at vcn * @start_vcn and save the array in @dst.  @dst_len is the size of @dst in * bytes and it should be at least equal to the value obtained by calling * ntfs_get_size_for_mapping_pairs(). * * If @rl is NULL, just write a single terminator byte to @dst. * * On success or ENOSPC error, if @stop_vcn is not NULL, *@stop_vcn is set to * the first vcn outside the destination buffer. Note that on error @dst has * been filled with all the mapping pairs that will fit, thus it can be treated * as partial success, in that a new attribute extent needs to be created or the * next extent has to be used and the mapping pairs build has to be continued * with @start_vcn set to *@stop_vcn. * * Return 0 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. *	ENOSPC	- The destination buffer is too small. */int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,		const int dst_len, const runlist_element *rl,		const VCN start_vcn, VCN *const stop_vcn){	LCN prev_lcn;	u8 *dst_max, *dst_next;	s8 len_len, lcn_len;	if (start_vcn < 0)		goto val_err;	if (!rl) {		if (start_vcn)			goto val_err;		if (stop_vcn)			*stop_vcn = 0;		if (dst_len < 1) {			errno = ENOSPC;			return -1;		}		/* Terminator byte. */		*dst = 0;		return 0;	}	/* Skip to runlist element containing @start_vcn. */	while (rl->length && start_vcn >= rl[1].vcn)		rl++;	if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn)		goto val_err;	/*	 * @dst_max is used for bounds checking in	 * ntfs_write_significant_bytes().	 */	dst_max = dst + dst_len - 1;	prev_lcn = 0;	/* Do the first partial run if present. */	if (start_vcn > rl->vcn) {		s64 delta;		/* We know rl->length != 0 already. */		if (rl->length < 0 || rl->lcn < LCN_HOLE)			goto err_out;		delta = start_vcn - rl->vcn;		/* Write length. */		len_len = ntfs_write_significant_bytes(dst + 1, dst_max,				rl->length - delta);		if (len_len < 0)			goto size_err;		/*		 * If the logical cluster number (lcn) denotes a hole and we		 * are on NTFS 3.0+, we don't store it at all, i.e. we need		 * zero space. On earlier NTFS versions we just write the lcn		 * change.  FIXME: Do we need to write the lcn change or just		 * the lcn in that case?  Not sure as I have never seen this		 * case on NT4. - We assume that we just need to write the lcn		 * change until someone tells us otherwise... (AIA)		 */		if (rl->lcn >= 0 || vol->major_ver < 3) {			prev_lcn = rl->lcn;			if (rl->lcn >= 0)				prev_lcn += delta;			/* Write change in lcn. */			lcn_len = ntfs_write_significant_bytes(dst + 1 +					len_len, dst_max, prev_lcn);			if (lcn_len < 0)				goto size_err;		} else			lcn_len = 0;		dst_next = dst + len_len + lcn_len + 1;		if (dst_next > dst_max)			goto size_err;		/* Update header byte. */		*dst = lcn_len << 4 | len_len;		/* Position at next mapping pairs array element. */		dst = dst_next;		/* Go to next runlist element. */		rl++;	}	/* Do the full runs. */	for (; rl->length; rl++) {		if (rl->length < 0 || rl->lcn < LCN_HOLE)			goto err_out;		/* Write length. */		len_len = ntfs_write_significant_bytes(dst + 1, dst_max,				rl->length);		if (len_len < 0)			goto size_err;		/*		 * If the logical cluster number (lcn) denotes a hole and we		 * are on NTFS 3.0+, we don't store it at all, i.e. we need		 * zero space. On earlier NTFS versions we just write the lcn		 * change. FIXME: Do we need to write the lcn change or just		 * the lcn in that case? Not sure as I have never seen this		 * case on NT4. - We assume that we just need to write the lcn		 * change until someone tells us otherwise... (AIA)		 */		if (rl->lcn >= 0 || vol->major_ver < 3) {			/* Write change in lcn. */			lcn_len = ntfs_write_significant_bytes(dst + 1 +					len_len, dst_max, rl->lcn - prev_lcn);			if (lcn_len < 0)				goto size_err;			prev_lcn = rl->lcn;		} else			lcn_len = 0;		dst_next = dst + len_len + lcn_len + 1;		if (dst_next > dst_max)			goto size_err;		/* Update header byte. */		*dst = lcn_len << 4 | len_len;		/* Position at next mapping pairs array element. */		dst += 1 + len_len + lcn_len;	}	/* Set stop vcn. */	if (stop_vcn)		*stop_vcn = rl->vcn;	/* Add terminator byte. */	*dst = 0;	return 0;size_err:	/* Set stop vcn. */	if (stop_vcn)		*stop_vcn = rl->vcn;	/* Add terminator byte. */	*dst = 0;	errno = ENOSPC;	return -1;val_err:	errno = EINVAL;	return -1;err_out:	if (rl->lcn == LCN_RL_NOT_MAPPED)		errno = EINVAL;	else		errno = EIO;	return -1;}/** * ntfs_rl_truncate - truncate a runlist starting at a specified vcn * @arl:	address of runlist to truncate * @start_vcn:	first vcn which should be cut off * * Truncate the runlist *@arl starting at vcn @start_vcn as well as the memory * buffer holding the runlist. * * Return 0 on success and -1 on error with errno set to the error code. * * NOTE: @arl is the address of the runlist. We need the address so we can * modify the pointer to the runlist with the new, reallocated memory buffer. */int ntfs_rl_truncate(runlist **arl, const VCN start_vcn){	runlist *rl;	BOOL is_end;	if (!arl || !*arl) {		errno = EINVAL;		return -1;	}	rl = *arl;	if (start_vcn < rl->vcn) {		// FIXME: Eeek! BUG()		ntfs_log_trace("Eeek! start_vcn lies outside front of runlist!  "				"Aborting.\n");		errno = EIO;		return -1;	}	/* Find the starting vcn in the run list. */	while (rl->length) {		if (start_vcn < rl[1].vcn)			break;		rl++;	}	if (!rl->length) {		// FIXME: Weird, probably a BUG()!		ntfs_log_trace("Weird!  Asking to truncate already truncated "				"runlist?!?  Abort.\n");		errno = EIO;		return -1;	}	if (start_vcn < rl->vcn) {		// FIXME: Eeek! BUG()		ntfs_log_trace("Eeek!  start_vcn < rl->vcn!  Aborting.\n");		errno = EIO;		return -1;	}	if (rl->length) {		is_end = FALSE;		/* Truncate the run. */		rl->length = start_vcn - rl->vcn;		/*		 * If a run was partially truncated, make the following runlist		 * element a terminator instead of the truncated runlist		 * element itself.		 */		if (rl->length) {			++rl;			if (!rl->length)				is_end = TRUE;			rl->vcn = start_vcn;			rl->length = 0;		}	} else		is_end = TRUE;	rl->lcn = (LCN)LCN_ENOENT;	/* Reallocate memory if necessary. */	if (!is_end) {		size_t new_size = (rl - *arl + 1) * sizeof(runlist_element);		rl = realloc(*arl, new_size);		if (rl)			*arl = rl;		else if (!new_size)			*arl = NULL;		else {			// FIXME: Eeek!			ntfs_log_trace("Eeek!  Failed to reallocate runlist buffer!  "				"Continuing regardless and returning success.\n");		}	}	/* Done! */	return 0;}/** * ntfs_rl_sparse - check whether runlist have sparse regions or not. * @rl:		runlist to check * * Return 1 if have, 0 if not, -1 on error with errno set to the error code. */int ntfs_rl_sparse(runlist *rl){	runlist *rlc;	if (!rl) {		ntfs_log_trace("Invalid argument passed.\n");		errno = EINVAL;		return -1;	}	for (rlc = rl; rlc->length; rlc++)		if (rlc->lcn < 0) {			if (rlc->lcn != LCN_HOLE) {				ntfs_log_trace("Received unmapped runlist.\n");				errno = EINVAL;				return -1;			}			return 1;		}	return 0;}/** * ntfs_rl_get_compressed_size - calculate length of non sparse regions * @vol:	ntfs volume (need for cluster size) * @rl:		runlist to calculate for * * Return compressed size or -1 on error with errno set to the error code. */s64 ntfs_rl_get_compressed_size(ntfs_volume *vol, runlist *rl){	runlist *rlc;	s64 ret = 0;	if (!rl) {		ntfs_log_trace("Invalid argument passed.\n");		errno = EINVAL;		return -1;	}	for (rlc = rl; rlc->length; rlc++) {		if (rlc->lcn < 0) {			if (rlc->lcn != LCN_HOLE) {				ntfs_log_trace("Received unmapped runlist.\n");				errno = EINVAL;				return -1;			}		} else

⌨️ 快捷键说明

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