【C语言】【unix c】获取文件的元数据(软链接,硬链接)(meta data)
2017-08-24 22:43
936 查看
一、获取文件的元数据(软链接,硬链接)(meta data) 1、元数据也就是常说的文件的属性 举例:用ls -l察看详细信息: - rw-rw-r-- 1 tarena tarena 0 8月 9 09:15 这些都是文件的元信息(不包括文件的名字) 文件的类型 文件的权限 文件的硬链接数 属主 属组 文件大小 时间 2、文件的链接分为两种:硬链接和软链接 3、每个文件有且仅有一个自己的inode(这是一个结构体,里面分为2部分,上部分是存储元数据的,下面部分(有15个区域的整形变量(60字节))是指向数据存储的地方)(文件和inode是多对一的关系)
4、硬链接: a、硬链接:两个文件有同一个inode,也就是读取两个文件所读取到的数据是一样的,文件信息也是一样的 b、如何为一个文件创建硬链接: 【ln 源文件 链接文件】 命令: tarena@ubuntu:~/day/day29$ ln hello h 结果: 总用量 0 -rw-rw-r-- 2 tarena tarena 0 8月 9 09:15 h //创建后硬链接数变为2 -rw-rw-r-- 2 tarena tarena 0 8月 9 09:15 hello 察看inode号:【ls -li】 命令: tarena@ubuntu:~/day/day29$ ls -li 结果: 总用量 0 1055687 -rw-rw-r-- 2 tarena tarena 0 8月 9 09:15 h //inode号是相同的,所以信息都是一样的 1055687 -rw-rw-r-- 2 tarena tarena 0 8月 9 09:15 hello 分析: 两个文件指向同一个inode,对其中一个的内容进行修改,另一个的内容也被修改,因为他们指向同一个数据区,删除一个文件,数据不会丢失 5、软链接: 就是inode下部分原本指向数据区的,现在指向一个文件的inode(文件名字要小于60字节,大于60的话会将名字存在数据区里然后来寻找) 如何创建软链接文件: 【ln -s 源文件 链接文件】 命令: tarena@ubuntu:~/day/day29$ ln -s h sh 命令: tarena@ubuntu:~/day/day29$ ls -li 结果: 总用量 0 1055687 -rw-rw-r-- 2 tarena tarena 0 8月 9 09:15 h 1055687 -rw-rw-r-- 2 tarena tarena 0 8月 9 09:15 hello 1055689 lrwxrwxrwx 1 tarena tarena 1 8月 9 09:44 sh -> h //sh是h的软链接 (文件类型是 l) 实验:软链接的关系 未删除h: tarena@ubuntu:~/day/day29$ cat sh hello 删除h: tarena@ubuntu:~/day/day29$ cat sh cat: sh: 没有那个文件或目录 分析: 软链接中,源文件丢失,软链接的文件也无法访问 实验:将软链接的文件复制后有什么效果: 命令: tarena@ubuntu:~/day/day29$ cp sh ../ 命令: tarena@ubuntu:~/day$ ls -li 结果: 总用量 56 662421 -rw-rw-r-- 1 tarena tarena 0 8月 9 09:52 h 662420 -rw-rw-r-- 1 tarena tarena 7 8月 9 09:54 sh //不再是软链接文件 分析:将文件拷贝后会创建一个新文件,inode也不一样了 6、如何通过程序获得文件的元数据: 使用stat(2)获取: #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(const char *path, struct stat *buf); 功能:获取文件的信息 参数: path:指定了文件的名字 buf:用来存储文件的属性的信息(元数据) 返回值:0 成功 -1 错误 errno被设置 第二个参数里包含了文件的许多信息,所以使用了结构体: struct stat:这个结构体中成员的信息: struct stat { dev_t st_dev; /* ID of device containing file */ 设备号 ino_t st_ino; /* inode number */ inode号(索引号) 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 */ 文件状态改变时间 }; 举例:获取文件的元数据(pstat.c) #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int main(int argc, char *argv[]) { struct stat b; //获取文件的元数据 int s = stat(argv[1], &b); if(s == -1) { perror("stat"); return -1; } //输出文件的元数据 printf("length:%ld\n", b.st_size); return 0; } 命令: tarena@ubuntu:~/day/day29$ a.o d880 ut hello 结果: length:7 分析: 这里可以输出文件的更多的信息,但是像时间,权限等等这里输出的格式还有很大的问题,所以还需要进行下面的转换 时间问题:系统记录的是1970年1月1日0点0分0秒到现在的秒数,需要将这个长整形的数转换为字符串格式 使用ctime(3)函数 #include <time.h> char *ctime(const time_t *timep); 功能:将时间的整数值转换为字符串的格式格式如:Wed Aug 9 09:54:03 2017 参数:timep:指定要转换的长整形的数 返回值:NULL: 错误 非空: 转换后的字符串的首地址 转换前: printf("last modification:%ld\n",b.st_mtime); last modification:1502243643 转换后: printf("last modification:%s\n",ctime(&b.st_mtime)); //要求传入的是一个地址 last modification:Wed Aug 9 09:54:03 2017 用户问题:用户看到的是文件的名字,而系统管理中使用的是用户的ID,数字 在程序中输出的是数字,但是需要转为字符串格式,方便用户的使用。那如何根据用户的id,找到用户的名字 getpwuid(3) #include <sys/types.h> #include <pwd.h> struct passwd *getpwuid(uid_t uid); 功能:获取passwd中的一条记录 参数: uid:指定用户的uid 返回值:指向匹配uid记录的首地址 NULL 未找到匹配的记录或者产生了错误 产生错误的话会设置errno passwd是一个结构体,该结构体的内容是: struct passwd { char *pw_name; /* username */ 名字 char *pw_passwd; /* user password */ 密码 uid_t pw_uid; /* user ID */ UID gid_t pw_gid; /* group ID */ GID char *pw_gecos; /* user information */ 使用着信息???? char *pw_dir; /* home directory */ 目录 char *pw_shell; /* shell program */ 壳程序???? }; 转换前: 命令: printf("user ID:%d\n", b.st_uid); 结果: user ID:1000 转换后: 命令: printf("user ID:%s\n", getpwuid(b.st_uid)->pw_name); 结果: user ID:tarena getgrgid(3) #include <sys/types.h> #include <grp.h> struct group *getgrgid(gid_t gid); 功能:获取passwd中的一条记录 参数: gid:指定用户组的GID 返回值: NULL 未找到匹配的记录或者产生了错误 产生错误的话会设置errno group结构体内的内容是: struct group { char *gr_name; /* group name */ 组名 char *gr_passwd; /* group password */ 组密码 gid_t gr_gid; /* group ID */ 组ID char **gr_mem; /* group members */ 组成员 }; 文件权限的问题: 使用下列宏可以判断文件的类型: b.st_mode & S_IFMT 得到的值和其他宏进行比较,用switch来选择 文件类型: 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) b.st_mode & S_IRWXU/S_IRWXG/S_IRWXO 得到一个值,将这个值和这一组的其他宏定义再按位与得值如果是1的话就输出该宏定义的类型/权限 属主权限: 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 举例: //判断文件的类型 switch(b.st_mode & S_IFMT) { case S_IFBLK: printf("b"); break; case S_IFCHR: printf("c"); break; case S_IFDIR: printf("d"); break; case S_IFIFO: printf("p|"); break; case S_IFLNK: printf("l@"); break; case S_IFREG: printf("-"); break; case S_IFSOCK: printf("s="); break; default: printf("unknown?\n"); break; } //判断文件拥有者的权限 int u = b.st_mode & S_IRWXU; if(u & S_IRUSR) printf("r"); else printf("-"); if(u & S_IWUSR) printf("w"); else printf("-"); if(u & S_IXUSR) printf("x"); else printf("-"); //判断文件拥有者组的权限 int g = b.st_mode & S_IRWXG; if(g & S_IRGRP) printf("r"); else printf("-"); if(g & S_IWGRP) printf("w"); else printf("-"); if(g & S_IXGRP) printf("x"); else printf("-"); //判断其他用户的权限 int o = b.st_mode & S_IRWXO; if(o & S_IROTH) printf("r"); else printf("-"); if(o & S_IWOTH) printf("w"); else printf("-"); if(o & S_IWOTH) printf("x"); else printf("-"); printf("\n"); 命令: tarena@ubuntu:~/day/day29$ a.out hello -rw-rw-r-- 补充: 在linux系统中用户的信息存放在/etc/passwd文件中 root:x:0:0:root:/root:/bin/bash tarena:x:1000:1000:tarena,,,:/home/tarena:/bin/bash 以:分割的7列 用户名字 是否有密码(x代表有密码) 用户的UID 用户的组ID(GID) 用户的注释信息 用户的工作主目录 用户登陆成功启动的第一个程序
相关文章推荐
- Unix高级编程:获取文件元数据、文件夹操作
- c语言 获取目录文件列表
- Android 从清单配置文件元数据中获取值
- 【C语言】【unix c】将头文件放在默认的头文件搜索目录里面
- C语言获取文件大小
- 获取Linux/Unix文件系统信息
- Unix下C语言----低级文件编程
- linux 获取文件元数据、文件夹的操作、ls功能实现
- 获取当前exe文件所在文件夹路径接口(c语言)
- 【C语言】【unix c】文件的操作(文件的打开,关闭,读,写,读写位置重定位)(对文件内容的操作)
- Android 从清单配置文件元数据中获取值
- 学习笔记(五)——chown,chmod,chattr,lsattr,suid,sgid,stick_bit,Linux搜索文件/命令,软链接,硬链接
- C语言获取文件大小
- 用C语言获取任意文件的长度(可能大于2GB)
- 五、Linux系统编程-文件和IO(三)文件元数据的获取
- 【C语言】【unix c】lseek(2)重新定位文件的读写位置的使用
- 如何用C语言获取文件的大小
- Linux 下C语言获取文件大小
- C语言获取文件CRC32算法附加CRC原理(转)
- Unix下C语言----目录文件编程