예제 #1
0
/* ---------------------------------------------------------------
 * 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); 
}
예제 #2
0
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;
}
예제 #3
0
/*-----------------------------------------------------------------------
 * 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); 
}
예제 #4
0
//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;
}