代码:
LS_Head.h:
/***********************************************************************
* File name : LS_Head.h
* Module Name : LS
* Author : George
* Create Date : 2023.03.27
* Abstract Description: 用于模拟实现ls -l功能
*
* ------------------------- Revision History -------------------------
* No Version Date Revise By Item Deacription
* 1 V1.0 2023.03.27 George (omit) 用于模拟实现ls -l功能
* 2 v1.1 2023.03.28 George (omit) 用于模拟实现ls -l功能
*
***********************************************************************/
#ifndef __LS_HEAD_H
#define __LS_HEAD_H
/***********************************************************************
* (1)Debug switch Section
***********************************************************************/
/***********************************************************************
* (2)Include File Section
***********************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#include <dirent.h>
#include <errno.h>
/***********************************************************************
* (3)Macro Define Section
***********************************************************************/
/***********************************************************************
* (4)Struct(Data Types) Define Section
***********************************************************************/
/***********************************************************************
* (5)Prototype Declare Section
***********************************************************************/
// stat
extern int GetStat(const char *pathname, struct stat *buf);
// type
extern int GetType(mode_t mode, char *ch);
// mode
extern int GetMode(mode_t mode, char modeRet[10]);
// uid
extern int GetUsrName(uid_t uid, char usrNameRet[20]);
// gid
extern int GetGrpName(gid_t gid, char grpNameRet[20]);
// mon
extern int GetMon(int mon, char monRet[4]);
// day time
extern int GetTime(time_t *time, int timeRet[4]);
// file name
extern int GetFileName(const char pathname[20], char fileNameRet[20]);
// single output
extern int OutPutFileInfo(char pathname[20]);
// absolute path
extern int GetAbsolutePath(char absPath[128], char dirPath[40], char pathname[20]);
// (main)multiple output
extern int MainFunc(void);
#endif
LS_Func.c:
/***********************************************************************
* File name : LS_Func.c
* Module Name : LS
* Author : George
* Create Date : 2023.03.27
* Abstract Description: 用于模拟实现ls -l功能
*
* ------------------------- Revision History -------------------------
* No Version Date Revise By Item Deacription
* 1 V1.0 2023.03.27 George (omit) 用于模拟实现ls -l功能
* 2 v1.1 2023.03.28 George (omit) 用于模拟实现ls -l功能
*
***********************************************************************/
/***********************************************************************
* (1)Debug switch Section
***********************************************************************/
/***********************************************************************
* (2)Include File Section
***********************************************************************/
#include "LS_Head.h"
/***********************************************************************
* (3)Macro Define Section
***********************************************************************/
#define __NO_ERR 0 // 正常
#define __INPUT_ERR -1 // 入口参数输入错误
#define __FUNC_INVOKE_ERR -2 // 调用函数返回错误
// 返回整型的错误退出检测封装
#define IF_ERR(MSG) if(0 > ret)\
{ \
printf(MSG); \
printf(" : exit with %d\n", ret); \
return __FUNC_INVOKE_ERR; \
}
// 返回指针的错误退出检测封装
#define IF_ERR_P(MSG, PTR) if(NULL == PTR)\
{ \
printf(MSG); \
printf(" : exit with NULL\n"); \
return __FUNC_INVOKE_ERR; \
}
/***********************************************************************
* (4)Struct(Data Types) Define Section
***********************************************************************/
/***********************************************************************
* (5)Prototype Declare Section
***********************************************************************/
/***********************************************************************
* (6)Global Variable Declare Section
***********************************************************************/
int ret = 0; // return for print error
/***********************************************************************
* (7)File Static Variable Define Section
***********************************************************************/
/***********************************************************************
* (8)Function Define Section
***********************************************************************/
/***********************************************************************
* Function : GetStat
* Description : 用于获取文件状态结构体
* Input : 文件路径,用于存储文件属性结构体的结构体
* Output : 无
* Input_Output: 文件属性结构体
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetStat(const char *pathname, struct stat *buf)
{
if(NULL == pathname | NULL == buf)
{
return __INPUT_ERR;
}
else
{
ret = stat(pathname, buf);
IF_ERR("stat")
else
{
return __NO_ERR;
}
}
}
/***********************************************************************
* Function : GetType
* Description : 用于获取文件种类{bsp-lcd}
* Input : st_mode文件类型及权限,用于存储文件类型的字符
* Output : 无
* Input_Output: 存储文件类型的字符
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetType(mode_t mode, char *ch)
{
if(NULL == ch)
{
return __INPUT_ERR;
}
else
{
switch (mode & S_IFMT)// bsp-lcd
{
case __S_IFBLK: *ch = 'b'; break;
case __S_IFSOCK: *ch = 's'; break;
case __S_IFIFO: *ch = 'p'; break;
case __S_IFREG: *ch = '-'; break;
case __S_IFLNK: *ch = 'l'; break;
case __S_IFCHR: *ch = 'c'; break;
case __S_IFDIR: *ch = 'd'; break;
default: return __INPUT_ERR; break;
}
return __NO_ERR;
}
}
/***********************************************************************
* Function : GetMode
* Description : 用于获取文件权限{rwx-}
* Input : st_mode文件类型及权限,用于存储文件权限的字符数组
* Output : 无
* Input_Output: 存储文件权限的字符数组
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetMode(mode_t mode, char modeRet[10])
{
if(NULL == modeRet)
{
return __INPUT_ERR;
}
else
{
char Temp[4] = "rwx";// 0-r 1-w 2-x
for(int i = 1; i < 10; i++)// 123 456 789
{
if(1 == (((mode) & (1 << 9-i)) >> 9-i))
{
modeRet[i-1] = Temp[(i-1)%3];
}
else
{
modeRet[i-1] = '-';
}
}
return __NO_ERR;
}
}
/***********************************************************************
* Function : GetUsrName
* Description : 用于通过uid获取所属用户名
* Input : uid,用于存储所属用户名的字符数组
* Output : 无
* Input_Output: 存储所属用户名的字符数组
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetUsrName(uid_t uid, char usrNameRet[20])
{
if(NULL == usrNameRet)
{
return __INPUT_ERR;
}
else
{
struct passwd *pwd = getpwuid(uid);
IF_ERR_P("getwuid", pwd)
else
{
strcpy(usrNameRet, pwd->pw_name);
return __NO_ERR;
}
}
}
/***********************************************************************
* Function : GetGrpName
* Description : 用于通过gid获取所属组用户名
* Input : gid,用于存储所属组用户名的字符数组
* Output : 无
* Input_Output: 存储所属组用户名的字符数组
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetGrpName(gid_t gid, char grpNameRet[20])
{
if(NULL == grpNameRet)
{
return __INPUT_ERR;
}
else
{
struct group *grp = getgrgid(gid);
IF_ERR_P("getgrgid", grp)
else
{
strcpy(grpNameRet, grp->gr_name);
return __NO_ERR;
}
}
}
/***********************************************************************
* Function : GetMon
* Description : 用于获取最后访问时间的月份
* Input : 由localtime获得的月份(加一版本),用于存储最后访问时间月份的字符数组
* Output : 无
* Input_Output: 最后访问时间月份的字符数组
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetMon(int mon, char monRet[4])
{
// input legal exam (omit)
if(NULL == monRet)
{
return __INPUT_ERR;
}
else
{
bzero(monRet, 4);
switch (mon)
{
case 1: strcpy(monRet, "Mon"); break;
case 2: strcpy(monRet, "Feb"); break;
case 3: strcpy(monRet, "Mar"); break;
case 4: strcpy(monRet, "Apr"); break;
case 5: strcpy(monRet, "May"); break;
case 6: strcpy(monRet, "Jun"); break;
case 7: strcpy(monRet, "Jul"); break;
case 8: strcpy(monRet, "Aug"); break;
case 9: strcpy(monRet, "Sep"); break;
case 10: strcpy(monRet, "Oct"); break;
case 11: strcpy(monRet, "Nov"); break;
case 12: strcpy(monRet, "Dec"); break;
default: return __INPUT_ERR; break;
}
return __NO_ERR;
}
}
/***********************************************************************
* Function : GetTime
* Description : 用于获取月份、小时、分钟
* Input : 文件最近访问时间返回的秒数,用于存储时间的数组
* Output : 无
* Input_Output: 存储时间的数组
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetTime(time_t *time, int timeRet[4])
{
if(NULL == time | NULL == timeRet)
{
return __INPUT_ERR;
}
else
{
struct tm *tm = localtime(time);
IF_ERR_P("localtime", tm);
timeRet[0] = tm->tm_mon+1;
timeRet[1] = tm->tm_mday;
timeRet[2] = tm->tm_hour;
timeRet[3] = tm->tm_sec;
return __NO_ERR;
}
}
/***********************************************************************
* Function : GetFileName
* Description : 用于获取文件名
* Input : 文件路径,用于存储文件名的字符数组
* Output : 无
* Input_Output: 存储文件名的字符数组
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetFileName(const char pathname[32], char fileNameRet[20])
{
if(NULL == pathname | NULL == fileNameRet)
{
return __INPUT_ERR;
}
else
{
int flag = 0;
for(int i = strlen(pathname)-1; i >= 0; i--)
{
if('/' == pathname[i])
{
flag = i+1;
break;
}
}
for(int i = flag, j = 0; i < strlen(pathname); i++, j++)
{
fileNameRet[j] = pathname[i];
}
return __NO_ERR;
}
}
/***********************************************************************
* Function : OutPutFileInfo
* Description : 调用其它函数实现单个文件ls -l功能
* Input : 文件的绝对路径
* Output : 无
* Input_Output: 无
* Return : 整型错误码
* Author : George
**********************************************************************/
int OutPutFileInfo(char absPath[160])
{
if(NULL == absPath)
{
return __INPUT_ERR;
}
else
{
// get file-stat
struct stat buf;
ret = GetStat(absPath, &buf);
IF_ERR("GetStat")
else
{
// get type
char ch = '\0';
ret = GetType(buf.st_mode, &ch);
IF_ERR("GetType")
// get mode
char modeRet[10] = "";
ret = GetMode(buf.st_mode, modeRet);
IF_ERR("GetMode")
// get link
int link = buf.st_nlink;
// get id
char usrNameRet[20] = "";
ret = GetUsrName(buf.st_uid, usrNameRet);
IF_ERR("GetUsrName")
char grpNameRet[20] = "";
ret = GetGrpName(buf.st_gid, grpNameRet);
IF_ERR("GetGrpName")
// get size
int size = buf.st_size;
// get time
int timeRet[4] = {0};
time_t time = buf.st_mtime;// st_atime st_ctime st_mtime
ret = GetTime(&time, timeRet);
IF_ERR("GetTime")
char monRet[4] = "";
ret = GetMon(timeRet[0], monRet);
IF_ERR("GetMon")
// get file name
char fileNameRet[20] = "";
ret = GetFileName(absPath, fileNameRet);
IF_ERR("GetFileName")
// output ls -l
printf("%c%s %d %s %s %5d %s %d %02d:%02d %s\n", \
ch, modeRet, \
link, \
usrNameRet, grpNameRet, \
size, \
monRet, timeRet[1], timeRet[2], timeRet[3], \
fileNameRet);
return __NO_ERR;
}
}
}
/***********************************************************************
* Function : GetAbsolutePath
* Description : 获取文件的绝对路径
* Input : 用于存储文件绝对路径的字符数组,目录绝对路径,文件名
* Output : 无
* Input_Output: 存储文件绝对路径的字符数组
* Return : 整型错误码
* Author : George
**********************************************************************/
int GetAbsolutePath(char absPath[160], char dirPath[128], char pathname[32])
{
if(NULL == absPath | NULL == dirPath | NULL == pathname)
{
return __INPUT_ERR;
}
else
{
bzero(absPath, 160);
strcpy(absPath, dirPath);
strcat(absPath, "/");
strcat(absPath, pathname);
return __NO_ERR;
}
}
/***********************************************************************
* Function : OutPutFileInfo
* Description : 调用其它函数实现完整ls -l功能
* Input : 无
* Output : 无
* Input_Output: 无
* Return : 整型错误码
* Author : George
**********************************************************************/
int MainFunc(void)
{
char dirPath[128] = "";
printf("Please input your path(Absolute path) >>> ");
scanf("%s", dirPath);
DIR *DirPtr = opendir(dirPath);
IF_ERR_P("opendir", DirPtr)
else
{
char absPath[160] = "";
struct dirent *readPtr = NULL;
while(1)
{
readPtr = readdir(DirPtr);
if(NULL == readPtr)
{
if(errno == 0)
{
break;
}
else
{
perror("readdir");
}
}
if(0 == strcmp(".", readPtr->d_name) | 0 == strcmp("..", readPtr->d_name))
{
continue;
}
ret = GetAbsolutePath(absPath, dirPath, readPtr->d_name);
IF_ERR("GetAbsolutePath")
ret = OutPutFileInfo(absPath);
IF_ERR("OutPutFileInfo")
}
ret = closedir(DirPtr);
IF_ERR("closedir")
return __NO_ERR;
}
}
main.c:
#include "LS_Head.h"
int main(int argc, char const *argv[])
{
MainFunc();
return 0;
}
运行截图:
已知缺陷:输入绝对路径,文件时间,文件名排序,输出对齐。
作业:拷贝图片
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/stat.h>
int main(int argc, char const *argv[])
{
// open file
int fd_src = open("./src.jpg", O_RDONLY);
int fd_des = open("./des.jpg", O_WRONLY|O_CREAT|O_TRUNC, 0664);
// Legality testing omit
// get size
int size = lseek(fd_src, 0, SEEK_END);
printf("size of pic : %d\n", size);
// copy
char cBuf = '\0';
ssize_t ret = 0;
pid_t iPid = fork();
if(iPid < 0)
{
perror("fork");
return -1;
}
else if(iPid > 0)// parent
{
lseek(fd_src, 0, SEEK_SET);
lseek(fd_des, 0, SEEK_SET);
for(int i = 0; i < size/2; i++)
{
read(fd_src, &cBuf, 1);
write(fd_des, &cBuf, 1);
}
printf("parent copy success.\n");
wait(NULL);
}
else// child
{
sleep(1);// the time blocked depends on the size of pic
lseek(fd_src, size/2, SEEK_SET);
lseek(fd_des, size/2, SEEK_SET);
for(int i = size/2; i < size; i++)
{
read(fd_src, &cBuf, 1);
write(fd_des, &cBuf, 1);
}
printf("child copy success.\n");
}
close(fd_src);
close(fd_des);
// Legality testing omit
return 0;
}
截图: