41>>ls

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>

#include<sys/stat.h>
#include<fcntl.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<dirent.h>

#include<linux/kdev_t.h>

#define A ~(0<<1)<<0
#define B ~(0<<1)<<1
#define C ~(0<<1)<<2
#define D ~(0<<1)<<3
#define E ~(0<<1)<<4
#define F ~(0<<1)<<5
#define G ~(0<<1)<<6
#define H ~(0<<1)<<7
#define I ~(0<<1)<<8
#define J ~(0<<1)<<9
#define K ~(0<<1)<<10
#define L ~(0<<1)<<11
#define M ~(0<<1)<<12
#define N ~(0<<1)<<13
#define O ~(0<<1)<<14
#define P ~(0<<1)<<15
#define Q ~(0<<1)<<16
#define R ~(0<<1)<<17
#define S ~(0<<1)<<18
#define T ~(0<<1)<<19
#define U ~(0<<1)<<20
#define V ~(0<<1)<<21
#define W ~(0<<1)<<22
#define X ~(0<<1)<<23
#define Y ~(0<<1)<<24
#define Z ~(0<<1)<<25

#define IS_A(mode) ((mode)&(~(~0<<1)<<0))
#define IS_B(mode) ((mode)&(~(~0<<1)<<1))
#define IS_C(mode) ((mode)&(~(~0<<1)<<2))
#define IS_D(mode) ((mode)&(~(~0<<1)<<3))
#define IS_E(mode) ((mode)&(~(~0<<1)<<4))
#define IS_F(mode) ((mode)&(~(~0<<1)<<5))
#define IS_G(mode) ((mode)&(~(~0<<1)<<6))
#define IS_H(mode) ((mode)&(~(~0<<1)<<7))
#define IS_I(mode) ((mode)&(~(~0<<1)<<8))
#define IS_J(mode) ((mode)&(~(~0<<1)<<9))
#define IS_K(mode) ((mode)&(~(~0<<1)<<10))
#define IS_L(mode) ((mode)&(~(~0<<1)<<11))
#define IS_M(mode) ((mode)&(~(~0<<1)<<12))
#define IS_N(mode) ((mode)&(~(~0<<1)<<13))
#define IS_O(mode) ((mode)&(~(~0<<1)<<14))
#define IS_P(mode) ((mode)&(~(~0<<1)<<15))
#define IS_Q(mode) ((mode)&(~(~0<<1)<<16))
#define IS_R(mode) ((mode)&(~(~0<<1)<<17))
#define IS_S(mode) ((mode)&(~(~0<<1)<<18))
#define IS_T(mode) ((mode)&(~(~0<<1)<<19))
#define IS_U(mode) ((mode)&(~(~0<<1)<<20))
#define IS_V(mode) ((mode)&(~(~0<<1)<<21))
#define IS_W(moed) ((mode)&(~(~0<<1)<<22))
#define IS_X(mode) ((mode)&(~(~0<<1)<<23))
#define IS_Y(mode) ((mode)&(~(~0<<1)<<24))
#define IS_Z(mode) ((mode)&(~(~0<<1)<<25))

/* defined this struct FILEPATH mainly to deal with
 * the display of file which in the sub directory
 */
typedef struct FILEPATH
{
    char *full_path;
    char *name;
}Fpath;

int my_get_opt(const int argc,const char **argv);
int get_file_list(const int argc,const char **argv,Fpath **file_list);
int show_dir(Fpath *file_list,const long int mode);
int show_file(Fpath *file_list,struct stat *buf,const long int mode);
int show_link_content(Fpath *file_list,struct stat *buf);

int main(int argc,char **argv)
{
    int i=0;
    Fpath *file_list=NULL;        //get the file list from the command line and store them in a struct Fpath
    int file_num=0;            //the file num that get from the command line
    struct stat buf;
    long int mode=9;        //option status
    mode=my_get_opt(argc,(const char **)argv);            //get the option and store the in a long int variable define in "myopt.h" file
    file_num=get_file_list(argc,(const char **)argv,&file_list);
    /*-------------------------------------------------------------------------------*/

    /*display every file that store in the file_list*/

    for(i=0;i<file_num;i++)
    {
        if ( lstat(file_list[i].full_path,&buf)==-1)
        {
            perror(file_list[i].full_path);
            continue;
        }
        /* if file is a symbol file, read the name of its refer and
         * store it in the buf point by real_path*/
        if(S_ISLNK(buf.st_mode))
        {
            show_file((file_list+i),&buf,mode);
            if( IS_L(mode) )
            {
                show_link_content((file_list+i),&buf);
                printf("\n");
            }
        }
        /* if file is a directory, make decision from the options
         * whether display the directory itself or the files
         * it contains. this is judge by a macro IS_D(mode)*/
        else if( S_ISDIR(buf.st_mode))
        {
            if(IS_D(mode))
            {
                show_file((file_list+i),&buf,mode);
                if(IS_L(mode))
                    printf("\n");
                continue;
            }
            else
            {
                show_dir((file_list + i),mode);
                if( IS_L(mode))
                {
                    printf("\n");
                }
            }
        }
        else
        {
            show_file((file_list + i ),&buf,mode);
            if( IS_L(mode))
                printf("\n");
        }
    }
    free(file_list);
    if(!(IS_L(mode)))
    {
        printf("\n");
    }
    return 0;
}

