/*----------------------------------------------------------------------- * unklink: Remove the link between two files * (1) get /a/b/c's INODE into memory * ino = iget(dev, filename); * rm = getino(dev, ino); * (2) Verify that rm is a file (NOT DIR) * (3) Decrement rm->INODE's link count by 1 * (4) If rm->links_count == 1, remove the file * Deallocate data blocks * Deallocate INODE * (5) Remove c from directory by * rm_child(rm, 'c') -----------------------------------------------------------------------*/ void ulink(char** args) { MINODE* rm; MINODE* parent; char* filename; int dev, ino, pino; int i; if(args[0] == NULL) { printf("Error: unlink requires a pathname\n"); return; } filename = strdup(args[0]); // (1) Load MINODE of file to be unlinked ino = getino(&dev, filename); // get it's inumber rm = iget(dev, ino); // and load the MINODE if(rm == NULL) { printf("Error: Invalid path %s\n", filename); return; } // (2) Verify file is regular (not DIR) if(!isreg(rm)) { printf("Error: unlink cannot be used on directories \n"); iput(rm); return; } rm->INODE.i_links_count--; // (3) Decrement links count dev = rm->dev; ino = rm->ino; // No remaining links if(rm->INODE.i_links_count < 1) { // Deallocate datablocks for(i=0; i<12; i++) bdealloc(dev, rm->INODE.i_block[i]); // Deallocate inode for(i=0; i<12; i++) idealloc(dev, ino); } // Remove from parent directory pino = getino(&dev, Dirname(filename)); // parent's directory parent = iget(dev, pino); // Remove child from parent's data blocks rm_child(parent, Basename(filename)); parent->dirty = 1; rm->dirty = 1; iput(parent); iput(rm); }
/* --------------------------------------------------------------- * rm_dir: * (1) ask for pathname to rmdir * (2) get rmdir's ino * ino = getino(&dev, pathname) * (3) get a pointer to its MINODE[] * mip = iget(dev, ino) * (4) check DIR type && not busy && is empty * (5) get parent directory into memory -----------------------------------------------------------------*/ void rm_dir(char* path) { // (1) Asks for pathname MINODE* mip; // directory to remove MINODE* pip; // parent minode int i; int ino, pino; // inumber and parent inumber int dev = running->cwd->dev; // (2) get inumber if((ino = getino(&dev, path)) == 0) { printf("Could not find directory %s\n", path); return; } // get pointer to MINODE[] of file to Dir to remove mip = iget(dev, ino); if(mip == NULL) { printf("Error: Unable to find directory %s\n", path); return; } // (3) Check DIR, not BUSY, and is empty if(!isdir(mip)) { printf("Error: %s is not a directory\n", path); iput(mip); return; } // (3.1) not BUSY if(mip->refCount > 1 || mip->mounted || mip == running->cwd) { printf("Error: %s is in use\n", path); iput(mip); return; } if(!isempty(mip)) // (3.2) is empty { printf("Error: %s is not empty\n", path); iput(mip); return; } char* parentPath = strdup(Dirname(path)); printf("parent path = %s\n", parentPath); char* base = strdup(Basename(path)); printf("base (to remove) = %s\n", base); // (5) get parent directory into memory pino = getino(&dev, parentPath); // get parent ino pip = iget(dev, pino); // get parent MINODE* rm_child(pip, base); // (6) Passed all the checks, deallocate block and inode // (6.1) deallocate block for(i=0; i<12; i++) { if(mip->INODE.i_block[i] == 0) // block already 0 continue; // Deallocate the block bdealloc(mip->dev, mip->INODE.i_block[i]); } // (6.2) Deallocate the INODE and inumber idealloc(mip->dev, mip->ino); mip->refCount=0; // Free minode[] entry pip->INODE.i_links_count--; pip->dirty = 1; iput(pip); }
//unlinks a file void my_unlink(char *path) { int ino, i; int parent_ino; MINODE *mip; MINODE *parent_mip; INODE *ip; INODE *parent_ip; char temp[64]; char my_dirname[64]; char my_basename[64]; if(!path)//check for path { printf("ERROR: no path given\n"); return; } ino = getino(running->cwd, path); if(ino == 0) { printf("ERROR: bad path\n"); return; } mip = iget(dev, ino); if(!mip)//make sure file exists { printf("ERROR: missing minode\n"); return; } if(S_ISDIR(mip->INODE.i_mode))//make sure it's a file { printf("ERROR: can't unlink a directory\n"); return; } printf("doing the unlinking\n"); ip = &mip->INODE; //decrement the links count ip->i_links_count--; //printf("links: %d\n", ip->i_links_count); //deallocate its blocks for(i = 0; i < 12 && ip->i_block[i] != 0; i++) { bdealloc(dev, ip->i_block[i]); } //deallocate its inode idealloc(dev, ino); //get basename and dirname strcpy(temp, path); strcpy(my_dirname, dirname(temp)); strcpy(temp, path); strcpy(my_basename, basename(temp)); printf("dirname is %s basename is %s\n", my_dirname, my_basename); //get its parent parent_ino = getino(running->cwd, my_dirname); parent_mip = iget(dev, parent_ino); parent_ip = &parent_mip->INODE; //remove child from parent printf("removing %s from %s\n", my_basename, my_dirname); rm_child(parent_mip, my_basename); parent_ip->i_atime = time(0L);//update times and mark dirty parent_ip->i_mtime = time(0L); parent_mip->dirty = 1; //write back iput(parent_mip); mip->dirty = 1; iput(mip); return; }