目录
1.文件属性相关函数
getpwuid()
#include <sys/types.h>
#include <pwd.h>
struct passwd *getpwuid(uid_t uid);
功能: 通过uid获取对应的用户信息
参数:
uid: 要获取信息uid(可以通过stat()获取uid)
返回值: 成功返回用户信息结构体
失败返回NULL 并置位错误码
struct passwd {
char *pw_name; /* username */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user ID */
gid_t pw_gid; /* group ID */
char *pw_gecos; /* user information */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
getgrgid()
#include <sys/types.h>
#include <grp.h>
struct group *getgrgid(gid_t gid);
功能: 通过gid获取对应组信息
参数:
gid: 要获取信息gid(可以通过stat()获取gid)
返回值: 成功返回用户信息结构体
失败返回NULL 并置位错误码
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group ID */
char **gr_mem; /* NULL-terminated array of pointersto names of group members */
};
2.操作目录相关函数
opendir()
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能: 打开置顶目录文件
参数:
name:目录路径及目录名
返回值: 成功返回目录指针
失败NULL,置位错误码
closedir()
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能: 关闭目录文件
参数:
dirp: 目录指针
返回值: 成功0 失败-1,置位错误码
readdir()
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能: 读取目录
参数:
dirp: 目录指针
返回值: 成功返回目录信息结构体
读到目录结尾返回NULL,不置位错误码
失败返回NULL,置位错误码
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
实例
// 显示指定目录下的所有文件名,除了隐藏文件
#include <dirent.h>
#include <stdio.h>
#include <sys/types.h>
int main(int argc, const char* argv[])
{
// 1.校验参数
if (argc != 2) {
printf("input error\n");
printf("usage: ./a.out dirname\n");
return -1;
}
// 2.打开目录
DIR* dp = opendir(argv[1]);
if(NULL == dp){
perror("opendir");
return -1;
}
// 3.循环获取目录下文件
struct dirent* red = NULL;
while(red = readdir(dp)){
if(red->d_name[0] != '.'){
printf("%s\n", red->d_name);
}
}
return 0;
}
3.进程
4.作业
4.1题
输入任意路径,将该路径下所有文件的详细信息显示出来,类似ls -l。
// 输入任意路径,将该路径下所有文件的详细信息显示出来,类似ls -l。
#include <dirent.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
// 获取文件权限
void file_privilege(mode_t m, char buf[10]);
// 获取文件类型
char file_type(mode_t m);
int main(int argc, const char* argv[])
{
// 1.校验参数
if (argc != 2) {
printf("input error\n");
printf("usage: ./a.out dirname\n");
return -1;
}
// 2.打开目录
DIR* dp = opendir(argv[1]);
if (NULL == dp) {
perror("opendir");
return -1;
}
char filename[1024] = "";
struct stat st_t; // 定义文件属性结构体
char type; // 保存文件类型
char privilege[10] = ""; // 保存文件权限
struct passwd* pwd = NULL; // 保存用户信息结构体
struct group* grp = NULL; // 保存组信息结构体
struct tm* t = NULL; // 时间结构体
char time[12] = ""; // 保存文件时间戳
struct dirent* red = NULL; // 目录结构体
// 3.循环获取目录下文件
while (red = readdir(dp)) {
// 4.设置文件路径
sprintf(filename, "%s/%s", argv[1], red->d_name);
// 5.获取文件属性信息
if (-1 == stat(filename, &st_t)) {
perror("stat");
return -1;
}
// 6.获取文件类型
type = file_type(st_t.st_mode);
// 7.获取文件权限
file_privilege(st_t.st_mode, privilege);
// 8.获取用户信息
pwd = getpwuid(st_t.st_uid);
if (NULL == pwd) {
perror("getpwuid");
return -1;
}
// 9.获取组信息
grp = getgrgid(st_t.st_gid);
if (NULL == grp) {
perror("getgrgid");
return -1;
}
// 10.格式化文件时间戳
t = localtime(&st_t.st_mtime);
sprintf(time, "%02d %02d %02d:%02d", t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min);
// 11.打印文件信息
printf("%c%s %ld %s %s %ld %s %s\n", type, privilege, st_t.st_nlink, pwd->pw_name, grp->gr_name, st_t.st_size, time, red->d_name);
}
return 0;
}
void file_privilege(mode_t m, char buf[10])
{
char per[] = "rwx";
for (int i = 0; i < 9; i++) {
// 循环右移,按位与
if (m & (0400) >> i) {
// 保存对于权限
buf[i] = per[i % 3];
} else {
// 设置无权限
buf[i] = '-';
}
}
}
char file_type(mode_t m)
{
switch (m & S_IFMT) {
case S_IFSOCK:
return 's';
break;
case S_IFLNK:
return 'l';
break;
case S_IFREG:
return '-';
break;
case S_IFBLK:
return 'b';
break;
case S_IFDIR:
return 'd';
break;
case S_IFCHR:
return 'c';
break;
case S_IFIFO:
return 'p';
break;
}
}
4.2题
使用两个进程拷贝文件,父进程拷贝前半部分,子进程拷贝后半部分
// 使用两个进程拷贝文件,父进程拷贝前半部分,子进程拷贝后半部分
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
/// @brief 初始化目标文件
/// @param destfile 目标文件路径及名字
/// @return 成功0 失败-1
int init_destfile(const char* destfile);
/// @brief 计算文件大小
/// @param filename 文件路径及名字
/// @return 成功返回文件大小 失败返回-1
int get_size_file(const char* filename);
/// @brief 拷贝文件
/// @param destfile 目标文件
/// @param srcfile 源文件
/// @param start 光标开始位置
/// @param end 光标结束位置
/// @return 成功0 失败-1
int copy_file(const char* destfile, const char* srcfile, int start, int end);
int main(int argc, const char* argv[])
{
// 1.校验参数
if (argc != 3) {
printf("input error\n");
printf("usage: ./a.out srcFileName destFileName\n");
return -1;
}
// 2.初始化目标文件
if (init_destfile(argv[2])) {
return -1;
}
// 3.获取源文件大小
int size = get_size_file(argv[1]);
if (-1 == size) {
return -1;
}
// 4.创建进程
pid_t pd = fork();
if (pd < 0) { // 创建失败
perror("fork");
return -1;
} else if (pd > 0) { // 父进程
// 拷贝前半部分数据
copy_file(argv[2], argv[1], 0, size / 2);
} else { // 子进程
// 拷贝后半部分数据
copy_file(argv[2], argv[1], size / 2, size - size / 2);
}
return 0;
}
int init_destfile(const char* destfile)
{
// 1.打开文件
int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (-1 == fd) {
perror("init_destfile open destfile");
return -1;
}
// 2.关闭文件
close(fd);
return 0;
}
int get_size_file(const char* filename)
{
// 1.打开文件
int fd = open(filename, O_RDONLY);
if (-1 == fd) {
perror("get_size_file open filename");
return -1;
}
// 2.移动光标,计算大小
int size = lseek(fd, 0, SEEK_END);
// 3.关闭文件
close(fd);
// 4.返回大小
return size;
}
int copy_file(const char* destfile, const char* srcfile, int start, int end)
{
// 1.打开两个文件
int destfd = open(destfile, O_RDWR);
if (-1 == destfd) {
perror("copy_file open destfile");
return -1;
}
int srcfd = open(srcfile, O_RDONLY);
if (-1 == srcfd) {
perror("copy_file open srcfile");
return -1;
}
// 2.设置光标位置
lseek(srcfd, start, SEEK_SET);
lseek(destfd, start, SEEK_SET);
int ret = 0; // 保存每次读取的字节数
int count = 0; // 保存已经读取的数据大小
char buf[128] = ""; // 保存读取到的数据
// 3.循环读取数据
while (1) {
// 4.读取数据
ret = read(srcfd, buf, sizeof(buf));
// 5.累加读取的数据大小
count += ret;
// 6.判断已经读取的数据大小是否超过end
if (count >= end) {
// 减去超出的数据
write(destfd, buf, ret - (count - end));
// 全部写完,退出循环
break;
}
// 7.写入数据
write(destfd, buf, ret);
}
// 8.关闭文件
close(srcfd);
close(destfd);
return 0;
}