Linux系统编程实例1
1.实现一个计算文件大小的函数
方法1(标准IO):
函数使用:
int fseek(FILE *stream, long offset, int whence); 返回值:成功0 失败-1
long int ftell(FILE *stream);返回值:返回位置标识符的当前值。如果发生错误,则返回 -1L
long file_size(const char* path)
{
FILE* fp = fopen(path,"r");
if(NULL == fp)
{
perror("fopen");
return -1;
}
fseek(fp,0,SEEK_END);
long size = ftell(fp);
fclose(fp);
return size;
}
方法2(系统IO):
函数使用:
off_t lseek(int fd, off_t offset, int whence); 返回值:成功返回调整后位置指针的位置 失败-1
int file_size(const char* path)
{
int fd = open(path,O_RDONLY);
if(0 > fp)
{
perror("open");
return -1;
}
int len = fseek(fp,0,SEEK_END);
close(fd);
return len;
}
2.使用系统IO实现一个带覆盖检测的cp命令
./a.out file1 file2
1、判断argc个数
2、以读方式打开file1
3、如果file2已存在,询问是否覆盖 是覆盖或者不存在:以写方式清空打开file2
4、循环读file1,写入file2,直到file1读取完毕
5、关闭文件
标准IO
#include <stdio.h>
int main(int argc,const char* argv[])
{
if(3 != argc)
{
printf("User: ./a.out file1 file2\n");
return 0;
}
FILE* file1 = fopen(argv[1],"r");
if(NULL == file1)
{
printf("被拷贝文件不存在,请检查\n");
return 0;
}
FILE* file2 = fopen(argv[2],"r");
if(file2)
{
printf("目标文件已存在,是否覆盖?(y/n)");
char cmd = getchar();
if('y' != cmd && 'Y' != cmd)
{
printf("已停止拷贝\n");
fclose(file1);
fclose(file2);
return 0;
}
fclose(file2);
}
// 重新写方式打开file2
file2 = fopen(argv[2],"w");
if(NULL == file2)
{
printf("文件权限受限,请检查\n");
fclose(file1);
return 0;
}
// 以二进制方式循环读写文件
char buf[1024] = {};
size_t buf_size = sizeof(buf);
int ret = 0;
while(ret = fread(buf,1,buf_size,file1))
{
fwrite(buf,1,ret,file2);
}
fclose(file1);
fclose(file2);
}
系统IO
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <getch.h>
int main(int argc,const char* argv[])
{
if(3 != argc)
{
printf("User: ./CP src dest\n");
return 0;
}
int src = open(argv[1],O_RDONLY);
if(0 > src)
{
printf("原文件不存在,请检查\n");
return 0;
}
int dest = open(argv[2],O_WRONLY|O_CREAT|O_EXCL,0644);
if(0 > dest) //O_EXCL 配合O_CREAT,如果文件存在则失败
{
printf("目标文件已存在,是否覆盖(y/n)?");
char cmd = getch();
if('y' != cmd && 'Y' != cmd)
{
printf("停止拷贝\n");
close(src);
return 0;
}
printf("开始覆盖\n");
dest = open(argv[2],O_WRONLY|O_TRUNC); //O_TRUNC 文件如果存在,则清空打开
}
char buf[4096] = {};
int ret = 0;
while(ret = read(src,buf,sizeof(buf)))
{
write(dest,buf,ret);
}
close(src);
close(dest);
printf("拷贝完成\n");
}
3.实现一个函数,可以删除某文件的[n,m)个字节
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdbool.h>
bool del_file_part(const char* path,size_t n,size_t m)
{
int fd = open(path,O_RDWR);
if(0 > fd)
{
perror("open");
return false;
}
// 计算文件大小
int len = lseek(fd,0,SEEK_END);
if(n > len) return false;
if(m > len) m = len;
char buf[4096] = {};
lseek(fd,m,SEEK_SET);
int ret = 0;
while(ret = read(fd,buf,sizeof(buf)))
{
lseek(fd,n,SEEK_SET);
write(fd,buf,ret);
m += ret;
n += ret;
lseek(fd,m,SEEK_SET);
}
ftruncate(fd,len-(m-n));
close(fd);
return true;
}
int main(int argc,const char* argv[])
{
printf("%d\n",del_file_part("hehe.txt",5,10));
}
4.实现一个完整的 ls -l 的功能
int stat(const char *pathname, struct stat *buf);
功能:根据文件路径获取文件的属性
buf:输出型参数 int fstat(int fd, struct stat *buf);
功能:根据文件描述符获取文件的属性
结构体 stat
struct stat
{
dev_t st_dev; // 设备ID
ino_t st_ino; // inode节点号
mode_t st_mode; // 文件的类型和权限
nlink_t st_nlink; // 硬链接数
uid_t st_uid; // 用户ID
gid_t st_gid; // 组ID
dev_t st_rdev; // 特殊设备ID
off_t st_size; // 总字节数
blksize_t st_blksize; // IO块总字节数
blkcnt_t st_blocks; // 占用大小512字节的内存块数量
struct timespec st_atim; // 最后访问时间
struct timespec st_mtim; // 最后修改时间
struct timespec st_ctim; // 最后状态修改时间
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
代码:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <dirent.h>
#include <limits.h>
// 显示文件类型
void file_type(mode_t mode)
{
switch(mode & S_IFMT)
{
case S_IFSOCK: printf("s"); break;
case S_IFLNK: printf("l"); break;
case S_IFREG: printf("-"); break;
case S_IFBLK: printf("b"); break;
case S_IFDIR: printf("d"); break;
case S_IFIFO: printf("p"); break;
}
}
// 显示文件权限
void file_mode(mode_t mode)
{
printf("%c",mode & S_IRUSR?'r':'-');
printf("%c",mode & S_IWUSR?'w':'-');
printf("%c",mode & S_IXUSR?'x':'-');
printf("%c",mode & S_IRGRP?'r':'-');
printf("%c",mode & S_IWGRP?'w':'-');
printf("%c",mode & S_IXGRP?'x':'-');
printf("%c",mode & S_IROTH?'r':'-');
printf("%c",mode & S_IWOTH?'w':'-');
printf("%c",mode & S_IXOTH?'x':'-');
}
// 显示用户名
void user_name(uid_t uid)
{
struct passwd* pwd = getpwuid(uid);
printf("%s ",pwd->pw_name);
}
// 显示组名
void group_name(gid_t gid)
{
struct group* grp = getgrgid(gid);
printf("%s ",grp->gr_name);
}
// 显示最后时间
void show_time(time_t st_time)
{
struct tm* t = localtime(&st_time);
printf("%02d月\t%02d %02d:%02d ",t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min);
}
// 计算目录层数
int dir_count(const char* path)
{
DIR* dir = opendir(path);
int count = 0;
for(struct dirent* d=readdir(dir); d; d=readdir(dir))
{
count += (DT_DIR == d->d_type);
}
closedir(dir);
return count;
}
// ls -l
void list_file_stat(const char* path)
{
// 获取文件属性
struct stat buf = {};
if(stat(path,&buf))
{
perror("stat");
return;
}
file_type(buf.st_mode);// 显示文件类型
file_mode(buf.st_mode);// 显示文件权限
printf(" %d ",S_ISDIR(buf.st_mode)?dir_count(path):1);// 计算目录层数
user_name(buf.st_uid);// 显示用户名
group_name(buf.st_gid);// 显示组名
printf("%8lu ",buf.st_size);// 显示文件大小
show_time(buf.st_mtime);// 显示最后时间
printf("%s\n",path);// 显示文件名
}
void ls(const char* path)
{
DIR* dir = opendir(path);
if(NULL == dir)
{
perror("opendir");
return;
}
// 备份原工作路径
char buf[PATH_MAX] = {};//PATH_MAX 是 #include <limits.h>宏定义
getcwd(buf,PATH_MAX);
// 修改工作路径
chdir(path);
for(struct dirent* d = readdir(dir); d; d = readdir(dir))
{
if('.' != d->d_name[0])
list_file_stat(d->d_name);
}
// 还原原工作路径
chdir(buf);
closedir(dir);
}
int main(int argc,const char* argv[])
{
if(1 == argc)
{
ls(".");
}
else
{
ls(argv[1]);
}
}
5.实现 rm -rf 的功能(容易破坏系统,运行前备份,检查)
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
void rm_rf_dir(const char* path)
{
if(0 == rmdir(path)) return;
// 备份当前工作路径
char buf[PATH_MAX] = {};
getcwd(buf,PATH_MAX);
// 设置工作路径
if(chdir(path)) return;
DIR* dir = opendir(".");
for(struct dirent* d=readdir(dir); d; d=readdir(dir))
{
if(DT_DIR == d->d_type)
{
if(strcmp(d->d_name,".") && strcmp(d->d_name,".."))//防止进入前一级目录删除
{
rm_rf_dir(d->d_name);
}
}
else
{
unlink(d->d_name);
}
}
closedir(dir);
// 还原工作路径
chdir(buf);
rmdir(path);
}
int main(int argc,const char* argv[])
{
if(2 != argc)
{
printf("User: ./RM dir\n");
return 0;
}
rm_rf_dir(argv[1]);
}
标签:Linux,--,编程,st,int,mode,printf,include,buf
From: https://www.cnblogs.com/bigflyny/p/17604122.html