⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dir.c

📁 一个完整的SHELL实现源代码
💻 C
字号:
#include "fs.h"

s_int g_curdir_ino=0;
char g_curdir_name[256]="";

/* char * get_last_name(char *path)
    
    path must be absolute directory(start with '/') or 
    relative directory(start not with '/')
    return the working path's inode number
*/
char * get_last_name(char *path)
{
    s_int i;
    for(i=strlen(path)-1;i>=0 && path[i]!='/';i--);
    if(i>=0) return path+i+1;
    else  return path; 
}

/* s_int get_working_dir_ino(char *path)
    
    path must be absolute directory(start with '/') or 
    relative directory(start not with '/')
    return the working path's inode number
*/
s_int get_working_dir_ino(char *path)
{
    s_int i;
    char p[256];
/*    #ifdef DEBUG_MODE
    printf("get_working_dir_ino: path[%s]",path); 
    #endif   /**/
    for(i=strlen(path)-1;i>=0 && path[i]!='/';i--);
/*    #ifdef DEBUG_MODE
    printf("last '/' is at [%d]'th char\n",i);
    #endif  /**/
    if(i>0)
    {
        strncpy(p,path,i);
        p[i]='\0';
        path+=i+1;
        /* #ifdef DEBUG_MODE
        printf("p[%s],path[%s]\n",p,path); 
        #endif  /* */
        i=namei(p);
        if(i<0)
        {
              #ifdef DEBUG_MODE
              printf("get_working_dir_ino: path not found.\n",i);
              #endif
        	return -1; /* path not found */
        }
    }
    else if(i<0)
    {
   	 i=g_curdir_ino;  /* create dir at the current directory */
    }
    /* if i==0 path start with a '/' and only 1 name ,so working dir is root */
/*    #ifdef DEBUG_MODE
    printf("[%d]\n",i);
    #endif /**/
    return i;
}

/* 目录搜索函数 */
/* fname must be absolute directory(start with '/') or 
    relative directory(start not with '/')
*/
s_int namei(char *fname)
{
    s_int i,*jp;
    s_int dirino;
    dir_rec *dirs;
    inode *ip;
    char tname[32];
/*   #ifdef DEBUG_MODE
    printf("namei():[%s]\n",fname); 
   #endif    /**/
    /* . is current directory 
    if(fname[0]=='.')return g_curdir_ino;*/
    
    /* search from root or from the current directory 
        and skip the root slash character if from root */    
    dirino= (fname[0]=='/')?(++fname,0): g_curdir_ino;

    Loop:
    if(*fname)
    {
        /* get a name from the fname */
        for(i=0;i<30 && fname[i];i++)
        {
            if(fname[i]=='/')break;
            tname[i]=fname[i];
        }
        tname[i]='\0';
        
        if(fname[i]&&fname[i]!='/')return -2; /* path error, not found */
        if(fname[i]=='/')fname++;
        fname+=i;
        ip=iget(dirino);
/*        #ifdef DEBUG_MODE
        printf("namei: dirino=[%d][%s]\n",dirino,fname);
        #endif	/**/
         if(ip==NULL)
        {
        	panic("namei:iget(dirino)==NULL");
        }
        for(jp=&ip->adr[0];jp<&ip->adr[8] && *jp;jp++)
        {
            dirs=(dir_rec *)bread(*jp);
            for(i=0;i<512/32;i++)
                if(!strncmp(dirs[i].name,tname,30))
                {
                	dirino=dirs[i].ino; /* found the name, go for the next part */
                	goto Loop;
                }
        }
        #ifdef DEBUG_MODE
        printf("namei: path not found.\n");
        #endif
        return -1; /* path not found */
    }
    return dirino;
}

/* 访问控制函数 */
s_int access()
{
    return 0;
}


/* 列目录函数 */
/* path must be absolute directory(start with '/') or 
    relative directory(start not with '/')
*/
s_int dir(char *path)
{
    s_int i,j;
    inode *ip,*ip2;
    dir_rec *dp;
    if(!strcmp(path,"."))i=g_curdir_ino;
    else i=namei(path);
    ip=iget(i);
    if((ip->mode & IFMT)!=IFDIR)
    {
    	iput(ip);
    	return -1;
    }
    for(i=0;i<8 && ip->adr[i];i++)
    {
    	dp=(dir_rec *)bread(ip->adr[i]);
    	for(j=0;j<512/32;j++)
    	{
    		if(dp[j].name[0] && dp[j].name[0]!='.')
    		{
    			ip2=iget(dp[j].ino);
    			switch(ip2->mode&IFMT)
    			{
    				case IFDIR:printf("/");break;
    				case IFCHR:break;
    			}
			printf("%s\t",dp[j].name);
    		}
    	}    	
    }
    iput(ip);
    return 0;
}


