Skip to content

ls.c

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
#include "kernel/fcntl.h"

TIP

格式化文件名

char*
fmtname(char *path)
{
  static char buf[DIRSIZ+1];
  char *p;

TIP

找到最后一个斜杠后面的第一个字符

  for(p=path+strlen(path); p >= path && *p != '/'; p--)
    ;
  p++;

TIP

返回用空格填充的名称

  if(strlen(p) >= DIRSIZ)
    return p;
  memmove(buf, p, strlen(p));
  memset(buf+strlen(p), ' ', DIRSIZ-strlen(p));
  return buf;
}

TIP

列出目录内容

void
ls(char *path)
{
  char buf[512], *p;
  int fd;
  struct dirent de;
  struct stat st;

TIP

打开路径

  if((fd = open(path, O_RDONLY)) < 0){
    fprintf(2, "ls: cannot open %s\n", path);
    return;
  }

TIP

获取文件状态

  if(fstat(fd, &st) < 0){
    fprintf(2, "ls: cannot stat %s\n", path);
    close(fd);
    return;
  }

  switch(st.type){
  case T_DEVICE:
  case T_FILE:
    printf("%s %d %d %d\n", fmtname(path), st.type, st.ino, (int) st.size);
    break;

  case T_DIR:
    if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
      printf("ls: path too long\n");
      break;
    }
    strcpy(buf, path);
    p = buf+strlen(buf);
    *p++ = '/';

TIP

读取目录项

    while(read(fd, &de, sizeof(de)) == sizeof(de)){
      if(de.inum == 0)
        continue;
      memmove(p, de.name, DIRSIZ);
      p[DIRSIZ] = 0;

TIP

获取目录项的状态

      if(stat(buf, &st) < 0){
        printf("ls: cannot stat %s\n", buf);
        continue;
      }
      printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, (int) st.size);
    }
    break;
  }
  close(fd);
}

TIP

程序入口

int
main(int argc, char *argv[])
{
  int i;

TIP

如果没有参数,则列出当前目录

  if(argc < 2){
    ls(".");
    exit(0);
  }

TIP

遍历所有参数(路径)

  for(i=1; i<argc; i++)
    ls(argv[i]);
  exit(0);
}