Advertisement
Guest User

utils

a guest
Dec 8th, 2016
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 49.40 KB | None | 0 0
  1. #include "type.h"
  2.  
  3.  
  4.  
  5. void init()
  6. {
  7. int i = 0;
  8. printf("Enter init.\n");
  9. //(1)
  10. P0.uid = 0; //root
  11. P1.uid = 1;
  12. P1.cwd = P0.cwd = 0;
  13.  
  14. /*(2) running = P0;*/
  15. running = &P0;
  16. P0.nextProcPtr = &P1;
  17. P1.nextProcPtr = &P0;
  18.  
  19. //(3)
  20. for(i = 0; i<NFD; i++)
  21. {
  22. P0.fd[i] = P1.fd[i] = 0;
  23. }
  24.  
  25. //last part of (1).
  26. for(i = 0; i<100;i++)
  27. {
  28. minode[i].refCount = minode[i].dev = minode[i].ino = 0;
  29. }
  30.  
  31. //(5)
  32. root = 0;
  33. printf("Exit init.\n");
  34. }
  35.  
  36. int get_block(int fd, unsigned long blk, char buf[ ])
  37. {
  38. lseek(fd, (long)blk*BLOCK_SIZE, SEEK_SET);
  39. read(fd, buf, BLOCK_SIZE);
  40. }
  41.  
  42. int put_block(int fd, int blk, char buf[ ])
  43. {
  44. lseek(fd, blk*BLOCK_SIZE, SEEK_SET);
  45. write(fd, buf, BLOCK_SIZE);
  46. }
  47.  
  48. char *basename(char *pathname)
  49. {
  50. char *dirtok = 0;
  51. char *rettok = 0;
  52. if(pathname != 0)
  53. {
  54. dirtok = strtok(pathname, "/");
  55.  
  56. do
  57. {
  58. rettok = dirtok;
  59. dirtok = strtok(NULL, "/");
  60. }while(dirtok != NULL);
  61. return rettok;
  62. }
  63. }
  64.  
  65. void mount_root()
  66. {
  67. printf("Enter mount_root.\n");
  68. MINODE *temp = 0;
  69. dev = fd = open(disk, O_RDWR); //dev is the disk fd
  70. get_block(fd, 1, buf);
  71. sp = (SUPER *) buf;
  72. printf("Checking EXT2 FS: ");
  73. if(sp->s_magic != 0xEF53)
  74. {
  75. printf("FAILED.\n");
  76. return;
  77. }
  78. printf("OK\n");
  79.  
  80. nblocks = sp->s_blocks_count;
  81. ninodes = sp->s_inodes_count;
  82.  
  83. get_block(fd, 2, buf);
  84. gp = (GD *) buf;
  85. bmap = gp->bg_block_bitmap;
  86. imap = gp->bg_inode_bitmap;
  87. inodes_start = gp->bg_inode_table;
  88.  
  89. printf("nblocks: %d\nninodes: %d\nbmap: %d\nimap: %d\ninodes_start: %d\n", nblocks, ninodes, bmap, imap, inodes_start);
  90.  
  91. root = (MINODE *) iget(dev, 2);
  92. P0.cwd = (MINODE *) iget(dev, 2);
  93. P1.cwd = (MINODE *) iget(dev, 2);
  94. printf("Exit mount_root.\n");
  95. }
  96.  
  97.  
  98. //If inode is in minode[] array inc ref count and return Minode ptr
  99. MINODE *iget(int dev, int ino)
  100. {
  101. int i = 0, j = 0, block, node;
  102.  
  103. MINODE *retPtr = 0;
  104. //see if there are dup inodes
  105. for (i = 0; i < 100; i++)
  106. {
  107. if(minode[i].ino == ino && minode[i].refCount > 0) // It exists! ++ ref
  108. {
  109. minode[i].refCount++;
  110. retPtr = (MINODE *) &minode[i];
  111.  
  112. return retPtr;
  113. }
  114. }
  115.  
  116. // Find empty Inode
  117. for (i = 0; i < 100; i++)
  118. {
  119. if (minode[i].refCount == 0)
  120. {
  121. // 3. Use mailman's
  122. block = (ino - 1)/8 + inodes_start;
  123. node = (ino - 1) % 8;
  124.  
  125.  
  126. // read blk into buf[ ];
  127. get_block(dev, block, buf);
  128. // 4. let INODE *ip = ( )buf + offset
  129. ip = (INODE *) buf + node; // Points at INODE in buf[]
  130.  
  131. // 5. COPY *ip into mip->INODE
  132. minode[i].INODE = *(ip);
  133.  
  134.  
  135. minode[i].refCount++;
  136. minode[i].dev = dev;
  137. minode[i].ino = ino;
  138. minode[i].dirty = 0;
  139. minode[i].mounted = 0;
  140. minode[i].mountptr = 0;
  141.  
  142. retPtr = (MINODE *) &minode[i];
  143.  
  144. // 7. return mip
  145. return retPtr;
  146. }
  147. }
  148. }
  149.  
  150. // Remove from minode list
  151. int iput(MINODE *mip)
  152. {
  153. int block, node;
  154.  
  155. // 1. dec refCount by 1.
  156. mip->refCount--;
  157.  
  158. // 2. No other refs so dont worry
  159. if (mip->refCount > 0)
  160. {
  161. return 0;
  162. }
  163. if (mip->dirty != 1) // no write back
  164. {
  165. return 0;
  166. }
  167.  
  168. block = (mip->ino - 1)/8 + inodes_start;
  169. node = (mip->ino - 1) % 8;
  170.  
  171. mip->dirty = 0;
  172.  
  173. // Read block into buf
  174. get_block(mip->dev, block, buf);
  175. ip = (INODE *) buf + node;
  176. // 5. Copy mip->INODE into *ip in buf[ ];
  177. *ip = mip->INODE;
  178. // 6. write block in the buf back to disk
  179. put_block(mip->dev, block, buf);
  180. }
  181.  
  182. void printInode(INODE *inode)
  183. {
  184. printf("i_mode: %x\n", inode->i_mode);
  185. printf("i_uid: %d\n", inode->i_uid);
  186. printf("i_size: %d\n", inode->i_size);
  187. }
  188.  
  189. // Find ino from path
  190. int getino(int dev, char *pathname)
  191. {
  192. char *dirtok, *temp = 0;
  193. char *cp;
  194. int i, j, currInode = 1, currBlock, currIno = 1;
  195. int InodeBeginBlock;
  196.  
  197. // read SUPER block
  198. get_block(dev, 1, buf);
  199. sp = (SUPER *)buf;
  200.  
  201.  
  202. if (sp->s_magic != 0xEF53)
  203. {
  204. printf("NOT an EXT2 FS\n");
  205. return 1;
  206. }
  207.  
  208. // Group descriptor block
  209. get_block(dev, 2, buf);
  210. gp = (GD *)buf;
  211.  
  212. // read InodeBeginBLock
  213. InodeBeginBlock = gp->bg_inode_table;
  214.  
  215. // Case 1: cwd no given path
  216. if (pathname == 0 || !strcmp(pathname, "") || !strcmp(pathname, "/"))
  217. {
  218. return running->cwd->ino; // return ino of cwd
  219. }
  220. // Case 2: ..
  221. else if(!strcmp(pathname, ".."))
  222. { // Mailman's algorithm
  223. currBlock = (running->cwd->ino - 1)/8 + InodeBeginBlock; // inode begin is offset
  224. currInode = (running->cwd->ino -1) % 8;
  225. }
  226. // Case 3: Not current working directory, not .., and doesn't begin with slash
  227. else if(pathname[0] != '/')
  228. { // Mailman's algorithm from InodeBeginBlock search all dirs
  229. currBlock = (running->cwd->ino-1)/8 + inodes_start;
  230. currInode = (running->cwd->ino - 1)%8;
  231. }
  232. else
  233. {
  234. currBlock = InodeBeginBlock;
  235. }
  236. temp = malloc(sizeof(char)*(strlen(pathname)+1));
  237. strcpy(temp, pathname);
  238. dirtok = (char *) strtok(temp, "/");
  239. do
  240. {
  241. get_block(dev, currBlock, buf);
  242. ip = (INODE *)buf+currInode;
  243. currIno = search(dev,ip, dirtok);
  244. if (currIno != -1)
  245. {
  246. currBlock = (currIno - 1)/8 + InodeBeginBlock;
  247. currInode = (currIno - 1) % 8;
  248. }
  249. else
  250. {
  251.  
  252. free(temp);
  253. return -1;
  254. }
  255. }while((dirtok=(char *)strtok(NULL, "/")) && (currIno > 0));
  256. free(temp);
  257. return currIno;
  258. }
  259.  
  260. // Finds the name string of myino in the parent's data block
  261.  
  262. int search(int dev, INODE *inodePtr, char *name)
  263. {
  264. int i = 0, j = 0, k = 0;
  265. char *cp;
  266. char temp[BLOCK_SIZE];
  267.  
  268. for (; i < 12; i++)
  269. {
  270. get_block(dev, inodePtr->i_block[i], buf);
  271. dp = (DIR *) buf;
  272. cp = buf;
  273. while(cp < buf+BLOCK_SIZE && dp->rec_len != 0)
  274. {
  275. for (j = 0; j < dp->name_len; j++)
  276. {
  277. temp[j] = dp->name[j];
  278. }
  279. temp[j] = '\0';
  280.  
  281. //printf("%s\n", temp);
  282.  
  283. if (strcmp(name, temp) == 0)
  284. {
  285. printf("Found %s at ino %d\n", name, dp->inode);
  286. return dp->inode;
  287. }
  288. cp += dp->rec_len;
  289. dp = (DIR *) cp;
  290. }
  291. }
  292. printf("Could not find \'%s\'\n", name);
  293. return -1;
  294. }
  295.  
  296. void ls(char *pathname)
  297. {
  298. MINODE *mip;
  299. int ino, nchars;
  300. NODE *temp;
  301. LIST *namelist;
  302. char *path;
  303.  
  304. // Case 1: Pathname is empty or root
  305. if(!strcmp(pathname, "") || !strcmp(pathname, "/"))
  306. {
  307. ino = getino(dev, pathname);
  308. }
  309. else
  310. { // Case 2: First character of pathname is not /, nor is the pathname . or ..
  311. if(pathname[0] != '/' && strcmp(pathname, ".") != 0 && strcmp(pathname, "..") != 0)
  312. {
  313. namelist = (LIST *) malloc(sizeof(LIST));
  314. done_flag = 0;
  315. recur_bp(root->ino, namelist);
  316. nchars = list_size(namelist) + strlen(pathname);
  317. path = (char *) malloc(sizeof(char) * nchars);
  318. strcpy(path, "/");
  319. temp = namelist->head;
  320. while(temp != 0)
  321. {
  322. strcat(path, temp->name);
  323. strcat(path, "/");
  324. temp = temp->nxt;
  325. }
  326. strcat(path, pathname);
  327. strcat(path, "\0");
  328. printf("%s\n", path);
  329.  
  330. ino = getino(dev, path);
  331. free(namelist);
  332. }
  333. else
  334. // Case 3: It's a path starting with a /
  335. ino = getino(dev, pathname);
  336. }
  337.  
  338. // If successful
  339. if(ino != -1)
  340. {
  341. mip = iget(dev, ino);
  342.  
  343. // If it's a dir
  344. if(mip->INODE.i_mode & 0040000 == 0040000)
  345. {
  346. list_dir(mip);
  347. }
  348. // If it's a file
  349. else
  350. {
  351. list_file(mip, pathname);
  352. }
  353.  
  354. iput(mip);
  355. }
  356. }
  357.  
  358. int list_dir(MINODE *mip)
  359. {
  360. MINODE *cip;
  361. INODE *ip = &mip->INODE;
  362. int i = 0, j = 0, k = 0;
  363. char *cp;
  364. char temp[BLOCK_SIZE];
  365. char tname[64];
  366.  
  367. for (; i < 12; i++) // ASSUME DIRs only has 12 direct blocks
  368. {
  369. if (mip->INODE.i_block[i] != 0)
  370. {
  371. printf("Data block: %d\n", i);
  372. }
  373. get_block(dev, mip->INODE.i_block[i], temp);
  374. dp = (DIR *) temp;
  375. cp = temp;
  376.  
  377. // Print dp->inode, dp->rec_len, dp->name_len, dp->name);
  378. while(cp < temp + BLOCK_SIZE && dp->rec_len != 0)
  379. {
  380. for(j = 0; j < dp->name_len && dp->name_len < 64; j++)
  381. {
  382. tname[j] = dp->name[j];
  383. }
  384. tname[j] = '\0';
  385. cip = iget(dev, dp->inode);
  386. list_file(cip, tname);
  387. cp+=dp->rec_len;
  388. dp = (DIR *) cp;
  389. iput(cip);
  390. }
  391. }
  392. }
  393.  
  394.  
  395. int list_file(MINODE *mip, char *name)
  396. {
  397. INODE *ip = &mip->INODE;
  398. int i, j;
  399. char *time;
  400. char syms[3] = {'r', 'w', 'x'};
  401.  
  402.  
  403. if ((ip->i_mode & 040000) == 040000)
  404. {
  405. putchar('d');
  406. }
  407. else if ((ip->i_mode & 0120000) == 0120000)
  408. {
  409. putchar('l');
  410. }
  411. else
  412. {
  413. putchar('-');
  414. }
  415.  
  416. for (i = 8, j = 0; i >= 0; i--, j++)
  417. {
  418. if (j > 2)
  419. {
  420. j = 0;
  421. }
  422.  
  423.  
  424. if (ip->i_mode & (1 << i))
  425. {
  426. printf("%c", syms[j]);
  427. }
  428. else
  429. {
  430. putchar('-');
  431. }
  432. }
  433.  
  434. printf(" %d %d %d %d\t", ip->i_links_count, ip->i_gid, ip->i_uid, (int) ip->i_size);
  435. time = (char *) ctime(&ip->i_mtime);
  436. time[strlen(time)-1] = 0;
  437. printf("%s", time);
  438. printf(" %s", basename(name));
  439. if((ip->i_mode & 0120000) == 0120000)
  440. {
  441. printf(" -> %s", (char *)ip->i_block);
  442. }
  443. putchar('\n');
  444. }
  445.  
  446. void cd(char *pn)
  447. {
  448. int ino, nchars;
  449. MINODE *mip;
  450. char *path;
  451.  
  452. if(!strcmp(pn, "") || !strcmp(pn, "/"))
  453. {
  454. ino = root->ino;
  455. }
  456. else
  457. {
  458. if(pn[0] != '/' && strcmp(pn, ".") != 0 && strcmp(pn, "..") != 0)
  459. {
  460.  
  461. path = my_cwd();
  462. path = realloc(path, sizeof(char)*(strlen(pn)+1));
  463. strcat(path, pn);
  464.  
  465. ino = getino(dev, path);
  466. }
  467. else
  468. {
  469. ino = getino(dev, pn);
  470. }
  471. }
  472. mip = iget(dev, ino);
  473.  
  474. if((mip->INODE.i_mode & 040000) == 040000)
  475. {
  476. iput(running->cwd);
  477. running->cwd = iget(dev, ino);
  478. printf("Set running->cwd to: %d\n", running->cwd->ino);
  479. }
  480. else
  481. {
  482. printf("\'%s\' is not a directory. i_mode: %x\n", pn, mip->INODE.i_mode);
  483. }
  484. iput(mip);
  485. }
  486.  
  487. int list_size(LIST *namelist)
  488. {
  489. int count = 0;
  490. NODE *currNode;
  491. if(namelist->head != 0)
  492. {
  493. currNode = namelist->head;
  494. while(currNode != 0)
  495. {
  496. count+=strlen(currNode->name)+1;
  497. currNode = currNode->nxt;
  498. }
  499. count+=2;
  500. }
  501. return count;
  502. }
  503.  
  504. void recur_bp(int currInode, LIST *namelist)
  505. {
  506. char temp[BLOCK_SIZE], tname[64];
  507. int i, j, block, node;
  508. char *cp;
  509. DIR *ndp; INODE *nip;
  510.  
  511. block = (currInode - 1)/8 + inodes_start;
  512. node = (currInode - 1)%8;
  513.  
  514. get_block(dev, block, temp);
  515. nip = (INODE *) temp + node;
  516.  
  517. for(i = 0; i < 12; i++)
  518. {
  519. get_block(dev, nip->i_block[i], temp);
  520. ndp = (DIR *) temp;
  521. cp = temp;
  522. if(i == 0 && ndp->rec_len != 0)
  523. {
  524. cp+=ndp->rec_len;
  525. ndp = (DIR *) cp;
  526. cp += ndp->rec_len;
  527. ndp = (DIR *) cp;
  528. }
  529. while(cp < temp + BLOCK_SIZE && ndp->rec_len != 0 && !done_flag)
  530. {
  531. if(ndp->file_type == 2)
  532. {
  533. for(j = 0; j < ndp->name_len; j++)
  534. {
  535. tname[j] = ndp->name[j];
  536. }
  537. tname[j] = '\0';
  538. add(tname, namelist);
  539. if(ndp->inode == running->cwd->ino)
  540. {
  541. done_flag = 1;
  542. }
  543. if(!done_flag)
  544. {
  545. recur_bp(ndp->inode, namelist);
  546. if(!done_flag)
  547. {
  548. delete_item(namelist);
  549. }
  550. }
  551. }
  552. cp+=ndp->rec_len;
  553. ndp = (DIR *) cp;
  554. }
  555. }
  556. }
  557.  
  558.  
  559. char *printpath(LIST *namelist)
  560. {
  561. NODE *currNode = namelist->head;
  562. char *path = 0;
  563. if(currNode != 0)
  564. {
  565. path = (char *) malloc(sizeof(char)*(strlen(currNode->name) + 3));
  566. strcpy(path, "/");
  567. strcat(path, currNode->name);
  568. strcat(path, "/");
  569. currNode = currNode->nxt;
  570. }
  571. while(currNode != 0)
  572. {
  573.  
  574. path = (char *) realloc(path, sizeof(char)*(strlen(currNode->name)+1));
  575. strcat(path, currNode->name);
  576. strcat(path, "/");
  577. currNode = currNode->nxt;
  578. }
  579. return path;
  580. }
  581.  
  582. void stack_add(char* name, LIST *namelist)
  583. {
  584. NODE *newNode = (NODE *) malloc(sizeof(NODE));
  585. strcpy(newNode->name, name);
  586. newNode->nxt = 0;
  587. newNode->prv = 0;
  588. if(namelist->head == 0)
  589. {
  590. namelist->head = newNode;
  591. namelist->tail = newNode;
  592. }
  593. else
  594. {
  595. //printf("Adding: %s\n", name);
  596. newNode->nxt = namelist->head;
  597. namelist->head->prv = newNode;
  598. namelist->head = newNode;
  599. }
  600. }
  601.  
  602. void add(char* name, LIST *namelist)
  603. {
  604. NODE *newNode = (NODE *) malloc(sizeof(NODE));
  605. strcpy(newNode->name, name);
  606. newNode->nxt = 0;
  607. newNode->prv = 0;
  608. if(namelist->head == 0)
  609. {
  610. namelist->head = newNode;
  611. namelist->tail = newNode;
  612. }
  613. else
  614. {
  615. //printf("Adding: %s\n", name);
  616. namelist->tail->nxt = newNode;
  617. newNode->prv = namelist->tail;
  618. namelist->tail = newNode;
  619. }
  620. }
  621.  
  622. void delete_item(LIST *namelist)
  623. {
  624. NODE *temp;
  625. if(namelist->head == 0)
  626. return;
  627. else if(namelist->head == namelist->tail)
  628. {
  629. namelist->tail = 0;
  630. namelist->head = 0;
  631. }
  632. else
  633. {
  634. temp = namelist->tail;
  635. namelist->tail = namelist->tail->prv;
  636. namelist->tail->nxt = 0;
  637. //printf("Removing: %s\n", temp->name);
  638. free(temp);
  639. }
  640. }
  641.  
  642. char *my_cwd()
  643. {
  644.  
  645. LIST *namelist = (LIST *) malloc(sizeof(LIST));
  646. int nextIno, currIno, oldIno = running->cwd->ino, block, node, i, j, done = -1;
  647. char name[64], tbuf[BLKSIZE], *cp, *path = 0;
  648. currIno = oldIno;
  649.  
  650. namelist->head = namelist->tail = 0;
  651. //if empty
  652. if(oldIno == 2)
  653. {
  654. path = malloc(sizeof(char)*2);
  655. strcpy(path,"/");
  656. return path;
  657. }
  658. else
  659. {
  660. while(done < 1)
  661. {
  662. // Locate inode using Mailman's
  663. block = (currIno - 1)/8 + inodes_start;
  664. node = (currIno - 1)%8;
  665.  
  666. get_block(dev, block, tbuf);
  667. ip = (INODE *) tbuf + node;
  668. for(i = 0; i < 12; i++)
  669. {
  670. if(ip->i_block[i] == 0)
  671. break;
  672. get_block(dev, ip->i_block[i], tbuf);
  673. dp = (DIR *) tbuf;
  674. cp = tbuf;
  675.  
  676. // get to last entry in block
  677. while(cp < tbuf + BLKSIZE && dp->rec_len != 0)
  678. {
  679. for(j = 0; j < dp->name_len; j++)
  680. {
  681. name[j] = dp->name[j];
  682. }
  683. name[j] = '\0';
  684.  
  685. if(!strcmp(name, "..")) // If ..
  686. {
  687. if(currIno == dp->inode)
  688. done = 1;
  689. nextIno = dp->inode;
  690. if(done == -1)
  691. {
  692. done++;
  693. currIno = nextIno;
  694. break;
  695. }
  696. }
  697.  
  698. else if((dp->inode == oldIno && strcmp(name, ".") != 0)) // If not .
  699. {
  700. oldIno = currIno;
  701. currIno = nextIno;
  702. stack_add(name, namelist);
  703. break;
  704. }
  705. cp += dp->rec_len;
  706. dp = (DIR *) cp;
  707. }
  708. }
  709. }
  710. path = printpath(namelist);
  711. }
  712. free(namelist);
  713. return path;
  714. }
  715.  
  716. void get_dirname(char *pathname)
  717. {
  718. char *tok;
  719. char *temp = malloc(sizeof(char)*(strlen(pathname)+1));
  720. char last[64] = {'\0'};
  721. strcpy(temp, pathname);
  722. tok = strtok(temp, "/");
  723.  
  724. dir[0] = '/';
  725. dir[1] = '\0';
  726. if(pathname != 0)
  727. {
  728. strcat(last, tok);
  729. while(tok = strtok(NULL, "/"))
  730. {
  731. if(tok != 0)
  732. {
  733. strcat(dir, last);
  734. strcat(dir, "/");
  735. }
  736. strcpy(last, tok);
  737. }
  738. }
  739. free(temp);
  740. }
  741.  
  742. void get_basename(char *pathname)
  743. {
  744. char *temp = malloc(sizeof(char)*(strlen(pathname)+1));
  745. char *tok;
  746. strcpy(temp, pathname);
  747. tok = strtok(temp, "/");
  748. base[0] = '\0';
  749.  
  750. //printf("base-pathname: %s\n", pathname);
  751. while(tok != NULL)
  752. {
  753. strcpy(base, tok);
  754. tok = strtok(NULL, "/");
  755. }
  756. free(temp);
  757. }
  758.  
  759. int mycreat(MINODE *pip, char *name)
  760. {
  761. /*
  762. - INODE's file type = 0x81A4 OR 0100644 regfile
  763. - links_count = 1
  764. - size = 0
  765. - do NOT inc parent's link count.
  766. */
  767.  
  768. int ino = ialloc(dev), i;
  769. char mbuf[BLKSIZE];
  770. MINODE *mip = iget(dev, ino);
  771. INODE *cip = &mip->INODE;
  772. DIR *mdp;
  773. char *mcp;
  774.  
  775. //---------given code--------
  776. cip->i_mode = 0x81a4;
  777. cip->i_uid = running->uid;
  778. cip->i_gid = running->gid;
  779. cip->i_size = 0; // NO data block, so size = 0
  780. cip->i_links_count = 1; // links_count = 1
  781. cip->i_atime = cip->i_ctime = cip->i_mtime = time(0L);
  782. cip->i_blocks = 0;
  783. cip->i_block[0] = 0;
  784. for(i = 1; i < 15; i++)
  785. {
  786. cip->i_block[i] = 0;
  787. }
  788.  
  789. mip->dirty = 1;
  790. mip->dev = dev;
  791. iput(mip);
  792.  
  793. enter_name(pip, ino, name);
  794.  
  795. return ino;
  796. }
  797.  
  798. int mymkdir(MINODE *pip, char *name)
  799. {
  800. //allocate an inode and a disk block for the new directory
  801. int ino = ialloc(dev);
  802. int bno = balloc(dev), i;
  803.  
  804. char mbuf[BLKSIZE];
  805.  
  806. MINODE *mip = iget(dev, ino); // To load the inode to minode
  807.  
  808. INODE *cip = &mip->INODE;
  809. DIR *mdp;
  810. char *mcp;
  811.  
  812. //writing contents to the INODE in memory
  813. //---------given code--------
  814. cip->i_mode = 0x41ed;
  815. cip->i_uid = running->uid; //owner UID
  816. cip->i_gid = running->gid; //group id
  817. cip->i_size = BLKSIZE; //size if bytes
  818. cip->i_links_count = 2; //link count=2 because of . and ..
  819. cip->i_atime = cip->i_ctime = cip->i_mtime = time(0L); //set to current time
  820. cip->i_blocks = 2; //LINUX: Block # in 512-byte chucks
  821. cip->i_block[0] = bno;
  822. for(i = 1; i < 15; i++)// for the last i_block array identifyer end
  823. {
  824. cip->i_block[i] = 0;
  825. }
  826.  
  827. mip->dirty = 1; // minode dirty
  828. mip->dev = dev;
  829. iput(mip); // Write INODE to disk
  830. //----end-------
  831. mdp = (DIR *) mbuf;
  832. mcp = mbuf;
  833.  
  834. // Write . into buf
  835. mdp->inode = root->ino;
  836. mdp->rec_len = 12;
  837. mdp->name_len = 1;
  838. mdp->name[0] = '.';
  839.  
  840. // Write .. into buf
  841. mcp += mdp->rec_len;
  842. mdp = (DIR *) mcp;
  843. mdp->inode = pip->ino;
  844. mdp->rec_len = 1012;
  845. mdp->name_len = 2;
  846. mdp->name[0] = '.';
  847. mdp->name[1] = '.';
  848.  
  849. // Write buf to the disk block bno
  850. put_block(dev, bno, mbuf);
  851.  
  852. // Enter name ENTRY into parent's directory
  853. enter_name(pip, ino, name);
  854. }
  855.  
  856. int enter_name(MINODE *pip, int myino, char *myname)
  857. {
  858. int lastRecLen = 0, remain, currNode, currBlock, ideal_len = 4*((11+strlen(myname))/4), i, j;
  859. char mbuf[BLKSIZE];
  860. INODE *mip;
  861. DIR *mdp;
  862. char *mcp;
  863. // 12 direct block, for each....
  864. for(i = 0; i < 12; i++)
  865. {
  866. if(pip->INODE.i_block[i] == 0)
  867. {
  868. printf("Data block %d was null\n", i);
  869. break;
  870. }
  871. else
  872. {
  873. // Get parent's ith data block into a buf
  874. get_block(dev, pip->INODE.i_block[i], mbuf);
  875. mdp = (DIR *) mbuf;
  876. mcp = mbuf;
  877.  
  878. // Step to LAST entry in block: int blk = parent->INODE.i_block[i]
  879. while(mcp < mbuf + BLKSIZE && mdp->rec_len != 0)
  880. {
  881. if(mcp + mdp->rec_len >= mbuf + BLKSIZE)
  882. break;
  883. mcp += mdp->rec_len; // increment
  884. mdp = (DIR *) mcp; //keep changing this as mcp goes up. haha
  885. } //dp or (mdp) now points at last entry in block
  886.  
  887. lastRecLen = mdp->rec_len;
  888. remain = lastRecLen - 4*((11+mdp->name_len)/4); // Each entry's ideal length is 4
  889. // let remain = Last entry's rec_len - it's IDEAL_LENGTH
  890.  
  891. if(remain >= ideal_len)
  892. {
  893. //enter the new entry as the last entry and trim the previous entry to its IDEAL_LENGTH
  894. mdp->rec_len = 4*((11+mdp->name_len)/4);//update new length for entry
  895. mcp += mdp->rec_len;
  896. mdp = (DIR *) mcp;
  897. //
  898. //
  899. // |LAST entry
  900. // --|-4---2----2--|----|---------|--------- rlen ->------------------------|
  901. // |ino rlen nlen NAME|.........|ino rlen nlen|NAME |
  902. // --------------------------------------------------------------------------
  903. // | NEW entry
  904. // --|-4---2----2--|----|---------|----ideal_len-----|--- rlen=remain ------|
  905. // |ino rlen nlen NAME|.........|ino rlen nlen|NAME|myino rlen nlen myname|
  906. //
  907.  
  908. mdp->inode = myino;
  909. mdp->rec_len = remain;
  910. mdp->name_len = strlen(myname);
  911. for(j = 0; j < strlen(myname); j++){
  912. mdp->name[j] = myname[j];
  913. }
  914. put_block(dev, pip->INODE.i_block[i], mbuf);
  915. return 0;
  916. }
  917. }
  918. }
  919.  
  920. // Reach here mean: NO space in existing data blocks
  921. // Allocate a new data block
  922. pip->INODE.i_block[i] = balloc(dev);
  923. strcpy(mbuf, "\0");
  924. mdp = (DIR *) mbuf;
  925.  
  926. mdp->inode = myino;
  927. mdp->rec_len = 1024;
  928. mdp->name_len = strlen(myname);
  929. for(j = 0; j < strlen(myname); j++)
  930. {
  931. mdp->name[j] = myname[j];
  932. }
  933. pip->INODE.i_size += 1024; // INC parent's isze by 1024;
  934.  
  935. // enter new entry as the first entry in the new data block with rec_len= BLKSIZE
  936. put_block(dev, pip->INODE.i_block[i], mbuf);
  937. return 1;
  938. }
  939.  
  940. int tst_bit(char *buf, int bit)
  941. {
  942. int i, j;
  943. i = bit/8; j=bit%8;
  944. if (buf[i] & (1 << j))
  945. return 1;
  946. return 0;
  947. }
  948.  
  949. int set_bit(char *buf, int bit)
  950. {
  951. int i, j;
  952. i = bit/8; j=bit%8;
  953. buf[i] |= (1 << j);
  954. }
  955.  
  956. int clr_bit(char *buf, int bit)
  957. {
  958. int i, j;
  959. i = bit/8; j=bit%8;
  960. buf[i] &= ~(1 << j);
  961. }
  962.  
  963. int decFreeInodes(int dev)
  964. {
  965. char buf[BLKSIZE];
  966.  
  967. // dec free inodes count in SUPER and GD
  968. get_block(dev, 1, buf);
  969. sp = (SUPER *)buf;
  970. sp->s_free_inodes_count--;
  971. put_block(dev, 1, buf);
  972.  
  973. get_block(dev, 2, buf);
  974. gp = (GD *)buf;
  975. gp->bg_free_inodes_count--;
  976. put_block(dev, 2, buf);
  977. }
  978.  
  979. // Allocates a FREE inode number
  980. int ialloc(int dev)
  981. {
  982. int i;
  983. char buf[BLKSIZE];
  984.  
  985. // read inode_bitmap block
  986. get_block(dev, imap, buf);
  987.  
  988. for (i = 0; i < ninodes; i++)
  989. {
  990. if (tst_bit(buf, i) == 0)
  991. {
  992. set_bit(buf,i);
  993. decFreeInodes(dev);
  994.  
  995. put_block(dev, imap, buf);
  996.  
  997. return i+1;
  998. }
  999. }
  1000. printf("ialloc(): no more free inodes\n");
  1001.  
  1002. return 0;
  1003. }
  1004.  
  1005. // Deallocate an ino
  1006. int idealloc(int dev, int ino)
  1007. {
  1008. int i;
  1009. char buf[BLKSIZE];
  1010.  
  1011. get_block(dev, imap, buf);
  1012. clr_bit(buf, ino-1);
  1013.  
  1014. get_block(dev, 1, buf);
  1015. sp = (SUPER *) buf;
  1016. sp->s_free_inodes_count++;
  1017. put_block(dev, 1, buf);
  1018.  
  1019. get_block(dev, 2, buf);
  1020. gp = (GD *) buf;
  1021. gp->bg_free_inodes_count++;
  1022. put_block(dev, 2, buf);
  1023. }
  1024.  
  1025. // Allocates a FREE block number
  1026. int balloc(int dev)
  1027. {
  1028. int i;
  1029. char buf[BLKSIZE];
  1030.  
  1031. // read block_bitmap block
  1032. get_block(dev, bmap, buf);
  1033.  
  1034. for (i = 0; i < nblocks; i++)
  1035. {
  1036. if (tst_bit(buf, i) == 0)
  1037. {
  1038. set_bit(buf,i);
  1039. decFreeBlocks(dev);
  1040.  
  1041. put_block(dev, bmap, buf);
  1042.  
  1043. return i+1;
  1044. }
  1045. }
  1046. printf("balloc(): no more free blocks\n");
  1047. return 0;
  1048.  
  1049. }
  1050.  
  1051. // Deallocate a bno
  1052. int bdealloc(int dev, int bno)
  1053. {
  1054. char buf[BLKSIZE];
  1055.  
  1056. get_block(dev, bmap, buf);
  1057. clr_bit(buf, bno-1);
  1058.  
  1059. get_block(dev, 1, buf);
  1060. sp = (SUPER *)buf;
  1061. sp->s_free_blocks_count++;
  1062. put_block(dev, 1, buf);
  1063.  
  1064. get_block(dev, 2, buf);
  1065. gp = (GD *)buf;
  1066. gp->bg_free_blocks_count++;
  1067. put_block(dev, 2, buf);
  1068. }
  1069.  
  1070. int decFreeBlocks(int dev)
  1071. {
  1072. char buf[BLKSIZE];
  1073.  
  1074. // dec free inodes count in SUPER and GD
  1075. get_block(dev, 1, buf);
  1076. sp = (SUPER *)buf;
  1077. sp->s_free_blocks_count--;
  1078. put_block(dev, 1, buf);
  1079.  
  1080. get_block(dev, 2, buf);
  1081. gp = (GD *)buf;
  1082. gp->bg_free_blocks_count--;
  1083. put_block(dev, 2, buf);
  1084. }
  1085.  
  1086. // rm_child(): removes the entry [INO rlen nlen name] from parent's data block.
  1087. int rm_child(MINODE *parent, char *name)
  1088. {
  1089. int i = 0, j;
  1090. int x;
  1091. DIR *tdp;
  1092. char temp[64], tbuf[BLKSIZE], *cp, *tcp;
  1093.  
  1094. for (; i < 12; i++)
  1095. {
  1096. if(parent->INODE.i_block[i] == 0)
  1097. break;
  1098. printf("data block: %d\n", i);
  1099. get_block(parent->dev, parent->INODE.i_block[i], tbuf);//every loop , you need to get the block
  1100. dp = (DIR *) tbuf;//typecast to shut up!
  1101. cp = tbuf;
  1102. while (cp < tbuf + BLKSIZE && dp->rec_len != 0)
  1103. {
  1104. for(j = 0; j < dp->name_len; j++)//copy everything to temp, so I can modify temp
  1105. {
  1106. temp[j] = dp->name[j];
  1107. }
  1108. temp[j] = '\0';
  1109.  
  1110. if (!strcmp(name, temp)) //if dp->name is the same as "name" parameter
  1111. {
  1112. // if (first entry in a data block)
  1113. if (BLKSIZE == dp->rec_len)//if the rec_len is the maximun size the block
  1114. {
  1115. printf("deleting block.\n");
  1116. bdealloc(dev, ip->i_block[i]);//deallocate the data block
  1117. parent->INODE.i_size -= BLKSIZE;//modify parent's file size
  1118. //move parent's NONZERO block upward, so that there is no HOLEs in parent's data block numbers
  1119. for(i; i < 11 && ip->i_block[i+1] != 0; i++)
  1120. {
  1121. ip->i_block[i] = ip->i_block[i+1];
  1122. }
  1123. }
  1124. // if NOT first entry in blo
  1125. else if (cp+dp->rec_len == tbuf+BLKSIZE)
  1126. {
  1127. //move all entries AFter this entry Left
  1128. cp = cp - x;
  1129. x = dp->rec_len;
  1130. dp = (DIR *)cp;
  1131. printf("%d //", dp->rec_len);
  1132. dp->rec_len += x;//add rec_len to the Last entry of the block
  1133. printf(" %d\n", dp->rec_len);
  1134. }
  1135. else
  1136. {
  1137. // write the parent's data block back to disk and mark parent minode Dirty for write-back
  1138. tdp = dp;
  1139. tcp = cp;
  1140. x = dp->rec_len;
  1141. cp+=dp->rec_len;
  1142. dp = (DIR *)cp;
  1143.  
  1144. while(cp < tbuf + BLKSIZE && dp->rec_len != 0)
  1145. {
  1146. tdp->name_len = dp->name_len;
  1147. tdp->rec_len = dp->rec_len;
  1148. tdp->inode = dp->inode;
  1149. for(j = 0; j < dp->name_len; j++)
  1150. {
  1151. tdp->name[j] = dp->name[j];
  1152. }
  1153. if(cp+dp->rec_len == tbuf+BLKSIZE)
  1154. {
  1155. tdp->rec_len+=x;
  1156. break;
  1157. }
  1158. cp+=dp->rec_len;
  1159. dp = (DIR *) cp;
  1160.  
  1161. tcp += tdp->rec_len;
  1162. tdp = (DIR *) tcp;
  1163. }
  1164. }
  1165. break;
  1166. }
  1167. x = dp->rec_len;
  1168. cp += dp->rec_len;
  1169. dp = (DIR *) cp;
  1170. }
  1171. put_block(parent->dev, parent->INODE.i_block[i], tbuf);
  1172. }
  1173. }
  1174.  
  1175. // Creates a file newFileName which has the SAME inode (number) as that of oldFileName.
  1176. int link(char *oldFileName, char *newFileName)
  1177. {
  1178. int inoOld, i;
  1179. char *temp = (char *) malloc(sizeof(char)*(strlen(oldFileName) + 1)), *pn = 0;
  1180. MINODE *mip, *pip;
  1181.  
  1182. strcpy(temp, oldFileName);
  1183. //Get the INODE into memory
  1184. //trivial
  1185. inoOld = getino(dev, temp);
  1186. free(temp);
  1187. mip = iget(dev, inoOld);
  1188.  
  1189. //check to see if it is a REG or LNK
  1190.  
  1191. //if it's a DIR //if it's a REG
  1192. if((mip->INODE.i_mode & 0100000) == 0100000 || (mip->INODE.i_mode & 012000 == 012000))
  1193. {
  1194.  
  1195. pn = (char *) malloc(sizeof(char)*(strlen(newFileName) + 1));
  1196. strcpy(pn, newFileName);
  1197.  
  1198. if(pn[0] == '/') // If the first char is a /, go ahead and get dirname on root
  1199. {
  1200. get_dirname(pn); // Get dirname
  1201. }
  1202. else // No /, specify cwd
  1203. {
  1204. free(pn);
  1205. pn = my_cwd(); // Get the "current working directory"
  1206. pn = realloc(pn, sizeof(char)*(strlen(pn)+strlen(newFileName)+1));
  1207. strcat(pn, newFileName); // Copy over the new file name
  1208. get_dirname(pn); // Get dirname
  1209. }
  1210.  
  1211. temp = (char *) malloc(sizeof(char)*(strlen(dir) + 1));
  1212. strcpy(temp, dir); // Store dir name in temp
  1213. i = getino(dev, temp); // Get inode of oldfile
  1214. free(temp);
  1215.  
  1216. if(i == -1) // if it failed to get inode
  1217. {
  1218. printf("dir \'%s\' doesn't exist.\n", dir);
  1219. free(pn);
  1220. return -1;
  1221. }
  1222. pip = iget(dev, i); // remember iget ends with iput
  1223. i = getino(dev, pn);
  1224.  
  1225. if(i != -1) // check /x/y exists and is a DIR but 'z' does not yet exist in /x/y/
  1226. {
  1227. printf("file already exists.\n");
  1228. free(pn);
  1229. iput(pip);
  1230. return -1;
  1231. }
  1232. get_basename(pn);
  1233. enter_name(pip, mip->ino, base); // Enter name ENTRY into parent's directory
  1234. mip->INODE.i_links_count++; // Increment count
  1235. mip->dirty = 1; // Make dirty
  1236.  
  1237. iput(pip);
  1238. free(pn);
  1239. }
  1240. //Back to Disk
  1241. iput(mip);
  1242. }
  1243.  
  1244. int symlink(char *oldName, char *newName)
  1245. {
  1246. int i, ino;
  1247. char *oldPn = 0, *newPn = 0;
  1248. MINODE *mip;
  1249. //////////////////////////////////////////////////////////////////////////////////
  1250. // Verify oldname exists
  1251. oldPn = (char *) malloc(sizeof(char)*(strlen(oldName) + 1));
  1252. strcpy(oldPn, oldName);
  1253. // if it begins with a /, so a specfied location...
  1254. if(oldPn[0] == '/')
  1255. {
  1256. i = getino(dev, oldPn);
  1257. }
  1258. else // looks like it's just name
  1259. {
  1260. free(oldPn);
  1261. oldPn = my_cwd();
  1262. oldPn = realloc(oldPn, sizeof(char)*(strlen(oldPn)+strlen(oldName)+1));
  1263. strcat(oldPn, oldName);
  1264. i = getino(dev, oldPn);
  1265. }
  1266. if(i == -1)//fails to get the inode
  1267. {
  1268. free(oldPn);
  1269. return -1;
  1270. }
  1271. ///////////////////////////////////////////////////////////////////////////////
  1272. // Check where user wants newname to be created
  1273. //Get the pathname then set it to the correct name for creat
  1274. newPn = (char *) malloc(sizeof(char)*(strlen(newName) + 1));
  1275. strcpy(newPn, newName);
  1276. if(newPn[0] == '/')
  1277. {
  1278. strcpy(pathname, newPn);
  1279. }
  1280. else
  1281. {
  1282. free(newPn);
  1283. newPn = my_cwd();
  1284. newPn = realloc(newPn, sizeof(char)*(strlen(newPn)+strlen(newName)+1));
  1285. strcat(newPn, newName);
  1286. strcpy(pathname, newPn);
  1287. }
  1288. //Complete
  1289.  
  1290. i = getino(dev, newPn);
  1291.  
  1292. if(i != -1)
  1293. {
  1294. free(newPn);
  1295. return -1;
  1296. }
  1297. /////////////////////////////////////////////////////////////////////////////////
  1298. ino = creat_file();
  1299. mip = iget(dev, ino);
  1300. mip->INODE.i_mode = 0xa1ff;
  1301. mip->INODE.i_size = strlen(oldPn);
  1302. mip->dirty = 1;
  1303.  
  1304. strcpy((char *) mip->INODE.i_block, oldPn);
  1305. //Back to Disc
  1306. iput(mip);
  1307. //proper remove!
  1308. free(newPn);
  1309. free(oldPn);
  1310.  
  1311. return 0;
  1312. }
  1313.  
  1314. int unlink(char* pn)
  1315. {
  1316. if (pn[0]=='\0'){ // Empty pathname
  1317. printf("Syntax: unlink [path]\n");
  1318. return -1;
  1319. }
  1320. char parentdir[64],name[64], *cp, *endcp, *last;
  1321. DIR * dp;
  1322. MINODE * pip,*targetip;
  1323. int parent, target;
  1324. cp = strrchr(pn, '/');
  1325.  
  1326. // 1. Check where the parent is and get the iNode based on cp
  1327.  
  1328. if (!cp){ // In the same directory
  1329. parent = running->cwd->ino; // Set parent to cwd inode
  1330. strcpy(name,pn);
  1331. }
  1332. else{ // In another directory
  1333. *(cp) = '\0';
  1334. strcpy(parentdir, pn);
  1335. parent = getino(fd,parentdir); // Get inode of parentdir, store into parent
  1336. strcpy(name,cp+1);
  1337. }
  1338.  
  1339. target = getino(fd,pn);
  1340.  
  1341. // Check if target file exists
  1342. if ((target==0)||(parent==0)){
  1343. printf("Error: File must exist\n");
  1344. return -1;
  1345. }
  1346. pip = iget(fd,parent);
  1347. targetip = iget(fd,target);
  1348.  
  1349. // 2. If the target exists, make sure it's not a dir...
  1350. if((targetip->INODE.i_mode & 0100000) != 0100000){
  1351. iput(pip);
  1352. printf("Error: Cannot unlink NON-REG files\n");
  1353. return -1;
  1354. }
  1355.  
  1356. // 3. Decrement links count
  1357. targetip->INODE.i_links_count--; // I links count--
  1358.  
  1359. // 4. Clear data with truncate
  1360. if (targetip->INODE.i_links_count == 0)
  1361. {
  1362. // Truncate for MINODE
  1363. targetip->INODE.i_size = 0; // Set targetip size to 0
  1364. targetip->INODE.i_atime = targetip->INODE.i_mtime = time(0L); // Touch time
  1365. targetip->dirty = 1; // Mark targetip dirty
  1366.  
  1367. targetip->refCount++;
  1368. iput(targetip);
  1369. idealloc(fd,targetip->ino);
  1370.  
  1371. }
  1372. else
  1373. {
  1374. iput(targetip);
  1375. }
  1376.  
  1377. return deleteChild(pip,name);
  1378. }
  1379.  
  1380. void mytouch(char *pathname)
  1381. {
  1382. /*
  1383. int ino = getino(fd, pathname);
  1384. MINODE *mip = iget(fd, ino);
  1385. printf("the file is touched\n");
  1386. mip->INODE.i_atime = mip->INODE.i_mtime = time(0L);
  1387. iput(mip);
  1388.  
  1389. */
  1390. unsigned long ino = getino(fd, pathname);
  1391.  
  1392. MINODE *mip = iget(fd, ino);
  1393. mip->INODE.i_atime = mip->INODE.i_mtime = time(0L);
  1394.  
  1395. iput(mip);
  1396. }
  1397. void mystat(char *path){
  1398. struct stat mystat;
  1399. int r = do_stat(path, &mystat);
  1400. return;
  1401. }
  1402.  
  1403. // Print out the stats for a pathname
  1404. // Loads the inode for the path and
  1405. // copies all of its fields to a stat struct
  1406. // then prints those fields
  1407. int do_stat(char *pathname, struct stat *stPtr)
  1408. {
  1409. unsigned long ino = getino(fd, pathname);
  1410. MINODE *mip = iget(fd, ino);
  1411. stPtr->st_dev = fd;
  1412. memcpy(&stPtr->st_ino, &ino, sizeof(ino_t));
  1413. memcpy(&stPtr->st_mode, &mip->INODE.i_mode, sizeof(mode_t));
  1414. memcpy(&stPtr->st_nlink, &mip->INODE.i_links_count, sizeof(nlink_t));
  1415. memcpy(&stPtr->st_uid, &mip->INODE.i_uid, sizeof(uid_t));
  1416. memcpy(&stPtr->st_gid, &mip->INODE.i_gid, sizeof(gid_t));
  1417. memcpy(&stPtr->st_size, &mip->INODE.i_size, sizeof(off_t));
  1418. stPtr->st_blksize = 1024;
  1419. memcpy(&stPtr->st_blocks, &mip->INODE.i_blocks, sizeof(blkcnt_t));
  1420. memcpy(&stPtr->st_atime, &mip->INODE.i_atime, sizeof(time_t));
  1421. memcpy(&stPtr->st_mtime, &mip->INODE.i_mtime, sizeof(time_t));
  1422. memcpy(&stPtr->st_ctime, &mip->INODE.i_ctime, sizeof(time_t));
  1423. printf("dev: %d\t", (int)stPtr->st_dev);
  1424. printf("ino: %u\t\t", (int)stPtr->st_ino);
  1425. printf("mode: %u\t", (unsigned short)stPtr->st_mode);
  1426. printf("nlink: %lu\t", (unsigned long)stPtr->st_nlink);
  1427. printf("uid: %u\t", (int)stPtr->st_uid);
  1428. printf("\n");
  1429. printf("gid: %u\t", (int)stPtr->st_gid);
  1430. printf("size: %d\t", (int)stPtr->st_size);
  1431. printf("blksize: %d\t", (int)stPtr->st_blksize);
  1432. printf("blocks: %lu\t", (unsigned long)stPtr->st_blocks);
  1433. char *time_string = ctime(&stPtr->st_ctime);
  1434. printf("\nctime: %s", time_string);
  1435. time_string = ctime(&stPtr->st_atime);
  1436. printf("atime: %s", time_string);
  1437. time_string = ctime(&stPtr->st_mtime);
  1438. printf("mtime: %s", time_string);
  1439. printf("\n");
  1440.  
  1441. iput(mip);
  1442. return 0;
  1443. }
  1444.  
  1445. void chmod_file(char *pathname)
  1446. {
  1447. char line[128];
  1448. int mode=0, i=0;
  1449. char perm[64];
  1450. for (i = 0; i < 64; i++) {
  1451. perm[i]=0;
  1452. }
  1453. unsigned long ino = getino(fd, pathname);
  1454. MINODE *mip = iget(fd, ino);
  1455. printf("input the new mode: ");
  1456. fgets(line, 128, stdin);
  1457. line[strlen(line)-1]=0;
  1458. sscanf(line, "%s", perm);
  1459. printf("\nprevious permissions: %o\n", mip->INODE.i_mode);
  1460. mode = perm[0]-48 << 6;
  1461. mode |= perm[1]-48 << 3;
  1462. mode |= perm[2]-48;
  1463. printf("mode %d\n", mode);
  1464. mip->INODE.i_mode &= 0xFF000;
  1465. mip->INODE.i_mode |= mode;
  1466. printf("new permissions: %o\n", mip->INODE.i_mode);
  1467. return;
  1468. }
  1469.  
  1470. MINODE* findParent(MINODE* mip,MINODE* pip)
  1471. {
  1472. MINODE* result;
  1473. DIR *dp;
  1474. char* cp;
  1475. int i;
  1476. char tmpbuff[1024];
  1477. for (i = 0; i < 12; i++) {
  1478. if ( pip->INODE.i_block[i]==0)
  1479. {
  1480. break;
  1481. }
  1482. cp = tmpbuff;
  1483. dp = (DIR *) tmpbuff;
  1484.  
  1485.  
  1486. lseek(fd, pip->INODE.i_block[i]*BLOCK_SIZE, SEEK_SET);
  1487. read(fd, tmpbuff, 1024);
  1488. //get rid of the first two entries or we will be stuck forever
  1489. cp += dp->rec_len;
  1490. dp = (DIR *)cp;
  1491. cp += dp->rec_len;
  1492. dp = (DIR *)cp;
  1493. //Depth first search
  1494. while(cp < tmpbuff + 1024)
  1495. {
  1496. if (dp->inode == mip->ino)
  1497. return pip;
  1498. else
  1499. {
  1500. MINODE* cip = iget(fd, dp->inode);
  1501. if (S_ISDIR( cip->INODE.i_mode))
  1502. {
  1503. result = findParent(mip,cip);
  1504. if (result!=NULL)
  1505. return result;
  1506. }
  1507. }
  1508.  
  1509. cp += dp->rec_len;
  1510. dp = (DIR *)cp;
  1511.  
  1512. }
  1513. }
  1514. return NULL;
  1515. }
  1516.  
  1517. // Prints the path to the current file
  1518. int printfilepath(MINODE* mip)
  1519. {
  1520. MINODE* pip = findParent(mip,root);
  1521. pwd(pip,0);
  1522. int i;
  1523. DIR *dp;
  1524. char* cp,name[64];
  1525. // 12 blocks. For each...
  1526. for (i = 0; i < 12; i++) {
  1527. get_block(fd,pip->INODE.i_block[i], buf);
  1528. // If the Block is NULL stop looping, you're done
  1529. if ( pip->INODE.i_block[i]==0)
  1530. {
  1531. break;
  1532. }
  1533. cp = buf;
  1534. dp = (DIR *) buf;
  1535.  
  1536. // First two entries are useless
  1537. cp += dp->rec_len;
  1538.  
  1539. dp = (DIR *)cp;
  1540. cp += dp->rec_len;
  1541. dp = (DIR *)cp;
  1542. // Depth first search
  1543. while(cp < buf + 1024)
  1544. {
  1545. if (dp->inode == mip->ino) // If the INODE number from the parameter is the same as entry of INODE
  1546. {
  1547. strncpy(name,dp->name,dp->name_len);
  1548. name[dp->name_len] = '\0';
  1549. printf("%s",name);
  1550. }
  1551. cp += dp->rec_len;
  1552. dp = (DIR *)cp;
  1553. }
  1554. }
  1555. return 0;
  1556. }
  1557.  
  1558. int pfd()
  1559. {
  1560. printf("Filename\tFD\tMode\tOffset\n");
  1561. printf("---------------------------------------\n");
  1562. //10 FDs
  1563.  
  1564. // For each pfd
  1565. int i = 0;
  1566. for(; i < 10; i++)
  1567. {
  1568. if (running->fd[i])
  1569. {
  1570. // 1. print its filepath
  1571. printfilepath(running->fd[i]->inodeptr);
  1572. printf("\t\t%d\t",i);
  1573. // 2. print out the mode according to it's fd[i]->mode
  1574. switch(running->fd[i]->mode)
  1575. {
  1576. case 0:
  1577. printf("READ\t");
  1578. break;
  1579. case 1:
  1580. printf("WRITE\t");
  1581. break;
  1582. case 2:
  1583. printf("R/W\t");
  1584. break;
  1585. case 3:
  1586. printf("APPEND\t");
  1587. break;
  1588. default:
  1589. break;
  1590. }
  1591. // 3. Then print its offset
  1592. printf("%d\n",running->fd[i]->offset);
  1593. }
  1594. }
  1595. return 0;
  1596. }
  1597.  
  1598. //Allocates a OFT pointer and assigns it to the next availble spot in the running process
  1599. int falloc(OFT* oftp)
  1600. {
  1601. int i = 0;
  1602.  
  1603. for(;i < 10; i++)
  1604. {
  1605. if (running->fd[i] == NULL)
  1606. break;
  1607. }
  1608. if (i == 10)
  1609. {
  1610. return -1;
  1611. }
  1612. running->fd[i]=oftp;
  1613.  
  1614. return i;
  1615. }
  1616.  
  1617. // 0 read 1 write 2 read/write 3 append
  1618. int open_file(char* path, char mode)
  1619. {
  1620. // user error check
  1621. if (mode == '\0' || path[0] == '\0')
  1622. {
  1623. printf("open [path] [mode (as int)]\n");
  1624. printf("modes: 0 = READ, 1 = WRITE, 2 = READ/WRITE, 3 = APPEND\n");
  1625. return -1;
  1626. }
  1627.  
  1628. int ino = getino(fd,path); // 1. get pathname's inumber:
  1629.  
  1630. MINODE * mip = iget(fd,ino); // 2. get its Minode pointer
  1631.  
  1632. // 3. check mip->INODE.i_mode to verify it's a REGULAR file
  1633. if (!S_ISREG( mip->INODE.i_mode ))
  1634. {
  1635. printf("Hey! it's not a regular file\n");
  1636. return -1;
  1637. }
  1638.  
  1639. // 3. and check if permission OK.
  1640. int i = 0;
  1641. for(;i < 10; i++)
  1642. {
  1643. //fd[i] is not NULL fd[i]->pointer is equal to INode of the path fd[i] is greater than 0
  1644. if ((running->fd[i] != 0 ) && (running->fd[i]->inodeptr == mip) && (running->fd[i]->mode>0))
  1645. {
  1646. printf("Hey! You opened the file already\n");
  1647. return -1;
  1648. }
  1649. }
  1650.  
  1651. // 4. Allocate a free OpenFileTable and fill in values
  1652. OFT* oftp = malloc(sizeof(OFT));
  1653. int index = falloc(oftp);
  1654.  
  1655. if (index == -1)
  1656. {
  1657. printf("Hey! no open file slot available\n");
  1658. return -1;
  1659. }
  1660.  
  1661. // If you reach here, then there is file descriptor slot
  1662. // 5. implement everything to oftp
  1663. oftp->mode = mode-48; // Set mode
  1664. oftp->refCount = 1;
  1665. oftp->inodeptr = mip;
  1666.  
  1667. // 6. Depending on the open mode 0|1|2|3, set the OFT's offset accordingly:
  1668. switch (oftp->mode)
  1669. {
  1670. case 0:
  1671. case 1:
  1672. case 2:
  1673. oftp->offset = 0; // All first three needs to initialize offset to 0
  1674. break;
  1675. case 3:
  1676. oftp->offset = mip->INODE.i_size;
  1677. break;
  1678. default:
  1679. printf("invalid node\n");
  1680. running->fd[index]=0;
  1681. return -1;
  1682. }
  1683.  
  1684. mip->INODE.i_atime = mip->INODE.i_mtime = time(0L); // Touch mtime and atime
  1685. mip->dirty = 1; // Make it dirty
  1686. return index;
  1687. }
  1688.  
  1689. // CLoses file given file descriptor fd
  1690. int close_file(int fd)
  1691. {
  1692. MINODE* mip;
  1693.  
  1694. // 1. Check if it's NULL
  1695. if (running->fd[fd]==NULL)
  1696. {
  1697. printf("Error: File descriptor not found \n");
  1698. return -1;
  1699. }
  1700. // There's 10 FDs from 0 to 9
  1701. // 2. Check for within fd's array
  1702. if (fd < 0 || fd >= 10)
  1703. {
  1704. printf("Error: Invalid File descriptor \n");
  1705. return -1;
  1706. }
  1707. // 3. Check for syntax
  1708. if (fd == -48)
  1709. {
  1710. printf("SYNTAX: close [fd (as int)]\n");
  1711. return -1;
  1712. }
  1713.  
  1714. OFT* oftp = running->fd[fd];
  1715. running->fd[fd] = 0; // Close it
  1716. oftp->refCount--; // Decrement reference count
  1717.  
  1718. if (oftp->refCount > 0) // It exists
  1719. {
  1720. return 0;
  1721. }
  1722. else
  1723. {
  1724. mip = oftp->inodeptr;
  1725. iput(mip);
  1726. }
  1727. return 0;
  1728. }
  1729.  
  1730. int read_file(int fd, int bytes)
  1731. {
  1732. if (fd < 0 || fd >= 10)
  1733. {
  1734. printf("read: syntax is fd followed by bytes\n");
  1735. return -1;
  1736. }
  1737. if (running->fd[fd] == NULL)
  1738. {
  1739. printf("Error: must select a valid file descriptor\n");
  1740. return -1;
  1741. }
  1742. if ((running->fd[fd]->mode != 0) && (running->fd[fd]->mode != 2))
  1743. {
  1744. printf("read: error fd is not set to read\n");
  1745. return -1;
  1746. }
  1747.  
  1748. return myread(fd,read_buff,bytes);
  1749. }
  1750.  
  1751. // read nbytes from fd to buf[ ], and returns the actual number of bytes read.
  1752. int myread(int fd,char* m_buff,long nbytes)
  1753. {
  1754. int is_indirect = 0, is_double_indirect = 0, count = 0;
  1755. char indir_buff[1024], dblindir_buff[1024];
  1756. long * indirect, * dblindirect;
  1757. long indblk, dblindblk, eloop = 0;
  1758.  
  1759. // The number of bytes still available in file.
  1760. long avil = running->fd[fd]->inodeptr->INODE.i_size - running->fd[fd]->offset;
  1761. long lbk, startByte = 0, blk;
  1762.  
  1763. while (nbytes && avil) // While there are still bytes in the file
  1764. {
  1765. // 1. Compute LOGICAL BLOCK number lbk and startByte in that block from offset
  1766. lbk = running->fd[fd]->offset / BLOCK_SIZE;
  1767. startByte = running->fd[fd]->offset % BLOCK_SIZE;
  1768.  
  1769. // 2. Get block from 1 of 3 cases:
  1770. if (lbk < 12) // CASE 1: lbk is a direct block
  1771. {
  1772. blk = running->fd[fd]->inodeptr->INODE.i_block[lbk];
  1773. }
  1774. else if (lbk >= 12 && lbk < 256+12) // CASE 2: indirect blocks
  1775. {
  1776. if (!is_indirect)
  1777. {
  1778. get_block(running->fd[fd]->inodeptr->dev,running->fd[fd]->inodeptr->INODE.i_block[13],indir_buff);
  1779. is_indirect = 1;
  1780. }
  1781. indirect = (long *)buf;
  1782. blk = * (indirect+(lbk-12));
  1783.  
  1784. }
  1785. else // CASE 3: double indirect blocks
  1786. {
  1787. if (!is_double_indirect) // First time always catches
  1788. {
  1789. get_block(running->fd[fd]->inodeptr->dev,running->fd[fd]->inodeptr->INODE.i_block[14],dblindir_buff);
  1790. is_double_indirect = 1;
  1791. }
  1792. dblindirect = (long *)dblindir_buff;
  1793. if (eloop != *(dblindirect+((lbk - 268) / 256)))
  1794. {
  1795. eloop = *(dblindirect+((lbk - 268) / 256));
  1796. get_block(running->fd[fd]->inodeptr->dev, eloop, indir_buff);
  1797. }
  1798.  
  1799. indirect = (long *)buf;
  1800. blk = *(indirect+((lbk - 268) % 256));
  1801. }
  1802.  
  1803. // 3. get the data block into readbuf[BLKSIZE]
  1804. get_block(running->fd[fd]->inodeptr->dev,blk,read_buff);
  1805.  
  1806. char *cq = buf;
  1807. // 4. copy from startByte to buf[ ], <= amount of remaining bytes in this block
  1808. char *cp = read_buff + startByte;
  1809. int remain = BLOCK_SIZE - startByte; // number of bytes remain in readbuf[]
  1810.  
  1811. while (remain > 0)
  1812. {
  1813. printf("%c", *cp);
  1814. *cq++ = *cp++; // copy byte from readbuf[] into buf[]
  1815. running->fd[fd]->offset++; // advance offset
  1816. count++; // inc count as number of bytes read
  1817. avil--; nbytes--; remain--;
  1818. if (nbytes <= 0 || avil <= 0)
  1819. printf("\n");
  1820. break;
  1821. }
  1822. }
  1823. printf("\n");
  1824. //printf("\nread : read %d char from file %d\n", count,fd);
  1825. return count; // count is the actual number of bytes read
  1826. }
  1827.  
  1828. int write_file(char *pfd, char *pstring)
  1829. {
  1830. int writefd = pfd[0] - 48;
  1831. if ((writefd < 0)||(writefd > 9)) {
  1832. printf("write: syntax is write (fd)\n");
  1833. return -1;
  1834. }
  1835. char string[1024];
  1836.  
  1837. strcpy(string, pstring);
  1838. string[strlen(string)] = 0;
  1839.  
  1840. if (running->fd[writefd]->mode == 0)
  1841. {
  1842. printf("write: error fd is not set to write\n");
  1843. return -1;
  1844. }
  1845. int nbytes = strlen(string);
  1846.  
  1847. return(mywrite(writefd, string, nbytes));
  1848.  
  1849. }
  1850.  
  1851. int mywrite(int fd, char *fbuf, int nbytes)
  1852. {
  1853. char wbuf[1024], indir_buff[1024], dblindir_buff[1024];
  1854. long * indirect, * dblindirect;
  1855. long eloop = 0, indblk, dblindblk, lbk, startByte, blk;
  1856. int count = 0, remain = 0, is_indirect = 0, is_double_indirect = 0;
  1857.  
  1858. OFT *oftp = running->fd[fd];
  1859. MINODE *mip = running->fd[fd]->inodeptr;
  1860.  
  1861. while (nbytes > 0)
  1862. {
  1863. // 1. Compute LOGICAL BLOCK number lbk and startByte in that block from offset
  1864. lbk = oftp->offset / BLOCK_SIZE;
  1865. startByte = oftp->offset % BLOCK_SIZE;
  1866.  
  1867. // 2. Get block from 1 of 3 cases:
  1868. if (lbk < 12) // CASE 1: lbk is a direct block
  1869. {
  1870. if (mip->INODE.i_block[lbk] == 0) // Block is not there
  1871. {
  1872. mip->INODE.i_block[lbk] = balloc(mip->dev);
  1873. }
  1874. blk = mip->INODE.i_block[lbk];
  1875. }
  1876. else if (lbk >= 12 && lbk < 256+12) // CASE 2: lbk is an indirect block
  1877. {
  1878. if(!is_indirect)
  1879. {
  1880. get_block(mip->dev,mip->INODE.i_block[13],indir_buff);
  1881. is_indirect = 1;
  1882. }
  1883. indirect = (long *)buf;
  1884. blk = *(indirect+(lbk-12));
  1885.  
  1886. }
  1887. else // CASE 3:double indirect block
  1888. {
  1889. if (!is_double_indirect)
  1890. {
  1891. get_block(mip->dev,mip->INODE.i_block[14],dblindir_buff);
  1892. is_double_indirect = 1;
  1893. }
  1894. dblindirect = (long *)dblindir_buff;
  1895. if (eloop != *(dblindirect+((lbk - 268) / 256)))
  1896. {
  1897. eloop = *(dblindirect+((lbk - 268) / 256));
  1898. get_block(mip->dev, eloop, indir_buff);
  1899. }
  1900. indirect = (long *)buf;
  1901. blk = *(indirect+((lbk - 268) % 256));
  1902. }
  1903.  
  1904. // 3. get the data block into readbuf[BLKSIZE]
  1905. get_block(mip->dev, blk, wbuf);
  1906. if(wbuf[0]==0)
  1907. memset(wbuf, 1024, 0);
  1908.  
  1909. char * cq = (char *)fbuf;
  1910. // 4. copy from startByte to buf[ ], <= amount of remaining bytes in this block
  1911. char * cp = wbuf + startByte;
  1912. remain = BLOCK_SIZE - startByte; // number of bytes remain in readbuf[]
  1913.  
  1914. while (remain > 0)
  1915. {
  1916. *cp++ = *cq++;
  1917. nbytes--, remain--;
  1918. count++;
  1919. oftp->offset++;
  1920. if(oftp->offset > mip->INODE.i_size)
  1921. mip->INODE.i_size++;
  1922. if(nbytes <=0)
  1923. break;
  1924. }
  1925. put_block(mip->dev, blk, wbuf);
  1926.  
  1927. }
  1928.  
  1929. mip->dirty = 1;
  1930. iput(mip);
  1931. printf("write %d char into file fd=%d\n",count, fd);
  1932. return nbytes;
  1933. }
  1934.  
  1935. void cat_file(char *filename)
  1936. {
  1937. // 1. Open file to read
  1938. int catfd = open_file(filename, '0');
  1939.  
  1940. if(catfd == -1){
  1941. printf("file is open already!!\n");
  1942. return;
  1943. }
  1944. int n=0;
  1945. // 2. Read contents
  1946. while( (n=read_file(catfd, 1024))){
  1947. }
  1948. printf("\n");
  1949.  
  1950. // 3. close(fd);
  1951. close_file(catfd);
  1952. }
  1953.  
  1954. // Seeks to a certain offset in an open file
  1955. int lseek_file(int fd, long position)
  1956. {
  1957. long original_offset;
  1958.  
  1959. if (fd == -48)
  1960. {
  1961. printf("SYNTAX: lseek [fd (as int)] [offset (as long)]\n");
  1962. return -1;
  1963. }
  1964. if (position > running->fd[fd]->inodeptr->INODE.i_size)
  1965. {
  1966. printf("ERROR: File length overrun\n");
  1967. return -1;
  1968. }
  1969. else if(position < 0)
  1970. {
  1971. printf("ERROR: Cannot Lseek a negitive number\n");
  1972. return -1;
  1973. }
  1974. original_offset = running->fd[fd]->offset; // Set original to open file offset
  1975. running->fd[fd]->offset = position-1; // Set offset to pos - 1
  1976.  
  1977. return original_offset; // Return
  1978. }
  1979.  
  1980. // Deletes the child of a minode with name name
  1981. int deleteChild(MINODE* pip,char* name) {
  1982. get_block(fd,pip->INODE.i_block[0],buf);
  1983.  
  1984. char* cp = buf;
  1985. DIR* dp = (DIR *) buf;
  1986. int flag, last = 0, tmp, i = 0;
  1987. char* endcp = buf;
  1988.  
  1989.  
  1990.  
  1991. // Traverse to end of buffer
  1992. while(endcp+dp->rec_len < buf +1024) {
  1993. endcp += dp->rec_len;
  1994. dp = (DIR *)endcp;
  1995. }
  1996.  
  1997. dp =(DIR *) cp;
  1998.  
  1999. while (cp < buf+1024)
  2000. {
  2001. if (dp->name_len == strlen(name))
  2002. {
  2003. // Compares name with dp->name but only up to the name_length
  2004. if (strncmp(name, dp->name, dp->name_len) == 0) // Delete file
  2005. {
  2006. tmp = dp->rec_len; // First, store rec_len in tmp
  2007.  
  2008. if (cp == endcp) // If it's at the end
  2009. {
  2010. dp = (DIR *) last;
  2011. dp->rec_len += tmp; // Increment rec_length by tmp
  2012. break;
  2013. }
  2014. else
  2015. {
  2016. dp = (DIR *) endcp;
  2017. dp->rec_len += tmp;
  2018. memcpy(cp, cp+tmp, 1024-i-tmp);
  2019. }
  2020. break;
  2021. }
  2022. }
  2023.  
  2024. last = (int)cp;
  2025. i += dp->rec_len;
  2026. cp += dp->rec_len;
  2027. dp = (DIR *)cp;
  2028. }
  2029. put_block(fd,pip->INODE.i_block[0],buf);
  2030.  
  2031. return 0;
  2032. }
  2033.  
  2034. int rm_file(char* path)
  2035. {
  2036. char parentdir[64], name[64], *cp, *endcp, *last;
  2037. DIR * dp;
  2038. MINODE * pip, *targetip;
  2039. int parent, target;
  2040.  
  2041. if (path[0] == '\0') // If the path is null probably if user forgets
  2042. {
  2043. printf("Syntax: rm [path]\n");
  2044. return -1;
  2045. }
  2046.  
  2047. cp = strrchr(path, '/'); // Returns a pointer to the last occurance of character in the string
  2048.  
  2049. if (!cp) // No occurance of /
  2050. {
  2051. parent = running->cwd->ino;
  2052. strcpy(name,path);
  2053. }
  2054. else
  2055. {
  2056. *(cp) = '\0';
  2057. strcpy(parentdir, path); // Copy path to parent directory
  2058. parent = getino(fd, parentdir); // Set parent to parent directory inode
  2059. strcpy(name, cp+1);
  2060. }
  2061. target = getino(fd,path);
  2062.  
  2063. // Check if the file exists
  2064. if (parent == 0 || target == 0)
  2065. {
  2066. printf("rm: file does not exist\n");
  2067. return -1;
  2068. }
  2069.  
  2070. pip = iget(fd,parent);
  2071. targetip = iget(fd,target);
  2072.  
  2073. // If it's not a regular file
  2074. if ((targetip->INODE.i_mode & 0100000) != 0100000)
  2075. {
  2076. iput(pip);
  2077. printf("rm: cannot remove non-regular file\n");
  2078. return -1;
  2079. }
  2080.  
  2081. // Truncate for MINODE
  2082. targetip->INODE.i_size = 0; // Set targetip size to 0
  2083. targetip->INODE.i_atime = targetip->INODE.i_mtime = time(0L); // Touch time
  2084. targetip->dirty = 1; // Mark targetip dirty
  2085.  
  2086. iput(targetip);
  2087. idealloc(fd,targetip->ino);
  2088. deleteChild(pip,name);
  2089.  
  2090. printf("rm: removed file '%s'\n", name);
  2091. return 0;
  2092. }
  2093.  
  2094. // Deallocates ALL the data blocks
  2095. void truncate(INODE *mip)
  2096. {
  2097. int i = 0;
  2098. for(; i < 15; i++)
  2099. {
  2100. if(mip->i_block[i] == 0)
  2101. return;
  2102. mip->i_block[i] = 0;
  2103. }
  2104. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement