Initial version
This commit is contained in:
commit
6f405265a5
102 changed files with 14486 additions and 0 deletions
197
code/filesys/openfile.cc
Normal file
197
code/filesys/openfile.cc
Normal file
|
@ -0,0 +1,197 @@
|
|||
// openfile.cc
|
||||
// Routines to manage an open Nachos file. As in UNIX, a
|
||||
// file must be open before we can read or write to it.
|
||||
// Once we're all done, we can close it (in Nachos, by deleting
|
||||
// the OpenFile data structure).
|
||||
//
|
||||
// Also as in UNIX, for convenience, we keep the file header in
|
||||
// memory while the file is open.
|
||||
//
|
||||
// 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 "filehdr.h"
|
||||
#include "openfile.h"
|
||||
#include "system.h"
|
||||
|
||||
#include <strings.h> /* for bzero */
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// OpenFile::OpenFile
|
||||
// Open a Nachos file for reading and writing. Bring the file header
|
||||
// into memory while the file is open.
|
||||
//
|
||||
// "sector" -- the location on disk of the file header for this file
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
OpenFile::OpenFile(int sector)
|
||||
{
|
||||
hdr = new FileHeader;
|
||||
hdr->FetchFrom(sector);
|
||||
seekPosition = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// OpenFile::~OpenFile
|
||||
// Close a Nachos file, de-allocating any in-memory data structures.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
OpenFile::~OpenFile()
|
||||
{
|
||||
delete hdr;
|
||||
hdr = NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// OpenFile::Seek
|
||||
// Change the current location within the open file -- the point at
|
||||
// which the next Read or Write will start from.
|
||||
//
|
||||
// "position" -- the location within the file for the next Read/Write
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
OpenFile::Seek(int position)
|
||||
{
|
||||
seekPosition = position;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// OpenFile::Read/Write
|
||||
// Read/write a portion of a file, starting from seekPosition.
|
||||
// Return the number of bytes actually written or read, and as a
|
||||
// side effect, increment the current position within the file.
|
||||
//
|
||||
// Implemented using the more primitive ReadAt/WriteAt.
|
||||
//
|
||||
// "into" -- the buffer to contain the data to be read from disk
|
||||
// "from" -- the buffer containing the data to be written to disk
|
||||
// "numBytes" -- the number of bytes to transfer
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
int
|
||||
OpenFile::Read(void *into, int numBytes)
|
||||
{
|
||||
int result = ReadAt(into, numBytes, seekPosition);
|
||||
seekPosition += result;
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
OpenFile::Write(const void *into, int numBytes)
|
||||
{
|
||||
int result = WriteAt(into, numBytes, seekPosition);
|
||||
seekPosition += result;
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// OpenFile::ReadAt/WriteAt
|
||||
// Read/write a portion of a file, starting at "position".
|
||||
// Return the number of bytes actually written or read, but has
|
||||
// no side effects (except that Write modifies the file, of course).
|
||||
//
|
||||
// There is no guarantee the request starts or ends on an even disk sector
|
||||
// boundary; however the disk only knows how to read/write a whole disk
|
||||
// sector at a time. Thus:
|
||||
//
|
||||
// For ReadAt:
|
||||
// We read in all of the full or partial sectors that are part of the
|
||||
// request, but we only copy the part we are interested in.
|
||||
// For WriteAt:
|
||||
// We must first read in any sectors that will be partially written,
|
||||
// so that we don't overwrite the unmodified portion. We then copy
|
||||
// in the data that will be modified, and write back all the full
|
||||
// or partial sectors that are part of the request.
|
||||
//
|
||||
// "into" -- the buffer to contain the data to be read from disk
|
||||
// "from" -- the buffer containing the data to be written to disk
|
||||
// "numBytes" -- the number of bytes to transfer
|
||||
// "position" -- the offset within the file of the first byte to be
|
||||
// read/written
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
int
|
||||
OpenFile::ReadAt(void *into, int numBytes, int position)
|
||||
{
|
||||
int fileLength = hdr->FileLength();
|
||||
int i, firstSector, lastSector, numSectors;
|
||||
char *buf;
|
||||
|
||||
if ((numBytes <= 0) || (position >= fileLength))
|
||||
return 0; // check request
|
||||
if ((position + numBytes) > fileLength)
|
||||
numBytes = fileLength - position;
|
||||
DEBUG('f', "Reading %d bytes at %d, from file of length %d.\n",
|
||||
numBytes, position, fileLength);
|
||||
|
||||
firstSector = divRoundDown(position, SectorSize);
|
||||
lastSector = divRoundDown(position + numBytes - 1, SectorSize);
|
||||
numSectors = 1 + lastSector - firstSector;
|
||||
|
||||
// read in all the full and partial sectors that we need
|
||||
buf = new char[numSectors * SectorSize];
|
||||
for (i = firstSector; i <= lastSector; i++)
|
||||
synchDisk->ReadSector(hdr->ByteToSector(i * SectorSize),
|
||||
&buf[(i - firstSector) * SectorSize]);
|
||||
|
||||
// copy the part we want
|
||||
bcopy(&buf[position - (firstSector * SectorSize)], into, numBytes);
|
||||
delete [] buf;
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
int
|
||||
OpenFile::WriteAt(const void *from, int numBytes, int position)
|
||||
{
|
||||
int fileLength = hdr->FileLength();
|
||||
int i, firstSector, lastSector, numSectors;
|
||||
bool firstAligned, lastAligned;
|
||||
char *buf;
|
||||
|
||||
if ((numBytes <= 0) || (position >= fileLength))
|
||||
return 0; // check request
|
||||
if ((position + numBytes) > fileLength)
|
||||
numBytes = fileLength - position;
|
||||
DEBUG('f', "Writing %d bytes at %d, from file of length %d.\n",
|
||||
numBytes, position, fileLength);
|
||||
|
||||
firstSector = divRoundDown(position, SectorSize);
|
||||
lastSector = divRoundDown(position + numBytes - 1, SectorSize);
|
||||
numSectors = 1 + lastSector - firstSector;
|
||||
|
||||
buf = new char[numSectors * SectorSize];
|
||||
|
||||
firstAligned = (position == (firstSector * SectorSize));
|
||||
lastAligned = ((position + numBytes) == ((lastSector + 1) * SectorSize));
|
||||
|
||||
// read in first and last sector, if they are to be partially modified
|
||||
if (!firstAligned)
|
||||
ReadAt(buf, SectorSize, firstSector * SectorSize);
|
||||
if (!lastAligned && ((firstSector != lastSector) || firstAligned))
|
||||
ReadAt(&buf[(lastSector - firstSector) * SectorSize],
|
||||
SectorSize, lastSector * SectorSize);
|
||||
|
||||
// copy in the bytes we want to change
|
||||
bcopy(from, &buf[position - (firstSector * SectorSize)], numBytes);
|
||||
|
||||
// write modified sectors back
|
||||
for (i = firstSector; i <= lastSector; i++)
|
||||
synchDisk->WriteSector(hdr->ByteToSector(i * SectorSize),
|
||||
&buf[(i - firstSector) * SectorSize]);
|
||||
delete [] buf;
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// OpenFile::Length
|
||||
// Return the number of bytes in the file.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
int
|
||||
OpenFile::Length()
|
||||
{
|
||||
return hdr->FileLength();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue