Initial version
This commit is contained in:
commit
6f405265a5
102 changed files with 14486 additions and 0 deletions
342
code/filesys/filesys.cc
Normal file
342
code/filesys/filesys.cc
Normal file
|
@ -0,0 +1,342 @@
|
|||
// filesys.cc
|
||||
// Routines to manage the overall operation of the file system.
|
||||
// Implements routines to map from textual file names to files.
|
||||
//
|
||||
// Each file in the file system has:
|
||||
// A file header, stored in a sector on disk
|
||||
// (the size of the file header data structure is arranged
|
||||
// to be precisely the size of 1 disk sector)
|
||||
// A number of data blocks
|
||||
// An entry in the file system directory
|
||||
//
|
||||
// The file system consists of several data structures:
|
||||
// A bitmap of free disk sectors (cf. bitmap.h)
|
||||
// A directory of file names and file headers
|
||||
//
|
||||
// Both the bitmap and the directory are represented as normal
|
||||
// files. Their file headers are located in specific sectors
|
||||
// (sector 0 and sector 1), so that the file system can find them
|
||||
// on bootup.
|
||||
//
|
||||
// The file system assumes that the bitmap and directory files are
|
||||
// kept "open" continuously while Nachos is running.
|
||||
//
|
||||
// For those operations (such as Create, Remove) that modify the
|
||||
// directory and/or bitmap, if the operation succeeds, the changes
|
||||
// are written immediately back to disk (the two files are kept
|
||||
// open during all this time). If the operation fails, and we have
|
||||
// modified part of the directory and/or bitmap, we simply discard
|
||||
// the changed version, without writing it back to disk.
|
||||
//
|
||||
// Our implementation at this point has the following restrictions:
|
||||
//
|
||||
// there is no synchronization for concurrent accesses
|
||||
// files have a fixed size, set when the file is created
|
||||
// files cannot be bigger than about 3KB in size
|
||||
// there is no hierarchical directory structure, and only a limited
|
||||
// number of files can be added to the system
|
||||
// there is no attempt to make the system robust to failures
|
||||
// (if Nachos exits in the middle of an operation that modifies
|
||||
// the file system, it may corrupt the 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 "disk.h"
|
||||
#include "bitmap.h"
|
||||
#include "directory.h"
|
||||
#include "filehdr.h"
|
||||
#include "filesys.h"
|
||||
|
||||
// Sectors containing the file headers for the bitmap of free sectors,
|
||||
// and the directory of files. These file headers are placed in well-known
|
||||
// sectors, so that they can be located on boot-up.
|
||||
#define FreeMapSector 0
|
||||
#define DirectorySector 1
|
||||
|
||||
// Initial file sizes for the bitmap and directory; until the file system
|
||||
// supports extensible files, the directory size sets the maximum number
|
||||
// of files that can be loaded onto the disk.
|
||||
#define BitsInByte 8
|
||||
#define FreeMapFileSize (NumSectors / BitsInByte)
|
||||
#define NumDirEntries 10
|
||||
#define DirectoryFileSize (sizeof(DirectoryEntry) * NumDirEntries)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FileSystem::FileSystem
|
||||
// Initialize the file system. If format = TRUE, the disk has
|
||||
// nothing on it, and we need to initialize the disk to contain
|
||||
// an empty directory, and a bitmap of free sectors (with almost but
|
||||
// not all of the sectors marked as free).
|
||||
//
|
||||
// If format = FALSE, we just have to open the files
|
||||
// representing the bitmap and the directory.
|
||||
//
|
||||
// "format" -- should we initialize the disk?
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
FileSystem::FileSystem(bool format)
|
||||
{
|
||||
DEBUG('f', "Initializing the file system.\n");
|
||||
if (format) {
|
||||
BitMap *freeMap = new BitMap(NumSectors);
|
||||
Directory *directory = new Directory(NumDirEntries);
|
||||
FileHeader *mapHdr = new FileHeader;
|
||||
FileHeader *dirHdr = new FileHeader;
|
||||
|
||||
DEBUG('f', "Formatting the file system.\n");
|
||||
|
||||
// First, allocate space for FileHeaders for the directory and bitmap
|
||||
// (make sure no one else grabs these!)
|
||||
freeMap->Mark(FreeMapSector);
|
||||
freeMap->Mark(DirectorySector);
|
||||
|
||||
// Second, allocate space for the data blocks containing the contents
|
||||
// of the directory and bitmap files. There better be enough space!
|
||||
|
||||
ASSERT(mapHdr->Allocate(freeMap, FreeMapFileSize));
|
||||
ASSERT(dirHdr->Allocate(freeMap, DirectoryFileSize));
|
||||
|
||||
// Flush the bitmap and directory FileHeaders back to disk
|
||||
// We need to do this before we can "Open" the file, since open
|
||||
// reads the file header off of disk (and currently the disk has garbage
|
||||
// on it!).
|
||||
|
||||
DEBUG('f', "Writing headers back to disk.\n");
|
||||
mapHdr->WriteBack(FreeMapSector);
|
||||
dirHdr->WriteBack(DirectorySector);
|
||||
|
||||
// OK to open the bitmap and directory files now
|
||||
// The file system operations assume these two files are left open
|
||||
// while Nachos is running.
|
||||
|
||||
freeMapFile = new OpenFile(FreeMapSector);
|
||||
directoryFile = new OpenFile(DirectorySector);
|
||||
|
||||
// Once we have the files "open", we can write the initial version
|
||||
// of each file back to disk. The directory at this point is completely
|
||||
// empty; but the bitmap has been changed to reflect the fact that
|
||||
// sectors on the disk have been allocated for the file headers and
|
||||
// to hold the file data for the directory and bitmap.
|
||||
|
||||
DEBUG('f', "Writing bitmap and directory back to disk.\n");
|
||||
freeMap->WriteBack(freeMapFile); // flush changes to disk
|
||||
directory->WriteBack(directoryFile);
|
||||
|
||||
if (DebugIsEnabled('f')) {
|
||||
freeMap->Print();
|
||||
directory->Print();
|
||||
|
||||
delete freeMap;
|
||||
delete directory;
|
||||
delete mapHdr;
|
||||
delete dirHdr;
|
||||
}
|
||||
} else {
|
||||
// if we are not formatting the disk, just open the files representing
|
||||
// the bitmap and directory; these are left open while Nachos is running
|
||||
freeMapFile = new OpenFile(FreeMapSector);
|
||||
directoryFile = new OpenFile(DirectorySector);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FileSystem::Create
|
||||
// Create a file in the Nachos file system (similar to UNIX create).
|
||||
// Since we can't increase the size of files dynamically, we have
|
||||
// to give Create the initial size of the file.
|
||||
//
|
||||
// The steps to create a file are:
|
||||
// Make sure the file doesn't already exist
|
||||
// Allocate a sector for the file header
|
||||
// Allocate space on disk for the data blocks for the file
|
||||
// Add the name to the directory
|
||||
// Store the new file header on disk
|
||||
// Flush the changes to the bitmap and the directory back to disk
|
||||
//
|
||||
// Return TRUE if everything goes ok, otherwise, return FALSE.
|
||||
//
|
||||
// Create fails if:
|
||||
// file is already in directory
|
||||
// no free space for file header
|
||||
// no free entry for file in directory
|
||||
// no free space for data blocks for the file
|
||||
//
|
||||
// Note that this implementation assumes there is no concurrent access
|
||||
// to the file system!
|
||||
//
|
||||
// "name" -- name of file to be created
|
||||
// "initialSize" -- size of file to be created
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
FileSystem::Create(const char *name, int initialSize)
|
||||
{
|
||||
Directory *directory;
|
||||
BitMap *freeMap;
|
||||
FileHeader *hdr;
|
||||
int sector;
|
||||
bool success;
|
||||
|
||||
DEBUG('f', "Creating file %s, size %d\n", name, initialSize);
|
||||
|
||||
directory = new Directory(NumDirEntries);
|
||||
directory->FetchFrom(directoryFile);
|
||||
|
||||
if (directory->Find(name) != -1)
|
||||
success = FALSE; // file is already in directory
|
||||
else {
|
||||
freeMap = new BitMap(NumSectors);
|
||||
freeMap->FetchFrom(freeMapFile);
|
||||
sector = freeMap->Find(); // find a sector to hold the file header
|
||||
if (sector == -1)
|
||||
success = FALSE; // no free block for file header
|
||||
else if (!directory->Add(name, sector))
|
||||
success = FALSE; // no space in directory
|
||||
else {
|
||||
hdr = new FileHeader;
|
||||
if (!hdr->Allocate(freeMap, initialSize))
|
||||
success = FALSE; // no space on disk for data
|
||||
else {
|
||||
success = TRUE;
|
||||
// everthing worked, flush all changes back to disk
|
||||
hdr->WriteBack(sector);
|
||||
directory->WriteBack(directoryFile);
|
||||
freeMap->WriteBack(freeMapFile);
|
||||
}
|
||||
delete hdr;
|
||||
}
|
||||
delete freeMap;
|
||||
}
|
||||
delete directory;
|
||||
return success;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FileSystem::Open
|
||||
// Open a file for reading and writing.
|
||||
// To open a file:
|
||||
// Find the location of the file's header, using the directory
|
||||
// Bring the header into memory
|
||||
//
|
||||
// "name" -- the text name of the file to be opened
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
OpenFile *
|
||||
FileSystem::Open(const char *name)
|
||||
{
|
||||
Directory *directory = new Directory(NumDirEntries);
|
||||
OpenFile *openFile = NULL;
|
||||
int sector;
|
||||
|
||||
DEBUG('f', "Opening file %s\n", name);
|
||||
directory->FetchFrom(directoryFile);
|
||||
sector = directory->Find(name);
|
||||
if (sector >= 0)
|
||||
openFile = new OpenFile(sector); // name was found in directory
|
||||
delete directory;
|
||||
return openFile; // return NULL if not found
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FileSystem::Remove
|
||||
// Delete a file from the file system. This requires:
|
||||
// Remove it from the directory
|
||||
// Delete the space for its header
|
||||
// Delete the space for its data blocks
|
||||
// Write changes to directory, bitmap back to disk
|
||||
//
|
||||
// Return TRUE if the file was deleted, FALSE if the file wasn't
|
||||
// in the file system.
|
||||
//
|
||||
// "name" -- the text name of the file to be removed
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
FileSystem::Remove(const char *name)
|
||||
{
|
||||
Directory *directory;
|
||||
BitMap *freeMap;
|
||||
FileHeader *fileHdr;
|
||||
int sector;
|
||||
|
||||
directory = new Directory(NumDirEntries);
|
||||
directory->FetchFrom(directoryFile);
|
||||
sector = directory->Find(name);
|
||||
if (sector == -1) {
|
||||
delete directory;
|
||||
return FALSE; // file not found
|
||||
}
|
||||
fileHdr = new FileHeader;
|
||||
fileHdr->FetchFrom(sector);
|
||||
|
||||
freeMap = new BitMap(NumSectors);
|
||||
freeMap->FetchFrom(freeMapFile);
|
||||
|
||||
fileHdr->Deallocate(freeMap); // remove data blocks
|
||||
freeMap->Clear(sector); // remove header block
|
||||
directory->Remove(name);
|
||||
|
||||
freeMap->WriteBack(freeMapFile); // flush to disk
|
||||
directory->WriteBack(directoryFile); // flush to disk
|
||||
delete fileHdr;
|
||||
delete directory;
|
||||
delete freeMap;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FileSystem::List
|
||||
// List all the files in the file system directory.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
FileSystem::List()
|
||||
{
|
||||
Directory *directory = new Directory(NumDirEntries);
|
||||
|
||||
directory->FetchFrom(directoryFile);
|
||||
directory->List();
|
||||
delete directory;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FileSystem::Print
|
||||
// Print everything about the file system:
|
||||
// the contents of the bitmap
|
||||
// the contents of the directory
|
||||
// for each file in the directory,
|
||||
// the contents of the file header
|
||||
// the data in the file
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
FileSystem::Print()
|
||||
{
|
||||
FileHeader *bitHdr = new FileHeader;
|
||||
FileHeader *dirHdr = new FileHeader;
|
||||
BitMap *freeMap = new BitMap(NumSectors);
|
||||
Directory *directory = new Directory(NumDirEntries);
|
||||
|
||||
printf("Bit map file header:\n");
|
||||
bitHdr->FetchFrom(FreeMapSector);
|
||||
bitHdr->Print();
|
||||
|
||||
printf("Directory file header:\n");
|
||||
dirHdr->FetchFrom(DirectorySector);
|
||||
dirHdr->Print();
|
||||
|
||||
freeMap->FetchFrom(freeMapFile);
|
||||
freeMap->Print();
|
||||
|
||||
directory->FetchFrom(directoryFile);
|
||||
directory->Print();
|
||||
|
||||
delete bitHdr;
|
||||
delete dirHdr;
|
||||
delete freeMap;
|
||||
delete directory;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue