日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux C语言实现ls -l

發布時間:2023/12/20 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux C语言实现ls -l 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LinuxC語言實現ls -l功能???


宗旨:技術的學習是有限的,分享的精神是無限的。

?

需求:用ls -l顯示文件夾下所有的文件及屬性??

分析:1 ls顯示文件夾下的所有文件,首先用opendir打開文件夾,再用readdir讀取文件夾里面的文件,最后closedir關閉文件夾。

? ? ? ? ? ? ?2 ls-l比較復雜,打印出來的內容包括:(文件屬性+文件名)由以下幾部分構成——文件的類型(d——目錄文件 -——文本文件...)文件的可執行權限 ? ?所屬組的權限,其它組的權限 ? ?硬鏈接數?????文件擁有者文件 ? ?擁有者組 ? ?文件大小 ? ?時間 ? ?文件名?????

?

解決方案:??

1. 要想實現ls -l就得知道通過什么系統調用獲取文件信息,首先自然是要通過man來查找相關的系統調用。

man -k file | grep status man -k file | grep information man -k file | grep info

通過上面的搜索就可以得到stat這個系統調用獲取文件屬性。

man 2 stat獲取系統調用的詳細使用方法:

#include <sys/types.h> #include <sys/stat.h> #include <unistd.h>struct stat {dev_t st_dev; /* ID of device containing file */ino_t st_ino; /* inode number */mode_t st_mode; /* protection */nlink_t st_nlink; /* number of hard links */uid_t st_uid; /* user ID of owner */gid_t st_gid; /* group ID of owner */dev_t st_rdev; /* device ID (if special file) */off_t st_size; /* total size, in bytes */blksize_t st_blksize; /*blocksize for file system I/O */blkcnt_t st_blocks; /* number of 512B blocks allocated */time_t st_atime; /* time of last access */time_t st_mtime; /* time of last modification */time_t st_ctime; /* time of last status change */ };

只要通過相應字段進行格式處理就行啦!

?

2.權限處理:st_mode就是文件的權限部分。St_mode本身就是一個16位的二進制,前四位是文件的類型,緊接著三位是特殊權限,左后九位就是ls -l列出來的九個權限。

linux本身提供了很多測試宏來測試文件的類型的

#define __S_IFMT 0170000 /* These bitsdetermine file type. */ /* File types. */ #define __S_IFDIR 0040000 /*目錄 */ #define __S_IFCHR 0020000 /* 字符設備 */ #define __S_IFBLK 0060000 /* 塊設備. */ #define __S_IFREG 0100000 /* 普通文件. */ #define __S_IFIFO 0010000 /* 管道文件 */ #define __S_IFLNK 0120000 /* 鏈接文件 */ #define __S_IFSOCK 0140000 /* 套接字*/

利用上面的測試宏就可以判斷文件的類型,至于文件的權限部分可以使用掩碼的方式來處理。

具體代碼如下:vim file_mode.c

#include"list.h"//man2 stat可看到文件基本屬性 void file_mode(struct stat *buf) {int i;char buff[10] = {"----------"};switch(buf->st_mode & S_IFMT)//按位&獲取文件基本屬性{case S_IFIFO:buff[0] = 'f';break;case S_IFDIR:buff[0] = 'd';break;case S_IFSOCK:buff[0] = 's';break;case S_IFBLK:buff[0] = 'b';break;case S_IFLNK:buff[0] = 'l';break;}if(buf->st_mode & S_IRUSR ){buff[1] = 'r';}if(buf->st_mode & S_IWUSR ){buff[2] = 'w';}if(buf->st_mode & S_IXUSR ){buff[3] = 'x';}if(buf->st_mode & S_IRGRP ){buff[4] = 'r';}if(buf->st_mode & S_IWGRP ){buff[5] = 'w';}if(buf->st_mode & S_IXGRP ){buff[6] = 'x';}if(buf->st_mode & S_IROTH ){buff[7] = 'r';}if(buf->st_mode & S_IWOTH ){buff[8] = 'w';}if(buf->st_mode & S_IXOTH ){buff[9] = 'x';}for(i = 0; i < 10; i++){printf("%c", buff[i]); //循環打印} }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

3.ctime時間處理:stat中的st_mtime是一個時間戳,而ls -l顯示出來的是一個格式化后的字符串,所以需要對st_mtime字段進行格式化處理。

ctime接受一個time_t類型的值,可將其轉換為FriJul 18 22:12:43 2014這樣的格式,其中最前面的星期幾不是我們要的,只要其后的值。代碼如下:

printf("\t%.12s",4 + ctime(&buf.st_mtime));//buf是一個文件的stat結構體。

?

4.文件所有者和文件所有者組:通過stat結構體的注釋信息可以看出,stat只能獲取文件的uidgid并不是uid gid對應的用戶或組的名稱。

uid找到對應的用戶名是可以通過getpwuid這個系統調用獲取,這個系統調用接受一個uid返回一個passwd的結構體,這個結構體成員如下:

char *pw_name;//User’s login name. uid_t pw_uid; //umerical user ID. gid_t pw_gid; //Numerical group ID. char *pw_dir;//Initial working directory. char *pw_shell;//Program to use as shell.<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

gid對應的組名同樣可以找到一個系統調用來獲取,通過man我發現可以通過getgrgid()系統調用傳入一個gid

返回這個gid對應的一個group結構體,這個結構體成員如下:

char *gr_name; /* The name of the group.*/ gid_t gr_gid; /*Numerical group ID.*/ char **gr_mem; /*Pointer to a null-terminated array of character pointers to member names.*/

實現代碼:

#include "list.h"void file_gid_uid(int uid, int gid) {struct passwd *ptr;struct group *str; //結構體中存放文件所有者名和文件所有者組名ptr = getpwuid(uid); //調用函數獲取文件所有者指針str = getgrgid(gid); //調用函數獲取文件所有者組指針printf("\t%s\t%s", ptr-> pw_name, str -> gr_name); //打印文件所有者和文件所有者組 }

5.完整代碼展示:

// list.h頭文件,接口的聲明 #ifndef LIST_H #define LIST_H#include<stdio.h> #include<sys/types.h> #include<dirent.h> #include<sys/stat.h> #include<string.h> #include<unistd.h> #include<fcntl.h> #include<stdlib.h> #include<time.h> #include<grp.h> #include<pwd.h>void file_mode(struct stat* buf); void file_gid_uid(int uid, int gid); void file_operation(char **argv);#endif /* LIST_H */<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

// list.c主框架 #include"list.h"int main(int argc, char **argv) {if(argc == 1){argv[1] = "./"; // 缺省為當前目錄}file_operation(argv);return 0; }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">???????</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

// file_mode.c文件屬性 #include"list.h"//man 2 stat可看到文件基本屬性 void file_mode(struct stat *buf) {int i;char buff[10] = {"----------"};switch(buf->st_mode & S_IFMT)//按位&獲取文件基本屬性{case S_IFIFO:buff[0] = 'f';break;case S_IFDIR:buff[0] = 'd';break;case S_IFSOCK:buff[0] = 's';break;case S_IFBLK:buff[0] = 'b';break;case S_IFLNK:buff[0] = 'l';break;}if(buf->st_mode & S_IRUSR ){buff[1] = 'r';}if(buf->st_mode & S_IWUSR ){buff[2] = 'w';}if(buf->st_mode & S_IXUSR ){buff[3] = 'x';}if(buf->st_mode & S_IRGRP ){buff[4] = 'r';}if(buf->st_mode & S_IWGRP ){buff[5] = 'w';}if(buf->st_mode & S_IXGRP ){buff[6] = 'x';}if(buf->st_mode & S_IROTH ){buff[7] = 'r';}if(buf->st_mode & S_IWOTH ){buff[8] = 'w';}if(buf->st_mode & S_IXOTH ){buff[9] = 'x';}for(i = 0; i < 10; i++){printf("%c", buff[i]); //循環打印} }

// file_gid_uid.c #include"list.h"void file_gid_uid(int uid, int gid) {struct passwd *ptr;struct group *str;//結構體中存放文件所有者名和文件所有者組名ptr = getpwuid(uid);//調用函數獲取文件所有者指針str = getgrgid(gid);//調用函數獲取文件所有者組指針printf("\t%s\t%s", ptr ->pw_name, str -> gr_name); //打印文件所有者和文件所有者組 }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>

// file_operation.c #include"list.h"void file_operation(char** argv) {DIR* fd; //定義文件夾類型struct dirent* fp;//fp文件夾返回值struct stat buf;int ret;//獲取文件屬性char temp[100]; //中間變量存放文件路徑if((fd = opendir(argv[1])) == NULL)//打開文件夾{perror("open file fail!");exit(0);}while((fp = readdir(fd)) != NULL)//循環讀取文件夾中的文件信息{strcpy(temp, argv[1]); //將路徑付給中間變量tempstrcat(temp, fp -> d_name); //把文件名字添加到路徑后面形成完整的路徑if((ret = stat(temp, &buf)) == -1) //獲取文件基本屬性{perror("stat");exit(0);}file_mode(&buf);//文件屬性(目錄,鏈接……,可讀,可寫,可執行)printf(" %d", buf.st_nlink); //打印鏈接數file_gid_uid(buf.st_uid, buf.st_gid); //調用函數打印出文件擁有者和文件所有者組printf("\t%ld", buf.st_size); //打印文件大小//Time();//獲取時間printf("\t%.12s ", 4 + ctime(&buf.st_mtime));printf(" %s\n", fp -> d_name); //打印文件名}closedir(fd); } #makefile: ###################################### # 可執行文件和動態鏈接庫的makefile ###################################### #source file #源文件,自動找所有.c和.cpp文件,并將目標定義為同名.o文件 SOURCE := $(wildcard *.c) $(wildcard *.cpp) OBJS := $(patsubst %.c,%.o,$(patsubst%.cpp,%.o,$(SOURCE)))#target youcan change test to what you want #目標文件名,輸入任意你想要的執行文件名 TARGET := app TARGET_2 := libtest.so#compile andlib parameter #編譯參數 CC :=gcc LIBS := LDFLAGS := DEFINES := INCLUDE := -I. CFLAGS := -g $(DEFINES) $(INCLUDE)#-Wall -O3 -DDEBUG CXXFLAGS:=$(CFLAGS) -DHAVE_CONFIG_H SHARE := -fPIC -shared -o #i think youshould do anything here #下面的基本上不需要做任何改動了 .PHONY :everything objs clean veryclean rebuildeverything :$(TARGET) $(TARGET_2)all :$(TARGET) $(TARGET_2)objs : $(OBJS)rebuild:veryclean everythingclean :rm -fr *.overyclean :cleanrm -fr $(TARGET)rm -fr $(TARGET_2) $(TARGET_2) :$(OBJS)$(CC) $(CXXFLAGS) $(SHARE) $@ $(OBJS)$(LDFLAGS) $(LIBS) $(TARGET) :$(OBJS)$(CC) $(CXXFLAGS) -o $@ $(OBJS)$(LDFLAGS) $(LIBS)

總結

以上是生活随笔為你收集整理的Linux C语言实现ls -l的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。