Page principale | Liste des namespaces | Hiérarchie des classes | Liste des classes | Répertoires | Liste des fichiers | Membres de namespace | Membres de classe | Membres de fichier

openfile.cc

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

Généré le Sun Jan 15 00:45:45 2006 pour Système NachOS : par  doxygen 1.4.4