Linux -- ls -l 命令的函數實現

  1. 函數:
      Linux – stat, fstat, lstat, fstatat函數
      Linux – asctime, ctime, gmtime, localtime, mktime, asctime_r, ctime_r, gmtime_r, localtime_r函數

  2. 效果:

  3. file_mode.h文件

    #ifndef __FILE_MODE_H
    
    #define __FILE_MODE_H
    
     void stat_mode(const char *pathname);
    
    #endif
    
  4. file_mode.c文件

    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include "../include/file_mode.h"
    #include <stdio.h>
    #include <pwd.h>
    #include <grp.h>
    #include <time.h>
    /**
     * 函數名:stat_mode
     * 功能: 顯示文件的類型和權限信息
     * 參數: const char *pathname -- 文件標識
     * 返回: 無
     */
     void stat_mode(const char *pathname){
    	 
    	struct stat sb;
    	struct passwd *getuser=NULL;
    	struct group *getgroup=NULL;
    	struct tm *status_tm=NULL;
    	char rwx[]={'x','w','r'};
    	char buf[1024];
        ssize_t len;
    	if(-1==lstat(pathname, &sb)){
    		perror("lstat");
    		exit(EXIT_FAILURE);
    	}
    	switch(sb.st_mode&S_IFMT){ /*判斷文件類型*/
    		case S_IFSOCK : fprintf(stderr , "%c" , 's');  break;	/*套接字文件*/  
    		case S_IFLNK  : fprintf(stderr , "%c" , 'l');  break;   /*符號鏈接文件*/
    		case S_IFREG  : fprintf(stderr , "%c" , '-');  break;   /*普通文件*/
     		case S_IFDIR  : fprintf(stderr , "%c" , 'd');  break;   /*目錄文件*/
    		case S_IFCHR  : fprintf(stderr , "%c" , 'c');  break;   /*字符設備文件*/
    		case S_IFIFO  : fprintf(stderr , "%c" , 'p');  break;   /*管道文件*/
    		case S_IFBLK  : fprintf(stderr , "%c" , 'b');  break;   /*塊設備文件*/
    		default 	  :	fprintf(stderr , "%s" , "unknown?");    /*未知文件*/
    	}
    	for(int i=8 ; i>=0 ; i--){	/*文件權限*/
    		if(sb.st_mode&0x1<<i)
    			fprintf(stderr,"%c",rwx[i%3]);
    		else
    			fprintf(stderr,"%c",'-');
    	}
    	fprintf(stderr," %2lu",sb.st_nlink);	/*硬鏈接數*/
    	
    	if(NULL==(getuser=getpwuid(sb.st_uid))){
    		perror("getpwuid");
    		exit(EXIT_FAILURE);		
    	}
    	fprintf(stderr," %s",getuser->pw_name);	/*用戶名稱*/
    	 
    	if(NULL==(getgroup=getgrgid(sb.st_gid))){
    		perror("getgrgid");
    		exit(EXIT_FAILURE);
    	}
    	fprintf(stderr," %s",getgroup->gr_name);/*組名稱*/
    	
    	fprintf(stderr," %5ld",sb.st_size);	/*文件的大小*/
    	
    	//status_tm=localtime(&sb.st_ctime) -- 另一種方式
    	if(NULL==(status_tm=localtime(&sb.st_ctim.tv_sec))){ /*獲取狀態改變的時間*/
    		perror("localtime");
    		exit(EXIT_FAILURE);
    	}
    
    	fprintf(stderr,"%2d月 %2d %02d:%02d %s", status_tm->tm_mon+1 , status_tm->tm_mday , 
    										    status_tm->tm_hour , status_tm->tm_min ,
    										    pathname );	 /* 月份 (0-11) */
    
    	if ((len = readlink(pathname, buf, sizeof(buf)-1)) != -1){ /*讀取符號鏈接的內容*/
    			buf[len] = '\0';
    			printf(" -> %s",buf);
    	}
    	putchar('\n');
     }
    
  5. user_main.c文件

    #include <stdio.h>
    #include "../include/file_mode.h"
    #include <sys/types.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    int main(int argc,char *argv[])      
    {
    	struct stat sb;
    	DIR *dirp=NULL;
    	struct dirent *dir=NULL;
    	char pathname[1024];
    	if(argc == 2 && !strcmp(argv[1],"-l"))  /*判斷命令參數*/
    	{
    		strcpy(pathname , ".");
    		
    	}
    	else if(argc != 3){
    		printf("Usage : %s -l [文件]\n", argv[0]);
    		exit(EXIT_FAILURE);
    	}
    	else {
    		strcpy(pathname,argv[2]);
    	}
    	if(-1==lstat(pathname, &sb)){
    		perror("lstat");
    		exit(EXIT_FAILURE);
    	}
    	if(S_ISDIR(sb.st_mode)){	/*判斷是否是目錄文件*/
    		if(NULL==(dirp=opendir(pathname))){
    			perror("opendir");
    			exit(EXIT_FAILURE);
    		}
    		
    		if(-1==chdir(pathname)) /*改變當前目錄已讓lstat讀取到目錄下的文件*/
    		{
    			perror("chdir");
    			exit(EXIT_FAILURE);			
    		}
    		
    		while(NULL!=(dir=readdir(dirp))){
    			if(*(dir->d_name)!='.') /*不顯示.和..目錄文件和隱藏文件*/
    				stat_mode(dir->d_name);	/*不是目錄文件*/
    		}
    		
    	}
    	else{
    		stat_mode(pathname);	/*不是目錄文件*/
    	}
    		
    	return 0;
    }       
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章