int show_link_content(Fpath *file_list,struct stat *buf)
{
    char real_path_buf[512]={'\0'};
    char *real_path=real_path_buf;
    int real_path_len=0;

    if((real_path_len=readlink(file_list->full_path,real_path_buf,512))==-1)
    {
        perror(file_list->full_path);
        return -1;
    }
    *(real_path + real_path_len)='\0';
    printf("->%s",real_path);
    return 0;
}

int show_file(Fpath *file_list,struct stat *buf,const long int mode)
{
    if(IS_I(mode))
    {
        printf("%lu",(unsigned long)(buf->st_ino));
    }
    if(IS_L(mode))
    {
        mode_t file_mode = (*buf).st_mode;
        char file_type = '\0';
        /* file type */
        if(S_ISREG(file_mode))
            file_type='-';
        else if(S_ISDIR(file_mode))
            file_type='d';
        else if(S_ISCHR(file_mode))
            file_type='c';
        else if(S_ISBLK(file_mode))
            file_type='b';
        else if(S_ISFIFO(file_mode))
            file_type='p';
        else if(S_ISSOCK(file_mode))
            file_type='s';
        else if(S_ISLNK(file_mode))
            file_type='l';
        printf("%c",file_type);

        char perm_buf[10]={'-','-','-','-','-','-','-','-','-','\0'};
        /*file permission */
        if(file_mode & S_IRUSR)
            perm_buf[0]='r';
        if(file_mode & S_IWUSR)
            perm_buf[1]='w';
        if(file_mode & S_IXUSR)
        {
            if(file_mode & S_ISUID)
                perm_buf[2]='s';
            else
                perm_buf[2]='x';
        }
        else
        {
            if(file_mode & S_ISUID)
                perm_buf[2]='S';
        }
        
        if(file_mode & S_IRGRP)
            perm_buf[3]='r';
        if(file_mode & S_IWGRP)
            perm_buf[4]='w';
        if(file_mode & S_IXGRP)
        {
            if(file_mode & S_ISGID)
                perm_buf[5]='s';
            else
                perm_buf[5]='x';
        }
        else
        {
            if(file_mode & S_ISGID)
                perm_buf[5]='S';
        }

        if(file_mode & S_IROTH)
            perm_buf[6]='r';
        if(file_mode & S_IWOTH)
            perm_buf[7]='w';
        if(file_mode & S_IXOTH)
        {
            if(file_mode & S_ISVTX)
                perm_buf[8]='t';
            else
                perm_buf[8]='x';
        }
        else
        {
            if(file_mode & S_ISVTX)
                perm_buf[8]='T';
        }
        printf("%s ",perm_buf);
        printf("%d ",(*buf).st_nlink);

        struct passwd *passwd_file;
        struct group *group_file;
        /*file owner and group*/
        if((passwd_file=getpwuid((*buf).st_uid))!=NULL)
            printf("%s ",(passwd_file->pw_name));
        else
            printf("%d ",(*buf).st_uid);
        if((group_file=getgrgid((*buf).st_gid))!=NULL)
        {
            printf("%s ",*group_file -> gr_name);
        }
        else
            printf("%d ",(*buf).st_gid);
        /*file size or device number */
        switch(file_type)
        {
            case '-':
            case 'd':
            case 'l':
            case 's':
            case 'p':
                printf("%8ld ",(*buf).st_size);
                break;
            case 'c':
            case 'b':
                printf("%lu    %lu ",(unsigned long)MAJOR(buf->st_rdev),(unsigned long)MINOR(buf->st_rdev));
                break;
            default:
                break;
        }

        /*file tiome*/
        time_t *get_time=&((*buf).st_mtime);
        char time_buf[100] = {'\0'},*my_time = time_buf;
        int time_len=0;
        strcpy(time_buf, ctime(get_time));
        time_len = strlen(my_time);
        *(my_time + time_len -1) = '\0';
        printf("%s ", my_time);
        printf("%s", file_list->name);
    }
    else
    {
        printf("%s\t", file_list->name);
    }
    return 0;
}

