04 ls——stat、chmod、chown、utime

1、ls能做什么

ls的默认动作是找到当前目录中所有文件的文件名,按字典序排序后输出,ls -l会列出每个文件的详细信息。所以ls做了一下两件事,第一列出目录的内容,第二显示文件的信息。

自己编写一个ls,一下三点需要掌握:

  • 如何列出目录内容
  • 如何读取并显示文件属性
  • 给一个名字,如何能够判断出它是目录还是文件

2、ls是如何实现的

ls的逻辑和who十分相似,主要区别是who从文件中读数据,而ls从目录中读数据。ls的工作流程:打开目录,读取每个条目,展示文件的信息,关闭目录。

目录是文件的列表,记录的序列,每条记录对应一个文件或子目录。通过readdir来读取目录中的记录,readdir返回一个指向目录的当前记录的指针,记录的类型是struct dirent,这个结构定义在/usr/include/dirent.h中,dirent结构中成员d_name用于存放文件名。

struct dirent:

ino_t  d_ino       File serial number.

char   d_name[]    Name of entry.

以上相当于完成了ls的第一件事列出目录内容。ls的第二件事ls -l显示文件的详细信息。ls -l每行总共包含7个字段:

  • 模式(mode):文件访问权限,针对3种对象用户、同组用户、其他用户的读、写、执行权限总共九种文件访问权限
  • 链接数(links):该文件被引用的次数
  • 文件所有者(ower):文件所有者的用户名
  • 组(group):文件所有者所在组
  • 大小(size):文件的大小
  • 最后修改时间(last-modified):文件的最后修改时间
  • 文件名(name):文件名

stat、chmod、chown、utime系统调用:

  • stat():用于得到文件的属性,result=stat(char *fname,struct stat *bufp),stat把文件fname的信息复制到指针bufp所指的结构中。
  • chmod():修改文件的许可权限和特殊属性,result=chmod(char *path,mode_t mode),将文件path的属性修改为mode。
  • chown():修改文件所有者和组,result=chown(char *path,uid_t owner,gid_t group),将文件的所有者id改为owner,文件的组id改为group。
  • utime():修改文件最后修改时间和最后访问时间,utime(char *path,struct utimebuf *newtime),将文件path的最后修改时间和最后访问时间修改为指向newtime的utimebuf结构体。

通过命令man -k file | grep -i stat查找有关文件状态的系统调用。用stat可以得到文件的信息,通过系统调用stat将文件filename的属性信息存入结构struct stat中去。struct stat的成员变量有:

  • st_mode:16位,4位文件类型、3位文件特殊属性、9位文件许可权限,可以通过掩码获取9位文件许可权限
  • st_uid:用户所有者的ID,可以通过系统调用getpwuid获取用户所有者的ID对应的用户名
  • st_gid:所在组ID,可以通过系统调用getgrgid获取用户所在组的ID对应的组名
  • st_size:所占字节数
  • st_nlink:文件链接数
  • st_mtime:文件最后修改时间
  • st_atime:文件最后访问时间
  • st_ctime:文件属性最后改变时间

              dev_t     st_dev     Device ID of device containing file.
              ino_t     st_ino     File serial number.
              mode_t    st_mode    Mode of file (see below).
              nlink_t   st_nlink   Number of hard links to the file.
              uid_t     st_uid     User ID of file.
              gid_t     st_gid     Group ID of file.

              dev_t     st_rdev    Device ID (if file is character or block special).

              off_t     st_size    For regular files, the file size in bytes.
                                   For symbolic links, the length in bytes of the
                                   pathname contained in the symbolic link.

                                   For a shared memory object, the length in bytes.

                                   For a typed memory object, the length in bytes.

                                   For other file types, the use of this field is
                                   unspecified.
              time_t    st_atime   Time of last access.
              time_t    st_mtime   Time of last data modification.
              time_t    st_ctime   Time of last status change.

              blksize_t st_blksize A file system-specific preferred I/O block size for
                                   this object. In some file system types, this may
                                   vary from file to file.
              blkcnt_t  st_blocks  Number of blocks allocated for this object.

