更新内容:
1.优化结果字符串内存分配
根据ls结果条数动态分配内存,超出`SHOW_MAX_SIZE`(300)自动扩容避免空间浪费
2.优化编码结构、变量声明
划分读取目录与文件不同操作
增加`_myStrcat`、`_myError`函数
重命名`struct stat`等结构体声明
3.修复bug
当读取`..`目录时无法找到文件(由于未切换工作目录`chdir`)
myls.c
#include "myls.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <grp.h>
#include <pwd.h>
#include <time.h>
#include <dirent.h>
void _myExit(const char *proc_name)
{
perror(proc_name);
exit(EXIT_FAILURE);
}
char *_myStrcat(char *desc, const char *src)
{
long total = sizeof(desc) + 1 + sizeof(src);
if (total > SHOW_MAX_SIZE) {
char *desc = realloc(desc, total + SHOW_MAX_SIZE);
if (!desc) _myExit("realloc");
}
strcat(desc, src);
strcat(desc, " ");
return desc;
}
char *list(const char *pathname, char *pstr)
{
statType buf;
if (stat(pathname, &buf) == -1)
_myExit("stat");
// check directory or file
if (S_ISDIR(buf.st_mode)) {
getDirFile(pstr, pathname);
} else {
getFileStat(pstr, &buf, pathname);
}
return pstr;
}
void getDirFile(char *pstr, const char *pathname)
{
DIR *dirp = opendir(pathname);
if (!dirp)
_myExit("opendir");
if (chdir(pathname) == -1)
_myExit("chdir");
dirType *dr = NULL;
// traverse files in the direntory
while ((dr = readdir(dirp))) {
statType *buf = (statType *)malloc(sizeof(statType));
if (stat(dr->d_name, buf) == -1)
_myExit("stat");
getFileStat(pstr, buf, dr->d_name);
strcat(pstr, "\n");
free(buf);
buf = NULL;
}
}
char *getFileStat(char *pstr, const statType *buf,
const char *filename)
{
getMode(pstr, &buf->st_mode);
getLinkNum(pstr, &buf->st_nlink);
getGID(pstr, &buf->st_gid);
getUID(pstr, &buf->st_uid);
getMTime(pstr, &buf->st_mtimespec);
getSize(pstr, &buf->st_size);
getFilename(pstr, filename);
return pstr;
}
void getMode(char *str, const mode_t *pdata)
{
char mstr[11] = { 0 }; // more 1 to '\0'
switch (*pdata & S_IFMT) {
case S_IFSOCK: mstr[0] = 's'; break;
case S_IFLNK: mstr[0] = 'l'; break;
case S_IFREG: mstr[0] = '-'; break;
case S_IFDIR: mstr[0] = 'd'; break;
default:;
}
mstr[1] = *pdata & S_IRUSR ? 'r' : '-';
mstr[2] = *pdata & S_IWUSR ? 'w' : '-';
mstr[3] = *pdata & S_IXUSR ? 'x' : '-';
mstr[4] = *pdata & S_IRGRP ? 'r' : '-';
mstr[5] = *pdata & S_IWGRP ? 'w' : '-';
mstr[6] = *pdata & S_IXGRP ? 'x' : '-';
mstr[7] = *pdata & S_IROTH ? 'r' : '-';
mstr[8] = *pdata & S_IWOTH ? 'w' : '-';
mstr[9] = *pdata & S_IXOTH ? 'x' : '-';
_myStrcat(str, mstr);
}
void getLinkNum(char *pstr,
const unsigned short *pdata)
{
char lstr[16] = { 0 };
sprintf(lstr, "%hu", *pdata);
_myStrcat(pstr, lstr);
}
void getGID(char *pstr, const unsigned *pdata)
{
grpType *gr = getgrgid(*pdata);
if (!gr)
_myExit("getgrgid");
_myStrcat(pstr, gr->gr_name);
}
void getUID(char *pstr, const unsigned *pdata)
{
pwType *pw = getpwuid(*pdata);
if (!pw)
_myExit("getpwuid");
_myStrcat(pstr, pw->pw_name);
}
void getMTime(char *pstr, const tmType *pdata)
{
char *pt = ctime(&pdata->tv_sec);
if (!pt)
_myExit("ctime");
*(pt + strlen(pt) - 1) = 0; // trim '\n' on the tail
_myStrcat(pstr, pt);
}
void getSize(char *pstr, const long long *pdata)
{
char ss[16];
sprintf(ss, "%lld", *pdata);
_myStrcat(pstr, ss);
}
void getFilename(char *pstr, const char *pdata)
{
_myStrcat(pstr, pdata);
}