⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 新建 文本文档 (2).txt

📁 对LS命令的详细注释
💻 TXT
📖 第 1 页 / 共 2 页
字号:
/*
 * 对UNUX V7 ls命令原代码的注释。
 * 位置:UNIX V7/usr/src/cmd/ls.c 
 */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/dir.h>
#include <stdio.h>
#define NFILES 1024
FILE *pwdf, *dirf;
char stdbuf[BUFSIZ];
/*   struc lbuf 封装了对ls有用的struct stat */
struct lbuf {
 union {
  char lname[15];
  char *namep;  //文件名 
 } ln;
 char ltype;  //文件类型 
 short lnum;   //索引结点号 
 short lflags; //权限位 
 short lnl;    //链接数 
 short luid;   //用户ID 
 short lgid;   //组ID 
 long lsize;  //文件大小 
 long lmtime; //访问时间 
};
/* 每个选项设置一个标记变量 */
int aflg, dflg, lflg, sflg, tflg, uflg, iflg, fflg, gflg, cflg;
int rflg = 1;  //颠倒排序标志 如果使用-r 选项,则rflg会被置-1 
long year;     //这个变量被设置为从1970年1月1日午夜到当前时间六个月前所经过的秒数 
int flags;
int lastuid = -1; //用户ID用于测试 
char tbuf[16];
long tblocks;   //文件所占用的磁盘块数 
int statreq;       //使用stat()系统调用的标志,如果为 1 则表示使用stat获取目录信息 
struct lbuf *flist[NFILES];
struct lbuf **lastp = flist;
struct lbuf **firstp = flist;//以上三个变量表示用ls 显示信息的文件 
char *dotp = ".";   //设置默认读取的目录,即当前目录 
char *makename();     //连接由斜杠字符分割的目录名和文件名并产生一个字符串 
struct lbuf *gstat();   //读取和存储文件信息的核心函数 
char *ctime();        //获得时间的函数 
long nblock();        //计算文件使用的磁盘块数 
#define ISARG 0100000  //用于区分一个文件是由命令行给定还是由目录中读取 
main(argc, argv)
char *argv[];
{
 int i;
 register struct lbuf *ep, **ep1;
 register struct lbuf **slastp;
 struct lbuf **epp;
 struct lbuf lb;
 char *t;
 int compar();
 setbuf(stdout, stdbuf);
 time(&lb.lmtime);        //获取当前时间 
 year = lb.lmtime - 6L*30L*24L*60L*60L; /* 6 个月之前 */
 if (--argc > 0 && *argv[1] == '-') { 
  argv++;                    //跳过程序文件名
  while (*++*argv) switch (**argv) {//扫描命令行上第一个参数 
  case 'a':  //输出所有目录项。如果没有该选项,则不输出 '.' 和 '..'。 
   aflg++;
   continue;
  case 's':  //输出文件大小。文件名以字母顺序排列 
   sflg++;
   statreq++;
   continue;
  case 'd':  //用于目录参数,输出目录本身的信息,而不是目录的内容 
   dflg++;
   continue;
  case 'g':  //用于 'ls -l',但输出组名而不是用户名 
   gflg++;
   continue;
  case 'l':  //在第一列与文件名或长列表一起输出结点索引号 
   lflg++;
   statreq++;
   continue;
  case 'r':  //颠倒顺序排列。文件名以字母顺序或时间顺序进行排列 
   rflg = -1;
   continue;
  case 't':  //以修改时间而不是文件名排列输出结果,最近修改的文件处于最前面 
   tflg++;
   statreq++;
   continue;
  case 'u': //以访问时间而不是修改时间排列输出结果,与-t或 -l一起使用 
   uflg++;
   continue;
  case 'c': //使用索引结点的改变时间,而不是文件的修改时间。该选项与-t或-l一起使用。 
   cflg++;
   continue;
  case 'i': //在第一列与文件名或长列表一起输出节点索引号 
   iflg++;
   continue;
  case 'f': //强迫每个参数都当作目录读取,然后输出在每个目录槽中找到的
                  //文件名。该选项使-l、-r、-s和-t选项无效,但激活了-a选项 
   fflg++;
   continue;
  default:  //忽略未知的选项字母 
   continue;
  }
  argc--;   //扫描完第一个参数后,由于argv的移动,将argc减1 
 }
 if (fflg) {
  aflg++;
  lflg = 0;//-f覆盖了-l、-s和-t选项 
  sflg = 0;
  tflg = 0;
  statreq = 0;
 }
 if(lflg) {   //打开口令或组文件 
  t = "/etc/passwd";
  if(gflg)           //V7 ls命令仅显示用户和组信息中的一项 
   t = "/etc/group";
  pwdf = fopen(t, "r");
 }
 if (argc==0) {//如果没有指定参数,则使用当前目录 
  argc++;  
  argv = &dotp - 1; //减1 是为了对下面的第139行'++argv'进行弥补 
 }
 for (i=0; i < argc; i++) { //获得每个文件信息 
  if ((ep = gstat(*++argv, 1))==NULL)//gstat的第二个参数表示如果为1则文件
                                           //由命令行参数给定,否则为假 
   continue;
  ep->ln.namep = *argv;   //获得文件名 
  ep->lflags |= ISARG;    //加入ISARG位,用于后面判断文件是由命令行给定还是由
                                //目录读取 
 }
 qsort(firstp, lastp - firstp, sizeof *lastp, compar);//对文件进行排序,这是个
                                                         //库中的排序函数 
 slastp = lastp;             //将lastt当前值保存在slastp中 
 for (epp=firstp; epp<slastp; epp++) {//对数组的每个元素进行循环以适当的方式
                                   //输出文件或目录信息 
  ep = *epp;
  if (ep->ltype=='d' && dflg==0 || fflg) {//如果文件类型为目录并且未提供-d
                  //选项或提供了-f选项,则ls必须读取该目录而不是输出该目录本身的信息 
   if (argc>1)//如果命令行提供了多个文件则输出目录名和一个冒号 
    printf("\n%s:\n", ep->ln.namep);
   lastp = slastp;           //重设lastp 
   readdir(ep->ln.namep);
//flist数组作为一个两层的文件名堆栈。命令行参数通过slastp-1保存在flist中,当readdir
//读取目录的时候它将该目录内容的struct lbuf结构置于该堆栈之上,由slastp开始直到lastp。 
   if (fflg==0)//如果-f选项无效,则对子目录项进行排序。 
    qsort(slastp,lastp - slastp,sizeof *lastp,compar);
   if (lflg || sflg)//输出目录中文件占用的块的总数用于-l或-s选项 
    printf("total %D\n", tblocks);//%D相当于现在的%ld 
   for (ep1=slastp; ep1<lastp; ep1++)//输出子目录每个文件的信息。 
    pentry(*ep1);                 //只深入到目录树的下一层,它没有用递归选项 
  } else 
   pentry(ep);
 }
 exit(0);
}
pentry(ap)  //输出关于文件的信息函数 
struct lbuf *ap;
{
 struct { char dminor, dmajor;};  //这个变量未被使用! 
 register t;
 register struct lbuf *p;
 register char *cp;
 p = ap;
 if (p->lnum == -1)//如果为真则 struct lbuf是无效的。返回。 
  return;
 if (iflg)
  printf("%5u ", p->lnum);  //索引节点号 
 if (sflg)
 printf("%4D ", nblock(p->lsize));//以块为单位的文件大小 
 if (lflg) {  //以长格式输出 
  putchar(p->ltype);//输出文件类型 
  pmode(p->lflags);//输出权限 
  printf("%2d ", p->lnl);
  t = p->luid;
  if(gflg)
   t = p->lgid;
  if (getname(t, tbuf)==0)
   printf("%-6.6s", tbuf);  //输出用户或组 
  else
   printf("%-6d", t);
  if (p->ltype=='b' || p->ltype=='c')//设备:主设备号和从设备号 
   printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
  else
   printf("%7ld", p->lsize);    //以字节为单位的文件大小 
  cp = ctime(&p->lmtime);
  if(p->lmtime < year)             //修改时间 
   printf(" %-7.7s %-4.4s ", cp+4, cp+20); else//如果早于六个月之前则程序
             //输出月、日、年否则输出月、日和时间 
   printf(" %-12.12s ", cp+4);
 }
 if (p->lflags&ISARG)    //文件名。对于命令行参数,是一个以'\0'结尾的字符串可以
                            //使用%s 
  printf("%s\n", p->ln.namep);
 else//对于从目录中读取的文件,可能并非以空字符结尾,因此必须使用确切精度的格式字符串%.14s 
  printf("%.14s\n", p->ln.lname);
}
getname(uid, buf)//将用户ID或组ID转换为相应的用户名和组名。 
int uid;
char buf[];
{
 int j, c, n, i;
 if (uid==lastuid)//如果为真表示测试成功,返回 
  return(0);
 if(pwdf == NULL) //安全检查 
  return(-1);
 rewind(pwdf);   //由文件内容的起始位置开始 
 lastuid = -1;
 do {
  i = 0;  //buf数组中的索引 
  j = 0;  //行中的计数器 ,记录当前遇到的冒号数:如果是名称则为0,如果是ID则为2。 
  n = 0;  //转换数字值 
  while((c=fgetc(pwdf)) != '\n') {//读取各行 
   if (c==EOF)
    return(-1);
   if (c==':') { //对成员记数 
    j++;
    c = '0';
   }
   if (j==0)    //第一个成员为名称 
    buf[i++] = c;
   if (j==2)    //第三个成员为数字ID 
    n = n*10 + c - '0';
  }
 } while (n != uid); //一直进行搜索直到找到ID 
 buf[i++] = '\0';
 lastuid = uid;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -