00001 // filehdr.cc 00002 // Routines for managing the disk file header (in UNIX, this 00003 // would be called the i-node). 00004 // 00005 // The file header is used to locate where on disk the 00006 // file's data is stored. We implement this as a fixed size 00007 // table of pointers -- each entry in the table points to the 00008 // disk sector containing that portion of the file data 00009 // (in other words, there are no indirect or doubly indirect 00010 // blocks). The table size is chosen so that the file header 00011 // will be just big enough to fit in one disk sector, 00012 // 00013 // Unlike in a real system, we do not keep track of file permissions, 00014 // ownership, last modification date, etc., in the file header. 00015 // 00016 // A file header can be initialized in two ways: 00017 // for a new file, by modifying the in-memory data structure 00018 // to point to the newly allocated data blocks 00019 // for a file already on disk, by reading the file header from disk 00020 // 00021 // Copyright (c) 1992-1993 The Regents of the University of California. 00022 // All rights reserved. See copyright.h for copyright notice and limitation 00023 // of liability and disclaimer of warranty provisions. 00024 00025 #include "copyright.h" 00026 00027 #include "filehdr.h" 00028 #include "debug.h" 00029 #include "synchdisk.h" 00030 #include "main.h" 00031 00032 //---------------------------------------------------------------------- 00033 // FileHeader::Allocate 00034 // Initialize a fresh file header for a newly created file. 00035 // Allocate data blocks for the file out of the map of free disk blocks. 00036 // Return FALSE if there are not enough free blocks to accomodate 00037 // the new file. 00038 // 00039 // "freeMap" is the bit map of free disk sectors 00040 // "fileSize" is the bit map of free disk sectors 00041 //---------------------------------------------------------------------- 00042 00043 bool 00044 FileHeader::Allocate(PersistentBitmap *freeMap, int fileSize) 00045 { 00046 numBytes = fileSize; 00047 numSectors = divRoundUp(fileSize, SectorSize); 00048 if (freeMap->NumClear() < numSectors) 00049 return FALSE; // not enough space 00050 00051 for (int i = 0; i < numSectors; i++) { 00052 dataSectors[i] = freeMap->FindAndSet(); 00053 // since we checked that there was enough free space, 00054 // we expect this to succeed 00055 ASSERT(dataSectors[i] >= 0); 00056 } 00057 return TRUE; 00058 } 00059 00060 //---------------------------------------------------------------------- 00061 // FileHeader::Deallocate 00062 // De-allocate all the space allocated for data blocks for this file. 00063 // 00064 // "freeMap" is the bit map of free disk sectors 00065 //---------------------------------------------------------------------- 00066 00067 void 00068 FileHeader::Deallocate(PersistentBitmap *freeMap) 00069 { 00070 for (int i = 0; i < numSectors; i++) { 00071 ASSERT(freeMap->Test((int) dataSectors[i])); // ought to be marked! 00072 freeMap->Clear((int) dataSectors[i]); 00073 } 00074 } 00075 00076 //---------------------------------------------------------------------- 00077 // FileHeader::FetchFrom 00078 // Fetch contents of file header from disk. 00079 // 00080 // "sector" is the disk sector containing the file header 00081 //---------------------------------------------------------------------- 00082 00083 void 00084 FileHeader::FetchFrom(int sector) 00085 { 00086 kernel->synchDisk->ReadSector(sector, (char *)this); 00087 } 00088 00089 //---------------------------------------------------------------------- 00090 // FileHeader::WriteBack 00091 // Write the modified contents of the file header back to disk. 00092 // 00093 // "sector" is the disk sector to contain the file header 00094 //---------------------------------------------------------------------- 00095 00096 void 00097 FileHeader::WriteBack(int sector) 00098 { 00099 kernel->synchDisk->WriteSector(sector, (char *)this); 00100 } 00101 00102 //---------------------------------------------------------------------- 00103 // FileHeader::ByteToSector 00104 // Return which disk sector is storing a particular byte within the file. 00105 // This is essentially a translation from a virtual address (the 00106 // offset in the file) to a physical address (the sector where the 00107 // data at the offset is stored). 00108 // 00109 // "offset" is the location within the file of the byte in question 00110 //---------------------------------------------------------------------- 00111 00112 int 00113 FileHeader::ByteToSector(int offset) 00114 { 00115 return(dataSectors[offset / SectorSize]); 00116 } 00117 00118 //---------------------------------------------------------------------- 00119 // FileHeader::FileLength 00120 // Return the number of bytes in the file. 00121 //---------------------------------------------------------------------- 00122 00123 int 00124 FileHeader::FileLength() 00125 { 00126 return numBytes; 00127 } 00128 00129 //---------------------------------------------------------------------- 00130 // FileHeader::Print 00131 // Print the contents of the file header, and the contents of all 00132 // the data blocks pointed to by the file header. 00133 //---------------------------------------------------------------------- 00134 00135 void 00136 FileHeader::Print() 00137 { 00138 int i, j, k; 00139 char *data = new char[SectorSize]; 00140 00141 printf("FileHeader contents. File size: %d. File blocks:\n", numBytes); 00142 for (i = 0; i < numSectors; i++) 00143 printf("%d ", dataSectors[i]); 00144 printf("\nFile contents:\n"); 00145 for (i = k = 0; i < numSectors; i++) { 00146 kernel->synchDisk->ReadSector(dataSectors[i], data); 00147 for (j = 0; (j < SectorSize) && (k < numBytes); j++, k++) { 00148 if ('\040' <= data[j] && data[j] <= '\176') // isprint(data[j]) 00149 printf("%c", data[j]); 00150 else 00151 printf("\\%x", (unsigned char)data[j]); 00152 } 00153 printf("\n"); 00154 } 00155 delete [] data; 00156 }