Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "type.h"
- void init()
- {
- int i = 0;
- printf("Enter init.\n");
- //(1)
- P0.uid = 0; //root
- P1.uid = 1;
- P1.cwd = P0.cwd = 0;
- /*(2) running = P0;*/
- running = &P0;
- P0.nextProcPtr = &P1;
- P1.nextProcPtr = &P0;
- //(3)
- for(i = 0; i<NFD; i++)
- {
- P0.fd[i] = P1.fd[i] = 0;
- }
- //last part of (1).
- for(i = 0; i<100;i++)
- {
- minode[i].refCount = minode[i].dev = minode[i].ino = 0;
- }
- //(5)
- root = 0;
- printf("Exit init.\n");
- }
- int get_block(int fd, unsigned long blk, char buf[ ])
- {
- lseek(fd, (long)blk*BLOCK_SIZE, SEEK_SET);
- read(fd, buf, BLOCK_SIZE);
- }
- int put_block(int fd, int blk, char buf[ ])
- {
- lseek(fd, blk*BLOCK_SIZE, SEEK_SET);
- write(fd, buf, BLOCK_SIZE);
- }
- char *basename(char *pathname)
- {
- char *dirtok = 0;
- char *rettok = 0;
- if(pathname != 0)
- {
- dirtok = strtok(pathname, "/");
- do
- {
- rettok = dirtok;
- dirtok = strtok(NULL, "/");
- }while(dirtok != NULL);
- return rettok;
- }
- }
- void mount_root()
- {
- printf("Enter mount_root.\n");
- MINODE *temp = 0;
- dev = fd = open(disk, O_RDWR); //dev is the disk fd
- get_block(fd, 1, buf);
- sp = (SUPER *) buf;
- printf("Checking EXT2 FS: ");
- if(sp->s_magic != 0xEF53)
- {
- printf("FAILED.\n");
- return;
- }
- printf("OK\n");
- nblocks = sp->s_blocks_count;
- ninodes = sp->s_inodes_count;
- get_block(fd, 2, buf);
- gp = (GD *) buf;
- bmap = gp->bg_block_bitmap;
- imap = gp->bg_inode_bitmap;
- inodes_start = gp->bg_inode_table;
- printf("nblocks: %d\nninodes: %d\nbmap: %d\nimap: %d\ninodes_start: %d\n", nblocks, ninodes, bmap, imap, inodes_start);
- root = (MINODE *) iget(dev, 2);
- P0.cwd = (MINODE *) iget(dev, 2);
- P1.cwd = (MINODE *) iget(dev, 2);
- printf("Exit mount_root.\n");
- }
- //If inode is in minode[] array inc ref count and return Minode ptr
- MINODE *iget(int dev, int ino)
- {
- int i = 0, j = 0, block, node;
- MINODE *retPtr = 0;
- //see if there are dup inodes
- for (i = 0; i < 100; i++)
- {
- if(minode[i].ino == ino && minode[i].refCount > 0) // It exists! ++ ref
- {
- minode[i].refCount++;
- retPtr = (MINODE *) &minode[i];
- return retPtr;
- }
- }
- // Find empty Inode
- for (i = 0; i < 100; i++)
- {
- if (minode[i].refCount == 0)
- {
- // 3. Use mailman's
- block = (ino - 1)/8 + inodes_start;
- node = (ino - 1) % 8;
- // read blk into buf[ ];
- get_block(dev, block, buf);
- // 4. let INODE *ip = ( )buf + offset
- ip = (INODE *) buf + node; // Points at INODE in buf[]
- // 5. COPY *ip into mip->INODE
- minode[i].INODE = *(ip);
- minode[i].refCount++;
- minode[i].dev = dev;
- minode[i].ino = ino;
- minode[i].dirty = 0;
- minode[i].mounted = 0;
- minode[i].mountptr = 0;
- retPtr = (MINODE *) &minode[i];
- // 7. return mip
- return retPtr;
- }
- }
- }
- // Remove from minode list
- int iput(MINODE *mip)
- {
- int block, node;
- // 1. dec refCount by 1.
- mip->refCount--;
- // 2. No other refs so dont worry
- if (mip->refCount > 0)
- {
- return 0;
- }
- if (mip->dirty != 1) // no write back
- {
- return 0;
- }
- block = (mip->ino - 1)/8 + inodes_start;
- node = (mip->ino - 1) % 8;
- mip->dirty = 0;
- // Read block into buf
- get_block(mip->dev, block, buf);
- ip = (INODE *) buf + node;
- // 5. Copy mip->INODE into *ip in buf[ ];
- *ip = mip->INODE;
- // 6. write block in the buf back to disk
- put_block(mip->dev, block, buf);
- }
- void printInode(INODE *inode)
- {
- printf("i_mode: %x\n", inode->i_mode);
- printf("i_uid: %d\n", inode->i_uid);
- printf("i_size: %d\n", inode->i_size);
- }
- // Find ino from path
- int getino(int dev, char *pathname)
- {
- char *dirtok, *temp = 0;
- char *cp;
- int i, j, currInode = 1, currBlock, currIno = 1;
- int InodeBeginBlock;
- // read SUPER block
- get_block(dev, 1, buf);
- sp = (SUPER *)buf;
- if (sp->s_magic != 0xEF53)
- {
- printf("NOT an EXT2 FS\n");
- return 1;
- }
- // Group descriptor block
- get_block(dev, 2, buf);
- gp = (GD *)buf;
- // read InodeBeginBLock
- InodeBeginBlock = gp->bg_inode_table;
- // Case 1: cwd no given path
- if (pathname == 0 || !strcmp(pathname, "") || !strcmp(pathname, "/"))
- {
- return running->cwd->ino; // return ino of cwd
- }
- // Case 2: ..
- else if(!strcmp(pathname, ".."))
- { // Mailman's algorithm
- currBlock = (running->cwd->ino - 1)/8 + InodeBeginBlock; // inode begin is offset
- currInode = (running->cwd->ino -1) % 8;
- }
- // Case 3: Not current working directory, not .., and doesn't begin with slash
- else if(pathname[0] != '/')
- { // Mailman's algorithm from InodeBeginBlock search all dirs
- currBlock = (running->cwd->ino-1)/8 + inodes_start;
- currInode = (running->cwd->ino - 1)%8;
- }
- else
- {
- currBlock = InodeBeginBlock;
- }
- temp = malloc(sizeof(char)*(strlen(pathname)+1));
- strcpy(temp, pathname);
- dirtok = (char *) strtok(temp, "/");
- do
- {
- get_block(dev, currBlock, buf);
- ip = (INODE *)buf+currInode;
- currIno = search(dev,ip, dirtok);
- if (currIno != -1)
- {
- currBlock = (currIno - 1)/8 + InodeBeginBlock;
- currInode = (currIno - 1) % 8;
- }
- else
- {
- free(temp);
- return -1;
- }
- }while((dirtok=(char *)strtok(NULL, "/")) && (currIno > 0));
- free(temp);
- return currIno;
- }
- // Finds the name string of myino in the parent's data block
- int search(int dev, INODE *inodePtr, char *name)
- {
- int i = 0, j = 0, k = 0;
- char *cp;
- char temp[BLOCK_SIZE];
- for (; i < 12; i++)
- {
- get_block(dev, inodePtr->i_block[i], buf);
- dp = (DIR *) buf;
- cp = buf;
- while(cp < buf+BLOCK_SIZE && dp->rec_len != 0)
- {
- for (j = 0; j < dp->name_len; j++)
- {
- temp[j] = dp->name[j];
- }
- temp[j] = '\0';
- //printf("%s\n", temp);
- if (strcmp(name, temp) == 0)
- {
- printf("Found %s at ino %d\n", name, dp->inode);
- return dp->inode;
- }
- cp += dp->rec_len;
- dp = (DIR *) cp;
- }
- }
- printf("Could not find \'%s\'\n", name);
- return -1;
- }
- void ls(char *pathname)
- {
- MINODE *mip;
- int ino, nchars;
- NODE *temp;
- LIST *namelist;
- char *path;
- // Case 1: Pathname is empty or root
- if(!strcmp(pathname, "") || !strcmp(pathname, "/"))
- {
- ino = getino(dev, pathname);
- }
- else
- { // Case 2: First character of pathname is not /, nor is the pathname . or ..
- if(pathname[0] != '/' && strcmp(pathname, ".") != 0 && strcmp(pathname, "..") != 0)
- {
- namelist = (LIST *) malloc(sizeof(LIST));
- done_flag = 0;
- recur_bp(root->ino, namelist);
- nchars = list_size(namelist) + strlen(pathname);
- path = (char *) malloc(sizeof(char) * nchars);
- strcpy(path, "/");
- temp = namelist->head;
- while(temp != 0)
- {
- strcat(path, temp->name);
- strcat(path, "/");
- temp = temp->nxt;
- }
- strcat(path, pathname);
- strcat(path, "\0");
- printf("%s\n", path);
- ino = getino(dev, path);
- free(namelist);
- }
- else
- // Case 3: It's a path starting with a /
- ino = getino(dev, pathname);
- }
- // If successful
- if(ino != -1)
- {
- mip = iget(dev, ino);
- // If it's a dir
- if(mip->INODE.i_mode & 0040000 == 0040000)
- {
- list_dir(mip);
- }
- // If it's a file
- else
- {
- list_file(mip, pathname);
- }
- iput(mip);
- }
- }
- int list_dir(MINODE *mip)
- {
- MINODE *cip;
- INODE *ip = &mip->INODE;
- int i = 0, j = 0, k = 0;
- char *cp;
- char temp[BLOCK_SIZE];
- char tname[64];
- for (; i < 12; i++) // ASSUME DIRs only has 12 direct blocks
- {
- if (mip->INODE.i_block[i] != 0)
- {
- printf("Data block: %d\n", i);
- }
- get_block(dev, mip->INODE.i_block[i], temp);
- dp = (DIR *) temp;
- cp = temp;
- // Print dp->inode, dp->rec_len, dp->name_len, dp->name);
- while(cp < temp + BLOCK_SIZE && dp->rec_len != 0)
- {
- for(j = 0; j < dp->name_len && dp->name_len < 64; j++)
- {
- tname[j] = dp->name[j];
- }
- tname[j] = '\0';
- cip = iget(dev, dp->inode);
- list_file(cip, tname);
- cp+=dp->rec_len;
- dp = (DIR *) cp;
- iput(cip);
- }
- }
- }
- int list_file(MINODE *mip, char *name)
- {
- INODE *ip = &mip->INODE;
- int i, j;
- char *time;
- char syms[3] = {'r', 'w', 'x'};
- if ((ip->i_mode & 040000) == 040000)
- {
- putchar('d');
- }
- else if ((ip->i_mode & 0120000) == 0120000)
- {
- putchar('l');
- }
- else
- {
- putchar('-');
- }
- for (i = 8, j = 0; i >= 0; i--, j++)
- {
- if (j > 2)
- {
- j = 0;
- }
- if (ip->i_mode & (1 << i))
- {
- printf("%c", syms[j]);
- }
- else
- {
- putchar('-');
- }
- }
- printf(" %d %d %d %d\t", ip->i_links_count, ip->i_gid, ip->i_uid, (int) ip->i_size);
- time = (char *) ctime(&ip->i_mtime);
- time[strlen(time)-1] = 0;
- printf("%s", time);
- printf(" %s", basename(name));
- if((ip->i_mode & 0120000) == 0120000)
- {
- printf(" -> %s", (char *)ip->i_block);
- }
- putchar('\n');
- }
- void cd(char *pn)
- {
- int ino, nchars;
- MINODE *mip;
- char *path;
- if(!strcmp(pn, "") || !strcmp(pn, "/"))
- {
- ino = root->ino;
- }
- else
- {
- if(pn[0] != '/' && strcmp(pn, ".") != 0 && strcmp(pn, "..") != 0)
- {
- path = my_cwd();
- path = realloc(path, sizeof(char)*(strlen(pn)+1));
- strcat(path, pn);
- ino = getino(dev, path);
- }
- else
- {
- ino = getino(dev, pn);
- }
- }
- mip = iget(dev, ino);
- if((mip->INODE.i_mode & 040000) == 040000)
- {
- iput(running->cwd);
- running->cwd = iget(dev, ino);
- printf("Set running->cwd to: %d\n", running->cwd->ino);
- }
- else
- {
- printf("\'%s\' is not a directory. i_mode: %x\n", pn, mip->INODE.i_mode);
- }
- iput(mip);
- }
- int list_size(LIST *namelist)
- {
- int count = 0;
- NODE *currNode;
- if(namelist->head != 0)
- {
- currNode = namelist->head;
- while(currNode != 0)
- {
- count+=strlen(currNode->name)+1;
- currNode = currNode->nxt;
- }
- count+=2;
- }
- return count;
- }
- void recur_bp(int currInode, LIST *namelist)
- {
- char temp[BLOCK_SIZE], tname[64];
- int i, j, block, node;
- char *cp;
- DIR *ndp; INODE *nip;
- block = (currInode - 1)/8 + inodes_start;
- node = (currInode - 1)%8;
- get_block(dev, block, temp);
- nip = (INODE *) temp + node;
- for(i = 0; i < 12; i++)
- {
- get_block(dev, nip->i_block[i], temp);
- ndp = (DIR *) temp;
- cp = temp;
- if(i == 0 && ndp->rec_len != 0)
- {
- cp+=ndp->rec_len;
- ndp = (DIR *) cp;
- cp += ndp->rec_len;
- ndp = (DIR *) cp;
- }
- while(cp < temp + BLOCK_SIZE && ndp->rec_len != 0 && !done_flag)
- {
- if(ndp->file_type == 2)
- {
- for(j = 0; j < ndp->name_len; j++)
- {
- tname[j] = ndp->name[j];
- }
- tname[j] = '\0';
- add(tname, namelist);
- if(ndp->inode == running->cwd->ino)
- {
- done_flag = 1;
- }
- if(!done_flag)
- {
- recur_bp(ndp->inode, namelist);
- if(!done_flag)
- {
- delete_item(namelist);
- }
- }
- }
- cp+=ndp->rec_len;
- ndp = (DIR *) cp;
- }
- }
- }
- char *printpath(LIST *namelist)
- {
- NODE *currNode = namelist->head;
- char *path = 0;
- if(currNode != 0)
- {
- path = (char *) malloc(sizeof(char)*(strlen(currNode->name) + 3));
- strcpy(path, "/");
- strcat(path, currNode->name);
- strcat(path, "/");
- currNode = currNode->nxt;
- }
- while(currNode != 0)
- {
- path = (char *) realloc(path, sizeof(char)*(strlen(currNode->name)+1));
- strcat(path, currNode->name);
- strcat(path, "/");
- currNode = currNode->nxt;
- }
- return path;
- }
- void stack_add(char* name, LIST *namelist)
- {
- NODE *newNode = (NODE *) malloc(sizeof(NODE));
- strcpy(newNode->name, name);
- newNode->nxt = 0;
- newNode->prv = 0;
- if(namelist->head == 0)
- {
- namelist->head = newNode;
- namelist->tail = newNode;
- }
- else
- {
- //printf("Adding: %s\n", name);
- newNode->nxt = namelist->head;
- namelist->head->prv = newNode;
- namelist->head = newNode;
- }
- }
- void add(char* name, LIST *namelist)
- {
- NODE *newNode = (NODE *) malloc(sizeof(NODE));
- strcpy(newNode->name, name);
- newNode->nxt = 0;
- newNode->prv = 0;
- if(namelist->head == 0)
- {
- namelist->head = newNode;
- namelist->tail = newNode;
- }
- else
- {
- //printf("Adding: %s\n", name);
- namelist->tail->nxt = newNode;
- newNode->prv = namelist->tail;
- namelist->tail = newNode;
- }
- }
- void delete_item(LIST *namelist)
- {
- NODE *temp;
- if(namelist->head == 0)
- return;
- else if(namelist->head == namelist->tail)
- {
- namelist->tail = 0;
- namelist->head = 0;
- }
- else
- {
- temp = namelist->tail;
- namelist->tail = namelist->tail->prv;
- namelist->tail->nxt = 0;
- //printf("Removing: %s\n", temp->name);
- free(temp);
- }
- }
- char *my_cwd()
- {
- LIST *namelist = (LIST *) malloc(sizeof(LIST));
- int nextIno, currIno, oldIno = running->cwd->ino, block, node, i, j, done = -1;
- char name[64], tbuf[BLKSIZE], *cp, *path = 0;
- currIno = oldIno;
- namelist->head = namelist->tail = 0;
- //if empty
- if(oldIno == 2)
- {
- path = malloc(sizeof(char)*2);
- strcpy(path,"/");
- return path;
- }
- else
- {
- while(done < 1)
- {
- // Locate inode using Mailman's
- block = (currIno - 1)/8 + inodes_start;
- node = (currIno - 1)%8;
- get_block(dev, block, tbuf);
- ip = (INODE *) tbuf + node;
- for(i = 0; i < 12; i++)
- {
- if(ip->i_block[i] == 0)
- break;
- get_block(dev, ip->i_block[i], tbuf);
- dp = (DIR *) tbuf;
- cp = tbuf;
- // get to last entry in block
- while(cp < tbuf + BLKSIZE && dp->rec_len != 0)
- {
- for(j = 0; j < dp->name_len; j++)
- {
- name[j] = dp->name[j];
- }
- name[j] = '\0';
- if(!strcmp(name, "..")) // If ..
- {
- if(currIno == dp->inode)
- done = 1;
- nextIno = dp->inode;
- if(done == -1)
- {
- done++;
- currIno = nextIno;
- break;
- }
- }
- else if((dp->inode == oldIno && strcmp(name, ".") != 0)) // If not .
- {
- oldIno = currIno;
- currIno = nextIno;
- stack_add(name, namelist);
- break;
- }
- cp += dp->rec_len;
- dp = (DIR *) cp;
- }
- }
- }
- path = printpath(namelist);
- }
- free(namelist);
- return path;
- }
- void get_dirname(char *pathname)
- {
- char *tok;
- char *temp = malloc(sizeof(char)*(strlen(pathname)+1));
- char last[64] = {'\0'};
- strcpy(temp, pathname);
- tok = strtok(temp, "/");
- dir[0] = '/';
- dir[1] = '\0';
- if(pathname != 0)
- {
- strcat(last, tok);
- while(tok = strtok(NULL, "/"))
- {
- if(tok != 0)
- {
- strcat(dir, last);
- strcat(dir, "/");
- }
- strcpy(last, tok);
- }
- }
- free(temp);
- }
- void get_basename(char *pathname)
- {
- char *temp = malloc(sizeof(char)*(strlen(pathname)+1));
- char *tok;
- strcpy(temp, pathname);
- tok = strtok(temp, "/");
- base[0] = '\0';
- //printf("base-pathname: %s\n", pathname);
- while(tok != NULL)
- {
- strcpy(base, tok);
- tok = strtok(NULL, "/");
- }
- free(temp);
- }
- int mycreat(MINODE *pip, char *name)
- {
- /*
- - INODE's file type = 0x81A4 OR 0100644 regfile
- - links_count = 1
- - size = 0
- - do NOT inc parent's link count.
- */
- int ino = ialloc(dev), i;
- char mbuf[BLKSIZE];
- MINODE *mip = iget(dev, ino);
- INODE *cip = &mip->INODE;
- DIR *mdp;
- char *mcp;
- //---------given code--------
- cip->i_mode = 0x81a4;
- cip->i_uid = running->uid;
- cip->i_gid = running->gid;
- cip->i_size = 0; // NO data block, so size = 0
- cip->i_links_count = 1; // links_count = 1
- cip->i_atime = cip->i_ctime = cip->i_mtime = time(0L);
- cip->i_blocks = 0;
- cip->i_block[0] = 0;
- for(i = 1; i < 15; i++)
- {
- cip->i_block[i] = 0;
- }
- mip->dirty = 1;
- mip->dev = dev;
- iput(mip);
- enter_name(pip, ino, name);
- return ino;
- }
- int mymkdir(MINODE *pip, char *name)
- {
- //allocate an inode and a disk block for the new directory
- int ino = ialloc(dev);
- int bno = balloc(dev), i;
- char mbuf[BLKSIZE];
- MINODE *mip = iget(dev, ino); // To load the inode to minode
- INODE *cip = &mip->INODE;
- DIR *mdp;
- char *mcp;
- //writing contents to the INODE in memory
- //---------given code--------
- cip->i_mode = 0x41ed;
- cip->i_uid = running->uid; //owner UID
- cip->i_gid = running->gid; //group id
- cip->i_size = BLKSIZE; //size if bytes
- cip->i_links_count = 2; //link count=2 because of . and ..
- cip->i_atime = cip->i_ctime = cip->i_mtime = time(0L); //set to current time
- cip->i_blocks = 2; //LINUX: Block # in 512-byte chucks
- cip->i_block[0] = bno;
- for(i = 1; i < 15; i++)// for the last i_block array identifyer end
- {
- cip->i_block[i] = 0;
- }
- mip->dirty = 1; // minode dirty
- mip->dev = dev;
- iput(mip); // Write INODE to disk
- //----end-------
- mdp = (DIR *) mbuf;
- mcp = mbuf;
- // Write . into buf
- mdp->inode = root->ino;
- mdp->rec_len = 12;
- mdp->name_len = 1;
- mdp->name[0] = '.';
- // Write .. into buf
- mcp += mdp->rec_len;
- mdp = (DIR *) mcp;
- mdp->inode = pip->ino;
- mdp->rec_len = 1012;
- mdp->name_len = 2;
- mdp->name[0] = '.';
- mdp->name[1] = '.';
- // Write buf to the disk block bno
- put_block(dev, bno, mbuf);
- // Enter name ENTRY into parent's directory
- enter_name(pip, ino, name);
- }
- int enter_name(MINODE *pip, int myino, char *myname)
- {
- int lastRecLen = 0, remain, currNode, currBlock, ideal_len = 4*((11+strlen(myname))/4), i, j;
- char mbuf[BLKSIZE];
- INODE *mip;
- DIR *mdp;
- char *mcp;
- // 12 direct block, for each....
- for(i = 0; i < 12; i++)
- {
- if(pip->INODE.i_block[i] == 0)
- {
- printf("Data block %d was null\n", i);
- break;
- }
- else
- {
- // Get parent's ith data block into a buf
- get_block(dev, pip->INODE.i_block[i], mbuf);
- mdp = (DIR *) mbuf;
- mcp = mbuf;
- // Step to LAST entry in block: int blk = parent->INODE.i_block[i]
- while(mcp < mbuf + BLKSIZE && mdp->rec_len != 0)
- {
- if(mcp + mdp->rec_len >= mbuf + BLKSIZE)
- break;
- mcp += mdp->rec_len; // increment
- mdp = (DIR *) mcp; //keep changing this as mcp goes up. haha
- } //dp or (mdp) now points at last entry in block
- lastRecLen = mdp->rec_len;
- remain = lastRecLen - 4*((11+mdp->name_len)/4); // Each entry's ideal length is 4
- // let remain = Last entry's rec_len - it's IDEAL_LENGTH
- if(remain >= ideal_len)
- {
- //enter the new entry as the last entry and trim the previous entry to its IDEAL_LENGTH
- mdp->rec_len = 4*((11+mdp->name_len)/4);//update new length for entry
- mcp += mdp->rec_len;
- mdp = (DIR *) mcp;
- //
- //
- // |LAST entry
- // --|-4---2----2--|----|---------|--------- rlen ->------------------------|
- // |ino rlen nlen NAME|.........|ino rlen nlen|NAME |
- // --------------------------------------------------------------------------
- // | NEW entry
- // --|-4---2----2--|----|---------|----ideal_len-----|--- rlen=remain ------|
- // |ino rlen nlen NAME|.........|ino rlen nlen|NAME|myino rlen nlen myname|
- //
- mdp->inode = myino;
- mdp->rec_len = remain;
- mdp->name_len = strlen(myname);
- for(j = 0; j < strlen(myname); j++){
- mdp->name[j] = myname[j];
- }
- put_block(dev, pip->INODE.i_block[i], mbuf);
- return 0;
- }
- }
- }
- // Reach here mean: NO space in existing data blocks
- // Allocate a new data block
- pip->INODE.i_block[i] = balloc(dev);
- strcpy(mbuf, "\0");
- mdp = (DIR *) mbuf;
- mdp->inode = myino;
- mdp->rec_len = 1024;
- mdp->name_len = strlen(myname);
- for(j = 0; j < strlen(myname); j++)
- {
- mdp->name[j] = myname[j];
- }
- pip->INODE.i_size += 1024; // INC parent's isze by 1024;
- // enter new entry as the first entry in the new data block with rec_len= BLKSIZE
- put_block(dev, pip->INODE.i_block[i], mbuf);
- return 1;
- }
- int tst_bit(char *buf, int bit)
- {
- int i, j;
- i = bit/8; j=bit%8;
- if (buf[i] & (1 << j))
- return 1;
- return 0;
- }
- int set_bit(char *buf, int bit)
- {
- int i, j;
- i = bit/8; j=bit%8;
- buf[i] |= (1 << j);
- }
- int clr_bit(char *buf, int bit)
- {
- int i, j;
- i = bit/8; j=bit%8;
- buf[i] &= ~(1 << j);
- }
- int decFreeInodes(int dev)
- {
- char buf[BLKSIZE];
- // dec free inodes count in SUPER and GD
- get_block(dev, 1, buf);
- sp = (SUPER *)buf;
- sp->s_free_inodes_count--;
- put_block(dev, 1, buf);
- get_block(dev, 2, buf);
- gp = (GD *)buf;
- gp->bg_free_inodes_count--;
- put_block(dev, 2, buf);
- }
- // Allocates a FREE inode number
- int ialloc(int dev)
- {
- int i;
- char buf[BLKSIZE];
- // read inode_bitmap block
- get_block(dev, imap, buf);
- for (i = 0; i < ninodes; i++)
- {
- if (tst_bit(buf, i) == 0)
- {
- set_bit(buf,i);
- decFreeInodes(dev);
- put_block(dev, imap, buf);
- return i+1;
- }
- }
- printf("ialloc(): no more free inodes\n");
- return 0;
- }
- // Deallocate an ino
- int idealloc(int dev, int ino)
- {
- int i;
- char buf[BLKSIZE];
- get_block(dev, imap, buf);
- clr_bit(buf, ino-1);
- get_block(dev, 1, buf);
- sp = (SUPER *) buf;
- sp->s_free_inodes_count++;
- put_block(dev, 1, buf);
- get_block(dev, 2, buf);
- gp = (GD *) buf;
- gp->bg_free_inodes_count++;
- put_block(dev, 2, buf);
- }
- // Allocates a FREE block number
- int balloc(int dev)
- {
- int i;
- char buf[BLKSIZE];
- // read block_bitmap block
- get_block(dev, bmap, buf);
- for (i = 0; i < nblocks; i++)
- {
- if (tst_bit(buf, i) == 0)
- {
- set_bit(buf,i);
- decFreeBlocks(dev);
- put_block(dev, bmap, buf);
- return i+1;
- }
- }
- printf("balloc(): no more free blocks\n");
- return 0;
- }
- // Deallocate a bno
- int bdealloc(int dev, int bno)
- {
- char buf[BLKSIZE];
- get_block(dev, bmap, buf);
- clr_bit(buf, bno-1);
- get_block(dev, 1, buf);
- sp = (SUPER *)buf;
- sp->s_free_blocks_count++;
- put_block(dev, 1, buf);
- get_block(dev, 2, buf);
- gp = (GD *)buf;
- gp->bg_free_blocks_count++;
- put_block(dev, 2, buf);
- }
- int decFreeBlocks(int dev)
- {
- char buf[BLKSIZE];
- // dec free inodes count in SUPER and GD
- get_block(dev, 1, buf);
- sp = (SUPER *)buf;
- sp->s_free_blocks_count--;
- put_block(dev, 1, buf);
- get_block(dev, 2, buf);
- gp = (GD *)buf;
- gp->bg_free_blocks_count--;
- put_block(dev, 2, buf);
- }
- // rm_child(): removes the entry [INO rlen nlen name] from parent's data block.
- int rm_child(MINODE *parent, char *name)
- {
- int i = 0, j;
- int x;
- DIR *tdp;
- char temp[64], tbuf[BLKSIZE], *cp, *tcp;
- for (; i < 12; i++)
- {
- if(parent->INODE.i_block[i] == 0)
- break;
- printf("data block: %d\n", i);
- get_block(parent->dev, parent->INODE.i_block[i], tbuf);//every loop , you need to get the block
- dp = (DIR *) tbuf;//typecast to shut up!
- cp = tbuf;
- while (cp < tbuf + BLKSIZE && dp->rec_len != 0)
- {
- for(j = 0; j < dp->name_len; j++)//copy everything to temp, so I can modify temp
- {
- temp[j] = dp->name[j];
- }
- temp[j] = '\0';
- if (!strcmp(name, temp)) //if dp->name is the same as "name" parameter
- {
- // if (first entry in a data block)
- if (BLKSIZE == dp->rec_len)//if the rec_len is the maximun size the block
- {
- printf("deleting block.\n");
- bdealloc(dev, ip->i_block[i]);//deallocate the data block
- parent->INODE.i_size -= BLKSIZE;//modify parent's file size
- //move parent's NONZERO block upward, so that there is no HOLEs in parent's data block numbers
- for(i; i < 11 && ip->i_block[i+1] != 0; i++)
- {
- ip->i_block[i] = ip->i_block[i+1];
- }
- }
- // if NOT first entry in blo
- else if (cp+dp->rec_len == tbuf+BLKSIZE)
- {
- //move all entries AFter this entry Left
- cp = cp - x;
- x = dp->rec_len;
- dp = (DIR *)cp;
- printf("%d //", dp->rec_len);
- dp->rec_len += x;//add rec_len to the Last entry of the block
- printf(" %d\n", dp->rec_len);
- }
- else
- {
- // write the parent's data block back to disk and mark parent minode Dirty for write-back
- tdp = dp;
- tcp = cp;
- x = dp->rec_len;
- cp+=dp->rec_len;
- dp = (DIR *)cp;
- while(cp < tbuf + BLKSIZE && dp->rec_len != 0)
- {
- tdp->name_len = dp->name_len;
- tdp->rec_len = dp->rec_len;
- tdp->inode = dp->inode;
- for(j = 0; j < dp->name_len; j++)
- {
- tdp->name[j] = dp->name[j];
- }
- if(cp+dp->rec_len == tbuf+BLKSIZE)
- {
- tdp->rec_len+=x;
- break;
- }
- cp+=dp->rec_len;
- dp = (DIR *) cp;
- tcp += tdp->rec_len;
- tdp = (DIR *) tcp;
- }
- }
- break;
- }
- x = dp->rec_len;
- cp += dp->rec_len;
- dp = (DIR *) cp;
- }
- put_block(parent->dev, parent->INODE.i_block[i], tbuf);
- }
- }
- // Creates a file newFileName which has the SAME inode (number) as that of oldFileName.
- int link(char *oldFileName, char *newFileName)
- {
- int inoOld, i;
- char *temp = (char *) malloc(sizeof(char)*(strlen(oldFileName) + 1)), *pn = 0;
- MINODE *mip, *pip;
- strcpy(temp, oldFileName);
- //Get the INODE into memory
- //trivial
- inoOld = getino(dev, temp);
- free(temp);
- mip = iget(dev, inoOld);
- //check to see if it is a REG or LNK
- //if it's a DIR //if it's a REG
- if((mip->INODE.i_mode & 0100000) == 0100000 || (mip->INODE.i_mode & 012000 == 012000))
- {
- pn = (char *) malloc(sizeof(char)*(strlen(newFileName) + 1));
- strcpy(pn, newFileName);
- if(pn[0] == '/') // If the first char is a /, go ahead and get dirname on root
- {
- get_dirname(pn); // Get dirname
- }
- else // No /, specify cwd
- {
- free(pn);
- pn = my_cwd(); // Get the "current working directory"
- pn = realloc(pn, sizeof(char)*(strlen(pn)+strlen(newFileName)+1));
- strcat(pn, newFileName); // Copy over the new file name
- get_dirname(pn); // Get dirname
- }
- temp = (char *) malloc(sizeof(char)*(strlen(dir) + 1));
- strcpy(temp, dir); // Store dir name in temp
- i = getino(dev, temp); // Get inode of oldfile
- free(temp);
- if(i == -1) // if it failed to get inode
- {
- printf("dir \'%s\' doesn't exist.\n", dir);
- free(pn);
- return -1;
- }
- pip = iget(dev, i); // remember iget ends with iput
- i = getino(dev, pn);
- if(i != -1) // check /x/y exists and is a DIR but 'z' does not yet exist in /x/y/
- {
- printf("file already exists.\n");
- free(pn);
- iput(pip);
- return -1;
- }
- get_basename(pn);
- enter_name(pip, mip->ino, base); // Enter name ENTRY into parent's directory
- mip->INODE.i_links_count++; // Increment count
- mip->dirty = 1; // Make dirty
- iput(pip);
- free(pn);
- }
- //Back to Disk
- iput(mip);
- }
- int symlink(char *oldName, char *newName)
- {
- int i, ino;
- char *oldPn = 0, *newPn = 0;
- MINODE *mip;
- //////////////////////////////////////////////////////////////////////////////////
- // Verify oldname exists
- oldPn = (char *) malloc(sizeof(char)*(strlen(oldName) + 1));
- strcpy(oldPn, oldName);
- // if it begins with a /, so a specfied location...
- if(oldPn[0] == '/')
- {
- i = getino(dev, oldPn);
- }
- else // looks like it's just name
- {
- free(oldPn);
- oldPn = my_cwd();
- oldPn = realloc(oldPn, sizeof(char)*(strlen(oldPn)+strlen(oldName)+1));
- strcat(oldPn, oldName);
- i = getino(dev, oldPn);
- }
- if(i == -1)//fails to get the inode
- {
- free(oldPn);
- return -1;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Check where user wants newname to be created
- //Get the pathname then set it to the correct name for creat
- newPn = (char *) malloc(sizeof(char)*(strlen(newName) + 1));
- strcpy(newPn, newName);
- if(newPn[0] == '/')
- {
- strcpy(pathname, newPn);
- }
- else
- {
- free(newPn);
- newPn = my_cwd();
- newPn = realloc(newPn, sizeof(char)*(strlen(newPn)+strlen(newName)+1));
- strcat(newPn, newName);
- strcpy(pathname, newPn);
- }
- //Complete
- i = getino(dev, newPn);
- if(i != -1)
- {
- free(newPn);
- return -1;
- }
- /////////////////////////////////////////////////////////////////////////////////
- ino = creat_file();
- mip = iget(dev, ino);
- mip->INODE.i_mode = 0xa1ff;
- mip->INODE.i_size = strlen(oldPn);
- mip->dirty = 1;
- strcpy((char *) mip->INODE.i_block, oldPn);
- //Back to Disc
- iput(mip);
- //proper remove!
- free(newPn);
- free(oldPn);
- return 0;
- }
- int unlink(char* pn)
- {
- if (pn[0]=='\0'){ // Empty pathname
- printf("Syntax: unlink [path]\n");
- return -1;
- }
- char parentdir[64],name[64], *cp, *endcp, *last;
- DIR * dp;
- MINODE * pip,*targetip;
- int parent, target;
- cp = strrchr(pn, '/');
- // 1. Check where the parent is and get the iNode based on cp
- if (!cp){ // In the same directory
- parent = running->cwd->ino; // Set parent to cwd inode
- strcpy(name,pn);
- }
- else{ // In another directory
- *(cp) = '\0';
- strcpy(parentdir, pn);
- parent = getino(fd,parentdir); // Get inode of parentdir, store into parent
- strcpy(name,cp+1);
- }
- target = getino(fd,pn);
- // Check if target file exists
- if ((target==0)||(parent==0)){
- printf("Error: File must exist\n");
- return -1;
- }
- pip = iget(fd,parent);
- targetip = iget(fd,target);
- // 2. If the target exists, make sure it's not a dir...
- if((targetip->INODE.i_mode & 0100000) != 0100000){
- iput(pip);
- printf("Error: Cannot unlink NON-REG files\n");
- return -1;
- }
- // 3. Decrement links count
- targetip->INODE.i_links_count--; // I links count--
- // 4. Clear data with truncate
- if (targetip->INODE.i_links_count == 0)
- {
- // Truncate for MINODE
- targetip->INODE.i_size = 0; // Set targetip size to 0
- targetip->INODE.i_atime = targetip->INODE.i_mtime = time(0L); // Touch time
- targetip->dirty = 1; // Mark targetip dirty
- targetip->refCount++;
- iput(targetip);
- idealloc(fd,targetip->ino);
- }
- else
- {
- iput(targetip);
- }
- return deleteChild(pip,name);
- }
- void mytouch(char *pathname)
- {
- /*
- int ino = getino(fd, pathname);
- MINODE *mip = iget(fd, ino);
- printf("the file is touched\n");
- mip->INODE.i_atime = mip->INODE.i_mtime = time(0L);
- iput(mip);
- */
- unsigned long ino = getino(fd, pathname);
- MINODE *mip = iget(fd, ino);
- mip->INODE.i_atime = mip->INODE.i_mtime = time(0L);
- iput(mip);
- }
- void mystat(char *path){
- struct stat mystat;
- int r = do_stat(path, &mystat);
- return;
- }
- // Print out the stats for a pathname
- // Loads the inode for the path and
- // copies all of its fields to a stat struct
- // then prints those fields
- int do_stat(char *pathname, struct stat *stPtr)
- {
- unsigned long ino = getino(fd, pathname);
- MINODE *mip = iget(fd, ino);
- stPtr->st_dev = fd;
- memcpy(&stPtr->st_ino, &ino, sizeof(ino_t));
- memcpy(&stPtr->st_mode, &mip->INODE.i_mode, sizeof(mode_t));
- memcpy(&stPtr->st_nlink, &mip->INODE.i_links_count, sizeof(nlink_t));
- memcpy(&stPtr->st_uid, &mip->INODE.i_uid, sizeof(uid_t));
- memcpy(&stPtr->st_gid, &mip->INODE.i_gid, sizeof(gid_t));
- memcpy(&stPtr->st_size, &mip->INODE.i_size, sizeof(off_t));
- stPtr->st_blksize = 1024;
- memcpy(&stPtr->st_blocks, &mip->INODE.i_blocks, sizeof(blkcnt_t));
- memcpy(&stPtr->st_atime, &mip->INODE.i_atime, sizeof(time_t));
- memcpy(&stPtr->st_mtime, &mip->INODE.i_mtime, sizeof(time_t));
- memcpy(&stPtr->st_ctime, &mip->INODE.i_ctime, sizeof(time_t));
- printf("dev: %d\t", (int)stPtr->st_dev);
- printf("ino: %u\t\t", (int)stPtr->st_ino);
- printf("mode: %u\t", (unsigned short)stPtr->st_mode);
- printf("nlink: %lu\t", (unsigned long)stPtr->st_nlink);
- printf("uid: %u\t", (int)stPtr->st_uid);
- printf("\n");
- printf("gid: %u\t", (int)stPtr->st_gid);
- printf("size: %d\t", (int)stPtr->st_size);
- printf("blksize: %d\t", (int)stPtr->st_blksize);
- printf("blocks: %lu\t", (unsigned long)stPtr->st_blocks);
- char *time_string = ctime(&stPtr->st_ctime);
- printf("\nctime: %s", time_string);
- time_string = ctime(&stPtr->st_atime);
- printf("atime: %s", time_string);
- time_string = ctime(&stPtr->st_mtime);
- printf("mtime: %s", time_string);
- printf("\n");
- iput(mip);
- return 0;
- }
- void chmod_file(char *pathname)
- {
- char line[128];
- int mode=0, i=0;
- char perm[64];
- for (i = 0; i < 64; i++) {
- perm[i]=0;
- }
- unsigned long ino = getino(fd, pathname);
- MINODE *mip = iget(fd, ino);
- printf("input the new mode: ");
- fgets(line, 128, stdin);
- line[strlen(line)-1]=0;
- sscanf(line, "%s", perm);
- printf("\nprevious permissions: %o\n", mip->INODE.i_mode);
- mode = perm[0]-48 << 6;
- mode |= perm[1]-48 << 3;
- mode |= perm[2]-48;
- printf("mode %d\n", mode);
- mip->INODE.i_mode &= 0xFF000;
- mip->INODE.i_mode |= mode;
- printf("new permissions: %o\n", mip->INODE.i_mode);
- return;
- }
- MINODE* findParent(MINODE* mip,MINODE* pip)
- {
- MINODE* result;
- DIR *dp;
- char* cp;
- int i;
- char tmpbuff[1024];
- for (i = 0; i < 12; i++) {
- if ( pip->INODE.i_block[i]==0)
- {
- break;
- }
- cp = tmpbuff;
- dp = (DIR *) tmpbuff;
- lseek(fd, pip->INODE.i_block[i]*BLOCK_SIZE, SEEK_SET);
- read(fd, tmpbuff, 1024);
- //get rid of the first two entries or we will be stuck forever
- cp += dp->rec_len;
- dp = (DIR *)cp;
- cp += dp->rec_len;
- dp = (DIR *)cp;
- //Depth first search
- while(cp < tmpbuff + 1024)
- {
- if (dp->inode == mip->ino)
- return pip;
- else
- {
- MINODE* cip = iget(fd, dp->inode);
- if (S_ISDIR( cip->INODE.i_mode))
- {
- result = findParent(mip,cip);
- if (result!=NULL)
- return result;
- }
- }
- cp += dp->rec_len;
- dp = (DIR *)cp;
- }
- }
- return NULL;
- }
- // Prints the path to the current file
- int printfilepath(MINODE* mip)
- {
- MINODE* pip = findParent(mip,root);
- pwd(pip,0);
- int i;
- DIR *dp;
- char* cp,name[64];
- // 12 blocks. For each...
- for (i = 0; i < 12; i++) {
- get_block(fd,pip->INODE.i_block[i], buf);
- // If the Block is NULL stop looping, you're done
- if ( pip->INODE.i_block[i]==0)
- {
- break;
- }
- cp = buf;
- dp = (DIR *) buf;
- // First two entries are useless
- cp += dp->rec_len;
- dp = (DIR *)cp;
- cp += dp->rec_len;
- dp = (DIR *)cp;
- // Depth first search
- while(cp < buf + 1024)
- {
- if (dp->inode == mip->ino) // If the INODE number from the parameter is the same as entry of INODE
- {
- strncpy(name,dp->name,dp->name_len);
- name[dp->name_len] = '\0';
- printf("%s",name);
- }
- cp += dp->rec_len;
- dp = (DIR *)cp;
- }
- }
- return 0;
- }
- int pfd()
- {
- printf("Filename\tFD\tMode\tOffset\n");
- printf("---------------------------------------\n");
- //10 FDs
- // For each pfd
- int i = 0;
- for(; i < 10; i++)
- {
- if (running->fd[i])
- {
- // 1. print its filepath
- printfilepath(running->fd[i]->inodeptr);
- printf("\t\t%d\t",i);
- // 2. print out the mode according to it's fd[i]->mode
- switch(running->fd[i]->mode)
- {
- case 0:
- printf("READ\t");
- break;
- case 1:
- printf("WRITE\t");
- break;
- case 2:
- printf("R/W\t");
- break;
- case 3:
- printf("APPEND\t");
- break;
- default:
- break;
- }
- // 3. Then print its offset
- printf("%d\n",running->fd[i]->offset);
- }
- }
- return 0;
- }
- //Allocates a OFT pointer and assigns it to the next availble spot in the running process
- int falloc(OFT* oftp)
- {
- int i = 0;
- for(;i < 10; i++)
- {
- if (running->fd[i] == NULL)
- break;
- }
- if (i == 10)
- {
- return -1;
- }
- running->fd[i]=oftp;
- return i;
- }
- // 0 read 1 write 2 read/write 3 append
- int open_file(char* path, char mode)
- {
- // user error check
- if (mode == '\0' || path[0] == '\0')
- {
- printf("open [path] [mode (as int)]\n");
- printf("modes: 0 = READ, 1 = WRITE, 2 = READ/WRITE, 3 = APPEND\n");
- return -1;
- }
- int ino = getino(fd,path); // 1. get pathname's inumber:
- MINODE * mip = iget(fd,ino); // 2. get its Minode pointer
- // 3. check mip->INODE.i_mode to verify it's a REGULAR file
- if (!S_ISREG( mip->INODE.i_mode ))
- {
- printf("Hey! it's not a regular file\n");
- return -1;
- }
- // 3. and check if permission OK.
- int i = 0;
- for(;i < 10; i++)
- {
- //fd[i] is not NULL fd[i]->pointer is equal to INode of the path fd[i] is greater than 0
- if ((running->fd[i] != 0 ) && (running->fd[i]->inodeptr == mip) && (running->fd[i]->mode>0))
- {
- printf("Hey! You opened the file already\n");
- return -1;
- }
- }
- // 4. Allocate a free OpenFileTable and fill in values
- OFT* oftp = malloc(sizeof(OFT));
- int index = falloc(oftp);
- if (index == -1)
- {
- printf("Hey! no open file slot available\n");
- return -1;
- }
- // If you reach here, then there is file descriptor slot
- // 5. implement everything to oftp
- oftp->mode = mode-48; // Set mode
- oftp->refCount = 1;
- oftp->inodeptr = mip;
- // 6. Depending on the open mode 0|1|2|3, set the OFT's offset accordingly:
- switch (oftp->mode)
- {
- case 0:
- case 1:
- case 2:
- oftp->offset = 0; // All first three needs to initialize offset to 0
- break;
- case 3:
- oftp->offset = mip->INODE.i_size;
- break;
- default:
- printf("invalid node\n");
- running->fd[index]=0;
- return -1;
- }
- mip->INODE.i_atime = mip->INODE.i_mtime = time(0L); // Touch mtime and atime
- mip->dirty = 1; // Make it dirty
- return index;
- }
- // CLoses file given file descriptor fd
- int close_file(int fd)
- {
- MINODE* mip;
- // 1. Check if it's NULL
- if (running->fd[fd]==NULL)
- {
- printf("Error: File descriptor not found \n");
- return -1;
- }
- // There's 10 FDs from 0 to 9
- // 2. Check for within fd's array
- if (fd < 0 || fd >= 10)
- {
- printf("Error: Invalid File descriptor \n");
- return -1;
- }
- // 3. Check for syntax
- if (fd == -48)
- {
- printf("SYNTAX: close [fd (as int)]\n");
- return -1;
- }
- OFT* oftp = running->fd[fd];
- running->fd[fd] = 0; // Close it
- oftp->refCount--; // Decrement reference count
- if (oftp->refCount > 0) // It exists
- {
- return 0;
- }
- else
- {
- mip = oftp->inodeptr;
- iput(mip);
- }
- return 0;
- }
- int read_file(int fd, int bytes)
- {
- if (fd < 0 || fd >= 10)
- {
- printf("read: syntax is fd followed by bytes\n");
- return -1;
- }
- if (running->fd[fd] == NULL)
- {
- printf("Error: must select a valid file descriptor\n");
- return -1;
- }
- if ((running->fd[fd]->mode != 0) && (running->fd[fd]->mode != 2))
- {
- printf("read: error fd is not set to read\n");
- return -1;
- }
- return myread(fd,read_buff,bytes);
- }
- // read nbytes from fd to buf[ ], and returns the actual number of bytes read.
- int myread(int fd,char* m_buff,long nbytes)
- {
- int is_indirect = 0, is_double_indirect = 0, count = 0;
- char indir_buff[1024], dblindir_buff[1024];
- long * indirect, * dblindirect;
- long indblk, dblindblk, eloop = 0;
- // The number of bytes still available in file.
- long avil = running->fd[fd]->inodeptr->INODE.i_size - running->fd[fd]->offset;
- long lbk, startByte = 0, blk;
- while (nbytes && avil) // While there are still bytes in the file
- {
- // 1. Compute LOGICAL BLOCK number lbk and startByte in that block from offset
- lbk = running->fd[fd]->offset / BLOCK_SIZE;
- startByte = running->fd[fd]->offset % BLOCK_SIZE;
- // 2. Get block from 1 of 3 cases:
- if (lbk < 12) // CASE 1: lbk is a direct block
- {
- blk = running->fd[fd]->inodeptr->INODE.i_block[lbk];
- }
- else if (lbk >= 12 && lbk < 256+12) // CASE 2: indirect blocks
- {
- if (!is_indirect)
- {
- get_block(running->fd[fd]->inodeptr->dev,running->fd[fd]->inodeptr->INODE.i_block[13],indir_buff);
- is_indirect = 1;
- }
- indirect = (long *)buf;
- blk = * (indirect+(lbk-12));
- }
- else // CASE 3: double indirect blocks
- {
- if (!is_double_indirect) // First time always catches
- {
- get_block(running->fd[fd]->inodeptr->dev,running->fd[fd]->inodeptr->INODE.i_block[14],dblindir_buff);
- is_double_indirect = 1;
- }
- dblindirect = (long *)dblindir_buff;
- if (eloop != *(dblindirect+((lbk - 268) / 256)))
- {
- eloop = *(dblindirect+((lbk - 268) / 256));
- get_block(running->fd[fd]->inodeptr->dev, eloop, indir_buff);
- }
- indirect = (long *)buf;
- blk = *(indirect+((lbk - 268) % 256));
- }
- // 3. get the data block into readbuf[BLKSIZE]
- get_block(running->fd[fd]->inodeptr->dev,blk,read_buff);
- char *cq = buf;
- // 4. copy from startByte to buf[ ], <= amount of remaining bytes in this block
- char *cp = read_buff + startByte;
- int remain = BLOCK_SIZE - startByte; // number of bytes remain in readbuf[]
- while (remain > 0)
- {
- printf("%c", *cp);
- *cq++ = *cp++; // copy byte from readbuf[] into buf[]
- running->fd[fd]->offset++; // advance offset
- count++; // inc count as number of bytes read
- avil--; nbytes--; remain--;
- if (nbytes <= 0 || avil <= 0)
- printf("\n");
- break;
- }
- }
- printf("\n");
- //printf("\nread : read %d char from file %d\n", count,fd);
- return count; // count is the actual number of bytes read
- }
- int write_file(char *pfd, char *pstring)
- {
- int writefd = pfd[0] - 48;
- if ((writefd < 0)||(writefd > 9)) {
- printf("write: syntax is write (fd)\n");
- return -1;
- }
- char string[1024];
- strcpy(string, pstring);
- string[strlen(string)] = 0;
- if (running->fd[writefd]->mode == 0)
- {
- printf("write: error fd is not set to write\n");
- return -1;
- }
- int nbytes = strlen(string);
- return(mywrite(writefd, string, nbytes));
- }
- int mywrite(int fd, char *fbuf, int nbytes)
- {
- char wbuf[1024], indir_buff[1024], dblindir_buff[1024];
- long * indirect, * dblindirect;
- long eloop = 0, indblk, dblindblk, lbk, startByte, blk;
- int count = 0, remain = 0, is_indirect = 0, is_double_indirect = 0;
- OFT *oftp = running->fd[fd];
- MINODE *mip = running->fd[fd]->inodeptr;
- while (nbytes > 0)
- {
- // 1. Compute LOGICAL BLOCK number lbk and startByte in that block from offset
- lbk = oftp->offset / BLOCK_SIZE;
- startByte = oftp->offset % BLOCK_SIZE;
- // 2. Get block from 1 of 3 cases:
- if (lbk < 12) // CASE 1: lbk is a direct block
- {
- if (mip->INODE.i_block[lbk] == 0) // Block is not there
- {
- mip->INODE.i_block[lbk] = balloc(mip->dev);
- }
- blk = mip->INODE.i_block[lbk];
- }
- else if (lbk >= 12 && lbk < 256+12) // CASE 2: lbk is an indirect block
- {
- if(!is_indirect)
- {
- get_block(mip->dev,mip->INODE.i_block[13],indir_buff);
- is_indirect = 1;
- }
- indirect = (long *)buf;
- blk = *(indirect+(lbk-12));
- }
- else // CASE 3:double indirect block
- {
- if (!is_double_indirect)
- {
- get_block(mip->dev,mip->INODE.i_block[14],dblindir_buff);
- is_double_indirect = 1;
- }
- dblindirect = (long *)dblindir_buff;
- if (eloop != *(dblindirect+((lbk - 268) / 256)))
- {
- eloop = *(dblindirect+((lbk - 268) / 256));
- get_block(mip->dev, eloop, indir_buff);
- }
- indirect = (long *)buf;
- blk = *(indirect+((lbk - 268) % 256));
- }
- // 3. get the data block into readbuf[BLKSIZE]
- get_block(mip->dev, blk, wbuf);
- if(wbuf[0]==0)
- memset(wbuf, 1024, 0);
- char * cq = (char *)fbuf;
- // 4. copy from startByte to buf[ ], <= amount of remaining bytes in this block
- char * cp = wbuf + startByte;
- remain = BLOCK_SIZE - startByte; // number of bytes remain in readbuf[]
- while (remain > 0)
- {
- *cp++ = *cq++;
- nbytes--, remain--;
- count++;
- oftp->offset++;
- if(oftp->offset > mip->INODE.i_size)
- mip->INODE.i_size++;
- if(nbytes <=0)
- break;
- }
- put_block(mip->dev, blk, wbuf);
- }
- mip->dirty = 1;
- iput(mip);
- printf("write %d char into file fd=%d\n",count, fd);
- return nbytes;
- }
- void cat_file(char *filename)
- {
- // 1. Open file to read
- int catfd = open_file(filename, '0');
- if(catfd == -1){
- printf("file is open already!!\n");
- return;
- }
- int n=0;
- // 2. Read contents
- while( (n=read_file(catfd, 1024))){
- }
- printf("\n");
- // 3. close(fd);
- close_file(catfd);
- }
- // Seeks to a certain offset in an open file
- int lseek_file(int fd, long position)
- {
- long original_offset;
- if (fd == -48)
- {
- printf("SYNTAX: lseek [fd (as int)] [offset (as long)]\n");
- return -1;
- }
- if (position > running->fd[fd]->inodeptr->INODE.i_size)
- {
- printf("ERROR: File length overrun\n");
- return -1;
- }
- else if(position < 0)
- {
- printf("ERROR: Cannot Lseek a negitive number\n");
- return -1;
- }
- original_offset = running->fd[fd]->offset; // Set original to open file offset
- running->fd[fd]->offset = position-1; // Set offset to pos - 1
- return original_offset; // Return
- }
- // Deletes the child of a minode with name name
- int deleteChild(MINODE* pip,char* name) {
- get_block(fd,pip->INODE.i_block[0],buf);
- char* cp = buf;
- DIR* dp = (DIR *) buf;
- int flag, last = 0, tmp, i = 0;
- char* endcp = buf;
- // Traverse to end of buffer
- while(endcp+dp->rec_len < buf +1024) {
- endcp += dp->rec_len;
- dp = (DIR *)endcp;
- }
- dp =(DIR *) cp;
- while (cp < buf+1024)
- {
- if (dp->name_len == strlen(name))
- {
- // Compares name with dp->name but only up to the name_length
- if (strncmp(name, dp->name, dp->name_len) == 0) // Delete file
- {
- tmp = dp->rec_len; // First, store rec_len in tmp
- if (cp == endcp) // If it's at the end
- {
- dp = (DIR *) last;
- dp->rec_len += tmp; // Increment rec_length by tmp
- break;
- }
- else
- {
- dp = (DIR *) endcp;
- dp->rec_len += tmp;
- memcpy(cp, cp+tmp, 1024-i-tmp);
- }
- break;
- }
- }
- last = (int)cp;
- i += dp->rec_len;
- cp += dp->rec_len;
- dp = (DIR *)cp;
- }
- put_block(fd,pip->INODE.i_block[0],buf);
- return 0;
- }
- int rm_file(char* path)
- {
- char parentdir[64], name[64], *cp, *endcp, *last;
- DIR * dp;
- MINODE * pip, *targetip;
- int parent, target;
- if (path[0] == '\0') // If the path is null probably if user forgets
- {
- printf("Syntax: rm [path]\n");
- return -1;
- }
- cp = strrchr(path, '/'); // Returns a pointer to the last occurance of character in the string
- if (!cp) // No occurance of /
- {
- parent = running->cwd->ino;
- strcpy(name,path);
- }
- else
- {
- *(cp) = '\0';
- strcpy(parentdir, path); // Copy path to parent directory
- parent = getino(fd, parentdir); // Set parent to parent directory inode
- strcpy(name, cp+1);
- }
- target = getino(fd,path);
- // Check if the file exists
- if (parent == 0 || target == 0)
- {
- printf("rm: file does not exist\n");
- return -1;
- }
- pip = iget(fd,parent);
- targetip = iget(fd,target);
- // If it's not a regular file
- if ((targetip->INODE.i_mode & 0100000) != 0100000)
- {
- iput(pip);
- printf("rm: cannot remove non-regular file\n");
- return -1;
- }
- // Truncate for MINODE
- targetip->INODE.i_size = 0; // Set targetip size to 0
- targetip->INODE.i_atime = targetip->INODE.i_mtime = time(0L); // Touch time
- targetip->dirty = 1; // Mark targetip dirty
- iput(targetip);
- idealloc(fd,targetip->ino);
- deleteChild(pip,name);
- printf("rm: removed file '%s'\n", name);
- return 0;
- }
- // Deallocates ALL the data blocks
- void truncate(INODE *mip)
- {
- int i = 0;
- for(; i < 15; i++)
- {
- if(mip->i_block[i] == 0)
- return;
- mip->i_block[i] = 0;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement