code/filesys/filehdr.cc
// filehdr.cc
// Routines for managing the disk file header (in UNIX, this
// would be called the i-node).
//
// The file header is used to locate where on disk the
// file's data is stored. We implement this as a fixed size
// table of pointers -- each entry in the table points to the
// disk sector containing that portion of the file data
// (in other words, there are no indirect or doubly indirect
// blocks). The table size is chosen so that the file header
// will be just big enough to fit in one disk sector,
//
// Unlike in a real system, we do not keep track of file permissions,
// ownership, last modification date, etc., in the file header.
//
// A file header can be initialized in two ways:
// for a new file, by modifying the in-memory data structure
// to point to the newly allocated data blocks
// for a file already on disk, by reading the file header from disk
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved. See copyright.h for copyright notice and limitation
// of liability and disclaimer of warranty provisions.
#include "copyright.h"
#include "system.h"
#include "filehdr.h"
//----------------------------------------------------------------------
// FileHeader::Allocate
// Initialize a fresh file header for a newly created file.
// Allocate data blocks for the file out of the map of free disk blocks.
// Return FALSE if there are not enough free blocks to accomodate
// the new file.
//
// "freeMap" is the bit map of free disk sectors
// "fileSize" is the bit map of free disk sectors
//----------------------------------------------------------------------
bool
FileHeader::Allocate(BitMap *freeMap, int fileSize)
{
numBytes = fileSize;
numSectors = divRoundUp(fileSize, SectorSize);
if (freeMap->NumClear() < numSectors)
return FALSE; // not enough space
for (int i = 0; i < numSectors; i++)
dataSectors[i] = freeMap->Find();
return TRUE;
}
//----------------------------------------------------------------------
// FileHeader::Deallocate
// De-allocate all the space allocated for data blocks for this file.
//
// "freeMap" is the bit map of free disk sectors
//----------------------------------------------------------------------
void
FileHeader::Deallocate(BitMap *freeMap)
{
for (int i = 0; i < numSectors; i++) {
ASSERT(freeMap->Test((int) dataSectors[i])); // ought to be marked!
freeMap->Clear((int) dataSectors[i]);
}
}
//----------------------------------------------------------------------
// FileHeader::FetchFrom
// Fetch contents of file header from disk.
//
// "sector" is the disk sector containing the file header
//----------------------------------------------------------------------
void
FileHeader::FetchFrom(int sector)
{
synchDisk->ReadSector(sector, (char *)this);
}
//----------------------------------------------------------------------
// FileHeader::WriteBack
// Write the modified contents of the file header back to disk.
//
// "sector" is the disk sector to contain the file header
//----------------------------------------------------------------------
void
FileHeader::WriteBack(int sector)
{
synchDisk->WriteSector(sector, (char *)this);
}
//----------------------------------------------------------------------
// FileHeader::ByteToSector
// Return which disk sector is storing a particular byte within the file.
// This is essentially a translation from a virtual address (the
// offset in the file) to a physical address (the sector where the
// data at the offset is stored).
//
// "offset" is the location within the file of the byte in question
//----------------------------------------------------------------------
int
FileHeader::ByteToSector(int offset)
{
return(dataSectors[offset / SectorSize]);
}
//----------------------------------------------------------------------
// FileHeader::FileLength
// Return the number of bytes in the file.
//----------------------------------------------------------------------
int
FileHeader::FileLength()
{
return numBytes;
}
//----------------------------------------------------------------------
// FileHeader::Print
// Print the contents of the file header, and the contents of all
// the data blocks pointed to by the file header.
//----------------------------------------------------------------------
void
FileHeader::Print()
{
int i, j, k;
char *data = new char[SectorSize];
printf("FileHeader contents. File size: %d. File blocks:\n", numBytes);
for (i = 0; i < numSectors; i++)
printf("%d ", dataSectors[i]);
printf("\nFile contents:\n");
for (i = k = 0; i < numSectors; i++) {
synchDisk->ReadSector(dataSectors[i], data);
for (j = 0; (j < SectorSize) && (k < numBytes); j++, k++) {
if ('\040' <= data[j] && data[j] <= '\176') // isprint(data[j])
printf("%c", data[j]);
else
printf("\\%x", (unsigned char)data[j]);
}
printf("\n");
}
delete [] data;
}