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

📄 runlist.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
 * On success, return a pointer to the new, combined, runlist. Note, both * runlists @dst and @src are deallocated before returning so you cannot use * the pointers for anything any more. (Strictly speaking the returned runlist * may be the same as @dst but this is irrelevant.) * * On error, return NULL, with errno set to the error code. Both runlists are * left unmodified. */static __inline__ runlist_element *ntfs_rl_split(runlist_element *dst,		int dsize, runlist_element *src, int ssize, int loc){	if (!dst || !src) {		ntfs_log_debug("Eeek. ntfs_rl_split() invoked with NULL pointer!\n");		errno = EINVAL;		return NULL;	}	/* Space required: @dst size + @src size + one new hole. */	dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1);	if (!dst)		return dst;	/*	 * We are guaranteed to succeed from here so can start modifying the	 * original runlists.	 */	/* Move the tail of @dst out of the way, then copy in @src. */	ntfs_rl_mm(dst, loc + 1 + ssize, loc, dsize - loc);	ntfs_rl_mc(dst, loc + 1, src, 0, ssize);	/* Adjust the size of the holes either size of @src. */	dst[loc].length		= dst[loc+1].vcn       - dst[loc].vcn;	dst[loc+ssize+1].vcn	= dst[loc+ssize].vcn   + dst[loc+ssize].length;	dst[loc+ssize+1].length	= dst[loc+ssize+2].vcn - dst[loc+ssize+1].vcn;	return dst;}/** * ntfs_runlists_merge - merge two runlists into one * @drl:	original runlist to be worked on * @srl:	new runlist to be merged into @drl * * First we sanity check the two runlists @srl and @drl to make sure that they * are sensible and can be merged. The runlist @srl must be either after the * runlist @drl or completely within a hole (or unmapped region) in @drl. * * Merging of runlists is necessary in two cases: *   1. When attribute lists are used and a further extent is being mapped. *   2. When new clusters are allocated to fill a hole or extend a file. * * There are four possible ways @srl can be merged. It can: *	- be inserted at the beginning of a hole, *	- split the hole in two and be inserted between the two fragments, *	- be appended at the end of a hole, or it can *	- replace the whole hole. * It can also be appended to the end of the runlist, which is just a variant * of the insert case. * * On success, return a pointer to the new, combined, runlist. Note, both * runlists @drl and @srl are deallocated before returning so you cannot use * the pointers for anything any more. (Strictly speaking the returned runlist * may be the same as @dst but this is irrelevant.) * * On error, return NULL, with errno set to the error code. Both runlists are * left unmodified. The following error codes are defined: *	ENOMEM		Not enough memory to allocate runlist array. *	EINVAL		Invalid parameters were passed in. *	ERANGE		The runlists overlap and cannot be merged. */runlist_element *ntfs_runlists_merge(runlist_element *drl,		runlist_element *srl){	int di, si;		/* Current index into @[ds]rl. */	int sstart;		/* First index with lcn > LCN_RL_NOT_MAPPED. */	int dins;		/* Index into @drl at which to insert @srl. */	int dend, send;		/* Last index into @[ds]rl. */	int dfinal, sfinal;	/* The last index into @[ds]rl with				   lcn >= LCN_HOLE. */	int marker = 0;	VCN marker_vcn = 0;	ntfs_log_debug("dst:\n");	ntfs_debug_runlist_dump(drl);	ntfs_log_debug("src:\n");	ntfs_debug_runlist_dump(srl);	/* Check for silly calling... */	if (!srl)		return drl;	/* Check for the case where the first mapping is being done now. */	if (!drl) {		drl = srl;		/* Complete the source runlist if necessary. */		if (drl[0].vcn) {			/* Scan to the end of the source runlist. */			for (dend = 0; drl[dend].length; dend++)				;			dend++;			drl = ntfs_rl_realloc(drl, dend, dend + 1);			if (!drl)				return drl;			/* Insert start element at the front of the runlist. */			ntfs_rl_mm(drl, 1, 0, dend);			drl[0].vcn = 0;			drl[0].lcn = LCN_RL_NOT_MAPPED;			drl[0].length = drl[1].vcn;		}		goto finished;	}	si = di = 0;	/* Skip any unmapped start element(s) in the source runlist. */	while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE)		si++;	/* Can't have an entirely unmapped source runlist. */	if (!srl[si].length) {		ntfs_log_debug("Eeek! ntfs_runlists_merge() received entirely "				"unmapped source runlist.\n");		errno = EINVAL;		return NULL;	}	/* Record the starting points. */	sstart = si;	/*	 * Skip forward in @drl until we reach the position where @srl needs to	 * be inserted. If we reach the end of @drl, @srl just needs to be	 * appended to @drl.	 */	for (; drl[di].length; di++) {		if (drl[di].vcn + drl[di].length > srl[sstart].vcn)			break;	}	dins = di;	/* Sanity check for illegal overlaps. */	if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) &&			(srl[si].lcn >= 0)) {		ntfs_log_debug("Run lists overlap. Cannot merge!\n");		errno = ERANGE;		return NULL;	}	/* Scan to the end of both runlists in order to know their sizes. */	for (send = si; srl[send].length; send++)		;	for (dend = di; drl[dend].length; dend++)		;	if (srl[send].lcn == (LCN)LCN_ENOENT)		marker_vcn = srl[marker = send].vcn;	/* Scan to the last element with lcn >= LCN_HOLE. */	for (sfinal = send; sfinal >= 0 && srl[sfinal].lcn < LCN_HOLE; sfinal--)		;	for (dfinal = dend; dfinal >= 0 && drl[dfinal].lcn < LCN_HOLE; dfinal--)		;	{	BOOL start;	BOOL finish;	int ds = dend + 1;		/* Number of elements in drl & srl */	int ss = sfinal - sstart + 1;	start  = ((drl[dins].lcn <  LCN_RL_NOT_MAPPED) ||    /* End of file   */		  (drl[dins].vcn == srl[sstart].vcn));	     /* Start of hole */	finish = ((drl[dins].lcn >= LCN_RL_NOT_MAPPED) &&    /* End of file   */		 ((drl[dins].vcn + drl[dins].length) <=      /* End of hole   */		  (srl[send - 1].vcn + srl[send - 1].length)));	/* Or we'll lose an end marker */	if (finish && !drl[dins].length)		ss++;	if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))		finish = FALSE;	ntfs_log_debug("dfinal = %i, dend = %i\n", dfinal, dend);	ntfs_log_debug("sstart = %i, sfinal = %i, send = %i\n", sstart, sfinal, send);	ntfs_log_debug("start = %i, finish = %i\n", start, finish);	ntfs_log_debug("ds = %i, ss = %i, dins = %i\n", ds, ss, dins);	if (start) {		if (finish)			drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins);		else			drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins);	} else {		if (finish)			drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins);		else			drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins);	}	if (!drl) {		ntfs_log_perror("Merge failed");		return drl;	}	free(srl);	if (marker) {		ntfs_log_debug("Triggering marker code.\n");		for (ds = dend; drl[ds].length; ds++)			;		/* We only need to care if @srl ended after @drl. */		if (drl[ds].vcn <= marker_vcn) {			int slots = 0;			if (drl[ds].vcn == marker_vcn) {				ntfs_log_debug("Old marker = %lli, replacing with "						"LCN_ENOENT.\n",						(long long)drl[ds].lcn);				drl[ds].lcn = (LCN)LCN_ENOENT;				goto finished;			}			/*			 * We need to create an unmapped runlist element in			 * @drl or extend an existing one before adding the			 * ENOENT terminator.			 */			if (drl[ds].lcn == (LCN)LCN_ENOENT) {				ds--;				slots = 1;			}			if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) {				/* Add an unmapped runlist element. */				if (!slots) {					/* FIXME/TODO: We need to have the					 * extra memory already! (AIA)					 */					drl = ntfs_rl_realloc(drl, ds, ds + 2);					if (!drl)						goto critical_error;					slots = 2;				}				ds++;				/* Need to set vcn if it isn't set already. */				if (slots != 1)					drl[ds].vcn = drl[ds - 1].vcn +							drl[ds - 1].length;				drl[ds].lcn = (LCN)LCN_RL_NOT_MAPPED;				/* We now used up a slot. */				slots--;			}			drl[ds].length = marker_vcn - drl[ds].vcn;			/* Finally add the ENOENT terminator. */			ds++;			if (!slots) {				/* FIXME/TODO: We need to have the extra				 * memory already! (AIA)				 */				drl = ntfs_rl_realloc(drl, ds, ds + 1);				if (!drl)					goto critical_error;			}			drl[ds].vcn = marker_vcn;			drl[ds].lcn = (LCN)LCN_ENOENT;			drl[ds].length = (s64)0;		}	}	}finished:	/* The merge was completed successfully. */	ntfs_log_debug("Merged runlist:\n");	ntfs_debug_runlist_dump(drl);	return drl;critical_error:	/* Critical error! We cannot afford to fail here. */	ntfs_log_perror("libntfs: Critical error");	ntfs_log_debug("Forcing segmentation fault!\n");	marker_vcn = ((runlist*)NULL)->lcn;	return drl;}/** * ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist * @vol:	ntfs volume on which the attribute resides * @attr:	attribute record whose mapping pairs array to decompress * @old_rl:	optional runlist in which to insert @attr's runlist * * Decompress the attribute @attr's mapping pairs array into a runlist. On * success, return the decompressed runlist. * * If @old_rl is not NULL, decompressed runlist is inserted into the * appropriate place in @old_rl and the resultant, combined runlist is * returned. The original @old_rl is deallocated. * * On error, return NULL with errno set to the error code. @old_rl is left * unmodified in that case. * * The following error codes are defined: *	ENOMEM		Not enough memory to allocate runlist array. *	EIO		Corrupt runlist. *	EINVAL		Invalid parameters were passed in. *	ERANGE		The two runlists overlap. * * FIXME: For now we take the conceptionally simplest approach of creating the * new runlist disregarding the already existing one and then splicing the * two into one, if that is possible (we check for overlap and discard the new * runlist if overlap present before returning NULL, with errno = ERANGE). */runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,		const ATTR_RECORD *attr, runlist_element *old_rl){	VCN vcn;		/* Current vcn. */	LCN lcn;		/* Current lcn. */	s64 deltaxcn;		/* Change in [vl]cn. */	runlist_element *rl;	/* The output runlist. */	const u8 *buf;		/* Current position in mapping pairs array. */	const u8 *attr_end;	/* End of attribute. */	int err, rlsize;	/* Size of runlist buffer. */	u16 rlpos;		/* Current runlist position in units of				   runlist_elements. */	u8 b;			/* Current byte offset in buf. */	ntfs_log_trace("Entering for attr 0x%x.\n",			(unsigned)le32_to_cpu(attr->type));	/* Make sure attr exists and is non-resident. */	if (!attr || !attr->non_resident ||			sle64_to_cpu(attr->lowest_vcn) < (VCN)0) {		errno = EINVAL;		return NULL;	}	/* Start at vcn = lowest_vcn and lcn 0. */	vcn = sle64_to_cpu(attr->lowest_vcn);	lcn = 0;	/* Get start of the mapping pairs array. */	buf = (const u8*)attr + le16_to_cpu(attr->mapping_pairs_offset);	attr_end = (const u8*)attr + le32_to_cpu(attr->length);	if (buf < (const u8*)attr || buf > attr_end) {		ntfs_log_debug("Corrupt attribute.\n");		errno = EIO;		return NULL;	}	/* Current position in runlist array. */	rlpos = 0;	/* Allocate first 4kiB block and set current runlist size to 4kiB. */	rl = malloc(rlsize = 0x1000);	if (!rl)		return NULL;	/* Insert unmapped starting element if necessary. */	if (vcn) {		rl->vcn = (VCN)0;		rl->lcn = (LCN)LCN_RL_NOT_MAPPED;		rl->length = vcn;		rlpos++;	}	while (buf < attr_end && *buf) {		/*		 * Allocate more memory if needed, including space for the		 * not-mapped and terminator elements.		 */		if ((int)((rlpos + 3) * sizeof(*old_rl)) > rlsize) {			runlist_element *rl2;			rlsize += 0x1000;			rl2 = realloc(rl, rlsize);			if (!rl2) {				int eo = errno;				free(rl);				errno = eo;				return NULL;			}			rl = rl2;		}		/* Enter the current vcn into the current runlist element. */		rl[rlpos].vcn = vcn;		/*		 * Get the change in vcn, i.e. the run length in clusters.		 * Doing it this way ensures that we signextend negative values.		 * A negative run length doesn't make any sense, but hey, I		 * didn't make up the NTFS specs and Windows NT4 treats the run		 * length as a signed value so that's how it is...		 */		b = *buf & 0xf;		if (b) {			if (buf + b > attr_end)				goto io_error;			for (deltaxcn = (s8)buf[b--]; b; b--)				deltaxcn = (deltaxcn << 8) + buf[b];		} else { /* The length entry is compulsory. */			ntfs_log_debug("Missing length entry in mapping pairs "					"array.\n");			deltaxcn = (s64)-1;		}		/*		 * Assume a negative length to indicate data corruption and		 * hence clean-up and return NULL.		 */		if (deltaxcn < 0) {			ntfs_log_debug("Invalid length in mapping pairs array.\n");			goto err_out;		}		/*		 * Enter the current run length into the current runlist		 * element.		 */		rl[rlpos].length = deltaxcn;		/* Increment the current vcn by the current run length. */		vcn += deltaxcn;		/*		 * There might be no lcn change at all, as is the case for		 * sparse clusters on NTFS 3.0+, in which case we set the lcn		 * to LCN_HOLE.		 */		if (!(*buf & 0xf0))			rl[rlpos].lcn = (LCN)LCN_HOLE;		else {			/* Get the lcn change which really can be negative. */			u8 b2 = *buf & 0xf;			b = b2 + ((*buf >> 4) & 0xf);			if (buf + b > attr_end)				goto io_error;			for (deltaxcn = (s8)buf[b--]; b > b2; b--)				deltaxcn = (deltaxcn << 8) + buf[b];			/* Change the current lcn to it's new value. */			lcn += deltaxcn;#ifdef DEBUG			/*			 * On NTFS 1.2-, apparently can have lcn == -1 to			 * indicate a hole. But we haven't verified ourselves			 * whether it is really the lcn or the deltaxcn that is

⌨️ 快捷键说明

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