linux cアナログlsコマンドの詳細解



/*
  ls , -tariRl. ,
  , ,
 */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/stat.h>
#include<dirent.h>
#include<sys/ioctl.h>
#include<pwd.h>
#include<grp.h>
#define LL (1<<0)  /* l */
#define IL (1<<1)  /* i */
#define RU (1<<2)  /* R */
#define TL (1<<16) /* t */
#define AL (1<<17) /* a */
#define RL (1<<18) /* r */
#define LENGTH 500 /* */
#define MAX_FILE_COUNT 500/* */
/* */
void error(char* error_message,int line);
void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode);
void display_simply(char (*namelist)[LENGTH],int n);
void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_LL_IL(struct stat * stalist,char (*namelist)[LENGTH],int n);
void display_RU(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_IL(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode);
void display_RU_IL_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode);
/* */
int main(int argc,char **argv)
{
    int i,j;
    /*mode 16 ,16 。 0-3 ,16-18 , , 。
    mode 0 1 l ,mode 1 1 i ,mode 2 1 R ,mode 16 1 t ,mode 17 1 a ,mode 18 1 r */
    int mode=0;
    char error_message[LENGTH]={0};/* */
    char path[LENGTH]={0};/* */
    struct stat stalist[MAX_FILE_COUNT];/* */
    char  namelist[MAX_FILE_COUNT][LENGTH];/* */
    int flag=0;/* */
    int count;/* */
    /* */
    for(i=1;i<argc;i++){
        if(argv[i][0]=='-'){/* */
     for(j=1;j<strlen(argv[i]);j++){
  if(argv[i][j]=='l')
      mode=mode|LL;
  else if(argv[i][j]=='i')
      mode=mode|IL;
  else if(argv[i][j]=='R')
      mode=mode|RU;
  else if(argv[i][j]=='r')
      mode=mode|RL;
  else if(argv[i][j]=='a')
      mode=mode|AL;
  else if(argv[i][j]=='t')
      mode=mode|TL;
  else{
      snprintf(error_message,LENGTH,"no option of %c",argv[i][j]);
      error(error_message,__LINE__);
  }     
     }
 }else{/* */
     if(flag==1)
  error("can not specify more then two dir or file",__LINE__);
     else
  flag=1;
            if(argv[i][0]!='/'){/* */
  strcat(path,get_current_dir_name());
  strcat(path,"/");
  strncat(path,argv[i],strlen(argv[i]));
     }else/* */
  strcpy(path,argv[i]);
 }
    }
    if(flag==0)/* , */
 strcat(path,get_current_dir_name());
    /* mode */
    count=file_list(path,stalist,namelist,mode);

    /* mode */
    display(stalist,namelist,count,mode);
    return 0;
}
/* */
int file_list(char* path,struct stat* stalist,char (*namelist)[LENGTH],int mode)
{
    int i=0,index,j,k;
    DIR *dir;
    struct dirent *ptr;
    char str[LENGTH];
    char nametemp[LENGTH];
    struct stat statemp;
    if(stat(path,&stalist[0])<0){
// puts(path);
 error("the specify file is not exist",__LINE__);
    }
    if(S_ISDIR(stalist[0].st_mode)){/* */
        if((dir=opendir(path))==NULL){/* */
     sprintf(str,"can not open %s",path);
     error(str,__LINE__);
 }
        chdir(path);/* path*/
        i=0;
 while((ptr=readdir(dir))!=NULL){/* */
     if(ptr->d_name[0]=='.' && !(mode & AL))/* */
  continue;
     /* stalist namelist */
     for(j=i;j>0;j--){
  if(strcmp(ptr->d_name,namelist[j-1])>0)
      break;
     }
     for(k=i;k>j;k--){
  strcpy(namelist[k],namelist[k-1]);
  stalist[k]=stalist[k-1];
     }
            strcpy(namelist[j],ptr->d_name);
            stat(ptr->d_name,&stalist[j]);
     i++;
     if(i==MAX_FILE_COUNT)
  error("file count beyond MAX_FILE_COUNT",__LINE__);
 }
 closedir(dir);
    }else{
 j=strlen(path)-1;
 while(j>=0 && path[j]!='/'){
     j--;
 }
 if(j<0)
     error("path error",__LINE__);
 j++;
 k=0;
        while(path[j]){
     namelist[0][k]=path[j];
            j++;
      k++;
 }
        namelist[0][k]=0;
        return 1;
    }
    if(mode & TL){/* */
 for(j=0;j<i;j++){
     index=j;
     for(k=j+1;k<i;k++)
  if(stalist[index].st_mtime<stalist[k].st_mtime){
      index=k;
  }
     statemp=stalist[j];
     stalist[j]=stalist[index];
     stalist[index]=statemp;
     strcpy(nametemp,namelist[j]);
     strcpy(namelist[j],namelist[index]);
     strcpy(namelist[index],nametemp);
 }
    }
    if(mode & RL){/* */
 for(j=0;j<i/2;j++){
     strcpy(nametemp,namelist[j]);
     strcpy(namelist[j],namelist[i-j-1]);
     strcpy(namelist[i-j-1],nametemp);
     statemp=stalist[j];
     stalist[j]=stalist[i-j-1];
     stalist[i-j-1]=statemp;
 }
    }
    return i;
}
/* mode */
void display(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)
{
    /* mode 16 0*/
    int m = mode & ((1<<16)-1);
    switch(m){
 case 0:
     display_simply(namelist,n);
     break;
 case 1:
     display_LL(stalist,namelist,n);
     break;
 case 2:
     display_IL(stalist,namelist,n);
     break;
 case 3:
     display_LL_IL(stalist,namelist,n);
     break;
 case 4:
     display_RU(stalist,namelist,n,mode);
     break;
 case 5:
     display_RU_LL(stalist,namelist,n,mode);
     break;
        case 6:
     display_RU_IL(stalist,namelist,n,mode);
     break;
 case 7:
     display_RU_IL_LL(stalist,namelist,n,mode);
     break;
    }
}
/* , */
void display_simply(char (*namelist)[LENGTH],int n)
{
    int i,maxlength=0,cols;
    struct winsize ts;
    for(i=0;i<n;i++)
 if(strlen(namelist[i])>maxlength)
     maxlength=strlen(namelist[i]);
    /* */
    ioctl(STDIN_FILENO,TIOCGWINSZ,&ts);
    cols=ts.ws_col;
    cols/=(maxlength+1);
    //lines=ts.ws_row;
    for(i=0;i<n;i++){
       if(i!=0 && i%cols==0)
    puts("");
       printf("%*s",-(maxlength+1),namelist[i]);
    }
    putchar('
');
}
/*-l , */
void display_LL(struct stat * stalist,char (*namelist)[LENGTH],int n)
{
    int i,mode;
    char* str;
    for(i=0;i<n;i++){
        mode=stalist[i].st_mode;
        if(S_ISDIR(mode))
     printf("d");
 else
     printf("-");
 if(mode & (1<<8))
     printf("r");
 else
     printf("-");
        if(mode & (1<<7))
     printf("w");
 else
     printf("-");
        if(mode & (1<<6))
     printf("x");
 else
     printf("-");
        if(mode & (1<<5))
     printf("r");
 else
     printf("-");
        if(mode & (1<<4))
     printf("w");
 else
     printf("-");
        if(mode & (1<<3))
     printf("x");
 else
     printf("-");
        if(mode & (1<<2))
     printf("r");
 else
     printf("-");
        if(mode & (1<<1))
     printf("w");
 else
     printf("-");
        if(mode & (1<<0))
     printf("x");
 else
     printf("-");
 printf(" %-3d",stalist[i].st_nlink);
 printf(" %-6s",getpwuid(stalist[i].st_uid)->pw_name);
 printf(" %-6s",getgrgid(stalist[i].st_gid)->gr_name);
 printf(" %-10d",stalist[i].st_size);
 str=ctime(&stalist[i].st_mtime);
 str[strlen(str)-2]=0;
 printf(" %s",str);
 printf(" %s
",namelist[i]);
    }
}
/*-i , */
void display_IL(struct stat* stalist,char (*namelist)[LENGTH],int n)
{
    int i,maxlength=0,cols;
    struct winsize ts;
    for(i=0;i<n;i++)
 if(strlen(namelist[i])>maxlength)
     maxlength=strlen(namelist[i]);
    /* */
    ioctl(STDIN_FILENO,TIOCGWINSZ,&ts);
    cols=ts.ws_col;
    cols/=(maxlength+9);
    //lines=ts.ws_row;

    for(i=0;i<n;i++){
       if(i!=0 && i%cols==0)
    puts("");
       printf("%-8d ",stalist[i].st_ino);
       printf("%*s",-(maxlength+1),namelist[i]);
    }
    putchar('
');  
}
/*-li , */
void display_LL_IL(struct stat * stalist,char (*namelist)[LENGTH],int n)
{
    int i,mode;
    char* str;
    for(i=0;i<n;i++){
        printf("%-8d ",stalist[i].st_ino);
        mode=stalist[i].st_mode;
        if(S_ISDIR(mode))
     printf("d");
 else
     printf("-");
 if(mode & (1<<8))
     printf("r");
 else
     printf("-");
        if(mode & (1<<7))
     printf("w");
 else
     printf("-");
        if(mode & (1<<6))
     printf("x");
 else
     printf("-");
        if(mode & (1<<5))
     printf("r");
 else
     printf("-");
        if(mode & (1<<4))
     printf("w");
 else
     printf("-");
        if(mode & (1<<3))
     printf("x");
 else
     printf("-");
        if(mode & (1<<2))
     printf("r");
 else
     printf("-");
        if(mode & (1<<1))
     printf("w");
 else
     printf("-");
        if(mode & (1<<0))
     printf("x");
 else
     printf("-");
 printf(" %-3d",stalist[i].st_nlink);
 printf(" %-6s",getpwuid(stalist[i].st_uid)->pw_name);
 printf(" %-6s",getgrgid(stalist[i].st_gid)->gr_name);
 printf(" %-10d",stalist[i].st_size);
 str=ctime(&stalist[i].st_mtime);
 str[strlen(str)-2]=0;
 printf(" %s",str);
 printf(" %s
",namelist[i]);

    }
}
/*-R , , */
void display_RU(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];
    puts(get_current_dir_name());
    display_simply(namelist,n);
    putchar('
');
    strcpy(path,get_current_dir_name());

    for(i=0;i<n;i++){
        if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
          continue;
 if(S_ISDIR(stalist[i].st_mode)){
     strcpy(temp,path);
     strcat(path,"/");
     strcat(path,namelist[i]);
     count=file_list(path,sta,name,mode);
     display_RU(sta,name,count,mode);
            strcpy(path,temp);
 }
    }
}
/*-Rl , , */
void display_RU_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];
    puts(get_current_dir_name());
    display_LL(stalist,namelist,n);
    putchar('
');
    strcpy(path,get_current_dir_name());

    for(i=0;i<n;i++){
 if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
          continue;
 if(S_ISDIR(stalist[i].st_mode)){
     strcpy(temp,path);
     strcat(path,"/");
     strcat(path,namelist[i]);
     count=file_list(path,sta,name,mode);
     display_RU_LL(sta,name,count,mode);
     strcpy(path,temp);
 }
    }
}
/*-Ri , , , */
void display_RU_IL(struct stat* stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];
    puts(get_current_dir_name());
    display_IL(stalist,namelist,n);
    putchar('
');
    strcpy(path,get_current_dir_name());

    for(i=0;i<n;i++){
 if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
          continue;
 if(S_ISDIR(stalist[i].st_mode)){
     strcpy(temp,path);
     strcat(path,"/");
     strcat(path,namelist[i]);
     count=file_list(path,sta,name,mode);
     display_RU_IL(sta,name,count,mode);
     strcpy(path,temp);
 }
    }
}
/*-Ril , , , */
void display_RU_IL_LL(struct stat * stalist,char (*namelist)[LENGTH],int n,int mode)
{
    int i,count;
    char path[LENGTH]={0},temp[LENGTH]={0};
    struct stat sta[MAX_FILE_COUNT];
    char name[MAX_FILE_COUNT][LENGTH];
    puts(get_current_dir_name());
    display_LL_IL(stalist,namelist,n);
    putchar('
');
    strcpy(path,get_current_dir_name());

    for(i=0;i<n;i++){
 if(strcmp(namelist[i],".")==0 || strcmp(namelist[i],"..")==0)
          continue;
 if(S_ISDIR(stalist[i].st_mode)){
     strcpy(temp,path);
     strcat(path,"/");
     strcat(path,namelist[i]);
     count=file_list(path,sta,name,mode);
     display_RU_IL_LL(sta,name,count,mode);
     strcpy(path,temp);
 }
    }
}
//
void error(char* error_message,int line)
{
    char str[5];
    sprintf(str,"%d:",line);
    strcat(str,error_message);
    perror(str);
    exit(EXIT_FAILURE);
}