xref: /plan9/sys/src/cmd/aux/antiword/datalist.c (revision f5736e95f14e1485b3a0291fa82d86cca323ab61)
1*f5736e95SDavid du Colombier /*
2*f5736e95SDavid du Colombier  * datalist.c
3*f5736e95SDavid du Colombier  * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
4*f5736e95SDavid du Colombier  *
5*f5736e95SDavid du Colombier  * Description:
6*f5736e95SDavid du Colombier  * Build, read and destroy a list of Word data blocks
7*f5736e95SDavid du Colombier  */
8*f5736e95SDavid du Colombier 
9*f5736e95SDavid du Colombier #include <stdlib.h>
10*f5736e95SDavid du Colombier #include <errno.h>
11*f5736e95SDavid du Colombier #include "antiword.h"
12*f5736e95SDavid du Colombier 
13*f5736e95SDavid du Colombier #if defined(__riscos)
14*f5736e95SDavid du Colombier #define EIO		42
15*f5736e95SDavid du Colombier #endif /* __riscos */
16*f5736e95SDavid du Colombier 
17*f5736e95SDavid du Colombier 
18*f5736e95SDavid du Colombier /*
19*f5736e95SDavid du Colombier  * Private structure to hide the way the information
20*f5736e95SDavid du Colombier  * is stored from the rest of the program
21*f5736e95SDavid du Colombier  */
22*f5736e95SDavid du Colombier typedef struct data_mem_tag {
23*f5736e95SDavid du Colombier 	data_block_type		tInfo;
24*f5736e95SDavid du Colombier 	struct data_mem_tag	*pNext;
25*f5736e95SDavid du Colombier } data_mem_type;
26*f5736e95SDavid du Colombier 
27*f5736e95SDavid du Colombier /* Variable to describe the start of the data block list */
28*f5736e95SDavid du Colombier static data_mem_type	*pAnchor = NULL;
29*f5736e95SDavid du Colombier /* Variable needed to read the data block list */
30*f5736e95SDavid du Colombier static data_mem_type	*pBlockLast = NULL;
31*f5736e95SDavid du Colombier /* Variable needed to read the data block list */
32*f5736e95SDavid du Colombier static data_mem_type	*pBlockCurrent = NULL;
33*f5736e95SDavid du Colombier static ULONG	ulBlockOffset = 0;
34*f5736e95SDavid du Colombier static size_t	tByteNext = 0;
35*f5736e95SDavid du Colombier /* Last block read */
36*f5736e95SDavid du Colombier static UCHAR	aucBlock[BIG_BLOCK_SIZE];
37*f5736e95SDavid du Colombier 
38*f5736e95SDavid du Colombier 
39*f5736e95SDavid du Colombier /*
40*f5736e95SDavid du Colombier  * vDestroyDataBlockList - destroy the data block list
41*f5736e95SDavid du Colombier  */
42*f5736e95SDavid du Colombier void
vDestroyDataBlockList(void)43*f5736e95SDavid du Colombier vDestroyDataBlockList(void)
44*f5736e95SDavid du Colombier {
45*f5736e95SDavid du Colombier 	data_mem_type	*pCurr, *pNext;
46*f5736e95SDavid du Colombier 
47*f5736e95SDavid du Colombier 	DBG_MSG("vDestroyDataBlockList");
48*f5736e95SDavid du Colombier 
49*f5736e95SDavid du Colombier 	pCurr = pAnchor;
50*f5736e95SDavid du Colombier 	while (pCurr != NULL) {
51*f5736e95SDavid du Colombier 		pNext = pCurr->pNext;
52*f5736e95SDavid du Colombier 		pCurr = xfree(pCurr);
53*f5736e95SDavid du Colombier 		pCurr = pNext;
54*f5736e95SDavid du Colombier 	}
55*f5736e95SDavid du Colombier 	pAnchor = NULL;
56*f5736e95SDavid du Colombier 	/* Reset all the control variables */
57*f5736e95SDavid du Colombier 	pBlockLast = NULL;
58*f5736e95SDavid du Colombier 	pBlockCurrent = NULL;
59*f5736e95SDavid du Colombier 	ulBlockOffset = 0;
60*f5736e95SDavid du Colombier 	tByteNext = 0;
61*f5736e95SDavid du Colombier } /* end of vDestroyDataBlockList */
62*f5736e95SDavid du Colombier 
63*f5736e95SDavid du Colombier /*
64*f5736e95SDavid du Colombier  * bAdd2DataBlockList - add an element to the data block list
65*f5736e95SDavid du Colombier  *
66*f5736e95SDavid du Colombier  * Returns TRUE when successful, otherwise FALSE
67*f5736e95SDavid du Colombier  */
68*f5736e95SDavid du Colombier BOOL
bAdd2DataBlockList(const data_block_type * pDataBlock)69*f5736e95SDavid du Colombier bAdd2DataBlockList(const data_block_type *pDataBlock)
70*f5736e95SDavid du Colombier {
71*f5736e95SDavid du Colombier 	data_mem_type	*pListMember;
72*f5736e95SDavid du Colombier 
73*f5736e95SDavid du Colombier 	fail(pDataBlock == NULL);
74*f5736e95SDavid du Colombier 	fail(pDataBlock->ulFileOffset == FC_INVALID);
75*f5736e95SDavid du Colombier 	fail(pDataBlock->ulDataPos == CP_INVALID);
76*f5736e95SDavid du Colombier 	fail(pDataBlock->ulLength == 0);
77*f5736e95SDavid du Colombier 
78*f5736e95SDavid du Colombier 	NO_DBG_MSG("bAdd2DataBlockList");
79*f5736e95SDavid du Colombier 	NO_DBG_HEX(pDataBlock->ulFileOffset);
80*f5736e95SDavid du Colombier 	NO_DBG_HEX(pDataBlock->ulDataPos);
81*f5736e95SDavid du Colombier 	NO_DBG_HEX(pDataBlock->ulLength);
82*f5736e95SDavid du Colombier 
83*f5736e95SDavid du Colombier 	if (pDataBlock->ulFileOffset == FC_INVALID ||
84*f5736e95SDavid du Colombier 	    pDataBlock->ulDataPos == CP_INVALID ||
85*f5736e95SDavid du Colombier 	    pDataBlock->ulLength == 0) {
86*f5736e95SDavid du Colombier 		werr(0, "Software (datablock) error");
87*f5736e95SDavid du Colombier 		return FALSE;
88*f5736e95SDavid du Colombier 	}
89*f5736e95SDavid du Colombier 	/* Check for continuous blocks */
90*f5736e95SDavid du Colombier 	if (pBlockLast != NULL &&
91*f5736e95SDavid du Colombier 	    pBlockLast->tInfo.ulFileOffset +
92*f5736e95SDavid du Colombier 	     pBlockLast->tInfo.ulLength == pDataBlock->ulFileOffset &&
93*f5736e95SDavid du Colombier 	    pBlockLast->tInfo.ulDataPos +
94*f5736e95SDavid du Colombier 	     pBlockLast->tInfo.ulLength == pDataBlock->ulDataPos) {
95*f5736e95SDavid du Colombier 		/* These are continous blocks */
96*f5736e95SDavid du Colombier 		pBlockLast->tInfo.ulLength += pDataBlock->ulLength;
97*f5736e95SDavid du Colombier 		return TRUE;
98*f5736e95SDavid du Colombier 	}
99*f5736e95SDavid du Colombier 	/* Make a new block */
100*f5736e95SDavid du Colombier 	pListMember = xmalloc(sizeof(data_mem_type));
101*f5736e95SDavid du Colombier 	/* Add the block to the data list */
102*f5736e95SDavid du Colombier 	pListMember->tInfo = *pDataBlock;
103*f5736e95SDavid du Colombier 	pListMember->pNext = NULL;
104*f5736e95SDavid du Colombier 	if (pAnchor == NULL) {
105*f5736e95SDavid du Colombier 		pAnchor = pListMember;
106*f5736e95SDavid du Colombier 	} else {
107*f5736e95SDavid du Colombier 		fail(pBlockLast == NULL);
108*f5736e95SDavid du Colombier 		pBlockLast->pNext = pListMember;
109*f5736e95SDavid du Colombier 	}
110*f5736e95SDavid du Colombier 	pBlockLast = pListMember;
111*f5736e95SDavid du Colombier 	return TRUE;
112*f5736e95SDavid du Colombier } /* end of bAdd2DataBlockList */
113*f5736e95SDavid du Colombier 
114*f5736e95SDavid du Colombier /*
115*f5736e95SDavid du Colombier  * ulGetDataOffset - get the offset in the data block list
116*f5736e95SDavid du Colombier  *
117*f5736e95SDavid du Colombier  * Get the fileoffset the current position in the data block list
118*f5736e95SDavid du Colombier  */
119*f5736e95SDavid du Colombier ULONG
ulGetDataOffset(FILE * pFile)120*f5736e95SDavid du Colombier ulGetDataOffset(FILE *pFile)
121*f5736e95SDavid du Colombier {
122*f5736e95SDavid du Colombier 	return pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset + tByteNext;
123*f5736e95SDavid du Colombier } /* end of ulGetDataOffset */
124*f5736e95SDavid du Colombier 
125*f5736e95SDavid du Colombier /*
126*f5736e95SDavid du Colombier  * bSetDataOffset - set the offset in the data block list
127*f5736e95SDavid du Colombier  *
128*f5736e95SDavid du Colombier  * Make the given fileoffset the current position in the data block list
129*f5736e95SDavid du Colombier  */
130*f5736e95SDavid du Colombier BOOL
bSetDataOffset(FILE * pFile,ULONG ulFileOffset)131*f5736e95SDavid du Colombier bSetDataOffset(FILE *pFile, ULONG ulFileOffset)
132*f5736e95SDavid du Colombier {
133*f5736e95SDavid du Colombier 	data_mem_type	*pCurr;
134*f5736e95SDavid du Colombier 	size_t	tReadLen;
135*f5736e95SDavid du Colombier 
136*f5736e95SDavid du Colombier 	DBG_HEX(ulFileOffset);
137*f5736e95SDavid du Colombier 
138*f5736e95SDavid du Colombier 	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
139*f5736e95SDavid du Colombier 		if (ulFileOffset < pCurr->tInfo.ulFileOffset ||
140*f5736e95SDavid du Colombier 		    ulFileOffset >= pCurr->tInfo.ulFileOffset +
141*f5736e95SDavid du Colombier 		     pCurr->tInfo.ulLength) {
142*f5736e95SDavid du Colombier 			/* The file offset is not in this block */
143*f5736e95SDavid du Colombier 			continue;
144*f5736e95SDavid du Colombier 		}
145*f5736e95SDavid du Colombier 		/* Compute the maximum number of bytes to read */
146*f5736e95SDavid du Colombier 		tReadLen = (size_t)(pCurr->tInfo.ulFileOffset +
147*f5736e95SDavid du Colombier 				pCurr->tInfo.ulLength -
148*f5736e95SDavid du Colombier 				ulFileOffset);
149*f5736e95SDavid du Colombier 		/* Compute the real number of bytes to read */
150*f5736e95SDavid du Colombier 		if (tReadLen > sizeof(aucBlock)) {
151*f5736e95SDavid du Colombier 			tReadLen = sizeof(aucBlock);
152*f5736e95SDavid du Colombier 		}
153*f5736e95SDavid du Colombier 		/* Read the bytes */
154*f5736e95SDavid du Colombier 		if (!bReadBytes(aucBlock, tReadLen, ulFileOffset, pFile)) {
155*f5736e95SDavid du Colombier 			return FALSE;
156*f5736e95SDavid du Colombier 		}
157*f5736e95SDavid du Colombier 		/* Set the control variables */
158*f5736e95SDavid du Colombier 		pBlockCurrent = pCurr;
159*f5736e95SDavid du Colombier 		ulBlockOffset = ulFileOffset - pCurr->tInfo.ulFileOffset;
160*f5736e95SDavid du Colombier 		tByteNext = 0;
161*f5736e95SDavid du Colombier 		return TRUE;
162*f5736e95SDavid du Colombier 	}
163*f5736e95SDavid du Colombier 	return FALSE;
164*f5736e95SDavid du Colombier } /* end of bSetDataOffset */
165*f5736e95SDavid du Colombier 
166*f5736e95SDavid du Colombier /*
167*f5736e95SDavid du Colombier  * iNextByte - get the next byte from the data block list
168*f5736e95SDavid du Colombier  */
169*f5736e95SDavid du Colombier int
iNextByte(FILE * pFile)170*f5736e95SDavid du Colombier iNextByte(FILE *pFile)
171*f5736e95SDavid du Colombier {
172*f5736e95SDavid du Colombier 	ULONG	ulReadOff;
173*f5736e95SDavid du Colombier 	size_t	tReadLen;
174*f5736e95SDavid du Colombier 
175*f5736e95SDavid du Colombier 	fail(pBlockCurrent == NULL);
176*f5736e95SDavid du Colombier 
177*f5736e95SDavid du Colombier 	if (tByteNext >= sizeof(aucBlock) ||
178*f5736e95SDavid du Colombier 	    ulBlockOffset + tByteNext >= pBlockCurrent->tInfo.ulLength) {
179*f5736e95SDavid du Colombier 		if (ulBlockOffset + sizeof(aucBlock) <
180*f5736e95SDavid du Colombier 					pBlockCurrent->tInfo.ulLength) {
181*f5736e95SDavid du Colombier 			/* Same block, next part */
182*f5736e95SDavid du Colombier 			ulBlockOffset += sizeof(aucBlock);
183*f5736e95SDavid du Colombier 		} else {
184*f5736e95SDavid du Colombier 			/* Next block, first part */
185*f5736e95SDavid du Colombier 			pBlockCurrent = pBlockCurrent->pNext;
186*f5736e95SDavid du Colombier 			ulBlockOffset = 0;
187*f5736e95SDavid du Colombier 		}
188*f5736e95SDavid du Colombier 		if (pBlockCurrent == NULL) {
189*f5736e95SDavid du Colombier 			/* Past the last part of the last block */
190*f5736e95SDavid du Colombier 			errno = EIO;
191*f5736e95SDavid du Colombier 			return EOF;
192*f5736e95SDavid du Colombier 		}
193*f5736e95SDavid du Colombier 		tReadLen = (size_t)
194*f5736e95SDavid du Colombier 				(pBlockCurrent->tInfo.ulLength - ulBlockOffset);
195*f5736e95SDavid du Colombier 		if (tReadLen > sizeof(aucBlock)) {
196*f5736e95SDavid du Colombier 			tReadLen = sizeof(aucBlock);
197*f5736e95SDavid du Colombier 		}
198*f5736e95SDavid du Colombier 		ulReadOff = pBlockCurrent->tInfo.ulFileOffset + ulBlockOffset;
199*f5736e95SDavid du Colombier 		if (!bReadBytes(aucBlock, tReadLen, ulReadOff, pFile)) {
200*f5736e95SDavid du Colombier 			errno = EIO;
201*f5736e95SDavid du Colombier 			return EOF;
202*f5736e95SDavid du Colombier 		}
203*f5736e95SDavid du Colombier 		tByteNext = 0;
204*f5736e95SDavid du Colombier 	}
205*f5736e95SDavid du Colombier 	return (int)aucBlock[tByteNext++];
206*f5736e95SDavid du Colombier } /* end of iNextByte */
207*f5736e95SDavid du Colombier 
208*f5736e95SDavid du Colombier /*
209*f5736e95SDavid du Colombier  * usNextWord - get the next word from the data block list
210*f5736e95SDavid du Colombier  *
211*f5736e95SDavid du Colombier  * Read a two byte value in Little Endian order, that means MSB last
212*f5736e95SDavid du Colombier  *
213*f5736e95SDavid du Colombier  * All return values can be valid so errno is set in case of error
214*f5736e95SDavid du Colombier  */
215*f5736e95SDavid du Colombier USHORT
usNextWord(FILE * pFile)216*f5736e95SDavid du Colombier usNextWord(FILE *pFile)
217*f5736e95SDavid du Colombier {
218*f5736e95SDavid du Colombier 	USHORT	usLSB, usMSB;
219*f5736e95SDavid du Colombier 
220*f5736e95SDavid du Colombier 	usLSB = (USHORT)iNextByte(pFile);
221*f5736e95SDavid du Colombier 	if (usLSB == (USHORT)EOF) {
222*f5736e95SDavid du Colombier 		errno = EIO;
223*f5736e95SDavid du Colombier 		return (USHORT)EOF;
224*f5736e95SDavid du Colombier 	}
225*f5736e95SDavid du Colombier 	usMSB = (USHORT)iNextByte(pFile);
226*f5736e95SDavid du Colombier 	if (usMSB == (USHORT)EOF) {
227*f5736e95SDavid du Colombier 		DBG_MSG("usNextWord: Unexpected EOF");
228*f5736e95SDavid du Colombier 		errno = EIO;
229*f5736e95SDavid du Colombier 		return (USHORT)EOF;
230*f5736e95SDavid du Colombier 	}
231*f5736e95SDavid du Colombier 	return (usMSB << 8) | usLSB;
232*f5736e95SDavid du Colombier } /* end of usNextWord */
233*f5736e95SDavid du Colombier 
234*f5736e95SDavid du Colombier /*
235*f5736e95SDavid du Colombier  * ulNextLong - get the next long from the data block list
236*f5736e95SDavid du Colombier  *
237*f5736e95SDavid du Colombier  * Read a four byte value in Little Endian order, that means MSW last
238*f5736e95SDavid du Colombier  *
239*f5736e95SDavid du Colombier  * All return values can be valid so errno is set in case of error
240*f5736e95SDavid du Colombier  */
241*f5736e95SDavid du Colombier ULONG
ulNextLong(FILE * pFile)242*f5736e95SDavid du Colombier ulNextLong(FILE *pFile)
243*f5736e95SDavid du Colombier {
244*f5736e95SDavid du Colombier 	ULONG	ulLSW, ulMSW;
245*f5736e95SDavid du Colombier 
246*f5736e95SDavid du Colombier 	ulLSW = (ULONG)usNextWord(pFile);
247*f5736e95SDavid du Colombier 	if (ulLSW == (ULONG)EOF) {
248*f5736e95SDavid du Colombier 		errno = EIO;
249*f5736e95SDavid du Colombier 		return (ULONG)EOF;
250*f5736e95SDavid du Colombier 	}
251*f5736e95SDavid du Colombier 	ulMSW = (ULONG)usNextWord(pFile);
252*f5736e95SDavid du Colombier 	if (ulMSW == (ULONG)EOF) {
253*f5736e95SDavid du Colombier 		DBG_MSG("ulNextLong: Unexpected EOF");
254*f5736e95SDavid du Colombier 		errno = EIO;
255*f5736e95SDavid du Colombier 		return (ULONG)EOF;
256*f5736e95SDavid du Colombier 	}
257*f5736e95SDavid du Colombier 	return (ulMSW << 16) | ulLSW;
258*f5736e95SDavid du Colombier } /* end of ulNextLong */
259*f5736e95SDavid du Colombier 
260*f5736e95SDavid du Colombier /*
261*f5736e95SDavid du Colombier  * usNextWordBE - get the next two byte value
262*f5736e95SDavid du Colombier  *
263*f5736e95SDavid du Colombier  * Read a two byte value in Big Endian order, that means MSB first
264*f5736e95SDavid du Colombier  *
265*f5736e95SDavid du Colombier  * All return values can be valid so errno is set in case of error
266*f5736e95SDavid du Colombier  */
267*f5736e95SDavid du Colombier USHORT
usNextWordBE(FILE * pFile)268*f5736e95SDavid du Colombier usNextWordBE(FILE *pFile)
269*f5736e95SDavid du Colombier {
270*f5736e95SDavid du Colombier 	USHORT usLSB, usMSB;
271*f5736e95SDavid du Colombier 
272*f5736e95SDavid du Colombier 	usMSB = (USHORT)iNextByte(pFile);
273*f5736e95SDavid du Colombier 	if (usMSB == (USHORT)EOF) {
274*f5736e95SDavid du Colombier 		errno = EIO;
275*f5736e95SDavid du Colombier 		return (USHORT)EOF;
276*f5736e95SDavid du Colombier 	}
277*f5736e95SDavid du Colombier 	usLSB = (USHORT)iNextByte(pFile);
278*f5736e95SDavid du Colombier 	if (usLSB == (USHORT)EOF) {
279*f5736e95SDavid du Colombier 		DBG_MSG("usNextWordBE: Unexpected EOF");
280*f5736e95SDavid du Colombier 		errno = EIO;
281*f5736e95SDavid du Colombier 		return (USHORT)EOF;
282*f5736e95SDavid du Colombier 	}
283*f5736e95SDavid du Colombier 	return (usMSB << 8) | usLSB;
284*f5736e95SDavid du Colombier } /* end of usNextWordBE */
285*f5736e95SDavid du Colombier 
286*f5736e95SDavid du Colombier /*
287*f5736e95SDavid du Colombier  * ulNextLongBE - get the next four byte value
288*f5736e95SDavid du Colombier  *
289*f5736e95SDavid du Colombier  * Read a four byte value in Big Endian order, that means MSW first
290*f5736e95SDavid du Colombier  *
291*f5736e95SDavid du Colombier  * All return values can be valid so errno is set in case of error
292*f5736e95SDavid du Colombier  */
293*f5736e95SDavid du Colombier ULONG
ulNextLongBE(FILE * pFile)294*f5736e95SDavid du Colombier ulNextLongBE(FILE *pFile)
295*f5736e95SDavid du Colombier {
296*f5736e95SDavid du Colombier 	ULONG	ulLSW, ulMSW;
297*f5736e95SDavid du Colombier 
298*f5736e95SDavid du Colombier 	ulMSW = (ULONG)usNextWordBE(pFile);
299*f5736e95SDavid du Colombier 	if (ulMSW == (ULONG)EOF) {
300*f5736e95SDavid du Colombier 		errno = EIO;
301*f5736e95SDavid du Colombier 		return (ULONG)EOF;
302*f5736e95SDavid du Colombier 	}
303*f5736e95SDavid du Colombier 	ulLSW = (ULONG)usNextWordBE(pFile);
304*f5736e95SDavid du Colombier 	if (ulLSW == (ULONG)EOF) {
305*f5736e95SDavid du Colombier 		DBG_MSG("ulNextLongBE: Unexpected EOF");
306*f5736e95SDavid du Colombier 		errno = EIO;
307*f5736e95SDavid du Colombier 		return (ULONG)EOF;
308*f5736e95SDavid du Colombier 	}
309*f5736e95SDavid du Colombier 	return (ulMSW << 16) | ulLSW;
310*f5736e95SDavid du Colombier } /* end of ulNextLongBE */
311*f5736e95SDavid du Colombier 
312*f5736e95SDavid du Colombier /*
313*f5736e95SDavid du Colombier  * tSkipBytes - skip over the given number of bytes
314*f5736e95SDavid du Colombier  *
315*f5736e95SDavid du Colombier  * Returns the number of skipped bytes
316*f5736e95SDavid du Colombier  */
317*f5736e95SDavid du Colombier size_t
tSkipBytes(FILE * pFile,size_t tToSkip)318*f5736e95SDavid du Colombier tSkipBytes(FILE *pFile, size_t tToSkip)
319*f5736e95SDavid du Colombier {
320*f5736e95SDavid du Colombier 	size_t	tToGo, tMaxMove, tMove;
321*f5736e95SDavid du Colombier 
322*f5736e95SDavid du Colombier 	fail(pFile == NULL);
323*f5736e95SDavid du Colombier 	fail(pBlockCurrent == NULL);
324*f5736e95SDavid du Colombier 
325*f5736e95SDavid du Colombier 	tToGo = tToSkip;
326*f5736e95SDavid du Colombier 	while (tToGo != 0) {
327*f5736e95SDavid du Colombier 		/* Goto the end of the current block */
328*f5736e95SDavid du Colombier 		tMaxMove = min(sizeof(aucBlock) - tByteNext,
329*f5736e95SDavid du Colombier 				(size_t)(pBlockCurrent->tInfo.ulLength -
330*f5736e95SDavid du Colombier 				ulBlockOffset - tByteNext));
331*f5736e95SDavid du Colombier 		tMove = min(tMaxMove, tToGo);
332*f5736e95SDavid du Colombier 		tByteNext += tMove;
333*f5736e95SDavid du Colombier 		tToGo -= tMove;
334*f5736e95SDavid du Colombier 		if (tToGo != 0) {
335*f5736e95SDavid du Colombier 			/* Goto the next block */
336*f5736e95SDavid du Colombier 			if (iNextByte(pFile) == EOF) {
337*f5736e95SDavid du Colombier 				return tToSkip - tToGo;
338*f5736e95SDavid du Colombier 			}
339*f5736e95SDavid du Colombier 			tToGo--;
340*f5736e95SDavid du Colombier 		}
341*f5736e95SDavid du Colombier 	}
342*f5736e95SDavid du Colombier 	return tToSkip;
343*f5736e95SDavid du Colombier } /* end of tSkipBytes */
344*f5736e95SDavid du Colombier 
345*f5736e95SDavid du Colombier /*
346*f5736e95SDavid du Colombier  * Translate  a data position to an offset in the file.
347*f5736e95SDavid du Colombier  * Logical to physical offset.
348*f5736e95SDavid du Colombier  *
349*f5736e95SDavid du Colombier  * Returns:	FC_INVALID: in case of error
350*f5736e95SDavid du Colombier  *		otherwise: the computed file offset
351*f5736e95SDavid du Colombier  */
352*f5736e95SDavid du Colombier ULONG
ulDataPos2FileOffset(ULONG ulDataPos)353*f5736e95SDavid du Colombier ulDataPos2FileOffset(ULONG ulDataPos)
354*f5736e95SDavid du Colombier {
355*f5736e95SDavid du Colombier 	data_mem_type	*pCurr;
356*f5736e95SDavid du Colombier 
357*f5736e95SDavid du Colombier 	fail(ulDataPos == CP_INVALID);
358*f5736e95SDavid du Colombier 
359*f5736e95SDavid du Colombier 	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
360*f5736e95SDavid du Colombier 		if (ulDataPos < pCurr->tInfo.ulDataPos ||
361*f5736e95SDavid du Colombier 		    ulDataPos >= pCurr->tInfo.ulDataPos +
362*f5736e95SDavid du Colombier 		     pCurr->tInfo.ulLength) {
363*f5736e95SDavid du Colombier 			/* The data offset is not in this block, try the next */
364*f5736e95SDavid du Colombier 			continue;
365*f5736e95SDavid du Colombier 		}
366*f5736e95SDavid du Colombier 		/* The data offset is in the current block */
367*f5736e95SDavid du Colombier 		return pCurr->tInfo.ulFileOffset +
368*f5736e95SDavid du Colombier 				ulDataPos -
369*f5736e95SDavid du Colombier 				pCurr->tInfo.ulDataPos;
370*f5736e95SDavid du Colombier 	}
371*f5736e95SDavid du Colombier 	/* Passed beyond the end of the list */
372*f5736e95SDavid du Colombier 	DBG_HEX_C(ulDataPos != 0, ulDataPos);
373*f5736e95SDavid du Colombier 	return FC_INVALID;
374*f5736e95SDavid du Colombier } /* end of ulDataPos2FileOffset */
375