Linux环境编程--功能函数编写1

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]);
}
posted @   BigBig飞  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示