/* 创建子目录函数 */
/* path must be absolute directory(start with '/') or 
    relative directory(start not with '/')
*/
s_int mkdir(char *path)
{
    s_int i,j;
    s_long size;
    inode *ip,*ip2;
    dir_rec *dp;
    i=get_working_dir_ino(path);
    if(i==-1)return -1;
    ip=iget(i);
    if((ip->mode & IFMT) !=IFDIR)
    {
        iput(ip);
        #ifdef DEBUG_MODE
        printf("mkdir :path not found\n",i);
        #endif
        return -1; /* path not found */
    }
    size=((s_long)ip->size0 << 16) + ip->size1;
    for(i=0;i<8 && ip->adr[i];i++)
    {
        dp=(dir_rec *)bread(ip->adr[i]);
        for(j=0;j<512/32;j++)
        {
            if(dp[j].name[0]=='\0')goto Add_record;
        }    	
    }
    if(i>=8)
    {
	    iput(ip);
	    printf("mkdir: directory file no more spaces, mkdir failed.\n");
	    return -2; /* directory file no more spaces, mkdir failed */
    }
    ip->adr[i]=balloc();
    if(ip->adr[i]==0)panic("mkdir: balloc return 0, must be block empty.");
    dp=(dir_rec *)bread(ip->adr[i]);
    memset(dp,0,512);
    size+=512;
    ip->size1=size & 0xffff;
    ip->size0=size>>16;
    j=0;
Add_record:
    ip2=ialloc();
    if(ip2==NULL)panic("mkdir: ialloc return NULL, must be inode empty.");
    dp[j].ino=ip2->number; /* link to sub dir */
    strcpy(dp[j].name,get_last_name(path));
    ip2->adr[0]=balloc();
    if(ip2->adr[0]==0)panic("mkdir: balloc return 0, must be block empty.");
    dp=(dir_rec *)bread(ip2->adr[0]);
    memset(dp,0,512);
    dp[0].ino=ip->number; /* link to father dir */
    ip->lastr++;
    iput(ip);
    strcpy(dp[0].name,"..");
    strcpy(dp[1].name,".");
    dp[1].ino=ip2->number; /* link to self */
    ip2->mode&=~IFMT;
    ip2->mode|=IFDIR;
    ip2->lastr=0;
    ip2->size1=512;
    ip2->size0=0;    
    iput(ip2);
    return 0;
}

/* 改变当前子目录函数 
    path must be absolute directory(start with '/') or 
    relative directory(start not with '/')
*/
s_int chdir(char *path)
{
    s_int i;
    i=namei(path);
/*    #ifdef DEBUG_MODE
    printf("chdir(): path[%s] i=%d\n",path,i);
    #endif /**/
    if(i<0)return i;   /* path error , not found */
    g_curdir_ino=i;
    if(i)
    {
    	if(!strcmp(path,".."))
    	{
    		g_curdir_name[get_last_name(g_curdir_name)-g_curdir_name-1]=0;
    	}
    	else if(path[0]=='/')
    	{
	    	strcpy(g_curdir_name,path);
    	}
    	else
    	{
	    	i=strlen(g_curdir_name);
	    	if(g_curdir_name[i-1]!='/')
	    	{
	    		g_curdir_name[i]='/';
	    		i++;
	    	}
	    	strcpy(g_curdir_name+i,path);
    	}
    }
    else strcpy(g_curdir_name,"/");
    return 0;
}

/*删除子目录函数 
    path must be absolute directory(start with '/') or 
    relative directory(start not with '/')
*/
s_int rmdir(char *path)
{
    s_int i,j;
    s_long size;
    inode *ip,*ip2;
    dir_rec *dp;
    char *name=get_last_name(path);
    if(!strcmp(name,".."))return 0; /* '..' is not a normal path */
    i=get_working_dir_ino(path);
    if(i==-1)return -1;
    ip=iget(i);
    if((ip->mode & IFMT) !=IFDIR)
    {
        iput(ip);
        #ifdef DEBUG_MODE
        printf("rmdir : working path not found\n",i);
        #endif
        return -1; /* path not found */
    }
    size=((s_long)ip->size0 << 16) + ip->size1;
    for(i=0;i<8 && ip->adr[i];i++)
    {
        dp=(dir_rec *)bread(ip->adr[i]);
        for(j=0;j<512/32;j++)
        {
            if(!strcmp(dp[j].name,name))goto Del_record;
        }    	
    }
    iput(ip);
    #ifdef DEBUG_MODE
    printf("rmdir: rm path not found.\n");
    #endif
    return -2; /* rm path not found. */
    Del_record:
    ip2=iget(dp[j].ino);
    if(ip2==NULL)return -3; /* dir's inode error */
    if((ip2->mode&IFMT)!=IFDIR)return -2; /* rm path not found, it is not a path */
    if(ip2->lastr>0)return -4; /* rm path not empty */
    ip->lastr--;
    iput(ip);
    for(i=0;i<8&&ip2->adr[i];i++)
    	if(ip2->adr[i])bfree(ip2->adr[i]);
    ifree(ip2->number);
    iput(ip2);
    dp[j].name[0]=0;
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -