首页 > 技术文章 > 20145305 《信息安全系统设计基础》第10周学习总结

summerharper 2016-11-16 21:08 原文

代码实践内容总结

cp

用来复制文件,函数大致步骤:
打开源文件
创建目标文件
针对源文件
把源文件读入缓冲区
把缓冲区内容写入目标文件
关闭源文件和目标文件

cp命令使用格式:cp src dst

运行以下命令:实现复制操作

操作之后cp1.c里面的内容被更改:

代码分析:

#include        <stdio.h>//标准输入输出
#include        <stdlib.h>//C标准函数库
#include        <unistd.h>//Unix类系统定义符号常量
#include        <fcntl.h>//定义了很多宏和open,fcntl函数原型

#define BUFFERSIZE      4096//定义存储器容量
#define COPYMODE        0644//定义复制的长度

void oops(char *, char *);

int main(int argc, char *argv[])
{
    int in_fd, out_fd, n_chars;//三个描述符值
    char buf[BUFFERSIZE];//存储器位置
    
    if (argc != 3) {//检查argc的值是否为三,如果不是,返回标准错误
        fprintf(stderr, "usage: %s source destination\n", *argv);
        exit(1);
    }
    /*检查cp的第一个参数,要复制的文件,用open打开,in_fd为open返回的描述符
    如果返回-1,代表打开失败,提示错误*/
    if ((in_fd = open(argv[1], O_RDONLY)) == -1)
        oops("Cannot open ", argv[1]);

    /*检查cp的第二个参数,复制的目的地址,用create在目的地址创建新文件,out_fd为open返回的描述符
    如果返回-1,代表创建失败,提示错误*/
    if ((out_fd = creat(argv[2], COPYMODE)) == -1)
        oops("Cannot creat", argv[2]);

    /*cp指令的动作就是读取一个文件的内容到存储器,在新的地址创建空白文件,再从存储器将内容写入新文件。
    这里判断复制是否成功:
    如果能读取顺利,而读取的位数和写的位数不同,是写错误;
    如果读取失败,是读错误。*/
    while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
        if (write(out_fd, buf, n_chars) != n_chars)
            oops("Write error to ", argv[2]);
    if (n_chars == -1)
        oops("Read error from ", argv[1]);

    /*这里执行的是关闭文件的动作,in_fd和out_fd两个文件描述符
    所指向的文件只要有一个关闭错误,就提示关闭错误。*/
    if (close(in_fd) == -1 || close(out_fd) == -1)
        oops("Error closing files", "");
}

/*这个是用来输出错误信息的函数*/
void oops(char *s1, char *s2)
{
    fprintf(stderr, "Error: %s ", s1);
    perror(s2);//用来将上一个函数发生错误的原因输出到标准设备(stderr)
    exit(1);
}

setecho & echostate

setecho
设置echo值的一个函数,输入yes后,键盘键入命令是可见的,而输入no后,键盘键入命令是不可见的,但是依然是可执行的

输入y(或是以y开头的一串字符),命令可见
否则(即输入不以y开头的字符),命令不可见

echostate
检查键盘键入命令是否可见,是与以上的setecho代码结合起来的

echo is on:命令可见
echo is off:命令不可见

注意这个过程中会有命令不可见的情形,所以很容易运行出错,必须仔细

代码分析setecho:

#include        <stdio.h>
#include        <stdlib.h>
#include        <termios.h>

#define  oops(s,x) { perror(s); exit(x); }

int main(int argc, char *argv[])
{
        struct termios info;
        if (argc == 1) //后面没有带参数的话就不做任何操作,退出
        exit(0);

        if (tcgetattr(0,&info)==-1)//tcgetattr函数用于获取与终端相关的参数。参数fd为终端的文件描述符,返回的结果保存在termios 结构体中,这里fd为0,是标准输入。这句用于读取设备属性
            oops("tcgettattr", 1);

        if ( argv[1][0] == 'y' )//如果运行命令后面的参数第一个字母是“y”,执行“设置打开提示符”的命令
                info.c_lflag |= ECHO ;/*打开提示符*/
        else//对其它所有的参数都执行“设置隐藏提示符”的命令
                info.c_lflag &= ~ECHO ;/*隐藏提示符*/

        if ( tcsetattr(0,TCSANOW,&info) == -1 )//将修改后的参数写回设备
               oops("tcsetattr",2);
    
        return 0;
}

