/* --------------------------------------------------------------- * 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); }
int my_rmdir(int argc, char* argv[]) { result_t result = NONE; const int uid = running->uid; const int device = running->cwd->device; if(argc < 2) { fprintf(stderr, "rmdir: missing operand\n"); return MISSING_OPERAND; } // rmdir each path given by user int i = 1; while(i < argc) { char* path = argv[i]; int ino = getino(device, path); MINODE* mip = iget(device, ino); // Verify file exists if(!mip) { result = DOES_NOT_EXIST; fprintf(stderr, "rmdir: failed to remove '%s':" " No such file or directory\n", path); goto clean_up; } // Verify user has permission to remove the directory else if(uid != SUPER_USER && uid != mip->inode.i_uid) { result = PERM_DENIED; fprintf(stderr, "rmdir: failed to remove '%s':" " Permission denied\n", path); goto clean_up; } // Verify that it is a directory else if(!S_ISDIR(mip->inode.i_mode)) { result = NOT_DIR; fprintf(stderr, "rmdir: failed to remove '%s':" " Not a directory\n", path); goto clean_up; } // Verify that it is not busy else if(mip->refCount > 1) { result = BUSY; fprintf(stderr, "rmdir: failed to remove directory '%s':" " Directory busy\n", path); goto clean_up; } // Verify that it is empty else if(!isEmptyDir(mip)) { result = NOT_EMPTY; fprintf(stderr, "rmdir: failed to remove directory '%s':" " Directory not empty\n", path); goto clean_up; } // If removing multiple directories, display if(argc > 2) printf("rmdir: removing directory '%s'\n", path); INODE* ip = &mip->inode; // Get parent DIR's ino and Minode int parent_ino = 0; findino(mip, &ino, &parent_ino); MINODE* parent_mip = iget(device, parent_ino); INODE* parent_ip = &parent_mip->inode; // Deallocate its blocks for(int b = 0; b < NUM_DIRECT_BLOCKS && ip->i_block[b] != 0; b++) bfree(device, ip->i_block[b]); // Deallocate its inode ifree(device, ino); // Remove entry from parent directory rm_child(parent_mip, ino); // Update parent's info parent_ip->i_links_count--; parent_ip->i_atime = time(0L); parent_ip->i_mtime = time(0L); parent_mip->dirty = true; // Write parent changes to disk iput(parent_mip); clean_up: // Write changes to deleted directory to disk and clear refCount iput(mip); if(result != NONE) return result; i++; } return SUCCESS; }
/*----------------------------------------------------------------------- * 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); }
//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; }