2017-2018-1 20155339 第十一周加分项Linux下Mypwd的实现

学习pwd命令

  • 通过man命令查看pwd命令的功能

  • 由图可知pwd命令的用途是显示工作目录的路径名称。pwd 命令将当前目录的全路径名称(从根目录)写入标准输出。全部目录使用 /(斜线)分隔。第一个 / 表示根目录,最后一个目录是当前目录。

  • pwd [-L]如果 PWD 环境变量包含了不包含文件名 .(点)或 ..(点点)的当前目录的绝对路径名,则显示 PWD 环境变量的值。否则,-L 标志与 -P 标志一样运行。

  • pwd [-p]显示当前目录的绝对路径名。与 -P 标志一起显示的绝对路径不包含在路径名的绝对路径中涉及到符号链接类型的文件的名称。

  • 运行结果

研究pwd实现需要的系统调用(man -k; grep),写出伪代码

  • 分析:由图可知,getcwd具备这个功能,除此之外```readdir``也可以实现该功能。
  • getcwd:通过查看帮助文档,可以知道该函数用途:取得当前的工作目录,头文件为#include <unistd.h>,使用方法:char *getcwd(char *buf, size_t size);getcwd()会将当前的工作目录绝对路径复制到参数buf 所指的内存空间,参数size 为buf 的空间大小。
  • getcwd伪代码:
char buf[256];
getcwd(buf,sizeof(buf));
输出buf;
  • readdir:通过查看readdir的帮助文档可知此处调用readdir的c函数库函数比较合适,查看其帮助文档,如下图,其用途为读取目录,头文件为#include <dirent.h>函数使用方法:struct dirent *readdir(DIR *dirp); 返回dirent结构体指针,dirent结构体成员如下,
 struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* not an offset; see NOTES */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all filesystem types */
char d_name[256]; /* filename */
};

  • 查看readdir的相关函数可以看到opendir,借鉴之前的经验,在read一个文件之前肯定需要先将这个文件打开,因此我们查看opendir的帮助文档,该函数用途为:打开目录文件,头文件为:
#include <sys/types.h>
#include <dirent.h>

函数原型:DIR *opendir(const char *name);

返回值:成功则返回DIR* 型态的目录流, 打开失败则返回NULL。

  • 文件是通过i节点对其内容进行一个索引,因此一个文件一个i节点,因此此处我们要实现pwd命令,必须要知道文件的i节点,并且通过实践可知(可以在根目录下查看i结点值可知,根节点与其父结点的i节点值一样,因此可以通过这一点来设定循环条件,通过man帮助文档进行查找,得到如下信息:

  • 选择stat函数:用途:获取文件信息,头文件:#include <sys/stat.h> #include <unistd.h>函数原型:int stat(const char *file_name, struct stat *buf);

    函数说明: 通过文件名filename获取文件信息,并保存在buf所指的结构体stat中

    返回值: 执行成功则返回0,失败返回-1,错误代码存于errno,结构体stat:

struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};

此处我们需要的是其结构体中的ino_t,来获取文件的节点。

  • 在此过程中,我们还需要改变当前工作的目录,通过man来查找,发现chdir()函数符合要求:函数功能:改变当前工作目录,

    头文件:#include<unistd.h>,

    函数定义:int chdir(const char *path),

    函数说明:将当前的工作目录改变成以参数path所指的目录。

    返回值:执行成功则返回0,失败返回-1,errno为错误代码。

  • readdir伪代码:


while(1)
{
通过文件名“.”获取当前目录的i节点;
通过文件名“..”获取当前目录的父级目录的i节点;
判断当前目录和上级目录的inode-number是否一样;
if(两个节点一样,则说明到达根目录 )
跳出循环;
else
切换至父级目录,获取inode-number,在父级目录中搜索对应的文件名并记录下来;
搜索文件名并存入文件名到数组中;
}
输出文件名;

实现mypwd

  • 通过getcwd实现:

#include "stdio.h"
#include "unistd.h"
int main(void)
{
char buf[256];
getcwd(buf,sizeof(buf));
printf("当前路径为:%s\n",buf);
return 0;
}
  • 通过readdir实现:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h> /*根据文件名获取文件inode-number*/
ino_t get_ino_byname(char *filename)
{
struct stat file_stat;
if (0 != stat(filename, &file_stat)) {
perror("stat");
exit(-1);
}
return file_stat.st_ino;
} /*根据inode-number ,在当前目录中查找对应的文件名*/
char* find_name_byino(ino_t ino)
{
DIR *dp = NULL;
struct dirent *dptr = NULL;
char *filename = NULL;
if (NULL == (dp = opendir("."))) {
fprintf(stderr, "Can not open Current Directory\n");
exit(-1);
} else {
while (NULL != (dptr = readdir(dp))) {
if (dptr->d_ino == ino) {
filename = strdup(dptr->d_name);
break;
}
}
closedir(dp);
}
return filename;
} #define MAX_DIR_DEPTH (256) int main(int argc, char *argv[])
{ char *dir_stack[MAX_DIR_DEPTH];
unsigned current_depth = 0; while(1){
/*1.通过特殊的文件名“.”获取当前目录的inode-number*/
ino_t c_ino = get_ino_byname(".");
/*2.通过特殊的文件名“..”获取当前目录的父级目录的inode-number*/
ino_t p_ino = get_ino_byname(".."); /*3.判断当前目录和上级目录的inode-number是否一样*/
if (c_ino == p_ino)
break; /*4.如果两个inode-number一样说明到达根目录*/ /*5.如果两个inode-number不一样*/ /*切换至父级目录,根据步骤1获取的inode-number,在父级目录中搜索对应的文件名并记录下来, 重新回到步骤1*/
chdir("..");
dir_stack[current_depth++] = find_name_byino(c_ino);
if (current_depth>=MAX_DIR_DEPTH) { /*路径名太深*/
fprintf(stderr, "Directory tree is too deep.\n");
exit(-1);
}
} /*输出完整路径名*/
//int i = current_depth-1;
int i;
for (i = current_depth-1; i>=0; i--) {
fprintf(stdout, "/%s", dir_stack[i]);
}
fprintf(stdout, "%s\n", current_depth==0?"/":""); return 0;
}

测试mypwd

  • getced实现:

  • readdir实现:

2017-2018-1 20155339 第十一周加分项Linux下Mypwd的实现的更多相关文章

  1. 2017-2018-1 20155338 《信息安全系统设计基础》第5周加分项Mybash的实现

    2017-2018-1 20155338 <信息安全系统设计基础>第5周加分项Mybash的实现 使用fork,exec,wait实现mybash 一.fork函数 定义和理解:fork( ...

  2. 20155322 2017-2018-1《信息安全系统设计》第二周 课堂测试 Linux下C语言实现MYOD

    20155322 2017-2018-1<信息安全系统设计>第二周 课堂测试 Linux下C语言实现MYOD [博客目录] 静态库测试 实现方法 相关资料 操作 动态库测试 实现方法 相关 ...

  3. 2017-2018-1 20155215 第九周 加分项 PWD命令的实现

    1 学习pwd命令 Linux中用 pwd 命令来查看"当前工作目录"的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pw ...

  4. “2017面向对象程序设计(Java)第十一周学习总结”存在问题的反馈及教学安排

    “2017面向对象程序设计(Java)第十一周学习总结”存在问题的反馈及教学安排1.“提出表扬的同学:姜依萍,王雪玲,徐楠,相文君,赵晓未提交作业的同学:任红强,王瑞强,宗鹏新,扎西才让,布旦刀杰,范 ...

  5. 2017面向对象程序设计(Java)第十一周学习总结

    首先,由于前几周同学们普遍反映知识点比较难,并且累积较多,难以掌握,所以老师在上周对教学方案进行了如下调整: (1)周四下午理论课第一学时,将结合实验八与实验九的编程题,通过范例演示同学们存在问题的解 ...

  6. 201521123061 《Java程序设计》第十一周学习总结

    201521123061 <Java程序设计>第十一周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 本周学习的是如何解决多线程访问中的互斥 ...

  7. 201521123038 《Java程序设计》 第十一周学习总结

    201521123038 <Java程序设计> 第十一周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多 ...

  8. 2017-2018-2 1723《程序设计与数据结构》第十一周作业 & 实验三 & (总体)第三周结对编程 总结

    作业地址 第十一次作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1933 (作业界面已评分,可随时查看,如果对自己的评分有 ...

  9. C语言程序设计I—第十一周教学

    第十一周教学总结(12/11-17/11) 教学内容 第4章 循环结构-break continue嵌套循环 4.3 判断素数,4.4求1! + 2! + -. + 100! 课前准备 在蓝墨云班课发 ...

随机推荐

  1. 008单例、继承、final

    内容:单例,类继承,final #################################################################################### ...

  2. PHP: APC Configuration and Usage Tips and Tricks

    原文链接:http://www.if-not-true-then-false.com/2012/php-apc-configuration-and-usage-tips-and-tricks/3/ T ...

  3. jwplayer视频--不兼容IE8

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  4. 关于crontab中的一些小问题

    今天写了个脚本,要写进crontab做定时任务,每5分钟跑一遍.关于crontab的介绍呢,请大家移步www.baidu.com,在这里我就不仔细介绍了.可以搜索一下“每天一个Linux命令”系列文章 ...

  5. UVa 10900 - So you want to be a 2n-aire?(期望DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  6. 【51nod 1514】 美妙的序列

    题目 我们发现我们得正难则反 还是设\(f_i\)表示长度为\(i\)的序列个数 考虑容斥 \[f_i=i!-\sum_{j=1}^{i-1}f_j(i-j)!\] \(i!\)显然是总方案数,我们减 ...

  7. 【[ZJOI2008]泡泡堂】

    想贪心就是反复\(hack\)自己的过程 首先这很田忌赛马,但是又不完全一样 田忌赛马保证了所有马的实力不同,因此没有平局 田忌赛马的策略是当自己最强的马比不过对方最强的马的时候,就用自己最弱的马来自 ...

  8. Hadoop学习之路(十八)MapReduce框架Combiner分区

    对combiner的理解 combiner其实属于优化方案,由于带宽限制,应该尽量map和reduce之间的数据传输数量.它在Map端把同一个key的键值对合并在一起并计算,计算规则与reduce一致 ...

  9. 从零搭建vue

    第一步: 安装node.js,一般安装 长期维护版  相对比较稳定 点击下载,下载好了之后双击运行,可选择安装路径,然后一路下一步即可. 安装完成后,在cmd输入 node -v 如果出现版本号,则安 ...

  10. 微服务之配置中心ConfigKeeper

    在微服务架构中,配置中心是必不可少的基础服务.ConfigKeeper已开源,本文将深度分析配置中心的核心内容,错过「Spring Cloud中国社区北京沙龙-2018.10.28 」的同学将从本篇文 ...