Linux网络编程综合运用之MiniFtp实现(九)
上次中实现了FTP命令的映射来避免很多if....else的判断,这次主要是开始实现目录列表的传输,先看一下目前实现的:
数据连接创建好之后则开始进行目录列表的传输了,而要传输目录列表,首先要将目录列表这些数据获取出来,所以这次主要是完成目录列表数据的获取。
还是对照着vsftpd的目录列表的显示来做参考:
将其列表输出拷贝出来:
其它跟"ls -l"的输出形式类似:
下面定义一个函数来将当前目录列出来:
int list_common(void)
{
//打开当前目录
DIR *dir = opendir(".");
if (dir == NULL)
{
return ;
} return ;
}
接下来读取目录进行遍历,可以通过如下函数:
【说明】:关于文件目录操作的知识,在之前的系统编程中已经学过了。
int list_common(void)
{
//打开当前目录
DIR *dir = opendir(".");
if (dir == NULL)
{
return ;
} //读取目录并进行遍历
struct dirent *dt;
while ((dt = readdir(dir)) != NULL)
{
} return ;
}
接下来读取文件的状态,并按vsftpd的输出格式来输出:
首先需要获取文件的状态,可以通过如下函数:
上面有两个获取文件状态的函数:stat、lstat,那这里要使用哪一个呢?这里要使用lstat,先看一下他们两者的区别:
所以代码如下:
int list_common(void)
{
//打开当前目录
DIR *dir = opendir(".");
if (dir == NULL)
{
return ;
} //读取目录并进行遍历
struct dirent *dt;
struct stat sbuf;
while ((dt = readdir(dir)) != NULL)
{ //获取文件的状态
if (lstat(dt->d_name, &sbuf) < 0)
{
continue;
}
} return ;
}
接下来从文件状态中来读取权限位,首先读取的是文件类型:
而它的获取,可以通过它来:
具体代码如下:
int list_common(void)
{
//打开当前目录
DIR *dir = opendir(".");
if (dir == NULL)
{
return ;
} //读取目录并进行遍历
struct dirent *dt;
struct stat sbuf;
while ((dt = readdir(dir)) != NULL)
{ //获取文件的状态
if (lstat(dt->d_name, &sbuf) < )
{
continue;
} char perms[] = "----------";
perms[0] = '?';
//获取文件类型
mode_t mode = sbuf.st_mode;
switch (mode & S_IFMT)
{
case S_IFREG://普通文件
perms[0] = '-';
break;
case S_IFDIR://目录文件
perms[0] = 'd';
break;
case S_IFLNK://链接文件
perms[0] = 'l';
break;
case S_IFIFO://管道文件
perms[0] = 'p';
break;
case S_IFSOCK://套接字文件
perms[0] = 's';
break;
case S_IFCHR://字符设备文件
perms[0] = 'c';
break;
case S_IFBLK://块设备文件
perms[0] = 'b';
break;
}
} return ;
}
接下来要获取的是9位的权限:
也可以通过这些来获取到:
具体代码如下:
int list_common(void)
{
//打开当前目录
DIR *dir = opendir(".");
if (dir == NULL)
{
return ;
} //读取目录并进行遍历
struct dirent *dt;
struct stat sbuf;
while ((dt = readdir(dir)) != NULL)
{ //获取文件的状态
if (lstat(dt->d_name, &sbuf) < )
{
continue;
} char perms[] = "----------";
perms[] = '?';
//获取文件类型
mode_t mode = sbuf.st_mode;
switch (mode & S_IFMT)
{
case S_IFREG://普通文件
perms[] = '-';
break;
case S_IFDIR://目录文件
perms[] = 'd';
break;
case S_IFLNK://链接文件
perms[] = 'l';
break;
case S_IFIFO://管道文件
perms[] = 'p';
break;
case S_IFSOCK://套接字文件
perms[] = 's';
break;
case S_IFCHR://字符设备文件
perms[] = 'c';
break;
case S_IFBLK://块设备文件
perms[] = 'b';
break;
} //获取文件9个权限位
if (mode & S_IRUSR)
{
perms[1] = 'r';
}
if (mode & S_IWUSR)
{
perms[2] = 'w';
}
if (mode & S_IXUSR)
{
perms[3] = 'x';
}
if (mode & S_IRGRP)
{
perms[4] = 'r';
}
if (mode & S_IWGRP)
{
perms[5] = 'w';
}
if (mode & S_IXGRP)
{
perms[6] = 'x';
}
if (mode & S_IROTH)
{
perms[7] = 'r';
}
if (mode & S_IWOTH)
{
perms[8] = 'w';
}
if (mode & S_IXOTH)
{
perms[9] = 'x';
}
} return ;
}
接下来就是一些特珠的权限位,下面来看下:
文件a的权限如上,下面给它更改一下权限:
同样的组权限也有类似的小s,大s,而其它组的权限有小t,大T权限,所以下面来处理这些特珠权限:
int list_common(void)
{
//打开当前目录
DIR *dir = opendir(".");
if (dir == NULL)
{
return ;
} //读取目录并进行遍历
struct dirent *dt;
struct stat sbuf;
while ((dt = readdir(dir)) != NULL)
{ //获取文件的状态
if (lstat(dt->d_name, &sbuf) < )
{
continue;
} char perms[] = "----------";
perms[] = '?';
//获取文件类型
mode_t mode = sbuf.st_mode;
switch (mode & S_IFMT)
{
case S_IFREG://普通文件
perms[] = '-';
break;
case S_IFDIR://目录文件
perms[] = 'd';
break;
case S_IFLNK://链接文件
perms[] = 'l';
break;
case S_IFIFO://管道文件
perms[] = 'p';
break;
case S_IFSOCK://套接字文件
perms[] = 's';
break;
case S_IFCHR://字符设备文件
perms[] = 'c';
break;
case S_IFBLK://块设备文件
perms[] = 'b';
break;
} //获取文件9个权限位
if (mode & S_IRUSR)
{
perms[] = 'r';
}
if (mode & S_IWUSR)
{
perms[] = 'w';
}
if (mode & S_IXUSR)
{
perms[] = 'x';
}
if (mode & S_IRGRP)
{
perms[] = 'r';
}
if (mode & S_IWGRP)
{
perms[] = 'w';
}
if (mode & S_IXGRP)
{
perms[] = 'x';
}
if (mode & S_IROTH)
{
perms[] = 'r';
}
if (mode & S_IWOTH)
{
perms[] = 'w';
}
if (mode & S_IXOTH)
{
perms[] = 'x';
}
//获取特珠权限位
if (mode & S_ISUID)
{
perms[3] = (perms[3] == 'x') ? 's' : 'S';
}
if (mode & S_ISGID)
{
perms[6] = (perms[6] == 'x') ? 's' : 'S';
}
if (mode & S_ISVTX)
{
perms[9] = (perms[9] == 'x') ? 't' : 'T';
}
} return ;
}
并且要将之前获取的权限信息与连接接,以及后面的那些信息连接起来格式化,所以下面将获取的信息格式化:
int list_common(void)
{
//打开当前目录
DIR *dir = opendir(".");
if (dir == NULL)
{
return ;
} //读取目录并进行遍历
struct dirent *dt;
struct stat sbuf;
while ((dt = readdir(dir)) != NULL)
{ //获取文件的状态
if (lstat(dt->d_name, &sbuf) < )
{
continue;
} char perms[] = "----------";
perms[] = '?';
//获取文件类型
mode_t mode = sbuf.st_mode;
switch (mode & S_IFMT)
{
case S_IFREG://普通文件
perms[] = '-';
break;
case S_IFDIR://目录文件
perms[] = 'd';
break;
case S_IFLNK://链接文件
perms[] = 'l';
break;
case S_IFIFO://管道文件
perms[] = 'p';
break;
case S_IFSOCK://套接字文件
perms[] = 's';
break;
case S_IFCHR://字符设备文件
perms[] = 'c';
break;
case S_IFBLK://块设备文件
perms[] = 'b';
break;
} //获取文件9个权限位
if (mode & S_IRUSR)
{
perms[] = 'r';
}
if (mode & S_IWUSR)
{
perms[] = 'w';
}
if (mode & S_IXUSR)
{
perms[] = 'x';
}
if (mode & S_IRGRP)
{
perms[] = 'r';
}
if (mode & S_IWGRP)
{
perms[] = 'w';
}
if (mode & S_IXGRP)
{
perms[] = 'x';
}
if (mode & S_IROTH)
{
perms[] = 'r';
}
if (mode & S_IWOTH)
{
perms[] = 'w';
}
if (mode & S_IXOTH)
{
perms[] = 'x';
}
//获取特珠权限位
if (mode & S_ISUID)
{
perms[] = (perms[] == 'x') ? 's' : 'S';
}
if (mode & S_ISGID)
{
perms[] = (perms[] == 'x') ? 's' : 'S';
}
if (mode & S_ISVTX)
{
perms[] = (perms[] == 'x') ? 't' : 'T';
} //格式化信息
char buf[1024] = {0};
int off = 0;
off += sprintf(buf, "%s ", perms);//连接权限位
off += sprintf(buf + off, " %3d %-8d %-8d ", sbuf.st_nlink, sbuf.st_uid, sbuf.st_gid);//连接连接数、uid、gid
off += sprintf(buf + off, "%8lu ", (unsigned long)sbuf.st_size);//连接文件大小,以8位的长度展现
} return ;
}
这两个日期显示的规则是这样:
下面来具体实现:
首先需要获取系统的当前时间,可以利用这个函数:
【说明】而格式化中的“%b”、“%e”、"%Y"是什么意思,可以查看该函数:strftime:
接下来将日期进行格式化:
最后一个信息则是文件名:
写了这么多,下面来编译运行一下:
一大堆头文件没有包含,所以需要包含一下:
再次编译运行:
编译通过了,下面来编写一下测试代码来验证当前目录输出代码是不OK:
运行看下效果:
再次编译运行:
将编译的可执行文件拷贝到home目录,以便跟vsftptd的进行对比,然后再进入home目录来运行:
修改代码如下:
再次编译运行:
上面来看已经跟vsftpd显示的效果基本一样了,但是有一个链接文件b是指向a的,这里没有显示出来,看下vsftpd是如何显示的:
所以下面得对符号链接文件要进行修改,代码如下:
其中判断一个文件是否是符号链接文件可以用宏S_ISLNK,实际它的内部是:
再次编译运行:
最后跟vsftpd的输出做一下对比:
好了,这次的东西有点多,需好好消化,下次则继续完成FTP目录列表的显示~
27_23
Linux网络编程综合运用之MiniFtp实现(九)的更多相关文章
- Linux网络编程综合运用之MiniFtp实现(一)
春节过后,万物复苏,在这元宵佳节的前一天,决定继续开启新年的学习计划,生命在于运动,提高源于学习,在经过漫长的Linux网络编程学习后,接下来会以一个综合的小项目来将所学的知识点综合运用,首先是对项目 ...
- Linux网络编程综合运用之MiniFtp实现(四)
从今天开始,正式进入MiniFtp的代码编写阶段了,好兴奋,接下来很长一段时间会将整个实现过程从无到有一点点实现出来,达到综合应用的效果,话不多说正入正题: 这节主要是将基础代码框架搭建好,基于上节介 ...
- Linux网络编程综合运用之MiniFtp实现(五)
转眼兴奋的五一小长假就要到来了,在放假前夕还是需要保持一颗淡定的心,上次中已经对miniFTP有基础框架进行了搭建,这次继续进行往上加代码,这次主要还是将经历投射到handle_child()服务进程 ...
- Linux网络编程综合运用之MiniFtp实现(八)
上节中实现了"USER"和"PASS"命令,如下: 事实上FTP是有很多命令组成的,如果就采用上面的这种方法来实现的话,就会有很多if...else if语句, ...
- Linux网络编程综合运用之MiniFtp实现(七)
上节中实现了配置文件的解析,这节来实现用户登录的验证,首先用客户端来登录vsftpd来演示登录的过程: 接着再连接miniftpd,来看下目前的效果: 接下来实现它,与协议相关的模块都是在ftppro ...
- Linux网络编程综合运用之MiniFtp实现(六)
间隔了一周时间没写了,由于今年的股势行情貌似不错的样子,对于对股市完全不懂的我也在蠢蠢欲动,所以最近一周业余时间在“不务正业”-----学习炒股.发现学习它其实挺费神的,满脑子都是走势图,而且是神经有 ...
- Linux网络编程综合运用之MiniFtp实现(三)
前面已经对FTP相关的一些概念有了基本的认识,接下来就要进入代码编写阶段了,也是非常兴奋的阶段,在开启这个它之前先对项目需求进行一个梳理,对其我们要实现的FTP服务器是一个什么样子. ftp命令列表 ...
- 【深入浅出Linux网络编程】 "开篇 -- 知其然,知其所以然"
[深入浅出Linux网络编程]是一个连载博客,内容源于本人的工作经验,旨在给读者提供靠谱高效的学习途径,不必在零散的互联网资源中浪费精力,快速的掌握Linux网络编程. 连载包含4篇,会陆续编写发出, ...
- 【linux草鞋应用编程系列】_5_ Linux网络编程
一.网络通信简介 第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章. 二.linux网络通信 在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...
随机推荐
- 微信小程序中的事件绑定
前言: 微信小程序中的事件绑定和Vue中的事件绑定其实有很多的相似之处,所以如果有过Vue相关的经验,学起来的话还是比较容易的. js代码: // 页面级的js文件必须调用Page函数来注册页面, / ...
- python 线程队列PriorityQueue(优先队列)(37)
在 线程队列Queue / 线程队列LifoQueue 文章中分别介绍了先进先出队列Queue和先进后出队列LifoQueue,而今天给大家介绍的是最后一种:优先队列PriorityQueue,对队列 ...
- JVM(一) 内存结构
JVM内存结构 方法区(JDK8以上叫元空间)和堆为线程共享区,虚拟机栈.本地方法栈及程序计数器为线程独占区, 还有一个没有在下图中体现的叫做直接内存(Direct Memory),不受JVM GC ...
- 开源软件“meld”-替代beyond compare -- & 放在linux命令后面真好用
1, 使用技巧 命令行直接对比文件 meld dir1 dir2 & 亦可以直接打开界面进行类似beyondCompare的操作. { & 放在命令后面表示设置此进程为后台进程 默认情 ...
- poj1056(字符串判断是否存在一个字符串是另一个字符串的前缀)
题目链接:https://vjudge.net/problem/POJ-1056 题意:给定一个字符串集,判断是否存在一个字符串是另一个字符串的前缀. 思路:和hdoj1671一样,有两种情况: 当前 ...
- hadoop 集群调优实践总结
调优概述# 几乎在很多场景,MapRdeuce或者说分布式架构,都会在IO受限,硬盘或者网络读取数据遇到瓶颈.处理数据瓶颈CPU受限.大量的硬盘读写数据是海量数据分析常见情况. IO受限例子: 索引 ...
- java后台面试之计算机网络问题集锦
1.http和https的区别 2.对称加密和非对称加密 3.三次握手与四次挥手的流程 4.为什么TCP需要三次握手?两次不可以吗?为什么 5.为什么TCP挥手需要四次?三次不行吗? 6.TCP协议如 ...
- [转帖]JVM—深入理解内存模型与垃圾收集机制
JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...
- Python06之分支和循环1(三目运算符)
Python 为了使得程序更加简洁而新引入过来的一个三目操作符,顾名思义就是有三个参数. 格式: x if 条件表达式 else y 先判断条件表达式真假,真则取 x 的值,否则取 y 的值. 例如: ...
- 【Qt】Qt5.12连接MySQl5.7(亲自测试成功)
目录 00. 目录 01. Qt5.12连接MySQL5.7测试代码 02. Qt5.12连接MySQL5.7问题描述 03. 解决办法 04. 结果测试 05. 打赏 00. 目录 01. Qt5. ...