Exemplo n.º 1
0
/**
Initialize the FAT cache and disk access

@param  aLocDrvCaps local drive capabilities
@param  aIgnoreFSInfo if ETrue, FSInfo sector shall be ignored. Used on volume remount to force FAT free clusters counting.

@leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
*/
void CFatMountCB::InitializeL(const TLocalDriveCaps& aLocDrvCaps, TBool aIgnoreFSInfo/*=EFalse*/) 
	{
    __PRINT1(_L("CFatMountCB::InitializeL() drv:%d"), DriveNumber());

    ASSERT(State() == EMounting); //-- we must get here only from MountL()
   
    //========== Find out number of clusters on the volume
	if(iRamDrive && SectorsPerCluster()!=1)
		{// Align iFirstFreeByte to cluster boundary if internal ram drive
		const TInt sectorsPerClusterLog2=ClusterSizeLog2()-SectorSizeLog2();
		const TInt rootDirEndSector=RootDirEnd()>>SectorSizeLog2();
		const TInt alignedSector=((rootDirEndSector+SectorsPerCluster()-1)>>sectorsPerClusterLog2)<<sectorsPerClusterLog2;
		iFirstFreeByte=alignedSector<<SectorSizeLog2();
		}
	else
		{
		if(Is32BitFat())
void CSVPHostMountCB::DirOpenL(const TDesC& aName ,CDirCB* aDir)
	{
	DP(_L("CFatMountCB::DirOpenL, drv:%d, %S"), DriveNumber(), &aName);
	CSVPHostDirCB& dir=(*((CSVPHostDirCB*)aDir));

	TBuf<KMaxPath> name;
	TUint driveNumber = Drive().DriveNumber();
	CanonicalizePathname(aName, driveNumber, name);
	TSVPHostFsDirOpenInfo info(driveNumber, name);
	TInt err = SVP_HOST_FS_DEVICE().DirOpen(info);

	User::LeaveIfError(err);

	dir.SetHandle(info.iHandle);
	TFileName n(TDriveUnit(Drive().DriveNumber()).Name());
	n.Append(aName);
	dir.SetFullName(n);
	}
Exemplo n.º 3
0
/**
Format a disk section, called iteratively to erase whole of media, on last iteration
creates an empty volume. If called with quick formatonly erases the Fat leaving the
rest of the volume intact.

@leave System wide error code
*/
void CFatFormatCB::DoFormatStepL()
	{
	if (iFormatInfo.iFormatIsCurrent==EFalse)
		{ // Only done first time through
		if (iMode & EForceErase)
			{
			TInt r = FatMount().ErasePassword();
			User::LeaveIfError(r);
			// CFatMountCB::ErasePassword() calls TBusLocalDrive::ForceRemount(),
			// so need to stop a remount from occurring in next call to :
			// TFsFormatNext::DoRequestL((), TDrive::CheckMount().
			FatMount().Drive().SetChanged(EFalse);
			}

        RecordOldInfoL();
		InitializeFormatDataL();
		FatMount().DoDismount();
		if (iVariableSize)
			FatMount().ReduceSizeL(0,I64LOW(FatMount().iSize));
		}
    //
    // Blank disk if not EQuickFormat
    //
	if (!iVariableSize && !(iMode & EQuickFormat) && iCurrentStep)
		{
		if (iFormatInfo.iFormatIsCurrent == EFalse)
			{//-- firstly invalidate sectors 0-6 inclusive, they may contain main boot sector, backup boot sector and FSInfo sector.
	        DoZeroFillMediaL(0, (KBkBootSectorNum+1)*iBytesPerSector);
            }
		TInt ret=FatMount().LocalDrive()->Format(iFormatInfo);
		if (ret!=KErrNone && ret!=KErrEof) // Handle format error
            ret = HandleCorrupt(ret);

        if (ret!=KErrNone && ret!=KErrEof) // KErrEof could be set by LocalDrive()->Format()
		    User::Leave(ret);

		if (ret==KErrNone)
			{
			iCurrentStep = I64LOW( 100 - (100 * TInt64(iFormatInfo.i512ByteSectorsFormatted)) / iMaxDiskSectors );
			if (iCurrentStep<=0)
				iCurrentStep=1;
			return;
			}
		}

	// ReMount since MBR may have been rewritten and partition may have moved / changed size
	TInt ret = LocalDrive()->ForceRemount(0);
	if (ret != KErrNone && ret != KErrNotSupported)
		User::Leave(ret);

	// MBR may have changed, so need to re-read iHiddenSectors etc.before BPB is written
	InitializeFormatDataL();

    // Translate bad sector number to cluster number which contains that sector
    // This only happens in full format, in quick format they are already cluster numbers
    if (!iVariableSize && !(iMode & EQuickFormat))
        User::LeaveIfError(BadSectorToCluster());

	//Check if root cluster is bad and update as required
	if(Is32BitFat() && !iVariableSize && (iMode & EQuickFormat))
		{
		if(iBadClusters.Find(iRootClusterNum) !=  KErrNotFound)
			{
			iRootClusterNum++;
            while(iBadClusters.Find(iRootClusterNum) != KErrNotFound)
				{
				iRootClusterNum++;
				}
			}
		}

    //
    // Do the rest of the disk in one lump
    //
	iCurrentStep=0;

    //-- zero-fill media from position 0 to the FAT end, i.e main & backup boot sector, FSInfo and its copy and all FATs
    const TUint32 posFatEnd = ((iSectorsPerFat*iNumberOfFats) + iReservedSectors) * iBytesPerSector; //-- last FAT end position
	
    if (iVariableSize)
		FatMount().EnlargeL(posFatEnd); 

    DoZeroFillMediaL(0, posFatEnd);
    
    if(Is32BitFat())
		{//create an empty root directory entry here
		
        const TUint KFat32EntrySz = 4; //-- FAT32 entry size, bytes
        const TInt  startFAT1   = iReservedSectors;              //-- FAT1 start sector
        const TInt  entryOffset = iRootClusterNum*KFat32EntrySz; //-- Root dir entry offset in the FAT, bytes

		TBuf8<KFat32EntrySz> EOF(KFat32EntrySz);
		EOF[0]=0xFF;		
		EOF[1]=0xFF;
		EOF[2]=0xFF;
		EOF[3]=0x0F;

        //-- write EOF mark to the every FAT copy
    	for(TInt i=0; i<iNumberOfFats; i++)
            {
		    const TInt rootDirEntryPos = iBytesPerSector*(startFAT1 + i*iSectorsPerFat) + entryOffset;
            User::LeaveIfError(LocalDrive()->Write(rootDirEntryPos, EOF));
            }

        //-- zero-fill FAT32 root directory (just 1 cluster)
		const TInt firstDataSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); //+RootDirSectors (not required for fat32)
        const TInt firstSectorOfCluster = ((iRootClusterNum - KFatFirstSearchCluster) * iSectorsPerCluster) + firstDataSector;
	
        const TUint32 posRootDirStart = firstSectorOfCluster * iBytesPerSector;
        const TUint32 posRootDirEnd = posRootDirStart + iSectorsPerCluster*iBytesPerSector;

        DoZeroFillMediaL(posRootDirStart, posRootDirEnd);
        }
	else
		{//-- FAT12/16
		    //-- Zero fill root directory
            const TInt rootDirSector = iReservedSectors + (iNumberOfFats * iSectorsPerFat); 
            const TInt rootDirSize   = iRootDirEntries * KSizeOfFatDirEntry; //-- size in bytes
            
            const TUint32 posRootDirStart = rootDirSector * iBytesPerSector;
            const TUint32 posRootDirEnd   = posRootDirStart + rootDirSize;

            const TInt numOfRootSectors=(rootDirSize%iBytesPerSector) ? (rootDirSize/iBytesPerSector+1) : (rootDirSize/iBytesPerSector);
		    if (iVariableSize)
			    FatMount().EnlargeL(iBytesPerSector*numOfRootSectors);

            DoZeroFillMediaL(posRootDirStart, posRootDirEnd);

		// Enlarge ram drive to take into account rounding of
		// data start to cluster boundary
		if(iVariableSize && iSectorsPerCluster!=1)
			{
			const TInt firstFreeSector=rootDirSector+numOfRootSectors;
			const TInt firstFreeCluster=firstFreeSector%iSectorsPerCluster ? firstFreeSector/iSectorsPerCluster+1 : firstFreeSector/iSectorsPerCluster;
			const TInt alignedSector=firstFreeCluster*iSectorsPerCluster;
			if(alignedSector!=firstFreeSector)
				FatMount().EnlargeL((alignedSector-firstFreeSector)*iBytesPerSector);
			}
		}

    //-- FAT[0] must contain media descriptor in the low byte, FAT[1] for fat16/32 may contain some flags
	TBuf8<8> startFat(8);
    startFat.Fill(0xFF);
   
    if(Is32BitFat()) //-- FAT32
        {//-- FAT32 uses only low 28 bits in FAT entry. 
        startFat[3] = 0x0F;
        startFat[7] = 0x0F;
        } 
    else if(iVariableSize||Is16BitFat()) //-- FAT16 or RAM drive which is always FAT16
        {
        startFat.SetLength(4);
        }
    else //-- FAT12
        {
        startFat.SetLength(3);
        }

    startFat[0]=KBootSectorMediaDescriptor;

    //-- write FAT[0] and FAT[1] entries to all copies of FAT
	for(TInt i=0;i<iNumberOfFats;i++)
        {
		User::LeaveIfError(LocalDrive()->Write(iBytesPerSector*(iReservedSectors+(iSectorsPerFat*i)),startFat));
        }

	//-- create boot sectors
    CreateBootSectorL();

    //-- create FSInfo sectors
    if (Is32BitFat())
		{
		CreateReservedBootSectorL();
        CreateFSInfoSectorL();
		}

    //-- here we have bad clusters numbers saved by the quick format
    //-- Interpret old bad cluster number to new cluster number and mark new bad clusters
    if (!iVariableSize && iBadClusters.Count()>0)
        {
 	
        //-- Here we need fully mounted volume, so mount it normally.
	    FatMount().MountL(EFalse);

        iBadClusters.Sort();
        TranslateL();
        const TInt mark = FatMount().Is32BitFat() ? KBad_32Bit : (FatMount().Is16BitFat() ? KBad_16Bit : KBad_12Bit);
        
        for (TInt i=0; i<iBadClusters.Count(); ++i)
            FatMount().FAT().WriteL(iBadClusters[i], mark);
        
        FatMount().FAT().FlushL();
        
        //-- indicate that the volume is "dirty" in order to the next Mount evend not to use FSInfo, which
        //-- contains incorrect value of free clusters because we already have bad ones saved.  
        //-- This is a very rare condition.
        FatMount().SetVolumeCleanL(EFalse); 

#if defined(_DEBUG)
	TInt r=FatMount().CheckDisk();
	__PRINT1(_L("CFatFormatCB::DoFormatStepL() CheckDisk res: %d"),r);
#endif
        }
        else
        {
        //-- We do not need to perform full mount in this case, the TDrive object will be marked as changed in ~CFormatCB and the
        //-- mount will be closed. Therefore on the first access to it it will be mounted normally.
        FatMount().MountL(ETrue); //-- force mount
        }

    __PRINT1(_L("CFatFormatCB::DoFormatStepL() Format complete drv:%d"), DriveNumber());
	}
Exemplo n.º 4
0
/**
Create the boot sector on media for the volume. For FAT32 also creates a backup copy of the boot sector.

@leave System wide error codes
*/
void CFatFormatCB::CreateBootSectorL()
	{
	__PRINT1(_L("CFatFormatCB::CreateBootSector() drive:%d"),DriveNumber());

    _LIT8(KName_Fat12,"FAT12   ");    ///< Name in BPB given to a Fat12 volume
    _LIT8(KName_Fat16,"FAT16   ");    ///< Name in BPB given to a Fat16 volume
    _LIT8(KName_Fat32,"FAT32   ");    ///< Name in BPB given to a Fat32 volume
    _LIT8(KDefaultVendorID, "EPOC");  ///< Vendor Name for BPB for any volume formated using a Symbian OS device

    const TBool bFat32 = Is32BitFat();
    
    TFatBootSector bootSector;

	bootSector.SetVendorID(KDefaultVendorID);
	bootSector.SetBytesPerSector(iBytesPerSector);
	bootSector.SetSectorsPerCluster(iSectorsPerCluster);
	bootSector.SetReservedSectors(iReservedSectors);
	bootSector.SetNumberOfFats(iNumberOfFats);
	iCountOfClusters=iMaxDiskSectors/iSectorsPerCluster;
	if (!bFat32)
		{
		if (iCountOfClusters>(TInt)KMaxTUint16)
			User::Leave(KErrTooBig);
		}

	bootSector.SetReservedByte(0);
	TTime timeID;
	timeID.HomeTime();
	bootSector.SetUniqueID(I64LOW(timeID.Int64()));	//	Generate Volume UniqueID from time
	bootSector.SetVolumeLabel(_L8(""));
	
    //-- set a text string in BPB that corresponds to the FS type
    switch(FatType())
        {
        case EFat12:
            bootSector.SetFileSysType(KName_Fat12);
        break;
        
        case EFat16:
            bootSector.SetFileSysType(KName_Fat16);
        break;
        
        case EFat32:
            bootSector.SetFileSysType(KName_Fat32);
        break;

        default:
            ASSERT(0);
            User::Leave(KErrArgument);
        };



	bootSector.SetJumpInstruction();
	bootSector.SetMediaDescriptor(KBootSectorMediaDescriptor);
	bootSector.SetNumberOfHeads(iNumberOfHeads);
	bootSector.SetHiddenSectors(iHiddenSectors);
	bootSector.SetSectorsPerTrack(iSectorsPerTrack);
	bootSector.SetPhysicalDriveNumber(128);
	bootSector.SetExtendedBootSignature(0x29);

	if(bFat32)
		{
		bootSector.SetFatSectors(0);
		bootSector.SetFatSectors32(iSectorsPerFat);
		bootSector.SetRootDirEntries(0);
		bootSector.SetTotalSectors(0);
		bootSector.SetHugeSectors(iMaxDiskSectors);
		bootSector.SetFATFlags(0);			
		bootSector.SetVersionNumber(0x00);	
		bootSector.SetRootClusterNum(iRootClusterNum);
		bootSector.SetFSInfoSectorNum(KFSInfoSectorNum);	
        bootSector.SetBkBootRecSector(KBkBootSectorNum);
		}
	else//fat12 and 16
		{
		bootSector.SetFatSectors32(0);
		bootSector.SetFatSectors(iSectorsPerFat);
		bootSector.SetRootDirEntries(iRootDirEntries);

		if (iMaxDiskSectors<=KMaxTUint16)
			{
			bootSector.SetTotalSectors(iMaxDiskSectors);
			bootSector.SetHugeSectors(0);
			}
		else
			{
			bootSector.SetTotalSectors(0);
			bootSector.SetHugeSectors(iMaxDiskSectors);
			}
		}

	//-- write main boot sector to the first sector on media
    User::LeaveIfError(FatMount().DoWriteBootSector(KBootSectorNum*bootSector.BytesPerSector(), bootSector));
	
    //-- for FAT32 write backup copy of the boot sector
    if(bFat32)
        {
        User::LeaveIfError(FatMount().DoWriteBootSector(KBkBootSectorNum*bootSector.BytesPerSector(), bootSector));    
        }

    }
Exemplo n.º 5
0
/**
Mount a Fat volume. 

@param aForceMount Flag to indicate whether mount should be forced to succeed if an error occurs
@leave KErrNoMemory,KErrNotReady,KErrCorrupt,KErrUnknown.
*/
void CFatMountCB::MountL(TBool aForceMount)
	{

    const TInt driveNo = Drive().DriveNumber();
    
    __PRINT3(_L("CFatMountCB::MountL() drv:%d, forceMount=%d, RuggedFAT:%d\n"), driveNo, aForceMount, IsRuggedFSys());

    ASSERT(State() == ENotMounted || State() == EDismounted);
    SetState(EMounting);
    SetReadOnly(EFalse);
   
	User::LeaveIfError(CreateDrive(driveNo));


    //-- read FAT configuration parameters from estart.txt
    iFatConfig.ReadConfig(driveNo);

    //-- initialise interface to the low-level drive access
    if(!iDriverInterface.Init(this))
        User::LeaveIfError(KErrNoMemory);    

	//-- get drive capabilities
    TLocalDriveCapsV2Buf capsBuf;
	User::LeaveIfError(LocalDrive()->Caps(capsBuf));
	

    iSize=capsBuf().iSize;
    iRamDrive = EFalse;

    if(capsBuf().iMediaAtt & KMediaAttVariableSize)
    {//-- this is a RAM drive
        UserSvr::UnlockRamDrive();
        iRamDrive = ETrue;
    }

	if(aForceMount)
	{//-- the state is "forcedly mounted", special case. This is an inconsistent state.
        SetState(EInit_Forced);  
    	return;
    }

    //-- read boot sector. If main is damaged, try to use backup one instead if this is not a RAM drive.
    TFatBootSector bootSector;
    User::LeaveIfError(ReadBootSector(bootSector, iRamDrive));


    //-- print out boot sector debug information
    bootSector.PrintDebugInfo();

    //-- determine FAT type by data from boot sector. This is done by counting number of clusters, not by BPB_RootEntCnt
    SetFatType(bootSector.FatType());
    ASSERT(iFatType != EInvalid); //-- this shall be checked in ReadBootSector()
    

    if(bootSector.RootDirEntries() == 0 && !Is32BitFat())
    {//-- FAT types mismatch. BPB_RootEntCnt is 0, which can be only for FAT32, but the number of clusters is less 
     //-- than required for FAT32. Probably this is incorrectly FAT32 formatted media. Put the drive into ReadOnly mode, assuming
     //-- that is FAT32.
        __PRINT(_L("FAT type mismatch! Setting drive to ReadOnly mode for FAT32. \n"));
        SetFatType(EFat32); //-- force FAT type to be FAT32
        SetReadOnly(ETrue);
    }

    //-- store volume UID, it can be checked on Remount
    iUniqueID = bootSector.UniqueID();

    //-- populate volume parameters with the values from boot sector. They had been validated in TFatBootSector::IsValid()
    iVolParam.Populate(bootSector); 
	
    //-- initialize the volume
    InitializeL(capsBuf());
    ASSERT(State()==EInit_R);

    GetVolumeLabelFromDiskL(bootSector);

	__PRINT2(_L("CFatMountCB::MountL() Completed, drv: %d, state:%d"), DriveNumber(), State());
	}
Exemplo n.º 6
0
/**
Set or reset "VolumeClean" (ClnShutBitmask) flag.

@param  aClean if ETrue, marks the volume as clean, otherwise as dirty.
@leave  if write error occured.        
*/
void CFatMountCB::SetVolumeCleanL(TBool aClean) 
    {

	//-- The volume can't be set clean if there are disk access objects opened on it. This precondition must be checked before calling this function
    if(aClean && Locked())
        {
        __PRINT1(_L("#- CFatMountCB::SetVolumeCleanL drive:%d isn't free!"),DriveNumber());
        ASSERT(0);
        User::Leave(KErrInUse);
        return;
        }
    
    if(FatType() == EFat12)
        {//-- Fat12 doesn't support this feature; do nothing other than notify the underlying drive (ignoring any error for now as there's nothing we can do with it)
		(void)LocalDrive()->Finalise(aClean);
        return;
        }

    //-- further read and write will be directly from the CProxyDrive, bypassing FAT cache. 
    //-- this is because CFatTable doesn't allow access to FAT[0] & FAT[1]
    //-- We also need to write data through CProxyDrive, because TDriveInterface has a call back that can call this method

    if(Is32BitFat())
        {//-- Fat32
		__PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT32"),DriveNumber(), aClean);
		
        TFat32Entry fatEntry;
        const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
        TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
        
        User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT32[1] entry

        const TFat32Entry tmp = fatEntry;
        
        if(aClean)
            fatEntry |= KFat32CleanShutDownMask;  //-- set ClnShutBit flag
        else
            fatEntry &= ~KFat32CleanShutDownMask; //-- reset ClnShutBit flag

        if(tmp != fatEntry)
            {//-- write FAT[1] entry to all available FATs
                for(TUint32 i=0; i<NumberOfFats(); ++i)
                {
                const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
                User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT32[1] entry
                }
            }

        __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);
        }
    else 
    if(Is16BitFat())
        {//-- Fat16. 
            __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL, drive:%d, param:%d, FAT16"),DriveNumber(), aClean);

            if(FatConfig().FAT16_UseCleanShutDownBit())
                {
            TFat16Entry fatEntry;
            const TInt  KFatEntrySize=sizeof(fatEntry); //-- FAT entry size in bytes
            TPtr8       ptrFatEntry((TUint8*)&fatEntry,KFatEntrySize);
        
            User::LeaveIfError(LocalDrive()->Read(StartOfFatInBytes()+KFatEntrySize, KFatEntrySize, ptrFatEntry)); //read FAT16[1] entry

            const TFat16Entry tmp = fatEntry;
        
            if(aClean)
                fatEntry |= KFat16CleanShutDownMask;  //-- set ClnShutBit flag
            else
                fatEntry &= ~KFat16CleanShutDownMask; //-- reset ClnShutBit flag

            if(tmp != fatEntry)
                {//-- write FAT[1] entry to all available FATs
                for(TUint32 i=0; i<NumberOfFats(); ++i)
                    {
                    const TInt64 pos = StartOfFatInBytes()+KFatEntrySize+(FatSizeInBytes()*i);
                    User::LeaveIfError(LocalDrive()->Write(pos, ptrFatEntry)); //write FAT16[1] entry
                    }
                }
		    
            __PRINT2(_L("#- CFatMountCB::SetVolumeCleanL() entry:  %x->%x"), tmp, fatEntry);    
            }
            else
            {
            __PRINT(_L("#- changing FAT16[1] is disabled in config!"));    
            }
        }
    else
        {//-- must never get here
        ASSERT(0);
        }
    
		//-- Notify the underlying media that the mount is consistent  (ignoring any error for now as there's nothing we can do with it)
		(void)LocalDrive()->Finalise(aClean);


    }