简易仿写linux命令ls

更新内容:

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);
}

>查看最新源码

猜你喜欢

转载自www.cnblogs.com/wangyubjhd/p/10280913.html
今日推荐