/*
   clmovmap.c - operations on the fixed cluster map.

   Copyright (C) 2003, Imre Leber.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have recieved a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   If you have any questions, comments, suggestions, or fixes please
   email me at:  imre.leber@worldonline.be.

*/

#include <stdlib.h>

#include "fte.h"
#include "..\..\modlgate\expected.h"

static char* FixedClusterMap = NULL;

/*static*/ BOOL FixedFileMarker(RDWRHandle handle,
                            struct DirectoryPosition* pos,
                            void** structure);
/*static*/ BOOL FixedClusterMarker(RDWRHandle handle,
                               CLUSTER label,
                               SECTOR  sector,
                               void**  structure);


BOOL CreateFixedClusterMap(RDWRHandle handle)
{
    unsigned long labelsinfat;
    
    labelsinfat = GetLabelsInFat(handle);
    if (!labelsinfat) return FALSE;
        
    FixedClusterMap = CreateBitField(labelsinfat);   
    if (!FixedClusterMap) return FALSE;
    
    if (!WalkDirectoryTree(handle, FixedFileMarker, (void**) NULL))
       return FALSE;  
       
    LogMessage("Fixed cluster map created.");    
    return TRUE;
}

/*static*/ BOOL FixedFileMarker(RDWRHandle handle,
                            struct DirectoryPosition* pos,
                            void** structure)
{
    CLUSTER firstcluster;
    struct DirectoryEntry entry;

    if (structure);
    
    if (!GetDirectory(handle, pos, &entry))
       return FAIL;
       
    if ((entry.attribute & FA_LABEL) ||
        (IsLFNEntry(&entry))         ||
        (IsDeletedLabel(entry)))
       return TRUE;
       
    if ((entry.attribute & FA_HIDDEN) ||
        (entry.attribute & FA_SYSTEM))
    {
       firstcluster = GetFirstCluster(&entry);
       if (firstcluster)
       {
          if (!FileTraverseFat(handle, firstcluster, FixedClusterMarker, 
                               (void**) NULL))
          {
              return FAIL;
          }
       }
    }

    return TRUE;
}

/*static*/ BOOL FixedClusterMarker(RDWRHandle handle,
                               CLUSTER label,
                               SECTOR  sector,
                               void**  structure)
{
    CLUSTER cluster;
    
    if (label);
    if (structure);
    
    cluster = DataSectorToCluster(handle, sector);
    if (!cluster) return FAIL;
  
    SetBitfieldBit(FixedClusterMap, cluster);

    return TRUE;
}

void DestroyFixedClusterMap(void)
{
    DestroyBitfield(FixedClusterMap);
    FixedClusterMap = NULL;
}

BOOL IsClusterMovable(RDWRHandle handle, CLUSTER cluster, BOOL* isMovable)
{
    if (handle);
    
    if (!FixedClusterMap)
    {
       LogMessage("Fixed tree map not created!");
       return FALSE;
    }
       
    *isMovable = !GetBitfieldBit(FixedClusterMap, cluster);
    
    return TRUE;
}