Main Page   Compound List   File List   Compound Members   File Members  

openfile.cc

Go to the documentation of this file.
00001 // openfile.cc 
00002 //      Routines to manage an open Nachos file.  As in UNIX, a
00003 //      file must be open before we can read or write to it.
00004 //      Once we're all done, we can close it (in Nachos, by deleting
00005 //      the OpenFile data structure).
00006 //
00007 //      Also as in UNIX, for convenience, we keep the file header in
00008 //      memory while the file is open.
00009 //
00010 // Copyright (c) 1992-1993 The Regents of the University of California.
00011 // All rights reserved.  See copyright.h for copyright notice and limitation 
00012 // of liability and disclaimer of warranty provisions.
00013 
00014 #include "copyright.h"
00015 #include "filehdr.h"
00016 #include "openfile.h"
00017 #include "system.h"
00018 
00019 extern "C" {
00020         int bcopy(char*, char *, int);
00021 };
00022 
00023 //----------------------------------------------------------------------
00024 // OpenFile::OpenFile
00025 //      Open a Nachos file for reading and writing.  Bring the file header
00026 //      into memory while the file is open.
00027 //
00028 //      "sector" -- the location on disk of the file header for this file
00029 //----------------------------------------------------------------------
00030 
00031 OpenFile::OpenFile(int sector)
00032 { 
00033     hdr = new FileHeader;
00034     hdr->FetchFrom(sector);
00035     seekPosition = 0;
00036 }
00037 
00038 //----------------------------------------------------------------------
00039 // OpenFile::~OpenFile
00040 //      Close a Nachos file, de-allocating any in-memory data structures.
00041 //----------------------------------------------------------------------
00042 
00043 OpenFile::~OpenFile()
00044 {
00045     delete hdr;
00046 }
00047 
00048 //----------------------------------------------------------------------
00049 // OpenFile::Seek
00050 //      Change the current location within the open file -- the point at
00051 //      which the next Read or Write will start from.
00052 //
00053 //      "position" -- the location within the file for the next Read/Write
00054 //----------------------------------------------------------------------
00055 
00056 void
00057 OpenFile::Seek(int position)
00058 {
00059     seekPosition = position;
00060 }       
00061 
00062 //----------------------------------------------------------------------
00063 // OpenFile::Read/Write
00064 //      Read/write a portion of a file, starting from seekPosition.
00065 //      Return the number of bytes actually written or read, and as a
00066 //      side effect, increment the current position within the file.
00067 //
00068 //      Implemented using the more primitive ReadAt/WriteAt.
00069 //
00070 //      "into" -- the buffer to contain the data to be read from disk 
00071 //      "from" -- the buffer containing the data to be written to disk 
00072 //      "numBytes" -- the number of bytes to transfer
00073 //----------------------------------------------------------------------
00074 
00075 int
00076 OpenFile::Read(char *into, int numBytes)
00077 {
00078    int result = ReadAt(into, numBytes, seekPosition);
00079    seekPosition += result;
00080    return result;
00081 }
00082 
00083 int
00084 OpenFile::Write(char *into, int numBytes)
00085 {
00086    int result = WriteAt(into, numBytes, seekPosition);
00087    seekPosition += result;
00088    return result;
00089 }
00090 
00091 //----------------------------------------------------------------------
00092 // OpenFile::ReadAt/WriteAt
00093 //      Read/write a portion of a file, starting at "position".
00094 //      Return the number of bytes actually written or read, but has
00095 //      no side effects (except that Write modifies the file, of course).
00096 //
00097 //      There is no guarantee the request starts or ends on an even disk sector
00098 //      boundary; however the disk only knows how to read/write a whole disk
00099 //      sector at a time.  Thus:
00100 //
00101 //      For ReadAt:
00102 //         We read in all of the full or partial sectors that are part of the
00103 //         request, but we only copy the part we are interested in.
00104 //      For WriteAt:
00105 //         We must first read in any sectors that will be partially written,
00106 //         so that we don't overwrite the unmodified portion.  We then copy
00107 //         in the data that will be modified, and write back all the full
00108 //         or partial sectors that are part of the request.
00109 //
00110 //      "into" -- the buffer to contain the data to be read from disk 
00111 //      "from" -- the buffer containing the data to be written to disk 
00112 //      "numBytes" -- the number of bytes to transfer
00113 //      "position" -- the offset within the file of the first byte to be
00114 //                      read/written
00115 //----------------------------------------------------------------------
00116 
00117 int
00118 OpenFile::ReadAt(char *into, int numBytes, int position)
00119 {
00120     int fileLength = hdr->FileLength();
00121     int i, firstSector, lastSector, numSectors;
00122     char *buf;
00123 
00124     if ((numBytes <= 0) || (position >= fileLength))
00125         return 0;                               // check request
00126     if ((position + numBytes) > fileLength)             
00127         numBytes = fileLength - position;
00128     DEBUG('f', "Reading %d bytes at %d, from file of length %d.\n",     
00129                         numBytes, position, fileLength);
00130 
00131     firstSector = divRoundDown(position, SectorSize);
00132     lastSector = divRoundDown(position + numBytes - 1, SectorSize);
00133     numSectors = 1 + lastSector - firstSector;
00134 
00135     // read in all the full and partial sectors that we need
00136     buf = new char[numSectors * SectorSize];
00137     for (i = firstSector; i <= lastSector; i++) 
00138         synchDisk->ReadSector(hdr->ByteToSector(i * SectorSize), 
00139                                         &buf[(i - firstSector) * SectorSize]);
00140 
00141     // copy the part we want
00142     bcopy(&buf[position - (firstSector * SectorSize)], into, numBytes);
00143     delete [] buf;
00144     return numBytes;
00145 }
00146 
00147 int
00148 OpenFile::WriteAt(char *from, int numBytes, int position)
00149 {
00150     int fileLength = hdr->FileLength();
00151     int i, firstSector, lastSector, numSectors;
00152     bool firstAligned, lastAligned;
00153     char *buf;
00154 
00155     if ((numBytes <= 0) || (position >= fileLength))
00156         return 0;                               // check request
00157     if ((position + numBytes) > fileLength)
00158         numBytes = fileLength - position;
00159     DEBUG('f', "Writing %d bytes at %d, from file of length %d.\n",     
00160                         numBytes, position, fileLength);
00161 
00162     firstSector = divRoundDown(position, SectorSize);
00163     lastSector = divRoundDown(position + numBytes - 1, SectorSize);
00164     numSectors = 1 + lastSector - firstSector;
00165 
00166     buf = new char[numSectors * SectorSize];
00167 
00168     firstAligned = (position == (firstSector * SectorSize));
00169     lastAligned = ((position + numBytes) == ((lastSector + 1) * SectorSize));
00170 
00171 // read in first and last sector, if they are to be partially modified
00172     if (!firstAligned)
00173         ReadAt(buf, SectorSize, firstSector * SectorSize);      
00174     if (!lastAligned && ((firstSector != lastSector) || firstAligned))
00175         ReadAt(&buf[(lastSector - firstSector) * SectorSize], 
00176                                 SectorSize, lastSector * SectorSize);   
00177 
00178 // copy in the bytes we want to change 
00179     bcopy(from, &buf[position - (firstSector * SectorSize)], numBytes);
00180 
00181 // write modified sectors back
00182     for (i = firstSector; i <= lastSector; i++) 
00183         synchDisk->WriteSector(hdr->ByteToSector(i * SectorSize), 
00184                                         &buf[(i - firstSector) * SectorSize]);
00185     delete [] buf;
00186     return numBytes;
00187 }
00188 
00189 //----------------------------------------------------------------------
00190 // OpenFile::Length
00191 //      Return the number of bytes in the file.
00192 //----------------------------------------------------------------------
00193 
00194 int
00195 OpenFile::Length() 
00196 { 
00197     return hdr->FileLength(); 
00198 }

Generated on Mon Feb 10 09:54:46 2003 for nachos by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002
The University of Southern California does not screen or control the content on this website and thus does not guarantee the accuracy, integrity, or quality of such content. All content on this website is provided by and is the sole responsibility of the person from which such content originated, and such content does not necessarily reflect the opinions of the University administration or the Board of Trustees