NJU/2019/OS
Description:
CODE:
Main.cpp:
1 /* 2 @author: Edwin Xu 3 @Date:2019/11/13 4 @Note: just ASCII 5 */ 6 #include <cstdio> 7 #include <cstdlib> 8 #include <cstring> 9 #include <iostream> 10 #include <string> 11 #include <iostream> 12 #include <vector> 13 14 #define IMG_PATH "a.img" 15 16 using namespace std; 17 18 //myPrint in NASM 19 extern "C" {void myPrint(char *c,int len,int color);} 20 //print func using myPrint() 21 char chars[513]; 22 void print(string s,int color){ 23 const char * c = s.c_str(); 24 strcpy(chars,s.c_str()); 25 myPrint(chars,s.length(),color); 26 } 27 28 29 30 //Part1: struct and util functions 31 struct File 32 { 33 string filename; 34 int size; 35 int firstCluster; 36 File(string n, int s, int cluster) { 37 filename = n; 38 size = s; 39 firstCluster = cluster; 40 } 41 File(){ 42 size = 0; 43 filename = ""; 44 firstCluster = 0; 45 } 46 }; 47 struct Directory 48 { 49 string dirName ; 50 //子目录 51 vector <Directory>subDirs ; 52 //当前文件夹的文件 53 vector <File>subFiles ; 54 int dirNum=0; 55 int fileNum=0; 56 57 void addDir(Directory d) { 58 this->subDirs.push_back(d); 59 dirNum++; 60 } 61 void addFile(string name,int size,int cluster) { 62 this->subFiles.push_back(File(name,size,cluster)); 63 fileNum++; 64 } 65 66 Directory() { 67 dirName = ""; 68 } 69 Directory(string n) { 70 this->dirName = n; 71 } 72 73 //判断有没有son这个儿子 74 int hasSon(string son) { 75 for (int i = 0; i < dirNum; i++) { 76 if (son.compare(subDirs[i].dirName) == 0) { 77 return 1; 78 } 79 } 80 return 0; 81 } 82 //判断有没有这个file, 并返回cluster 83 int hasFile(string file) { 84 for (int i = 0; i < fileNum; i++) { 85 if (file.compare(subFiles[i].filename) == 0) { 86 return subFiles[i].firstCluster; //存在文件,返回cluster 87 } 88 } 89 return -1; //不存在文件,返回-1 90 } 91 92 }; 93 94 95 vector<string> path; //当前已经遍历的目录 96 97 string getPath() { 98 string res = "/"; 99 for (int i = 0; i < path.size(); i++) { 100 res += (path[i] + "/"); 101 } 102 return res ; 103 } 104 105 void ls_display(Directory d) { 106 if (d.dirName.length()>0) path.push_back(d.dirName); //if not root dir 107 print(getPath()+": ",0); 108 if(d.dirName.length()>0) print(". .. ",1); 109 for (int i = 0; i < d.dirNum; i++) { 110 print(d.subDirs[i].dirName+" ",1); 111 } 112 for (int i = 0; i < d.fileNum; i++) { 113 print(d.subFiles[i].filename+" ",0); 114 } 115 print(" ",0); 116 for (int i = 0; i < d.dirNum; i++) { 117 ls_display(d.subDirs[i]); 118 } 119 if (d.dirName.length() > 0) 120 { 121 path.pop_back(); 122 } 123 } 124 125 void ls_l_display(Directory d) { 126 if (d.dirName.length() > 0) path.push_back(d.dirName); //if not root dir 127 print(getPath() +" " + to_string(d.dirNum) + " " + to_string(d.fileNum)+": ",0); 128 if (d.dirName.length() > 0) print( ". .. ",1); 129 for (int i = 0; i < d.dirNum; i++) { 130 print(d.subDirs[i].dirName,1); 131 print(" " + to_string(d.subDirs[i].dirNum) + " " + to_string(d.subDirs[i].fileNum)+" ",0); 132 } 133 for (int i = 0; i < d.fileNum; i++) { 134 print(d.subFiles[i].filename +" " + to_string(d.subFiles[i].size)+" ",0); 135 } 136 print(" ",0); 137 for (int i = 0; i < d.dirNum; i++) { 138 ls_l_display(d.subDirs[i]); 139 } 140 if (d.dirName.length() > 0) path.pop_back(); 141 } 142 143 144 /* 145 get dir node by dir name (note: name is unique) 146 */ 147 Directory getDirectory(Directory beginDir,string dirName) { 148 if (beginDir.dirName.compare(dirName) == 0) { 149 return beginDir; //get it, the current dir is what i want 150 } 151 //fond in the subdir: 152 for (int i = 0; i < beginDir.dirNum; i++) { 153 Directory temp_dir= getDirectory(beginDir.subDirs[i], dirName); 154 if (temp_dir.dirName.length() != 0)return temp_dir; 155 } 156 return Directory(); 157 } 158 159 160 161 162 //Part2: BPB and FAT operations 163 164 typedef unsigned char u8; //1B 165 typedef unsigned short u16; //2B 166 typedef unsigned int u32; //4B 167 168 int BytsPerSec; //Bytes of every sector 169 int SecPerClus; //sectors of a cluster 170 int RsvdSecCnt; //Boot记录占用的扇区数 171 int NumFATs; //FAT tables Num 172 int RootEntCnt; //max files Num of root directory 173 int FATSz; //num of FAT sectors 174 175 #pragma pack (1) /*指定按1字节对齐*/ 176 177 //offset is 11 bytes 178 struct BPB { 179 u16 BPB_BytsPerSec; //每扇区字节数 180 u8 BPB_SecPerClus; //每簇扇区数 181 u16 BPB_RsvdSecCnt; //Boot记录占用的扇区数 182 u8 BPB_NumFATs; //FAT表个数 183 u16 BPB_RootEntCnt; //根目录最大文件数 184 u16 BPB_TotSec16; 185 u8 BPB_Media; 186 u16 BPB_FATSz16; //FAT扇区数 187 u16 BPB_SecPerTrk; 188 u16 BPB_NumHeads; 189 u32 BPB_HiddSec; 190 u32 BPB_TotSec32; //如果BPB_FATSz16为0,该值为FAT扇区数 191 }; 192 //BPB over,length is 25 bytes 193 194 //root directory entry 195 struct RootEntry { 196 char DIR_Name[11]; 197 u8 DIR_Attr; //file attr 198 char reserved[10]; 199 u16 DIR_WrtTime; 200 u16 DIR_WrtDate; 201 u16 DIR_FstClus; //start cluster No 202 u32 DIR_FileSize; 203 }; 204 //根目录条目结束,32字节 205 #pragma pack () /*取消指定对齐,恢复缺省对齐*/ 206 207 struct subEntry { 208 char DIR_Name[11]; 209 u8 DIR_Attr; 210 char reserved[10]; 211 u16 DIR_WrTime; 212 u16 DIR_WrDate; 213 u16 DIR_FstClus; 214 u32 DIR_FileSize; 215 }; 216 217 #pragma pack () /*取消指定对齐,恢复缺省对齐*/ 218 219 220 void fillBPB(struct BPB* bpb_ptr); //载入BPB 221 void printFiles(struct RootEntry* rootEntry_ptr, Directory* rootnode); //打印文件名,这个函数在打印目录时会调用下面的printChildren 222 void printChildren(char * directory, int startClus,Directory * d); //打印目录及目录下子文件名 223 int getFATValue(int num); //读取num号FAT项所在的两个字节,并从这两个连续字节中取出FAT项的值, 224 void printFileContent(int startClus); 225 int getFATValue(int num); 226 227 Directory root; 228 FILE* fat12; //global variable 229 230 void init() { 231 struct BPB bpb; 232 struct BPB* bpb_ptr = &bpb; 233 234 //载入BPB 235 fillBPB(bpb_ptr); 236 237 //init all global variables 238 BytsPerSec = bpb_ptr->BPB_BytsPerSec; 239 SecPerClus = bpb_ptr->BPB_SecPerClus; 240 RsvdSecCnt = bpb_ptr->BPB_RsvdSecCnt; 241 NumFATs = bpb_ptr->BPB_NumFATs; 242 RootEntCnt = bpb_ptr->BPB_RootEntCnt; 243 if (bpb_ptr->BPB_FATSz16 != 0) { 244 FATSz = bpb_ptr->BPB_FATSz16; 245 } 246 else { 247 FATSz = bpb_ptr->BPB_TotSec32; 248 } 249 250 struct RootEntry rootEntry; 251 struct RootEntry* rootEntry_ptr = &rootEntry; 252 253 //print in cursion 254 printFiles(rootEntry_ptr,&root); 255 } 256 //erase the spaces in the biginning and end 257 string& trim(std::string &s) 258 { 259 if (s.empty()) return s; 260 s.erase(0, s.find_first_not_of(" ")); 261 s.erase(s.find_last_not_of(" ") + 1); 262 return s; 263 } 264 265 string ls_l_resolve(string command) { 266 const char * cmd1 = command.c_str(); 267 int len = command.length(); 268 269 //处理 -lll这种多个l的情况 270 int _l_beginIndex = 0; 271 for (int i = 0; i < len-1; i++) { 272 if (cmd1[i] == '-'&&cmd1[i + 1] == 'l') { 273 _l_beginIndex = i + 1; 274 break; 275 } 276 } 277 int l_endIndex = _l_beginIndex; 278 for (int i = _l_beginIndex + 1; i < len; i++) { 279 if (cmd1[i] != 'l') { 280 l_endIndex = i; 281 break; 282 } 283 } 284 if (_l_beginIndex != l_endIndex) { 285 command = command.substr(0, _l_beginIndex+1) + command.substr(l_endIndex,len-l_endIndex); 286 } 287 //cout << "comm:" << command << endl; 288 const char * cmd = command.c_str(); 289 len = command.length(); 290 291 int beginIndex = 0, endIndex = 0; 292 int hasBegun = 0; //是否已经进入目录的 beginIndex 293 294 //form1:ls path -l 295 if (cmd[len - 1] == 'l'&&cmd[len - 2] == '-') { 296 for (int i = 3; i < len; i++) { 297 if (cmd[i] != ' '&&!hasBegun) { 298 beginIndex = i; 299 hasBegun = 1; 300 //break; 301 } 302 if (hasBegun && (cmd[i] == ' ' || cmd[i] == '-')) { 303 endIndex = i; 304 break; 305 } 306 } 307 } 308 else { 309 //form2:ls -l path 310 for (int i = 3; i < len; i++) { 311 if (cmd[i] == '-'&&cmd[i + 1] == 'l') { 312 beginIndex = i + 1; 313 break; 314 } 315 } 316 for (int i = beginIndex+1; i < len; i++) { 317 if (cmd[i] != ' ') { 318 beginIndex = i; 319 break; 320 } 321 } 322 endIndex = len; 323 } 324 string res = command.substr(beginIndex, endIndex - beginIndex); 325 return res; 326 } 327 //to upper 328 string upper(string s) { 329 string res; 330 const char* c = s.c_str(); 331 for (int i = 0; i < s.length(); i++) { 332 if (c[i] > 96&&c[i]<127)res += (c[i] - 32); 333 else res += c[i]; 334 } 335 return res; 336 } 337 //tranform path like '/a/b/c', return a vector 338 vector<string> getPathVector(string path) { 339 vector<string> pathVec; 340 const char* pathChars = path.c_str(); 341 int len = path.length(); 342 int beginIndex = 0; 343 if (pathChars[0] == '/')beginIndex++; 344 char temp[20];//temp char arr 345 for (int i = beginIndex; i < len; i++) { 346 if (pathChars[i] == '/'||i==len-1) { 347 pathVec.push_back(path.substr(beginIndex,(i==len-1)?len:i-beginIndex)); 348 beginIndex = i + 1; 349 } 350 } 351 return pathVec; 352 } 353 354 //得到路径中的目录 355 Directory locateDirectory(string path) { 356 path = upper(path); 357 vector<string> pathVector = getPathVector(path); 358 vector <Directory> dirArr; 359 360 for (int i = 0; i < pathVector.size(); i++) { 361 dirArr.push_back(getDirectory(root, pathVector[i])); 362 } 363 364 Directory res = dirArr[dirArr.size() - 1]; 365 int isOK = 1; 366 if(dirArr.size()==1){ 367 if(dirArr[0].dirName.length()==0)isOK=0; 368 } 369 else{ 370 for (int i = 0; i < pathVector.size() - 1; i++) { 371 if (!dirArr[i].hasSon(dirArr[i + 1].dirName)) { 372 isOK = 0; 373 break; 374 } 375 } 376 } 377 if (!isOK) res.dirNum = -1; //如果路径不正确,将返回目录节点的dirName置-1 378 return res; 379 } 380 381 void Main() { 382 string inp; 383 while (1) 384 { 385 print(">",0); 386 getline(cin, inp); 387 inp = trim(inp); 388 389 const char* c_inp = inp.c_str(); 390 391 int has_ = 0; 392 for(int i =0;i<inp.length();i++){ 393 if(c_inp[i]=='-'){ 394 has_ = 1; 395 break; 396 } 397 } 398 399 if (inp.compare("exit") == 0) { 400 print( "Bye! ",0); 401 break; 402 } 403 if (inp.length() >= 2 && c_inp[0] == 'l'&&c_inp[1] == 's') { 404 if (!inp.compare("ls")) { 405 ls_display(root); 406 } 407 else if(!inp.substr(0,2).compare("ls")&&!has_){ 408 string path = inp.substr(2,inp.length()-2); 409 path = trim(path); 410 Directory dir = locateDirectory(path); 411 ls_display(dir); 412 } 413 else if(!inp.compare("ls -l")) { 414 ls_l_display(root); 415 } 416 else if(!inp.substr(0,5).compare("ls -L")) { 417 print("your command is invalid! ",0); 418 } 419 else { 420 string path = ls_l_resolve(inp); 421 //cout << "path: " << path << endl; 422 423 if (path.length() == 0) { 424 print("The path is invalid! Try again! ",0); 425 } 426 else { 427 Directory dir = locateDirectory(path); 428 if (dir.dirNum==-1) { 429 print("The path is invalid! Try again! ",0); 430 } 431 else { 432 ls_l_display(dir); 433 } 434 } 435 } 436 } 437 else if (!inp.substr(0,3).compare("cat")) { 438 int i; 439 for (i = 3; i < inp.length(); i++) { 440 if (c_inp[i] != ' ')break; //取出cat后面的space 441 } 442 //取出文件和目录: 443 int endIndex = inp.length() - 1; 444 for (int i = endIndex; i >= 3; i--) { 445 if (c_inp[i] == '/') { 446 endIndex = i; 447 break; 448 } 449 } 450 451 string path = inp.substr(i, endIndex - i); 452 string fileName = inp.substr(endIndex + 1, inp.length() - endIndex - 1); 453 454 if (endIndex == inp.length() - 1) { 455 path = ""; 456 fileName = inp.substr(i, inp.length()-i); 457 } 458 //cout << "path: " << path << " file: " << fileName << endl; 459 Directory dir; 460 if (path.length() == 0) { //path is empty, so it's root entry 461 dir = root; 462 } 463 else { 464 dir = locateDirectory(path); 465 } 466 if (dir.dirNum == -1) { 467 print("The path is invalid! ",0); 468 } 469 else { 470 int cluster = dir.hasFile(upper(fileName)); 471 if (cluster==-1) { 472 print("The file is not exist! ",0); 473 } 474 else { 475 if (cluster >= 2) 476 printFileContent(cluster); 477 } 478 479 } 480 } 481 else if(inp.length()>0){ 482 string s = "Wrong Command! Try Again! "; 483 print(s,0); 484 } 485 } 486 } 487 488 489 void fillBPB( struct BPB* bpb_ptr) { 490 int check; 491 //BPB从偏移11个字节处开始 492 check = fseek(fat12, 11, SEEK_SET); 493 if (check == -1) 494 print("fseek in fillBPB failed! ",0); 495 496 //BPB长度为25字节 497 check = fread(bpb_ptr, 1, 25, fat12); 498 if (check != 25) 499 print("fread in fillBPB failed! ",0); 500 } 501 502 503 void printFiles(struct RootEntry* rootEntry_ptr, Directory* root) { 504 int base = (RsvdSecCnt + NumFATs * FATSz) * BytsPerSec; //根目录首字节的偏移数 505 int check; 506 char realName[12]; //暂存将空格替换成点后的文件名 507 508 //依次处理根目录中的各个条目 509 int i; 510 for (i = 0; i < RootEntCnt; i++) { 511 512 check = fseek(fat12, base, SEEK_SET); 513 if (check == -1) 514 print("fseek in printFiles failed! ",0); 515 516 check = fread(rootEntry_ptr, 1, 32, fat12); 517 if (check != 32) 518 print("fread in printFiles failed! ",0); 519 base += 32; 520 if (rootEntry_ptr->DIR_Name[0] == '