1. 程式人生 > >實現ls-l功能

實現ls-l功能

1、“ls -l”的意義

  以長格式顯示目錄下的內容列表。輸出的資訊從左到右依次包括檔名,檔案型別、許可權模式、硬連線數、所有者、組、檔案大小和檔案的最後修改時間等。

  例:-rw-rw-r-- 1 using using 3102 7月 22 17:06 test.c

    drwxrwxr-x 2 using using 4096 7月 22 18:39 testdir

    lrwxrwxrwx 1 using using 17 7月 22 18:43 shared -> /media/sf_shared/

  其中深藍色為目錄檔案,天藍色為軟連線檔案(具體顏色和vimrc配置有關)。

  第一欄位:首字母代表的是檔案型別 ,其中"-"為普通檔案、"d"為目錄檔案、"c"為字元裝置檔案、"b"為塊裝置檔案、"p"為管道檔案、"l"為連結檔案、"s"為socket檔案。“rwx”分別代表擁有讀、寫和執行許可權,“-”代表無對應許可權。三個“rwx”依次代表檔案所有者、檔案所有者所在使用者組、其它使用者對檔案擁有的許可權。

  第二欄位:檔案硬連線數量

  第三欄位:檔案擁有者

  第四欄位:檔案擁有者所在組

  第五欄位:檔案大小(以位元組為單位)

  第六欄位:檔案最後更改時間

  第七欄位:檔名(若為連結檔案則追加顯示其連結的原檔案的路徑)

實現程式碼

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <pwd.h> 
#include <grp.h> 
#include <libgen.h>


#define ERR_EXIT(m) \
do\
{\
    perror(m);\
    exit(EXIT_FAILURE);\
}while(0)\

void lsdir(char *dirname);
void lsfile(char *filename);
void lsfile(char *filename);
char getFileType(struct stat *fstat);
void getFilePerm(struct stat *st, char *perm);

int main(int argc,char **argv)
{

if(argc != 2){
    fprintf(stderr,"usage:%s [filepath]\n",argv[0]);
    exit(EXIT_FAILURE);
}
struct stat fstat;
if(lstat(argv[1],&fstat) == -1)
    ERR_EXIT("STAT ERROR");

if(S_ISDIR(fstat.st_mode))
{
    lsdir(argv[1]);
}
else{
    lsfile(argv[1]);
}
return 0;
}

void lsdir(char *dirname)
{
DIR *dir;
char filename[100] = {0};
dir =opendir(dirname); 
if(dir == NULL)
    ERR_EXIT("opendir error");
struct dirent *dentry;
while((dentry = readdir(dir)) != NULL)
{
    
    char *fname;
    fname = dentry->d_name;
    if(strncmp(fname,".",1) == 0)
        continue;
    sprintf(filename,"%s/%s",dirname,fname);
    lsfile(filename);
}

closedir(dir);

}

//-rw-r--r--.   1            zxy        zxy        2586        Jul 10 17:00    ls.c
//型別及許可權  硬連結數        擁有者    所屬組    檔案大小    建立時間        檔名
void lsfile(char *filename)
{
struct stat tmpstat;
if(lstat(filename,&tmpstat) == -1)
    ERR_EXIT("STAT ERROR");
char buf[11]= {0};
strcpy(buf,"----------");
char type;
type = getFileType(&tmpstat);
char *bname = basename(filename);
buf[0] = type;
if(type == 'l'){
    char content[1024];
    if(readlink(filename,content,1024) == -1)
        ERR_EXIT("readlink error");
    sprintf(bname,"%s -> %s",bname,content);

}
getFilePerm(&tmpstat,buf);
struct tm *ftime;
ftime = localtime(&tmpstat.st_mtime);

printf("%s %d %s %s %10ld %02d %02d %02d:%02d %s\n",
    buf,tmpstat.st_nlink,
    getpwuid(tmpstat.st_uid)->pw_name,
    getgrgid(tmpstat.st_gid)->gr_name,
    tmpstat.st_size,
    ftime->tm_mon+1,
    ftime->tm_mday,
    ftime->tm_hour,
    ftime->tm_min,
    bname);

}

//獲得檔案型別
char getFileType(struct stat *st)
{
char type = '-';
switch (st->st_mode  & S_IFMT)
{
    case S_IFSOCK:
    type = 's';
            break;
    case S_IFLNK:
    type = 'l';
            break;
    case S_IFREG:
    type = '-';
            break;
    case S_IFBLK:
    type = 'b';
            break;
    case S_IFDIR:
    type = 'd';
            break;
    case S_IFCHR:
    type = 'c';
            break;
    case S_IFIFO:
    type = 'p';
            break;
}
return type;
}

//獲得檔案訪問許可權
void getFilePerm(struct stat *st, char *perm)
{
mode_t mode = st->st_mode;
if (mode & S_IRUSR)
    perm[1] = 'r';
if (mode & S_IWUSR)
    perm[2] = 'w';
if (mode & S_IXUSR)
    perm[3] = 'x';
if (mode & S_IRGRP)
    perm[4] = 'r';
if (mode & S_IWGRP)
    perm[5] = 'w';
if (mode & S_IXGRP)
    perm[6] = 'x';
if (mode & S_IROTH)
    perm[7] = 'r';
if (mode & S_IWOTH)
    perm[8] = 'w';
if (mode & S_IXOTH)
    perm[9] = 'x';
}