3、自己编写一个ls

ls1.c

#include<stdio.h>
#include<sys/types.h>
#include<dirent.h>
void do_ls(char dirname[])
{
    DIR *dir_ptr;
    struct dirent* direntp;
    if((dir_ptr=opendir(dirname))==NULL)
	fprintf(stderr,"ls1:cannot open %s\n",dirname);
    else
    {
	while((direntp=readdir(dir_ptr))!=NULL)
	    printf("%s\n",direntp->d_name);
	closedir(dir_ptr);
    }
}
int main(int argc,char *argv[])
{
    if(argc==1)
        do_ls(".");
    else
    {
	while(--argc)
	{
	    printf("%s:\n",*++argv);
	    do_ls(*argv);
	}
    }
    return 0;
}

ls2.c

#include<stdio.h>
#include<sys/types.h>
#include<dirent.h>
#include<sys/stat.h>
void do_ls(char dirname[])
{
    DIR *dir_ptr;
    struct dirent *direntp;
    if((dir_ptr=opendir(dirname))==NULL)
	fprintf(stderr,"ls1:cannot open %s\n",dirname);
    else
    {
        while((direntp=readdir(dir_ptr))!=NULL)
	    dostat(direntp->d_name);
	closedir(dir_ptr);
    }
}
void dostat(char *filename)
{
    struct stat info;
    if(stat(filename,&info)==-1)
        perror(filename);
    else
	show_file_info(filename,&info);
}
void show_file_info(char *filename,struct stat *info_p)
{
    char *uid_to_name(),*gid_to_name(),*ctime(),*filemode();  //先声明两个函数
    char modestr[11];
    mode_to_letters(info_p->st_mode,modestr);
    printf("%s",modestr);
    printf("%4d ",(int)info_p->st_nlink);
    printf("%-8s ",uid_to_name(info_p->st_uid));
    printf("%-8s ",gid_to_name(info_p->st_gid));
    printf("%8ld ",(long)info_p->st_size);
    printf("%.12s ",4+ctime(&info_p->st_mtime));
    printf("%s\n",filename);
}
void mode_to_letters(int mode,char str[])
{
    strcpy(str,"----------");
    if(S_ISDIR(mode)) str[0]='d';
    if(S_ISCHR(mode)) str[0]='c';
    if(S_ISBLK(mode)) str[0]='b';

    if(mode&S_IRUSR) str[1]='r';
    if(mode&S_IWUSR) str[2]='w';
    if(mode&S_IXUSR) str[3]='x';

    if(mode&S_IRGRP) str[4]='r';
    if(mode&S_IWGRP) str[5]='w';
    if(mode&S_IXGRP) str[6]='x';

    if(mode&S_IROTH) str[7]='r';
    if(mode&S_IWOTH) str[8]='w';
    if(mode&S_IXOTH) str[9]='x';
    
}
#include<pwd.h>
char *uid_to_name(uid_t uid)
{
    struct passwd *pw_ptr;
    static char numstr[10];
    if((pw_ptr=getpwuid(uid))==NULL)
    {
        sprintf(numstr,"%d",uid);
        return numstr;
    }
    else
        return pw_ptr->pw_name;
}
#include<grp.h>
char *gid_to_name(gid_t gid)
{
    struct group *grp_ptr;
    static char numstr[10];
    if((grp_ptr=getgrgid(gid))==NULL)
    {
        sprintf(numstr,"%d",gid);
        return numstr;
    }
    else
        return grp_ptr->gr_name;
}
int main(int argc,char *argv[])
{
    if(argc==1)
        do_ls(".");
    else
    {
        while(--argc)
        {
            printf("%s:\n",*++argv);
            do_ls(*argv);
        }
    }
    return 0;
}

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值