fileinfo & filesize

fileinfo
可显示文件信息

filesize
可计算文件的字节数

以上两个代码都是先判断是否有错误,有错就打印报错信息,没有就执行功能代码

mode:st_mode        文件的类型和存取的权限         
links:st_nlink      连到该文件的硬链接数目,刚建立的文件值为1
user:st_uid         用户ID
group:st_gid        组ID          
size:st_size        文件字节数
modtime:st_mtime    最后一次修改时间
name:               输入的文件名

代码分析fileinfo:

#include    <stdio.h>
#include    <sys/types.h>
#include    <dirent.h>

void do_ls(char []);

int main(int argc, char *argv[])
{
    /*如果操作数只有1个,表明ls后面没有带参数,默认为当前目录,.表示当前目录。*/
    if ( argc == 1 )
        do_ls( "." );
    /*如果ls后面有参数,就把参数读入argv中。*/
    else
        while ( --argc ){
            printf("%s:\n", *++argv );
            do_ls( *argv );
        }

    return 0;
}

/*因为ls和dir功能相近,用dir来实现ls*/
void do_ls( char dirname[] )
{
    DIR     *dir_ptr;
    struct dirent   *direntp;

    /*如果没有指向的那个地址,报错*/
    if ( ( dir_ptr = opendir( dirname ) ) == NULL )
        fprintf(stderr,"ls1: cannot open %s\n", dirname);
    else
    {
        /*递归的方式来读取*/
        while ( ( direntp = readdir( dir_ptr ) ) != NULL )
            printf("%s\n", direntp->d_name );
        closedir(dir_ptr);
    }
}

ls

ls老师给了两个代码,第一个实现功能显示当前文件夹内容,第二个在第一个的基础上更加完善,还可显示出文件的详细信息,如读写权限,大小和创建时间等

ls实现的功能:

ls -l:显示文件信息
ls -a:列出文件目录
ls -lu:最后访问时间
ls -s:以块为单位的文件大小
ls -t:按时间排序
ls -F:显示文件类型

文件树
文件和目录被组织成目录树(tree),节点是目录或者文件
目录是一种特殊文件,文件内容就是目录和文件的名字,与utmp类似
与文件不同,目录不会为空

伪代码:

打开目录文件
针对目录文件
读取目录条目
显示文件名
关闭文件目录文件

如下是运行过程:

spwd

列出当前目录

testioctl

获得终端设备的窗口大小

下图一个是我的终端全屏的,一个是还原之后的

who

who也有两个代码,运行的结果是一样的,代码实现的功能是一样的,主要是从UTMP_FILE文件中读取信息到存储器中,然后再用标准输出函数打印到屏幕上,最后关闭文件

who命令是查询当前登录的每个用户,输出包括用户名、终端类型、登录日期及远程主机

who命令是读取/var/run/utmp文件来得到信息的

utmp这个文件,是二进制文件,里面保存的是结构体数组,这些数组是struct utmp结构体的

伪代码:

打开utmp文件
针对文件
读取一条记录
显示记录
关闭文件

如下是运行过程:

视频实践内容记录

代码托管

代码托管连接

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 200/200 2/2 30/30
第二周 300/500 1/3 20/50
第三周 100/600 1/4 20/70
第五周 300/900 1/5 30/100
第六周 136/1036 1/6 20/120
第七周 124/1160 1/7 20/140
第八周 0/1160 3/10 20/160
第九周 338/1498 1/11 25/185
第十周 505/2003 2/13 25/210

参考资料

推荐阅读