ls命令的实现
2012-09-05 20:15
447 查看
转自:http://blog.chinaunix.net/space.php?uid=25909722&do=blog&id=2856481
http://blog.chinaunix.net/uid-25909722-id-2876133.html
ls - list directory contents (man ls)
ls的功能是列出目录中的内容。那目录中都有写什么内容呢?我们知道磁盘上的文件系统由文件和目录组成,文件的内容可以是任意的数据,而目录的内容只能是文件名的列表和子目录名的列表。
也就是说:目录中的内容是该目录下的文件和子目录它们的名字的列表。
我们先来看一看关于目录的结构体:(/usr/include/bits/dirent.h)
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 supportedby
all file system types */
char d_name[256]; /* filename */
};
d_ino是目录中的文件的i-node节点号,通过d_ino可以找到该文件的i-node节点,而i-node节点中保存了文件的属性等信息。通过i-node节点就可以访问到文件的内容。
关于目录访问的一些函数:(/usr/include/dirent.h)
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
struct dirent *readdir(DIR *dirp);
int readdir_r(DIR *dirp, struct
dirent *entry, struct dirent **result);
int closedir(DIR *dirp);
void rewinddir(DIR *dirp);
关于目录中文件的属性等信息使用struct
stat结构体来描述的,其结构的定义如下: (/usr/include/bits/stat.h)
struct stat
{
__dev_t st_dev; /* Device. */
unsigned short int __pad1; /* 用于填充对齐 */
__ino_t st_ino; /* 32bit
file serial number. */
__mode_t st_mode; /* File
mode. */
__nlink_t st_nlink; /* Link count. */
__uid_t st_uid; /* User
ID of the file's owner. */
__gid_t st_gid; /* Group
ID of the file's group.*/
__dev_t st_rdev; /* Device
number, if device. */
unsigned short int __pad2; /* 用于填充对齐 */
__off_t st_size; /* Size
of file, in bytes. */
__blksize_t st_blksize; /* Optimal
block size for I/O. */
__blkcnt_t st_blocks; /* Number
512-byte blocks allocated. */
struct timespec st_atim; /* Time of
last access. */
struct timespec st_mtim; /* Time of
last modification. */
struct timespec st_ctim; /* Time of
last status change. */
# define st_atime st_atim.tv_sec /* Backward
compatibility. */
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
__ino64_t st_ino; /* File
serial number. */
};
该结构体提供了关于文件(或者设备)的如下重要信息:
st_mode 文件类型和许可权限
st_nlink 文件链接数
st_uid 文件属主id
st_gid 文件属主所在组的id
st_size 文件的字节数
st_blocks 文件所占的块数
“ACM”三个时间:
st_atime 文件最后访问时间 (access time)
st_mtime 文件最后修改时间 (modification time)
st_ctime 文件属性/状态最后改变的时间 (change status time)
另外在/usr/include/sys/stat.h中提供了下列关于文件信息的宏定义:
typedef __dev_t dev_t;
typedef __gid_t gid_t;
typedef __ino_t ino_t;
typedef __mode_t mode_t;
typedef __nlink_t nlink_t;
typedef __off_t off_t;
typedef __uid_t uid_t;
typedef __blkcnt_t blkcnt_t;
typedef __blksize_t blksize_t;
/* Test macros for file
types. */
#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
// directory 目录文件类型
#define S_ISCHR(mode) __S_ISTYPE((mode), __S_IFCHR)
// char 字文件类型
#define S_ISBLK(mode) __S_ISTYPE((mode), __S_IFBLK)
// block 块文件类型
#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
// regular 普通文件类型
#define S_ISFIFO(mode) __S_ISTYPE((mode), __S_IFIFO)
// FIFO 管道文件类型
#define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
// link 链接文件类型
#define S_ISSOCK(mode) __S_ISTYPE((mode), __S_IFSOCK) // sock
网络套接字文件类型
/* Protection bits. */
#define S_ISUID __S_ISUID /* Set user
ID on execution. */
#define S_ISGID __S_ISGID /* Set group
ID on execution. */
#define S_IRUSR __S_IREAD /* Read by owner. */
#define S_IWUSR __S_IWRITE /* Write by owner. */
#define S_IXUSR __S_IEXEC /* Execute by owner. */
/* Read, write, and execute
by owner. */
#define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC)
#define S_IRGRP (S_IRUSR >> 3) /* Read
by group. */
#define S_IWGRP (S_IWUSR >> 3) /* Write
by group. */
#define S_IXGRP (S_IXUSR >> 3) /* Execute
by group. */
/* Read, write, and execute
by group. */
#define S_IRWXG (S_IRWXU >> 3)
#define S_IROTH (S_IRGRP >> 3) /* Read
by others. */
#define S_IWOTH (S_IWGRP >> 3) /* Write
by others. */
#define S_IXOTH (S_IXGRP >> 3) /* Execute
by others. */
/* Read, write, and execute
by others. */
#define S_IRWXO (S_IRWXG >> 3)
# define S_BLKSIZE 512 /* Block size for `st_blocks'. */
在上一篇博文http://blog.chinaunix.net/space.php?uid=25909722&do=blog&id=2856481中,我们学习了实现ls命令要涉及到的相关的结构体和函数。有了前面的基础,本文我们实实在在的实现ls命令:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
void do_ls(char[]);
void do_stat(char*);
void show_file_info(char*, struct
stat*);
void mode_str(int, char[]);
char *uid_str(uid_t);
char *gid_str(gid_t);
int main(int argc, char *argv[])
{
if(argc == 1)
do_ls(".");
else
while(--argc){
printf("%s:\n", *++argv);
do_ls(*argv);
}
return 0;
}
void do_ls(char dirname[])
{
DIR *dir_ptr; /* the
directory */
struct dirent *direntp; /* each entry */
char full_path[256];
if((dir_ptr = opendir(dirname)) == NULL){
fprintf(stderr, "ls2:
cannot open %s\n", dirname);
}else{
while((direntp = readdir(dir_ptr)) != NULL){
strcpy(full_path, dirname);
int dir_len = strlen(dirname);
if(dirname[dir_len - 1] != '/'){
/* 处理目录字符串最后没有‘/’的情况 */
full_path[dir_len] = '/';
strcpy(full_path + dir_len + 1, direntp->d_name);
}else
strcpy(full_path + dir_len, direntp->d_name);
do_stat(full_path);
}
closedir(dir_ptr);
}
}
void do_stat(char *filename) /* 获得目录中文件的相关信息 */
{
struct stat info;
/* 如果filename最后没有‘/’的话,stat调用失败 */
if(stat(filename, &info) == -1){ /* cannot
stat */
perror("stat"); /* say
why */
printf("filename:%s\n", filename);
}else{
char *pname = strrchr(filename, '/');
show_file_info(pname + 1, &info);
}
}
void show_file_info(char *filename, struct
stat *info_p) /* 打印文件的相关信息 */
{
char modestr[11];
mode_str(info_p->st_mode, modestr);
printf("%s", modestr);
printf("%3d ", (int)info_p->st_nlink);
printf("%-8s", uid_str(info_p->st_uid));
printf("%-8s", gid_str(info_p->st_gid));
printf("%4ld ", (long)info_p->st_size);
printf("%.12s ", 4 + ctime(&info_p->st_mtime));
printf("%s\n", filename);
}
void mode_str(int mode, char
str[]) /* 将文件的相关信息转化成
“crw-rw---"的形式 */
{
strcpy(str, "----------"); /* default = no
perms */
if(S_ISDIR(mode)) str[0] = 'd'; /* directory */
if(S_ISCHR(mode)) str[0] = 'c'; /* char
device */
if(S_ISBLK(mode)) str[0] = 'b'; /* block
device */
if(S_ISLNK(mode)) str[0] = 'l';
if(mode & S_IRUSR) str[1] = 'r'; /* 3
bits for user */
if(mode & S_IWUSR) str[2] = 'w';
if(mode & S_IXUSR) str[3] = 'x';
if(mode & S_IRGRP) str[4] = 'r'; /* 3
bits for group */
if(mode & S_IWGRP) str[5] = 'w';
if(mode & S_IXGRP) str[6] = 'x';
if(mode & S_IROTH) str[7] = 'r'; /* 3
bits for other */
if(mode & S_IWOTH) str[8] = 'w';
if(mode & S_IXOTH) str[9] = 'x';
}
char *uid_str(uid_t uid) /* 将uid转化成username */
{
static char numstr[10];
struct passwd *pw_ptr;
if((pw_ptr = getpwuid(uid)) == NULL){
sprintf(numstr, "%d", uid);
return numstr;
}else
return pw_ptr->pw_name;
}
char *gid_str(gid_t gid) /* 将gid转化成groupname */
{
static char numstr[10];
struct group *grp_ptr;
if((grp_ptr = getgrgid(gid)) == NULL){
sprintf(numstr, "%
d", gid);
return numstr;
}else
return grp_ptr->gr_name;
}
编译和运行结果:
digdeep@ubuntu:~/uulp$ gcc -Wall -o ls1 ls1.c
digdeep@ubuntu:~/uulp$ ./ls1 /etc/network/
/etc/network/:
drwxr-x--- 2 root root 4096 Apr 26 07:03 if-down.d
drwxr-x--- 2 root root 4096 Jul 14 10:47 if-up.d
drwxr-x--- 2 root root 4096 Apr 26 07:05 if-pre-up.d
drwxr-x--- 6 root root 4096 Jun 14 05:34 .
drwxr-x--- 2 root root 4096 Apr 26 07:05 if-post-down.d
-rwrr----- 1 root root 196 Jun 14 05:33 interfaces
drwxr-x---147 root root 12288 Sep 19 20:33 ..
http://blog.chinaunix.net/uid-25909722-id-2876133.html
ls - list directory contents (man ls)
ls的功能是列出目录中的内容。那目录中都有写什么内容呢?我们知道磁盘上的文件系统由文件和目录组成,文件的内容可以是任意的数据,而目录的内容只能是文件名的列表和子目录名的列表。
也就是说:目录中的内容是该目录下的文件和子目录它们的名字的列表。
我们先来看一看关于目录的结构体:(/usr/include/bits/dirent.h)
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 supportedby
all file system types */
char d_name[256]; /* filename */
};
d_ino是目录中的文件的i-node节点号,通过d_ino可以找到该文件的i-node节点,而i-node节点中保存了文件的属性等信息。通过i-node节点就可以访问到文件的内容。
关于目录访问的一些函数:(/usr/include/dirent.h)
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
struct dirent *readdir(DIR *dirp);
int readdir_r(DIR *dirp, struct
dirent *entry, struct dirent **result);
int closedir(DIR *dirp);
void rewinddir(DIR *dirp);
关于目录中文件的属性等信息使用struct
stat结构体来描述的,其结构的定义如下: (/usr/include/bits/stat.h)
struct stat
{
__dev_t st_dev; /* Device. */
unsigned short int __pad1; /* 用于填充对齐 */
__ino_t st_ino; /* 32bit
file serial number. */
__mode_t st_mode; /* File
mode. */
__nlink_t st_nlink; /* Link count. */
__uid_t st_uid; /* User
ID of the file's owner. */
__gid_t st_gid; /* Group
ID of the file's group.*/
__dev_t st_rdev; /* Device
number, if device. */
unsigned short int __pad2; /* 用于填充对齐 */
__off_t st_size; /* Size
of file, in bytes. */
__blksize_t st_blksize; /* Optimal
block size for I/O. */
__blkcnt_t st_blocks; /* Number
512-byte blocks allocated. */
struct timespec st_atim; /* Time of
last access. */
struct timespec st_mtim; /* Time of
last modification. */
struct timespec st_ctim; /* Time of
last status change. */
# define st_atime st_atim.tv_sec /* Backward
compatibility. */
# define st_mtime st_mtim.tv_sec
# define st_ctime st_ctim.tv_sec
__ino64_t st_ino; /* File
serial number. */
};
该结构体提供了关于文件(或者设备)的如下重要信息:
st_mode 文件类型和许可权限
st_nlink 文件链接数
st_uid 文件属主id
st_gid 文件属主所在组的id
st_size 文件的字节数
st_blocks 文件所占的块数
“ACM”三个时间:
st_atime 文件最后访问时间 (access time)
st_mtime 文件最后修改时间 (modification time)
st_ctime 文件属性/状态最后改变的时间 (change status time)
另外在/usr/include/sys/stat.h中提供了下列关于文件信息的宏定义:
typedef __dev_t dev_t;
typedef __gid_t gid_t;
typedef __ino_t ino_t;
typedef __mode_t mode_t;
typedef __nlink_t nlink_t;
typedef __off_t off_t;
typedef __uid_t uid_t;
typedef __blkcnt_t blkcnt_t;
typedef __blksize_t blksize_t;
/* Test macros for file
types. */
#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
// directory 目录文件类型
#define S_ISCHR(mode) __S_ISTYPE((mode), __S_IFCHR)
// char 字文件类型
#define S_ISBLK(mode) __S_ISTYPE((mode), __S_IFBLK)
// block 块文件类型
#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
// regular 普通文件类型
#define S_ISFIFO(mode) __S_ISTYPE((mode), __S_IFIFO)
// FIFO 管道文件类型
#define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
// link 链接文件类型
#define S_ISSOCK(mode) __S_ISTYPE((mode), __S_IFSOCK) // sock
网络套接字文件类型
/* Protection bits. */
#define S_ISUID __S_ISUID /* Set user
ID on execution. */
#define S_ISGID __S_ISGID /* Set group
ID on execution. */
#define S_IRUSR __S_IREAD /* Read by owner. */
#define S_IWUSR __S_IWRITE /* Write by owner. */
#define S_IXUSR __S_IEXEC /* Execute by owner. */
/* Read, write, and execute
by owner. */
#define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC)
#define S_IRGRP (S_IRUSR >> 3) /* Read
by group. */
#define S_IWGRP (S_IWUSR >> 3) /* Write
by group. */
#define S_IXGRP (S_IXUSR >> 3) /* Execute
by group. */
/* Read, write, and execute
by group. */
#define S_IRWXG (S_IRWXU >> 3)
#define S_IROTH (S_IRGRP >> 3) /* Read
by others. */
#define S_IWOTH (S_IWGRP >> 3) /* Write
by others. */
#define S_IXOTH (S_IXGRP >> 3) /* Execute
by others. */
/* Read, write, and execute
by others. */
#define S_IRWXO (S_IRWXG >> 3)
# define S_BLKSIZE 512 /* Block size for `st_blocks'. */
在上一篇博文http://blog.chinaunix.net/space.php?uid=25909722&do=blog&id=2856481中,我们学习了实现ls命令要涉及到的相关的结构体和函数。有了前面的基础,本文我们实实在在的实现ls命令:
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
void do_ls(char[]);
void do_stat(char*);
void show_file_info(char*, struct
stat*);
void mode_str(int, char[]);
char *uid_str(uid_t);
char *gid_str(gid_t);
int main(int argc, char *argv[])
{
if(argc == 1)
do_ls(".");
else
while(--argc){
printf("%s:\n", *++argv);
do_ls(*argv);
}
return 0;
}
void do_ls(char dirname[])
{
DIR *dir_ptr; /* the
directory */
struct dirent *direntp; /* each entry */
char full_path[256];
if((dir_ptr = opendir(dirname)) == NULL){
fprintf(stderr, "ls2:
cannot open %s\n", dirname);
}else{
while((direntp = readdir(dir_ptr)) != NULL){
strcpy(full_path, dirname);
int dir_len = strlen(dirname);
if(dirname[dir_len - 1] != '/'){
/* 处理目录字符串最后没有‘/’的情况 */
full_path[dir_len] = '/';
strcpy(full_path + dir_len + 1, direntp->d_name);
}else
strcpy(full_path + dir_len, direntp->d_name);
do_stat(full_path);
}
closedir(dir_ptr);
}
}
void do_stat(char *filename) /* 获得目录中文件的相关信息 */
{
struct stat info;
/* 如果filename最后没有‘/’的话,stat调用失败 */
if(stat(filename, &info) == -1){ /* cannot
stat */
perror("stat"); /* say
why */
printf("filename:%s\n", filename);
}else{
char *pname = strrchr(filename, '/');
show_file_info(pname + 1, &info);
}
}
void show_file_info(char *filename, struct
stat *info_p) /* 打印文件的相关信息 */
{
char modestr[11];
mode_str(info_p->st_mode, modestr);
printf("%s", modestr);
printf("%3d ", (int)info_p->st_nlink);
printf("%-8s", uid_str(info_p->st_uid));
printf("%-8s", gid_str(info_p->st_gid));
printf("%4ld ", (long)info_p->st_size);
printf("%.12s ", 4 + ctime(&info_p->st_mtime));
printf("%s\n", filename);
}
void mode_str(int mode, char
str[]) /* 将文件的相关信息转化成
“crw-rw---"的形式 */
{
strcpy(str, "----------"); /* default = no
perms */
if(S_ISDIR(mode)) str[0] = 'd'; /* directory */
if(S_ISCHR(mode)) str[0] = 'c'; /* char
device */
if(S_ISBLK(mode)) str[0] = 'b'; /* block
device */
if(S_ISLNK(mode)) str[0] = 'l';
if(mode & S_IRUSR) str[1] = 'r'; /* 3
bits for user */
if(mode & S_IWUSR) str[2] = 'w';
if(mode & S_IXUSR) str[3] = 'x';
if(mode & S_IRGRP) str[4] = 'r'; /* 3
bits for group */
if(mode & S_IWGRP) str[5] = 'w';
if(mode & S_IXGRP) str[6] = 'x';
if(mode & S_IROTH) str[7] = 'r'; /* 3
bits for other */
if(mode & S_IWOTH) str[8] = 'w';
if(mode & S_IXOTH) str[9] = 'x';
}
char *uid_str(uid_t uid) /* 将uid转化成username */
{
static char numstr[10];
struct passwd *pw_ptr;
if((pw_ptr = getpwuid(uid)) == NULL){
sprintf(numstr, "%d", uid);
return numstr;
}else
return pw_ptr->pw_name;
}
char *gid_str(gid_t gid) /* 将gid转化成groupname */
{
static char numstr[10];
struct group *grp_ptr;
if((grp_ptr = getgrgid(gid)) == NULL){
sprintf(numstr, "%
d", gid);
return numstr;
}else
return grp_ptr->gr_name;
}
编译和运行结果:
digdeep@ubuntu:~/uulp$ gcc -Wall -o ls1 ls1.c
digdeep@ubuntu:~/uulp$ ./ls1 /etc/network/
/etc/network/:
drwxr-x--- 2 root root 4096 Apr 26 07:03 if-down.d
drwxr-x--- 2 root root 4096 Jul 14 10:47 if-up.d
drwxr-x--- 2 root root 4096 Apr 26 07:05 if-pre-up.d
drwxr-x--- 6 root root 4096 Jun 14 05:34 .
drwxr-x--- 2 root root 4096 Apr 26 07:05 if-post-down.d
-rwrr----- 1 root root 196 Jun 14 05:33 interfaces
drwxr-x---147 root root 12288 Sep 19 20:33 ..
相关文章推荐
- 实现自己的ls命令
- linux 下用 c 实现 ls -l 命令
- ls命令的自己实现
- ls命令的简要实现
- Unix - ls命令的简要实现
- 用文件IO操作实现ls命令
- C语言实现Linux系统下ls命令的过滤文件功能
- Linux 简单实现 ls -l 命令
- Python实现Linux环境下的ls命令
- linux文件和目录操作(附ls命令实现)
- Linux&C编程之Linux系统命令“ls -l”的简单实现
- linux ls命令的的简单实现APUE-1.4 文件和目录
- 在linux下代码实现ls -l 命令(利用移位 和 与 操作 对指定位的分离 )(指定位段的分离)
- ls(1)命令的实现
- 使用C语言将ls命令重定向实现
- C 语言实现shell里的ls命令
- Linux---Ls命令 初级实现
- 编程实践----实现自己的ls命令
- 如何实现ls命令在Win7下正常运行
- linux命令实现:ls