int show_dir(Fpath *file_list, const long int mode)
{
    DIR *dir;
    struct dirent *dir_str;
    struct stat sub_buf;
    char path_buf[512] = { '\0'}, *ppath_buf = path_buf;
    char path[512] = {'\0'}, *ppath = path;

    ppath_buf = strcpy( ppath_buf, file_list->full_path);
    if ((dir = opendir( file_list->full_path))==NULL)
    {
        perror( file_list->full_path );
        return -1;
    }
    if( IS_R( mode ))
        printf( "%s:\n", file_list->full_path);
    
    while(( dir_str = readdir( dir ))!= NULL)
    {
        ppath = strcpy( ppath, ppath_buf);
        if( !IS_A(mode) && *(dir_str->d_name) == '.')
            continue;
        if( ppath[strlen(ppath) - 1] != '/')
            ppath = strcat( ppath, "/");
        ppath = strcat( ppath, dir_str->d_name);
        file_list->full_path = ppath;
        file_list->name = dir_str->d_name;
        if( lstat( file_list->full_path, &sub_buf) == -1)
        {
            perror( file_list->full_path);
            continue;
        }
        show_file( file_list, &sub_buf, mode);
        if( S_ISLNK( sub_buf.st_mode) && ( IS_L(mode)))
            show_link_content(file_list, &sub_buf);
        if( IS_L(mode) )
            printf( "\n");
    }
    /* traverse directory again, recursively show all sub directories */
    if( IS_R(mode) )
    {
        rewinddir( dir );
        while(( dir_str = readdir( dir ))!=NULL)
        {
            ppath = strcpy( ppath, ppath_buf );
            if( IS_A(mode) && *(dir_str->d_name) == '.' )
                continue;
            if( ppath[strlen( ppath ) - 1] != '/' )
                ppath = strcat( ppath, "/" );
            ppath = strcat(ppath, dir_str->d_name );
            file_list->full_path=ppath;
            file_list->name = dir_str->d_name;
            if( lstat( file_list->full_path, &sub_buf ) == -1)
            {
                perror( file_list->full_path );
                continue;
            }
            if( S_ISDIR( sub_buf.st_mode ) && strcmp( dir_str->d_name, ".") !=0 && strcmp( dir_str->d_name, ".." ) != 0 )
            {
                printf("\n");
                show_dir( file_list, mode);
            }
        }
    }
    closedir(dir);
    return 0;
}

/* scan the arg list to get the cmd line args start with the '-' */
/*long int my_get_opt(const int argc, cont char * argv[]) */
int my_get_opt( const int argc, const char **argv)
{
    int i=0;
    int opt_sub_num = 0;
    long int mode = 0;
    char ch = '\0';
    for( i = 1; i < argc; i++)
    {
        ch = **(argv + i);
        if(( ch == '-' ) && ((opt_sub_num = strlen( *(argv + i))) > 1 ))
        {
            int j = 0;
            while( --opt_sub_num )
            {
                switch( *(*(argv + i) + (++j)))
                {
                    case 'l':
                        mode |= L;    /* L is defined in the header "myopt.h"*/
                        break;
                    case 'd':
                        mode |= D;
                        break;
                    case 'r':
                        mode |= R;
                        break;
                    case 'i':
                        mode |= I;
                        break;
                    case 'a':
                        mode |= A;
                        break;
                    default:
                        break;
                }
            }
        }
    }
    return mode;
}
/* get the file list which would list by the command */
int get_file_list( const int argc, const char **argv, Fpath **file_list)
{
    int file_num = 0, i = 0, file_index = 0;
    char ch = '\0';
    for( i=1; i < argc ; i++)
    {
        ch = **(argv + i);
        if( ch == '-' )
        {
            continue;
        }
        file_num++;
    }
    // printf( "file_num = %d\n",file_num );
    if( file_num ==0 )
    {
        file_num = 1;
        *file_list = (Fpath *)malloc(sizeof(Fpath));
        (*file_list + file_index)->full_path = ".";
        (*file_list + file_index++)->name = ".";
    }
    else
    {
        *file_list = (Fpath *)malloc(file_num * sizeof (Fpath));
        for( i=1; i< argc; i++)
        {
            ch = **(argv+ i);
            if( ch== '-')
                continue;
            (*file_list + file_index)->full_path = (char *)*(argv+ i);
            (*file_list + file_index++)->name = (char *)*(argv + i);
        }
    }
    /*
     * for( i = 0; i < file_index; i++ )
     *         printf( "file %d :%s\n", i, file_list[i].full_path );
     */
    return file_num;
}

posted @ 2015-07-11 23:13  little-snake  阅读(126)  评论(0编辑  收藏  举报