What is the directory overhead when burning to a DVD-R?

vbimport

#1

I wrote a program than looks at the various folders that I want to burn onto a DVD-R and figures out how to optimally fill the available space.

I’m starting with a DVD-R size of 4,707,319,808 bytes.

I’m totalling the file sizes in each folder and rounding each up for a 2048 sector size. I’m adding 2048 bytes for the DVD overhead. Based on trial and error I’m giving each file and folder 1951 bytes for its directory entry. But using this I just had a selection not fit (according to Nero).

I’d like to incorporate the exact calculation of the directory space used. So I looked for the DVD-R spec. I found this document:
c041925_ISO_IEC_23912_2005(E).pdf

But it was totally confusing. I know the length of each file pathname. Following what I read in the CDR specs that appears to be part of the space used.

I am excluding multi-session burns, which obviously waste a lot more directory space.

So how to I calculate the exact space overhead?

Thanks, Don.


#2

Hello and welcome Don.

If you are burning in ISO 9660 mode this article should be handy. It’s helped me write ISO parsers. I haven’t any knowledge of the UDF file system. Keep in mind that the first 16 sectors are reserved. It’s possible that Nero wants to use even more than required in the ISO spec though. Multisession will add lots more overhead but I don’t know the details.


#3

Hi Richman,

I’ve seen the 9660 specs, though not in that more understandable format. But it isn’t clear to me that they also apply to DVDs. DVD-Rs appear to come under ISO 23912.

I never burn multi-session, and they don’t belong into a program that is trying to optimize the fit on a DVD in one burn.


#4

Sorry…now I see that you said you were ‘excluding’ multi-session. Missed that in your first post.

DVDs and DVD-Rs use ISO 9660 unless you choose to use UDF. Nero has both options.


#5

ISO 23912 is the physical and optical spec of the DVD. The ISO 9660 spec is the format (layout of the data) that is written to the DVD (or CD), there is also UDF but I’ll assume you are using ISO 9660.

You should take a look at the document “ECMA-119.pdf”. http://www.ecma-international.org/publications/standards/Ecma-119.htm

Take a look at section 6.8 “Directory structure” and specifically a “Directory Record” (DR), and 9.1 “Format of a Directory Record”.

Note that the minimum length of a DR is 34 bytes. This 34 bytes increases with long filenames. A DR is built up in 2048 byte logical sector blocks, if a DR for a given path has N folders in it that mean the DR goes over the end of a 2048 byte block, another block is needed for that DR. The number of folders you can fit in a 2048 byte block depends on the length of the folders name (long names again).

And also note that there are two DR’s – one for short filenames and one for long filenames. Obviously the one for long filenames is larger (unless all file and folder names are less than 13 characters in length).

This code might help you too (if you know how to read C/C++), something I wrote a few years back. If you compare it along with the DR section mentioned above it might make it clearer.

“BuildDirRecEntry” builds one DR entry for a folder. If you look at the “BuildDirRecThisFolder” function, you will see it call “BuildDirRecEntry” for each folder.

“BuildDirRecThisFolder” is recursive, it starts with the “szCurrentPath” parameter set to “” which is the root. The first thing it does is call BuildDirRecEntry to make the “.” and “…” folder DR’s; then it adds all other folders in that path and subfolders by calling itself.


//////////////////////////////////////////////////////////////////////
// Note: On CD data roms there are 2048 bytes data, 288 bytes ECC checksums, 12 bytes 
// header and 4 bytes EDC. Making a raw sector size of 2352 bytes.

//////////////////////////////////////////////////////////////////////
// Directory Record Structure
//
//  BP						Field name									Content
//  1						Length of Directory Record (LEN-DR)			numerical value
//  2						Extended Attribute Record Length			numerical value
//  3 to 10					Location of Extent							numerical value
//  11 to 18				Data Length									numerical value
//  19 to 25				Recording Date and Time						numerical values
//  26						File Flags									8 bits
//  27						File Unit Size								numerical value
//  28						Interleave Gap Size							numerical value
//  29 to 32				Volume Sequence Number						numerical value
//  33						Length of File Identifier (LEN_FI)			numerical value
//  34 to (33+LEN_FI)		File Identifier								d-characters,
//  																	d1-characters,
//  																	SEPARATOR 1,
//  																	SEPARATOR 2,
//  																	(00) or (01) byte
//  (34 + LEN_FI)			Padding Field (00) byte
//  (LEN_DR-LEN_SU+1)
//  to LEN_DR
//  						System Use									LEN_SU bytes

#define DR_RECORD_LEN 0
#define DR_EXTENDED_RECORD_LEN 1
#define DR_LOCATION_OF_EXTENT_LE 2
#define DR_LOCATION_OF_EXTENT_BE 6
#define DR_DATA_LEN_LE 10
#define DR_DATA_LEN_BE 14
#define DR_DATE_AND_TIME 18
#define DR_FILE_FLAGS 25
#define DR_FILE_UNIT_SIZE 26
#define DR_INTERLEAVE_GAP_SIZE 27
#define DR_VOL_SEQ_NO_LE 28
#define DR_VOL_SEQ_NO_BE 30
#define DR_LEN_FI 32				
#define DR_FI 33						// file identifier

enum directory_record_file_flags { 
		FILEFLAGS_HIDDEN=0x1, 
		FILEFLAGS_DIRECTORY=0x2, 
		FILEFLAGS_ASSOCIATED=0x4,
		FILEFLAGS_RECORD=0x8, 
		FILEFLAGS_PROTECTION=0x10, 
		// Bits 5 to 6 are reserved
		FILEFLAGS_MULTI_EXTENT=0x80 
};

#define LOGICAL_BLOCK_SIZE 2048
#define LOGICAL_BLOCK_SIZE_AUDIO 2352

//////////////////////////////////////////////////////////////////////
// int Ciso9660::BuildDirRecEntry( CFileList *pFileList, BYTE bFileFlags, char *szFileName, 
//					BYTE bFileIdent, BYTE *bSector, struct tm *tCreated, BOOL bFolderIsEmpty,
//					unsigned int iLen  )
//
// BYTE bFileFlags			- File flags, hidden (FILEFLAGS_HIDDEN) & folder (FILEFLAGS_DIRECTORY)
// char *szFileName			- Filename
// BYTE bFileIdent,			- Usually -1. If the entry is a special NULL folder ident set this to 0,1. 
// BYTE *bSector			- Destination for the DR data to be stored in
// struct tm *tCreated		- Time file/folder was created
// unsigned int iLen		- Length of file or LOGICAL_CLOCK_SIZE for a folder
// BOOL bFolderIsEmpty		- TRUE if the folder is empty (its Location 
//							of Extent will point to itself).
//							Only valid if the entry is a folder

int Ciso9660::BuildDirRecEntry( CFileList *pFileList, BYTE bFileFlags, char *szFileName, 
						char *sz83FileName,	BYTE bFileIdent, BYTE *bSector, BYTE *bLongSector, 
						struct tm *tCreated, unsigned int iLen,
						BOOL bFolderIsEmpty, short sParentFolder, 
						unsigned int iFolderLB,	unsigned int iFolderLB_L )
{
	char szFileIdent[256], szFileIdentLong[256];

	// ------------------------------------------------------
	// Normal Directory Record

	// Prepare filename -------------------
	strcpy( szFileIdent, sz83FileName );
	strupr( szFileIdent );

	
	if( !(bFileFlags & FILEFLAGS_DIRECTORY) )
	{
		strcat( szFileIdent, ";1" );		// Its a file
		if( strlen(szFileIdent)>=255 )
		{
			szFileIdent[254] = ';';
			szFileIdent[255] = '1';
			szFileIdent[256] = '\0';
		}
	}
	else
	{
		if( iLen==0 )						// Its a folder
			iLen = LOGICAL_BLOCK_SIZE;

		if( strcmp( szFileName, "" ) !=0 )
		{
			pFileList->m_iItemPTFolderNumber = ++m_iPathTableRecordNo;
			pFileList->m_iItemPTParentFolderNum = sParentFolder;
		}
	}

	BYTE bLenRecord = 33;	// 34 is the mininum length of a record. It is made longer by
	// the length of the "File Identifier" (filename).

	// 1  Length of directory Record. should be 0 as we dont use the extended stuff
	bSector[DR_EXTENDED_RECORD_LEN] = 0;

	// 3 to 10               Location of Extent
	if( (bFileFlags & FILEFLAGS_DIRECTORY) && bFolderIsEmpty )
	{
		*(unsigned int*)&bSector[DR_LOCATION_OF_EXTENT_LE] = iFolderLB;		
		*(unsigned int*)&bSector[DR_LOCATION_OF_EXTENT_BE] = ReverseEndian(*(unsigned int*)&bSector[DR_LOCATION_OF_EXTENT_LE]);
	}
	else
	{
		if( bFileFlags & FILEFLAGS_DIRECTORY )
		{			
			// If its a folder then keep it at the centre
			// Need to make room at the next logic block after the last folder 
			// and before the data. Will need to adjust all refs to logic blocks
			// after this one.

			m_iLogicalBlockSectorAt++;
			pFileList->m_iBlockStartPos = m_iLogicalBlockSectorAt;
			*(unsigned int*)&bSector[DR_LOCATION_OF_EXTENT_LE] = m_iLogicalBlockSectorAt;
		}
		else
		{			
			// If its a file, put its data at the end (m_iNextLogcalBlockFree). 
			*(unsigned int*)&bSector[DR_LOCATION_OF_EXTENT_LE] = m_iNextLogcalBlockFree;	
			unsigned int iLenBlocks = (iLen / LOGICAL_BLOCK_SIZE);
			if( (iLenBlocks*LOGICAL_BLOCK_SIZE) < iLen )
				iLenBlocks++;
			m_iNextLogcalBlockFree += iLenBlocks;
		}
		*(unsigned int*)&bSector[DR_LOCATION_OF_EXTENT_BE] = ReverseEndian(*(unsigned int*)&bSector[2]);
	}

	// 11 to 18              Data Length
	*(unsigned int*)&bSector[DR_DATA_LEN_LE] = iLen; //LOGICAL_BLOCK_SIZE;
	*(unsigned int*)&bSector[DR_DATA_LEN_BE] = ReverseEndian((unsigned int)iLen);
	
	// 19 to 25              Recording Date and Time
	// 1    Number of years since 1900
	// 2    Month of the year from 1 to 12
	// 3    Day of the month from 1 to 31
	// 4    Hour of the day from 0 to 23
	// 5    Minute of the hour from 0 to 59
	// 6    Second of the minute from 0 to 59
	// 7    Offset from Greenwich Mean Time in number of 15
	//      min intervals from -48 (West) to + 52 (East) recorded
	//      according to 7.1.2
	RecordDRDataAndTime( tCreated, &bSector[DR_DATE_AND_TIME] );

	// 26                    File Flags
	bSector[DR_FILE_FLAGS] = bFileFlags;

	// 27 "File Unit Size" is always zero except for interleaved mode discs
	bSector[DR_FILE_UNIT_SIZE] = 0;	
	
	// 28  Interleave Gap Size, zero for non interleaved discs (see above)
	bSector[DR_INTERLEAVE_GAP_SIZE] = 0;	

	// 29 to 32              Volume Sequence Number, will be 1 for first disc, 2 for second, etc.
	// Somehow I don't think I'll be supporting multiple volumes for a while....
	*(unsigned short*)&bSector[DR_VOL_SEQ_NO_LE] = 1;	
	*(unsigned short*)&bSector[DR_VOL_SEQ_NO_BE] = ReverseEndian((unsigned short)1);	

	if( (bFileIdent==0 || bFileIdent==1) && bFileFlags & FILEFLAGS_DIRECTORY )
	{
		// directory with no name and iden 0 or 1
		// 33  Length of File Identifier (LEN_FI) Byte 
		bSector[32]=1;

		// 34 to (33 + LEN_FI)   File Identifier
		bSector[33]=bFileIdent;

		bLenRecord++;
	}
	else
	{
		// a normal file or directory with a given name
		// 33  Length of File Identifier (LEN_FI) Byte 
		BYTE bLenFileIdent = strlen( szFileIdent );
		bSector[DR_LEN_FI] = bLenFileIdent;

		// 34 to (33 + LEN_FI)   File Identifier
		if( bLenFileIdent>0 )
			memcpy( &bSector[DR_FI], szFileIdent, bLenFileIdent );

		bLenRecord += bLenFileIdent;

		// If it ends on an odd byte we need to pad with a zero
		if( bLenRecord & 1 )
		{
			bSector[DR_FI+bLenFileIdent] = 0;
			bLenRecord++;
		}
	}

	bSector[DR_RECORD_LEN] = bLenRecord;
	// ------------------------------------------------------

	// ------------------------------------------------------
	// Long Name Directory Record

	// The long filename DR area is built in the same LB position as the 
	// normal DR area (i.e. starting at 0x13). 
	// Only when the whole DR area is finished the "location of extent's"
	// are adjusted to fit with the long filename DR's position. E.g. if 
	// the long filename DR is 4 LB's in front of the normal DR then
	// 4 is added to the long filenames "location of extent" entries.
	
	memcpy( bLongSector, bSector, LOGICAL_BLOCK_SIZE );

	// 3 to 10               Location of Extent
	if( (bFileFlags & FILEFLAGS_DIRECTORY) && bFolderIsEmpty )
	{
		*(unsigned int*)&bLongSector[DR_LOCATION_OF_EXTENT_LE] = iFolderLB_L;
		*(unsigned int*)&bLongSector[DR_LOCATION_OF_EXTENT_BE] = ReverseEndian(*(unsigned int*)&bLongSector[DR_LOCATION_OF_EXTENT_LE]);
	}
	else
	{
		if( bFileFlags & FILEFLAGS_DIRECTORY )
		{			
			// If its a folder then keep it at the centre
			// Need to make room at the next logic block after the last folder 
			// and before the data. Will need to adjust all refs to logic blocks
			// after this one.

			m_iLogicalBlockSectorAt_L++;
			pFileList->m_iBlockStartPos_L = m_iLogicalBlockSectorAt_L;
			*(unsigned int*)&bLongSector[DR_LOCATION_OF_EXTENT_LE] = m_iLogicalBlockSectorAt_L;

			//AdjustDREntries( 1, m_iLogicalBlockSectorAt, 
			//	m_bDirectoryRecordData, m_iDirectoryRecordDataSize, MODE_ALTER_BOTH );
			//AdjustDREntries( 1, m_iLogicalBlockSectorAt_L, 
			//	m_bDirectoryRecordDataLongname, m_iDirectoryRecordDataSize, MODE_ALTER_BOTH );
			
			//AdjustPTEntries( 1, m_iLogicalBlockSectorAt,
				//m_bPathTableData, m_iPathTableSize );
			//AdjustPTEntries( 1, m_iLogicalBlockSectorAt_L,
			//	m_bPathTableLongnameData, m_iPathTableLongnameSize );

			// Add the block to the DR data......?

			// m_iNextDREntryFree++;
			*(unsigned int*)&bLongSector[DR_LOCATION_OF_EXTENT_BE] = ReverseEndian(*(unsigned int*)&bLongSector[DR_LOCATION_OF_EXTENT_LE]);
		}
	}

	m_bLenRecordLong = bLenRecord;

	if( strlen(szFileName) < 256 )
		strcpy( szFileIdentLong, szFileName );
	else
	{
		memcpy( szFileIdentLong, szFileName, 255 );
		szFileIdentLong[255] = '\0';
	}

	if( !(bFileFlags & FILEFLAGS_DIRECTORY) )
	{
		strcat( szFileIdentLong, ";1" );
		if( strlen(szFileIdentLong)>=255 )
		{
			szFileIdentLong[254] = ';';
			szFileIdentLong[255] = '1';
			szFileIdentLong[256] = '\0';
		}
	}

	LimitFilenameLength( szFileIdentLong, MAX_LONGNAME_WIDE_LENGTH );
		
	if( (bFileIdent==0 || bFileIdent==1) && bFileFlags & FILEFLAGS_DIRECTORY )
	{
	}
	else
	{
		// Store the name in long filename format

		// a normal file or directory with a given name
		// 33  Length of File Identifier (LEN_FI) Byte 
		BYTE bLenFileIdent = strlen( szFileIdentLong );
		//m_bLenRecordLong -= bLenFileIdent;
		//if( m_bLenRecordLong & 1 )
			//m_bLenRecordLong--;
				
		bLongSector[DR_LEN_FI] = bLenFileIdent*2;

		wchar_t wStr[121];
		int len=MultiByteToWideChar(CP_THREAD_ACP,MB_PRECOMPOSED,szFileIdentLong,bLenFileIdent,wStr,120);
		memcpy_le( &bLongSector[DR_FI], (unsigned char*)wStr, bLenFileIdent*2 );

		m_bLenRecordLong = 0x22+(bLenFileIdent*2);
		bLongSector[DR_FI+bLenFileIdent*2] = 0;
	}

	bLongSector[DR_RECORD_LEN] = m_bLenRecordLong;
	
	// ------------------------------------------------------

	if((bFileFlags & FILEFLAGS_DIRECTORY) && bFileIdent!=1) 
	{

		// Add the directory to the path table
		if( strcmp( szFileName, "" )==0 && sParentFolder==0 )
			AddToPathTable(szFileIdent, szFileIdentLong, sParentFolder, pFileList);
		else
		if( strcmp( szFileName, "" )!=0 )
			AddToPathTable(szFileIdent, szFileIdentLong, sParentFolder, pFileList);
	}

	return bLenRecord;
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Build all DR entries in the folder "szCurrentPath".

void Ciso9660::BuildDirRecThisFolder(char *szCurrentPath, CFileList *pFileList, 
						 int iFileListPosition, struct tm *tCreated, 
						 unsigned int iSecPos, unsigned int iSecPosLongname,
						 unsigned int iParentFoldersLB, unsigned int iThisFoldersLB,
						 unsigned int iParentFoldersLB_L, unsigned int iThisFoldersLB_L,
						 unsigned int iSecPosDRFolderFrom, unsigned int iSecPosDRFolderFromLongname,
						 unsigned int iParentPathTableEntryNum, unsigned int iThisFolderPathTableNum,
						 BOOL bLongDR)
{
	BOOL bFinished=FALSE;

	BYTE bDirRecEntry[LOGICAL_BLOCK_SIZE];
	BYTE bDirLongnameRecEntry[LOGICAL_BLOCK_SIZE];
	int iDirRecLen;

	iFileListPosition = 0;

	// First two entries are blank directories ("." and "..").

	// "." ---------------------------------------------------------------------------------
	unsigned int iSecPosDRDotEntry = iSecPos;
	// point "." to this LB
	iDirRecLen = BuildDirRecEntry( pFileList, FILEFLAGS_DIRECTORY, "", "", 0x00, bDirRecEntry, 
		bDirLongnameRecEntry, tCreated, LOGICAL_BLOCK_SIZE, TRUE, 
		iParentPathTableEntryNum, iThisFoldersLB , iThisFoldersLB_L );	
	
	unsigned int iSecPosDRDotEntryLongname;
	memcpy( &m_bDirectoryRecordData[iSecPos], &bDirRecEntry[0], iDirRecLen );
	iSecPos += iDirRecLen;
	iSecPosDRDotEntryLongname = iSecPosLongname;
	memcpy( &m_bDirectoryRecordDataLongname[iSecPosLongname], &bDirLongnameRecEntry[0], GetLongnameDREntryLength() );
	iSecPosLongname += GetLongnameDREntryLength();

	// ".." ---------------------------------------------------------------------------------
	iDirRecLen = BuildDirRecEntry( pFileList, FILEFLAGS_DIRECTORY, "", "", 0x01, bDirRecEntry, 
		bDirLongnameRecEntry, tCreated, LOGICAL_BLOCK_SIZE, TRUE, 
		iParentPathTableEntryNum, iParentFoldersLB, iParentFoldersLB_L );		// point ".." to iParentFoldersLB

	memcpy( &m_bDirectoryRecordData[iSecPos], &bDirRecEntry[0], iDirRecLen );
	iSecPos += iDirRecLen;
	memcpy( &m_bDirectoryRecordDataLongname[iSecPosLongname], &bDirLongnameRecEntry[0], GetLongnameDREntryLength() );
	iSecPosLongname += GetLongnameDREntryLength();

	// ---------------------------------------------------------------------------------
	if( pFileList->GetNumEntries()== 0 )
		return;

	// Now for the files & folders in this directory.
	// After finishing the contents here, recursively go into the folders in order
	BYTE bFileFlags;
	int iFileListPositionStart = iFileListPosition;
	char szPath[MAX_PATH];

	do
	{
		pFileList = pFileList->GetItemN(iFileListPosition);
		if( pFileList==NULL || pFileList->m_szFilePath==NULL )
		{
			bFinished= TRUE;
			break;
		}

		if( pFileList!=NULL && pFileList->m_szFilePath!=NULL )
		{
			GetFilePath( pFileList->m_szFilePath, szPath );

			if( strcmp( szCurrentPath, szPath )==0 )
			{
				// File List item is in this path, add it to the current DR

				bFileFlags = 0;
				if( pFileList->m_bAttributes & _A_HIDDEN )
					bFileFlags |= FILEFLAGS_HIDDEN;
				if( pFileList->m_bAttributes & _A_SUBDIR )
					bFileFlags |= FILEFLAGS_DIRECTORY;
				struct tm *tMod = localtime( &pFileList->m_tModified );
				BOOL bFolderIsEmpty = FALSE;
				bFolderIsEmpty = FALSE;	//TRUE;		//TODO - or is it? folders always have . and ,. in them
			

				char szFileName[MAX_PATH];
				ExtractFileName(pFileList->m_szFilePath, szFileName);
				iDirRecLen = BuildDirRecEntry( pFileList, bFileFlags, szFileName, 
					pFileList->m_sz83FileName, -1, bDirRecEntry, bDirLongnameRecEntry,
					tMod, (unsigned int)pFileList->m_i64FileLen, bFolderIsEmpty, 
					iThisFolderPathTableNum, iThisFoldersLB, iThisFoldersLB_L );

				unsigned int iModSize;
				pFileList->m_iItemNumber = m_iCurrentItem++;

				iModSize = iSecPos % LOGICAL_BLOCK_SIZE;
				if( iModSize+iDirRecLen > LOGICAL_BLOCK_SIZE )
				{
					// This directory record has spilled over the Logical Block and needs
					// to use the next logical block too.
					// This will mean all blocks following that have been assigned will be shifted on
					// one logical block. And we will need to adjust all references previous to this
					// directory entry for this (add +1).

					// Make our directory reocord buffer larger and add the latest entry
					AddBlockToDirectoryRecordArea(iSecPosDRDotEntry, 
						iSecPosDRFolderFrom);

					unsigned int iSecPosNew = iSecPos;
					if( (iSecPosNew % LOGICAL_BLOCK_SIZE)!=0 )
						iSecPosNew += LOGICAL_BLOCK_SIZE;
					iSecPosNew /= LOGICAL_BLOCK_SIZE;
					iSecPosNew *= LOGICAL_BLOCK_SIZE;
					

					if( (iSecPos % LOGICAL_BLOCK_SIZE)!=0 )
						iSecPos += LOGICAL_BLOCK_SIZE;
					iSecPos /= LOGICAL_BLOCK_SIZE;
					iSecPos *= LOGICAL_BLOCK_SIZE;
					unsigned int count=m_iDirectoryRecordDataSize-LOGICAL_BLOCK_SIZE;
					count /= LOGICAL_BLOCK_SIZE;
					while( iSecPos < m_iDirectoryRecordDataSize-LOGICAL_BLOCK_SIZE )
					{
						memcpy( &m_bDirectoryRecordData[count*LOGICAL_BLOCK_SIZE], &m_bDirectoryRecordData[(count-1)*LOGICAL_BLOCK_SIZE], LOGICAL_BLOCK_SIZE );
						AdjustMovedFolder( 1, 0x14, count, pFileList, FALSE );
						iSecPos+=LOGICAL_BLOCK_SIZE;
						count--;
					}
					memset( &m_bDirectoryRecordData[count*LOGICAL_BLOCK_SIZE], 0, LOGICAL_BLOCK_SIZE );

					iSecPos = iSecPosNew;						// next record must start at next 
																// logical block and not overlap 
																// the boundary
					
					memcpy( &m_bDirectoryRecordData[iSecPos], &bDirRecEntry[0], iDirRecLen );
					pFileList->m_iItemDRSecPos = iSecPos;
					iSecPos += iDirRecLen;

					// Adjust all entries currently in the list
					m_iDREntrieExtensionCount++;

					// Adjust all entries in previous record entry blocks (if any)
					m_iLogicalBlockSectorAt++;		// new 04/05/2004 for paths after files in root over 800
				}
				else
				{
					memcpy( &m_bDirectoryRecordData[iSecPos], &bDirRecEntry[0], iDirRecLen );
					pFileList->m_iItemDRSecPos = iSecPos;
					//iThisFolderSecPos = iSecPos;
					iSecPos += iDirRecLen;
				}

				iModSize = iSecPosLongname % LOGICAL_BLOCK_SIZE;
				if( iModSize+GetLongnameDREntryLength() > LOGICAL_BLOCK_SIZE )
				{
					// This directory record has spilled over the Logical Block and needs
					// to use the next logical block too.
					// This will mean all blocks following that have been assigned will be shifted on
					// one logical block. And we will need to adjust all references previous to this
					// directory entry for this (add +1).

					// Make our directory reocord buffer larger and add the latest entry
					AddBlockToDirectoryRecordAreaLongname(iSecPosDRDotEntryLongname, 
						iSecPosDRFolderFromLongname);

					unsigned int iSecPosNew = iSecPosLongname;
					if( (iSecPosNew % LOGICAL_BLOCK_SIZE)!=0 )
						iSecPosNew += LOGICAL_BLOCK_SIZE;
					iSecPosNew /= LOGICAL_BLOCK_SIZE;
					iSecPosNew *= LOGICAL_BLOCK_SIZE;
					

					if( (iSecPosLongname % LOGICAL_BLOCK_SIZE)!=0 )
						iSecPosLongname += LOGICAL_BLOCK_SIZE;
					iSecPosLongname /= LOGICAL_BLOCK_SIZE;
					iSecPosLongname *= LOGICAL_BLOCK_SIZE;
					int iLBFixed = 0x13+(iSecPosLongname/LOGICAL_BLOCK_SIZE);
					unsigned int count=m_iDirectoryRecordDataSizeLongname-LOGICAL_BLOCK_SIZE;
					count /= LOGICAL_BLOCK_SIZE;
					while( iSecPosLongname < m_iDirectoryRecordDataSizeLongname-LOGICAL_BLOCK_SIZE )
					{
						memcpy( &m_bDirectoryRecordDataLongname[count*LOGICAL_BLOCK_SIZE], &m_bDirectoryRecordDataLongname[(count-1)*LOGICAL_BLOCK_SIZE], LOGICAL_BLOCK_SIZE );
						AdjustMovedFolder( 1, iLBFixed, count, pFileList, TRUE );
						iSecPosLongname+=LOGICAL_BLOCK_SIZE;
						count--;
					}
					memset( &m_bDirectoryRecordDataLongname[count*LOGICAL_BLOCK_SIZE], 0, LOGICAL_BLOCK_SIZE );

					iSecPosLongname = iSecPosNew;						// next record must start at next 
																// logical block and not overlap 
																// the boundary
					
					memcpy( &m_bDirectoryRecordDataLongname[iSecPosLongname], &bDirLongnameRecEntry[0], GetLongnameDREntryLength() );
					pFileList->m_iItemDRSecPosLongname = iSecPosLongname;
					iSecPosLongname += GetLongnameDREntryLength();

					// Adjust all entries currently in the list
					m_iLongNameDREntrieExtensionCount++;

					// Adjust all entries in previous record entry blocks (if any)
					m_iLogicalBlockSectorAt_L++;		// new 04/05/2004 for paths after files in root over 800
				}
				else
				{
					memcpy( &m_bDirectoryRecordDataLongname[iSecPosLongname], &bDirLongnameRecEntry[0], GetLongnameDREntryLength() );
					pFileList->m_iItemDRSecPosLongname = iSecPosLongname;
					iSecPosLongname += GetLongnameDREntryLength();
				}

				if( pFileList->m_bAttributes & _A_SUBDIR )
				{
					// Do the subfolder now.......
					unsigned int iSecPosPass = m_iDirectoryRecordDataSize;
					unsigned int iSecPosLongnamePass = m_iDirectoryRecordDataSizeLongname;
					AddBlockToDirectoryRecordArea(iSecPosDRDotEntry, 
						iSecPosDRFolderFrom, TRUE);
					AddBlockToDirectoryRecordAreaLongname(iSecPosDRDotEntryLongname, 
						iSecPosDRFolderFromLongname, TRUE);
					BuildDirRecThisFolder(pFileList->m_szFilePath, pFileList, 
						iFileListPosition, tCreated, 
						iSecPosPass, iSecPosLongnamePass, 
						iThisFoldersLB, pFileList->m_iBlockStartPos,
						iThisFoldersLB_L, pFileList->m_iBlockStartPos_L,
						pFileList->m_iItemDRSecPos, pFileList->m_iItemDRSecPosLongname,  
						iThisFolderPathTableNum, pFileList->m_iItemPTFolderNumber, bLongDR);
				}
			}
		}

		iFileListPosition++;
		if( pFileList->GetNext()==NULL )
			bFinished= TRUE;
	}while( !bFinished );

}

//////////////////////////////////////////////////////////////////////