作者:曹忠明,华清远见嵌入式学院讲师。
ls命令是linux下最常用的命令之一,它的使用很简单,可是功能却很多,有很多的参数,这里我们就自己写一个ls命令,实现ls基本的功能。在这之前我们先介绍几个在实现ls过程中使用的函数。
stat/lstat函数
这两个函数功能基本相同,都是获得文件的属性,区别在于如果文件是符号链接stat返回的是符号链接指向文件的属性,而lstat返回的是符号链接本身的属性。
函数原型:
int stat(const char *path, struct stat *buf); int lstat(const char *path, struct stat *buf);
path为文件路径,buf为返回的状态,类型为struct stat,结构体内容为:
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 */ };
这个结构体中成员st_mode用来表示文件的类型和文件的权限,它的定义如下:
S_IFMT 0170000 bit mask for the file type bit fields S_IFSOCK 0140000 socket S_IFLNK 0120000 symbolic link S_IFREG 0100000 regular file S_IFBLK 0060000 block device S_IFDIR 0040000 directory S_IFCHR 0020000 character device S_IFIFO 0010000 FIFO S_ISUID 0004000 set UID bit S_ISGID 0002000 set-group-ID bit (see below) S_ISVTX 0001000 sticky bit (see below) S_IRWXU 00700 mask for file owner permissions S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 mask for group permissions S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 mask for permissions for others (not in group) S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission
我们可以通过下面宏来判断文件的类型
S_ISREG(m) is it a regular file? S_ISDIR(m) directory? S_ISCHR(m) character device? S_ISBLK(m) block device? S_ISFIFO(m) FIFO (named pipe)? S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
接着我们就实现ls的第一步:获得文件的属性
这个例子只能实现查看一个特定文件的属性,而ls实现的功能是如果是文件则显示文件属性,如果是目录则显示目录中各个文件的属性。这些功能需要的函数为:
opendir/readdir函数用来获取目录项
原型:
DIR *opendir(const char *name); struct dirent *readdir(DIR *dirp); struct dirent描述目录中每一项的内容 struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* offset to the next dirent */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all file system types */ char d_name[256]; /* filename */ };
getopt用来实现命令选项功能:
原型:
int getopt(int argc, char * const argv[], const char *optstring); extern char *optarg; extern int optind, opterr, optopt;
readlink读取符号链接内容:
原型:
ssize_t readlink(const char *path, char *buf, size_t bufsiz); path为符号链接路径 buf为符号链接内容 bufsize为要获得内容长度 文件按照属性显示颜色 033[mode;foreground;backgroundmhello/033[0m
mode为显示模式: 0、1、22、4、24、5、25、7、27,分别表示设定颜色、黑体、非黑体、下画线、非下画线、闪烁、非闪烁、翻转、非翻转。
foreground为前景颜色: 30 (黑色)、31 (红色)、32 (绿色)、33 (黄色)、34 (蓝色)、35 ( 紫红色)、36 (青色)和37 (白色)
background为背景颜色: 40 (黑色)、41 (红色)、42 (绿色)、43 (黄色)、44 (蓝色)、45 ( 紫红色)、46 (青色)和47 (白色)
实现如下:
结果:
这里只实现了ls的部分功能,后面还会继续完成其余的功能!