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. BZOJ1334:[Baltic2008]Elect(背包DP)

    Description N个政党要组成一个联合内阁,每个党都有自己的席位数. 现在希望你找出一种方案,你选中的党的席位数要大于总数的一半,并且联合内阁的席位数越多越好. 对于一个联合内阁,如果某个政党 ...

  2. [TJOI2018]智力竞赛

    题目 发现我们需要最大化最小值,基本是二分了 那么我们二分出来一个值我们将小于等于这个值的都删去,现在的问题变成了如何用\(n+1\)条路径覆盖这张图 这不最小路径覆盖吗 于是我就忘了最小路径覆盖怎么 ...

  3. Django中模型(二)

    Django中模型(二) 三.定义模型 1.模型.属性.表.字段间的关系: 一个模型类在数据库中对应一张表:在模型类中定义的属性,对应该模型对照表中的字段. 2.定义属性 A.概述 ·django根据 ...

  4. fastjson反序列化JdbcRowSetImpl

    Gadget com.sun.rowset.JdbcRowSetImpl setAutoCommit() -> connect() -> InitialContext.lookup() p ...

  5. shell脚本进阶 详解及其实例(一)

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  6. 模块XXXX可能与您正在运行的Windows版本不兼容。检查该模块是否与regsvr32.exe的x86(32位)x64(64位)版本兼容。

    最近自己在编写ActiveX控件.遇到的麻烦事不少. 今天遇到了这个问题“模块XXXX可能与您正在运行的Windows版本不兼容.检查该模块是否与regsvr32.exe的x86(32位)x64(64 ...

  7. cocos2d-x3.0 用CCDictionary写文件

    bool CDownLoad_LocalData::WriteToConfigFile( DownLoadLocalData* downdata ){ CCDictionary* pDict = CC ...

  8. 前端基础-HTML的的标签详解

    阅读目录 一.head内常用标签 二. HTML语义化 三. 字符实体 四. h系列标签 五. p标签 六. img标签 七. a标签 八. 列表标签 九. table标签 十. form标签 一. ...

  9. Java Activiti 工作流引擎 springmvc SSM 流程审批 后台框架源码

    1.模型管理 :web在线流程设计器.预览流程xml.导出xml.部署流程 2.流程管理 :导入导出流程资源文件.查看流程图.根据流程实例反射出流程模型.激活挂起 3.运行中流程:查看流程信息.当前任 ...

  10. iOS:时间相关(18-10-13更)

    先整理出时间相关的程序,以后有空再写成单例. 1.日历(NSCalendar) 2.时间格式() 3.时间戳 附录: 1.定时器 1.日历(NSCalendar) 1.想要获取 世纪.年.月.日.时. ...