Ejemplo n.º 1
0
//handling stat request
void stat_handler(Msg *msg, int sender_pid)
{
    char pathname[MAXPATHNAMELEN];
    CopyFrom(sender_pid,pathname,msg->ptr1,msg->num1+1);

    char* filename = pathname+msg->num2;
    int direct_len = msg->num2;
    while ((*filename)!='/' && filename!=pathname) {
        filename--;
        direct_len--;
    }
    if ((*filename)=='/') {
        direct_len++;
        filename++;
    }

    int parent_inum = path_to_inum(pathname,direct_len,msg->num2,0);
    int inum=check_dir(parent_inum,filename);
    struct Stat s;
    inode_cache *n = read_inode(inum);
    s.inum = inum;
    s.type = n->data.type;
    s.size = n->data.size;
    s.nlink = n->data.nlink;
    CopyTo(sender_pid,msg->ptr2,&s,sizeof(struct Stat));

}
Ejemplo n.º 2
0
//handling readlink request
void readlink_handler(Msg *msg, int sender_pid)
{

    char symname[MAXPATHNAMELEN];
    memset(symname,'\0',MAXPATHNAMELEN);
    CopyFrom(sender_pid,symname,msg->ptr1,msg->num2+1);
    int return_len=msg->num3;

    char* filename = symname+msg->num2;
    int direct_len = msg->num2;
    while ((*filename)!='/' && filename!=symname) {
        filename--;
        direct_len--;
    }
    if ((*filename)=='/') {
        direct_len++;
        filename++;
    }

    int parent_inum=path_to_inum(symname,direct_len,msg->num1,0);
    int sym_inum=check_dir(parent_inum,filename);
    if(sym_inum<=0){
        msg->type=-1;
        return;
    }
    inode_cache *sym_inode=read_inode(sym_inum);
    block_cache *sym_block=read_block(sym_inode->data.direct[0]);
    if(sym_inode->data.size<return_len)
        return_len=sym_inode->data.size;

    CopyTo(sender_pid,msg->ptr2,sym_block->data,return_len);

    msg->num3=return_len;

}
Ejemplo n.º 3
0
void mkdir(int fd, std::string name) {
	std::vector<std::string> dirs = split(name, '/');

	int inum = 1; //1 represents the root

	SuperBlock sb(fd);
	//Get the i-number for each directory along the path,
	//Until the first directory along the path isn't found
	//Create that directory
	for(std::vector<std::string>::iterator it = dirs.begin(); it != dirs.end(); ++it) {
		dout << *it << std::endl;
		int child_inum = path_to_inum(fd, *it, inum);

		//if the directory is not present
		if(child_inum < 1) {
			child_inum = sb.allocate_inode(fd);
			if(child_inum < 1) {
				std::cerr << "I-nodes depleted. Cannot allocate directory entry." << std::endl;
				return;
			}

			INode node(child_inum);
			node.flags = 0x8000 | 0x4000; //allocated and directory

			//We've allocated an inode, now we need to allocate a data block
			//Populate that data block with the entries for . and ..
			//and associate it with the inode.
			int block = sb.allocate_block(fd);
			if(block < 0) {
				std::cerr << "Data blocks depleted. Cannot allocate directory entry." << std::endl;
				return;
			}

			char buffer[BLOCK_SIZE] = {};
			write_long(child_inum, sizeof(child_inum), buffer);
			buffer[sizeof(child_inum)] = '.';
			write_long(inum, sizeof(inum), buffer + DIR_SIZE);
			buffer[sizeof(inum) + DIR_SIZE] = '.';
			buffer[sizeof(inum) + DIR_SIZE + 1] = '.';

			lseek(fd, block, SEEK_SET);
			write(fd, buffer, BLOCK_SIZE);

			char dir_entry[DIR_SIZE];
			write_long(child_inum, sizeof(child_inum), dir_entry);
			strncpy(dir_entry + sizeof(child_inum), (*it).c_str(), DIR_SIZE - sizeof(child_inum));

			//Add child inode to parent's directory listing
			addDirEntry(fd, inum, dir_entry);					

			node.flush(fd);
		}

		inum = child_inum;
	}

	sb.flush(fd);
}
Ejemplo n.º 4
0
//handling symlink request
void symlink_handler(Msg *msg, int sender_pid)
{

    char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN];
    memset(oldname,'\0',MAXPATHNAMELEN);
    memset(newname,'\0',MAXPATHNAMELEN);
    CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1);
    CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1);

    int dir_len=msg->num3;
    char *dir_newname=newname+msg->num3;
    while((*dir_newname)!='/'&&dir_newname!=newname){
        dir_len--;
        dir_newname--;
    }

    if((*dir_newname)=='/'){
        dir_len++;
        dir_newname++;
    }
    int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); 
    int sym_inum=alloc_inode(INODE_SYMLINK,parent_inum);
    if(sym_inum<=0){
        msg->type=-1;
        return;
    }

    inode_cache *parent_inode=read_inode(parent_inum);
    inode_cache *sym_inode=read_inode(sym_inum);
    int sym_bnum=alloc_block();
    block_cache *sym_block=read_block(sym_bnum);

    struct dir_entry *sym_dir_entry=search_dir_entry(parent_inum,dir_newname);
    if(sym_dir_entry!=NULL){
        msg->type=-1;
        return;
    }
    if((sym_dir_entry=empty_dir(msg->num1))==NULL){
        msg->type=-1;
        return;
    }

    sym_dir_entry->inum=sym_inum;
    memcpy(sym_dir_entry->name,dir_newname,msg->num3-dir_len);


    sym_inode->data.size=msg->num2;
    sym_inode->data.nlink=1;
    sym_inode->data.direct[0]=sym_bnum;

    sym_block->dirty=1;
    memcpy(sym_block->data,oldname,msg->num2);
    parent_inode->data.size+=sizeof(struct dir_entry);
    parent_inode->dirty=1;

}
Ejemplo n.º 5
0
//handling mkdir request
void mkdir_handler(Msg *msg, int sender_pid)
{
    char pathname[MAXPATHNAMELEN];
    CopyFrom(sender_pid,pathname,msg->ptr1,msg->num1+1);
    char* dir_name = pathname+msg->num1;
    int direct_len = msg->num1;
    while ((*dir_name)!='/' && dir_name!=pathname) {
        dir_name--;
        direct_len--;
    }
    if ((*dir_name)=='/') {
        direct_len++;
        dir_name++;
    }
    if (strlen(dir_name)==0) {
        perror("invalid pathname when creating file!");
        msg->type = ERROR;
        return;
    }
    int direct_inum = path_to_inum(pathname,direct_len,msg->num2,0);
    if (direct_inum<=0) {
        perror("invalid pathname when creating file!");
        msg->type = ERROR;
        return;
    }
    int new_inum = check_dir(direct_inum,dir_name);
    if (new_inum<0) {
        perror("invalid pathname when creating file!");
        msg->type = ERROR;
        return;
    }

    //exist same file name in the directory
    else if (new_inum>0) {
        perror("exist a directory with same name");
        msg->type = ERROR;
        return;
    }
    else if (new_inum==0) {
        new_inum = alloc_inode(INODE_DIRECTORY,direct_inum);
        struct dir_entry *d = empty_dir(direct_inum);
        if (d==NULL) {
            perror("no empty space for new directory");
            msg->type = ERROR;
            return;
        }
        d->inum = new_inum;
        memcpy(d->name,dir_name,strlen(dir_name));
        inode_cache *n = read_inode(direct_inum);
        n->data.nlink++;
        n->data.size+=sizeof(struct dir_entry);
        n->dirty = 1;
        msg->num1 = 0;
    }
}
Ejemplo n.º 6
0
//handling open request
void open_handler(Msg *msg, int sender_pid)
{
    //msg->ptr1 is pathname, msg->num1 is length of pathname, msg->num2 is proc_inode
    char pathname[MAXPATHNAMELEN];
    CopyFrom(sender_pid,pathname,msg->ptr1,msg->num1+1);
    int open_inum = path_to_inum(pathname,msg->num1,msg->num2,0);
    if (open_inum<=0) {
        msg->type = ERROR;
    }
    else {
        msg->num1 = open_inum;
        inode_cache *n = read_inode(open_inum);
        msg->num2 = n->data.reuse;
    }
}
Ejemplo n.º 7
0
//handling chdir request
void chdir_handler(Msg *msg, int sender_pid)
{
    char pathname[MAXPATHNAMELEN];
    CopyFrom(sender_pid,pathname,msg->ptr1,msg->num1+1);
    int target_inum = path_to_inum(pathname,msg->num1,msg->num2,0);
    if (target_inum<=0) {
        perror("illegal destination directory!");
        msg->type = ERROR;
        return;
    }
    inode_cache *n = read_inode(target_inum);
    if (n->data.type!=INODE_DIRECTORY) {
        perror("trying to change current directory to a non-directory place");
        msg->type = ERROR;
        return;
    }
    msg->num1 = target_inum;
}
Ejemplo n.º 8
0
unsigned int path_to_inum(int fd, std::vector<std::string>& path, int inum, int pathPos) {
	//dout << path << " " << inum << std::endl;
	//Get the first directory name in the path
	char delim = '/';
	std::string dir;
	if(pathPos < path.size()) {
		//Read the inode which represents a directory
		//and look for a file whose name matches dir
		dir = path[pathPos];
		char buffer[BLOCK_SIZE] = {};
		unsigned int block = 0;
		ByteAndBlock* rtnVal;
		rtnVal = copyBlock(fd, inum, block); 
		lseek(fd, rtnVal->block * BLOCK_SIZE, SEEK_SET);
		read(fd, buffer, BLOCK_SIZE);

		while(rtnVal->bytesRead > 0) {
			for(int offset = 0; offset < rtnVal->bytesRead; offset += DIR_SIZE) {
				std::string name(buffer + offset + sizeof(unsigned int), DIR_SIZE - sizeof(unsigned int));
				if(stringEquals(dir, name)) {
					delete rtnVal;
					return path_to_inum(fd, path, read_long(buffer + offset, sizeof(int)), pathPos + 1);
				}

			}
			delete rtnVal;

			rtnVal = copyBlock(fd, inum, block++); 
			lseek(fd, rtnVal->block * BLOCK_SIZE, SEEK_SET);
			read(fd, buffer, BLOCK_SIZE);
		}
		delete rtnVal;
		return -1;
	} else {
		return inum;
	}

}
Ejemplo n.º 9
0
//find an inode along the path
int path_to_inum(char *pathname, int len_path, int proc_inum, int symlink_cnt)
{
    if (pathname==NULL) return 0;
    int cur_inode = proc_inum;
    if (len_path==0) {
        return cur_inode;
    }

    //get a component in path
    char node_name[DIRNAMELEN];
    memset(node_name,'\0',DIRNAMELEN);
    if (pathname[0]=='/') {
        while (len_path>0 && *pathname=='/') {
            pathname++;
            len_path--;
        }

        cur_inode = ROOTINODE;
        return path_to_inum(pathname,len_path,cur_inode,symlink_cnt);
    }
    int i = 0;
    while (len_path>0 && (*pathname!='/')) {
        node_name[i] = *pathname;
        i++;
        pathname++;
        len_path--;
    }
    while (len_path>0 && *pathname=='/') {
        pathname++;
        len_path--;
    }

    //looking up the inum in cur_inode for the acquired component
    inode_cache *n = read_inode(cur_inode);

    if (n->data.type!=INODE_DIRECTORY) {
        perror("illegal pathname!");
        return -1;
    }

    int sub_inum = check_dir(cur_inode, node_name);
 

    if (sub_inum<=0) {
        //perror("illegal pathname, non-exist directory");
        return -1;
    }
    n = read_inode(sub_inum);
    if (n->data.type==INODE_SYMLINK) {
        if (symlink_cnt>=MAXSYMLINKS) {
            perror("symlink traverse more than MAXSYMLINKS!");
            return -1;
        }
        char *new_pathname = (char*)malloc(sizeof(char)*(n->data.size)+len_path+1);
        block_cache *b = read_block(n->data.direct[0]);
        memcpy(new_pathname,b->data,n->data.size);
        char *t1 = new_pathname+n->data.size;
        *t1 = '/';
        t1++;
        memcpy(t1,pathname,len_path);
        return path_to_inum(new_pathname,n->data.size+1+len_path,cur_inode,symlink_cnt+1);
    }
    else return path_to_inum(pathname,len_path,sub_inum,symlink_cnt);

}
Ejemplo n.º 10
0
//handling unlink request
void unlink_handler(Msg *msg, int sender_pid)
{

    char pathname[MAXPATHNAMELEN];
    memset(pathname,'\0',MAXPATHNAMELEN);
    CopyFrom(sender_pid,pathname,msg->ptr1,msg->num2+1);

    int dir_len=msg->num2;
    char *dir_pathname=pathname+msg->num2;
    while((*dir_pathname)!='/'&&dir_pathname!=pathname){
        dir_len--;
        dir_pathname--;
    }

    if((*dir_pathname)=='/'){
        dir_len++;
        dir_pathname++;
    }
    int parent_inum=path_to_inum(pathname,dir_len,msg->num1,0); 

    int path_inum=check_dir(parent_inum,dir_pathname);

    if(path_inum<=0||parent_inum<=0){
        msg->type=-1;
        return;
    }

    inode_cache *path_inode=read_inode(path_inum);
    inode_cache *parent_inode=read_inode(parent_inum);
    if(path_inode->data.type==INODE_DIRECTORY){
        msg->type=-1;
        return;
    }

    struct dir_entry *path_dir_entry=search_dir_entry(parent_inum,dir_pathname);
    


    if(path_inode->data.nlink>1){
        path_dir_entry->inum=0;
        path_inode->data.nlink--;
        memset(path_dir_entry->name,'\0',DIRNAMELEN);
        parent_inode->data.size-=sizeof(struct dir_entry);
        parent_inode->dirty=1;
        
    }
    else if(path_inode->data.nlink==1){
        path_dir_entry->inum=0;
        path_inode->data.nlink--;
        memset(path_dir_entry->name,'\0',DIRNAMELEN);
        free_inode(path_inum);//XXX
        path_inode->dirty=1;
        parent_inode->data.size-=sizeof(struct dir_entry);
        parent_inode->dirty=1;
    }
    else{
        msg->type=-1;
        return;
    }

}
Ejemplo n.º 11
0
//handling link request
void link_handler(Msg *msg, int sender_pid)
{

    char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN];

    if(path_to_inum(newname,msg->num3,msg->num1,0)>0){
        /*newname exists*/
        msg->type=-1;
        return;
    }

    memset(oldname,'\0',MAXPATHNAMELEN);
    memset(newname,'\0',MAXPATHNAMELEN);
    CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1);
    CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1);
    int dir_len=msg->num3;
    char *dir_newname=newname+msg->num3;
    while((*dir_newname)!='/'&&dir_newname!=newname){
        dir_len--;
        dir_newname--;
    }

    if((*dir_newname)=='/'){
        dir_len++;
        dir_newname++;
    }
    int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); 
    
    int dir_len_old=msg->num2;
    char *dir_oldname=oldname+msg->num2;
    while((*dir_oldname)!='/'&&dir_oldname!=oldname){
        dir_len_old--;
        dir_oldname--;
    }

    if((*dir_oldname)=='/'){
        dir_len_old++;
        dir_oldname++;
    }

    int parent_old_inum=path_to_inum(oldname,dir_len_old,msg->num1,0);
    int old_inum=check_dir(parent_old_inum,dir_oldname);

    if(old_inum<=0){
        msg->type=-1;
        return;
    }

    inode_cache *old_inode=read_inode(old_inum);
    if(old_inode->data.type==INODE_DIRECTORY){
        msg->type=-1;
        return;
    }

    struct dir_entry *newlink=search_dir_entry(parent_inum,dir_newname);
    if(newlink!=NULL){
        msg->type=-1;
        return;
    }
    if((newlink=empty_dir(parent_inum))==NULL){
        msg->type=-1;
        return;
    }
 
    inode_cache *parent_inode=read_inode(parent_inum);
    parent_inode->data.size+=sizeof(struct dir_entry);
    parent_inode->dirty=1;
    newlink->inum=old_inum;
    memcpy(newlink->name,dir_newname,msg->num3-dir_len);
    old_inode->data.nlink++;
    old_inode->dirty=1;

}
Ejemplo n.º 12
0
//handling rmdir request
void rmdir_handler(Msg *msg, int sender_pid)
{
    char pathname[MAXPATHNAMELEN];
    CopyFrom(sender_pid,pathname,msg->ptr1,msg->num1);
    int rm_inum = path_to_inum(pathname,msg->num1,msg->num2,0);
    if (rm_inum<=0) {
        msg->type = ERROR;
        return;
    }
    inode_cache *n = read_inode(rm_inum);
    if (n->data.size>2*sizeof(struct dir_entry)) {
        perror("try to remove a non-empty directory!");
        msg->type = ERROR;
        return;
    }
    block_cache *b = read_block(n->data.direct[0]);
    struct dir_entry *d = (struct dir_entry*)(b->data);
    int pare_inum = d[1].inum;
   
    free_inode(rm_inum);

    //remove the dir_entry of rm_inum in parent directory
    inode_cache *dir = read_inode(pare_inum);
    if (dir->data.type!=INODE_DIRECTORY) {
        perror("parent not a directory when remove dir");
        return;
    }

    dir->data.size-=sizeof(struct dir_entry);
    int i,block_num;

    //check direct blocks
    for (i=0; i<NUM_DIRECT; i++) {
        if (dir->data.direct[i]<=0) continue;
        block_num = dir->data.direct[i];
        block_cache *b = read_block(block_num);
        struct dir_entry *d = (struct dir_entry*)(b->data);
        int j;
        for (j=0; j<DIRS_PER_BLOCK; j++) {
            if (d[j].inum<=0) continue;
            if (d[j].inum==rm_inum) {
                d[j].inum = 0;
                memset(d[j].name,'\0',DIRNAMELEN);
                b->dirty = 1;
                return;
            }
        }
    }

    //check indirect bloc
    if (dir->data.indirect!=0) {
        block_num = dir->data.indirect;
        block_cache *b = read_block(block_num);
        int j;
        block_cache *tmp;
        for (j=0; j<BLOCKSIZE; j+=4) {
            block_num = *(int*)(b->data+j);
            if (block_num!=0) {
                tmp = read_block(block_num);
                struct dir_entry *d = (struct dir_entry*)(tmp->data);
                int k;
                for (k=0; k<DIRS_PER_BLOCK; k++) {
                    if (d[j].inum<=0) continue;
                    if (d[j].inum==rm_inum) {
                        d[j].inum = 0;
                        memset(d[j].name,'\0',DIRNAMELEN);
                        tmp->dirty = 1;
                        return;
                    }
                }
            }
        }
    }

}
Ejemplo n.º 13
0
unsigned int path_to_inum(int fd, std::string path, int inum) {
	std::vector<std::string> pathVector = split(path, '/');
	return path_to_inum(fd, pathVector, inum, 0);
}
Ejemplo n.º 14
0
unsigned int path_to_inum(int fd, std::string path) {
	return path_to_inum(fd, path, 1);
}