1. 程式人生 > >系統呼叫實現Linux命令 ls -al

系統呼叫實現Linux命令 ls -al

二話不說直接上程式碼(這是我之前在網易部落格上寫的搬過來)

ls.c 如下:

#include "ls.h"
/**********************************************************************/
//將路徑定位到argv[1]目錄下 開啟該目錄 返回指標指向該檔案
//讀取檔案 每讀取一次檔案目錄下的指標方向後移 並返回檔案屬性結構體
//由於讀取檔案時的檔案屬性結構體不完整 
//所以將檔案指標指向的檔名傳入stat函式得到該檔名的詳細屬性
//獲取時間時  注意範圍 具體規則將man手冊 man localtime
//注意型別的對應關係
/**********************************************************************/

void ls_al(char path[]){
	
	//將目錄切換到輸入的資料夾下argv[1]
	if(-1 == chdir(path)){ 
		ERR_PRINT("<ls.h>In ls_al:chdir");
	}
	
	/*開啟使用者輸入的資料夾argv[1]*/ 
	//DIR *opendir(const char *name);
	//輸入資料夾路徑名
	//返回一個指向該資料夾指標
	DIR *dir = opendir(path);//DIR* 類似 FILE*

	/*讀取當前資料夾下的資訊*/
	//struct dirent *readdir(DIR *dirp);
	//輸入一個資料夾指標
	//返回一個該資料夾下的資訊結構體
	struct dirent *dir_info = readdir(dir); // It returns NULL on reaching the end of the directory
	
	struct stat info_buf;			//目錄下所有檔案詳細資訊結構體
	char file_style = '-';			//檔案型別
	char power[10] = "---------";	//各使用者對檔案許可權
	
	int dev_main,dev_sub; //裝置驅動號
	int file_size;		  //檔案大小	
	
	struct tm *time_struct; //時間結構體 localtime(info_buf.st_atime);
	
	while(NULL != dir_info){ // It returns NULL on reaching the end of the directory

		/*獲取某個檔案的詳細資訊存入結構體info_buf*/
		//int stat(const char *path, struct stat *buf);
		//輸入目錄下的某個檔名 要存入的結構體
		if(-1 == stat(dir_info->d_name,&info_buf))
			ERR_PRINT("<ls.h>In ls_al:stat");
		
		time_struct = localtime(&info_buf.st_atime);//根據最後一次訪問的時間(秒數)獲取本地世紀結構體
		
		/*獲取檔案的型別*/
		switch(info_buf.st_mode & S_IFMT){
			case S_IFSOCK:file_style = 's';break;
			case S_IFLNK :file_style = 'l';break;
			case S_IFREG :file_style = '-';break;
			case S_IFBLK :file_style = 'b';break;
			case S_IFDIR :file_style = 'd';break;
			case S_IFCHR :file_style = 'c';break;
			case S_IFIFO :file_style = 'p';break;
		}
		/*獲取USR GRP OTH 的許可權*/
		power[0] = ((info_buf.st_mode & S_IRWXU) & S_IRUSR) ? 'r' : '-';
		power[1] = ((info_buf.st_mode & S_IRWXU) & S_IWUSR) ? 'w' : '-';
		power[2] = ((info_buf.st_mode & S_IRWXU) & S_IXUSR) ? 'x' : '-';
		
		power[3] = ((info_buf.st_mode & S_IRWXG) & S_IRGRP) ? 'r' : '-';
		power[4] = ((info_buf.st_mode & S_IRWXG) & S_IWGRP) ? 'w' : '-';
		power[5] = ((info_buf.st_mode & S_IRWXG) & S_IXGRP) ? 'x' : '-';
		
		power[6] = ((info_buf.st_mode & S_IRWXO) & S_IROTH) ? 'r' : '-';
		power[7] = ((info_buf.st_mode & S_IRWXO) & S_IWOTH) ? 'w' : '-';
		power[8] = ((info_buf.st_mode & S_IRWXO) & S_IXOTH) ? 'x' : '-';
		
		/*獲取目錄下某個檔案的UID GID*/
		//struct passwd *getpwuid(uid_t uid);
		//struct group *getgrgid(gid_t gid);
		//輸入某個檔案的ID 由結構體info_buf.st_uid,info_buf.st_gid獲得
		//返回一個結構體 裡面包含ID名
		struct passwd *uid_struct = getpwuid(info_buf.st_uid);
		struct group  *gid_struct = getgrgid(info_buf.st_gid);
		
		/*獲取非裝置驅動檔案大小 和 裝置驅動的主驅動號和副驅動號 dev_main & dev_sub*/
		if('b' == file_style || 'c' == file_style){//(裝置檔案)
			dev_main = (info_buf.st_rdev>>8)&0XFF;
			dev_sub = (info_buf.st_rdev>>0)&0XFF;
			
			//列印某一個檔案的詳細資訊(裝置檔案)
			printf("%c%s %3d %8s %8s %3d,%3d %4d-%d-%d %2d:%2d:%2d  %s \n"
			,file_style				//檔案型別
			,power					//使用者對檔案的許可權
			,info_buf.st_nlink		//檔案連結號
			,uid_struct->pw_name	//UID name
			,gid_struct->gr_name	//GID name
			,dev_main				//主驅動號
			,dev_sub				//副驅動號
			,time_struct->tm_year+1900//年月日時分秒
			,time_struct->tm_mon+1
			,time_struct->tm_mday
			,time_struct->tm_hour
			,time_struct->tm_min
			,time_struct->tm_sec
			,dir_info->d_name		//檔名
			);
		}
		else{//(非裝置檔案)
			file_size = info_buf.st_size;
			
			//列印某一個檔案的詳細資訊(非裝置檔案)
			printf("%c%s %3d %8s %8s %7d %4d-%d-%d %2d:%2d:%2d  %s \n"
			,file_style				//檔案型別
			,power					//使用者對檔案的許可權
			,info_buf.st_nlink		//檔案連結號
			,uid_struct->pw_name	//UID name
			,gid_struct->gr_name	//GID name
			,file_size				//檔案大小
			,time_struct->tm_year+1900//年月日時分秒
			,time_struct->tm_mon+1
			,time_struct->tm_mday
			,time_struct->tm_hour
			,time_struct->tm_min
			,time_struct->tm_sec
			,dir_info->d_name		//檔名
			);
		}
		
		//檔案指標下移一位 讀取下一個檔案(每讀取一次 dir指標下移一位 類似指標)
		dir_info = readdir(dir);
		
	}
	
}
main.c如下:
#include "alldef.h"#include "ls.h"

/*
 *	功能:C語言實現 ls -al 命令
 *	作者:KayChan
 *	日期:2015-08-05
 */


int main(int argc,char *argv[]){
	
	ls_al(argv[1]);
	
	return 0;
}

執行: ./ls + pathname