00001 // directory.cc 00002 // Routines to manage a directory of file names. 00003 // 00004 // The directory is a table of fixed length entries; each 00005 // entry represents a single file, and contains the file name, 00006 // and the location of the file header on disk. The fixed size 00007 // of each directory entry means that we have the restriction 00008 // of a fixed maximum size for file names. 00009 // 00010 // The constructor initializes an empty directory of a certain size; 00011 // we use ReadFrom/WriteBack to fetch the contents of the directory 00012 // from disk, and to write back any modifications back to disk. 00013 // 00014 // Also, this implementation has the restriction that the size 00015 // of the directory cannot expand. In other words, once all the 00016 // entries in the directory are used, no more files can be created. 00017 // 00018 // Copyright (c) 1992-1993 The Regents of the University of California. 00019 // All rights reserved. See copyright.h for copyright notice and limitation 00020 // of liability and disclaimer of warranty provisions. 00021 00022 #include "copyright.h" 00023 #include "utility.h" 00024 #include "filehdr.h" 00025 #include "directory.h" 00026 00027 //---------------------------------------------------------------------- 00028 // Directory::Directory 00029 // Initialize a directory; initially, the directory is completely 00030 // empty. If the disk is being formatted, an empty directory 00031 // is all we need, but otherwise, we need to call FetchFrom in order 00032 // to initialize it from disk. 00033 // 00034 // "size" is the number of entries in the directory 00035 //---------------------------------------------------------------------- 00036 00037 Directory::Directory(int size) 00038 { 00039 table = new DirectoryEntry[size]; 00040 tableSize = size; 00041 for (int i = 0; i < tableSize; i++) 00042 table[i].inUse = FALSE; 00043 } 00044 00045 //---------------------------------------------------------------------- 00046 // Directory::~Directory 00047 // De-allocate directory data structure. 00048 //---------------------------------------------------------------------- 00049 00050 Directory::~Directory() 00051 { 00052 delete [] table; 00053 } 00054 00055 //---------------------------------------------------------------------- 00056 // Directory::FetchFrom 00057 // Read the contents of the directory from disk. 00058 // 00059 // "file" -- file containing the directory contents 00060 //---------------------------------------------------------------------- 00061 00062 void 00063 Directory::FetchFrom(OpenFile *file) 00064 { 00065 (void) file->ReadAt((char *)table, tableSize * sizeof(DirectoryEntry), 0); 00066 } 00067 00068 //---------------------------------------------------------------------- 00069 // Directory::WriteBack 00070 // Write any modifications to the directory back to disk 00071 // 00072 // "file" -- file to contain the new directory contents 00073 //---------------------------------------------------------------------- 00074 00075 void 00076 Directory::WriteBack(OpenFile *file) 00077 { 00078 (void) file->WriteAt((char *)table, tableSize * sizeof(DirectoryEntry), 0); 00079 } 00080 00081 //---------------------------------------------------------------------- 00082 // Directory::FindIndex 00083 // Look up file name in directory, and return its location in the table of 00084 // directory entries. Return -1 if the name isn't in the directory. 00085 // 00086 // "name" -- the file name to look up 00087 //---------------------------------------------------------------------- 00088 00089 int 00090 Directory::FindIndex(char *name) 00091 { 00092 for (int i = 0; i < tableSize; i++) 00093 if (table[i].inUse && !strncmp(table[i].name, name, FileNameMaxLen)) 00094 return i; 00095 return -1; // name not in directory 00096 } 00097 00098 //---------------------------------------------------------------------- 00099 // Directory::Find 00100 // Look up file name in directory, and return the disk sector number 00101 // where the file's header is stored. Return -1 if the name isn't 00102 // in the directory. 00103 // 00104 // "name" -- the file name to look up 00105 //---------------------------------------------------------------------- 00106 00107 int 00108 Directory::Find(char *name) 00109 { 00110 int i = FindIndex(name); 00111 00112 if (i != -1) 00113 return table[i].sector; 00114 return -1; 00115 } 00116 00117 //---------------------------------------------------------------------- 00118 // Directory::Add 00119 // Add a file into the directory. Return TRUE if successful; 00120 // return FALSE if the file name is already in the directory, or if 00121 // the directory is completely full, and has no more space for 00122 // additional file names. 00123 // 00124 // "name" -- the name of the file being added 00125 // "newSector" -- the disk sector containing the added file's header 00126 //---------------------------------------------------------------------- 00127 00128 bool 00129 Directory::Add(char *name, int newSector) 00130 { 00131 if (FindIndex(name) != -1) 00132 return FALSE; 00133 00134 for (int i = 0; i < tableSize; i++) 00135 if (!table[i].inUse) { 00136 table[i].inUse = TRUE; 00137 strncpy(table[i].name, name, FileNameMaxLen); 00138 table[i].sector = newSector; 00139 return TRUE; 00140 } 00141 return FALSE; // no space. Fix when we have extensible files. 00142 } 00143 00144 //---------------------------------------------------------------------- 00145 // Directory::Remove 00146 // Remove a file name from the directory. Return TRUE if successful; 00147 // return FALSE if the file isn't in the directory. 00148 // 00149 // "name" -- the file name to be removed 00150 //---------------------------------------------------------------------- 00151 00152 bool 00153 Directory::Remove(char *name) 00154 { 00155 int i = FindIndex(name); 00156 00157 if (i == -1) 00158 return FALSE; // name not in directory 00159 table[i].inUse = FALSE; 00160 return TRUE; 00161 } 00162 00163 //---------------------------------------------------------------------- 00164 // Directory::List 00165 // List all the file names in the directory. 00166 //---------------------------------------------------------------------- 00167 00168 void 00169 Directory::List() 00170 { 00171 for (int i = 0; i < tableSize; i++) 00172 if (table[i].inUse) 00173 printf("%s\n", table[i].name); 00174 } 00175 00176 //---------------------------------------------------------------------- 00177 // Directory::Print 00178 // List all the file names in the directory, their FileHeader locations, 00179 // and the contents of each file. For debugging. 00180 //---------------------------------------------------------------------- 00181 00182 void 00183 Directory::Print() 00184 { 00185 FileHeader *hdr = new FileHeader; 00186 00187 printf("Directory contents:\n"); 00188 for (int i = 0; i < tableSize; i++) 00189 if (table[i].inUse) { 00190 printf("Name: %s, Sector: %d\n", table[i].name, table[i].sector); 00191 hdr->FetchFrom(table[i].sector); 00192 hdr->Print(); 00193 } 00194 printf("\n"); 00195 delete hdr; 00196 }