Linux下C语言编程实现spwd函数

介绍

  • spwd函数

    • 功能:显示当前目录路径
    • 实现:通过编译执行该代码,可在终端中输出当前路径

代码实现

代码链接

所需结构体、函数、系统调用等查询(前期准备)

st_ino

  • 执行指令查看stat:man 2 stat

    • 其中用红框标注的引起了我的注意:ino_t st_ino /* inode number */

    • 而这一个结构体的成员表示,文件的索引信息(进入点),“number”告诉我们它是一个数字表示,而不是一个确切的路径,这就好比我们有时候用文件描述符来操作文件,而不用字符数组(文件名)来操作。

    • 也就是说,我们想要找到文件的路径,st_ino这个信息试关键。

opendir

  • 要读取路径,必定要先打开路径,路径如何打开可以用指令查询一下:man -k dir | grep open
  • 根据查询结果接着输入指令:man 3 opendir查看详细信息
    • 也就是说输入参数为一个文件(目录)名,才能打开该目录,并返回为DIR类型

  • 而我们知道,当前目录的目录名为.,父级目录的目录名为..,知道目录名就好办了。

readdir

  • st_ino只能表示该文件的索引信息,那如何将它的各个父目录读取出来呢?肯定跟读取有关(read)

  • 所以我们用指令搜索查询一下:man -k dir | grep read

  • 找到相关项后输入指令:man 3 readdir

    • 根据上述可观察到,该函数属于库<dirent.h>中,readdir函数的返回类型为一个dirent结构体,结构体的各个成员变量在截图中有明显标出

    • 可以容易发现,其中有d_inod_name[256],这两者应该是一一对应的,也就是说我只要取得了其索引号,就可以将其翻译为文件名了。

代码介绍

  • 代码由4个函数组成,分别是:

    • main函数:主函数
    • get_inode函数:取某个文件的索引信息(进入点)
    • printpathto函数:打印路径
    • inum_to_name函数:将长整型的索引信息转化为字符串的形式

整体编写思路(算法)

  • Step1:调用get_inode函数,来取得当前目录文件的st_ino值;
  • Step2:进入父目录后,打开当前目录文件,并读取该目录的dirent结构体
  • Step3:判断此时打开的目录文件的索引节点号是否与正确的子目录(进入该目录之前的那个目录)的节点号相同。若相同,输出相应dirent结构体中的d_name[256]变量;反之,继续打开后一个该目录文件的后一个位置。(此处有点像打开某个具体的文本文件,会有一个文件指针不停地向后移动,直到EOF);
  • Step4:重复Step3,直到“父目录的索引节点”等于“该目录的索引节点”(意为到达了根目录);
  • Step5:输出结果,程序完毕
  • 补充:分析上述流程不难发现,大致的思路是从当前文件夹下一直cd到根文件夹下,实现目录搜索;而我们人习惯的阅读方式则是先看根文件夹再看到当前文件夹下,加上关键的函数又是可以重复调用的,所以此处我们可以采取递归函数的特性,来实现这一点。

get_inode函数

ino_t get_inode( char *fname )
{
struct stat info; if ( stat( fname , &info ) == -1 ){
fprintf(stderr, "Cannot stat ");
perror(fname);
exit(1);
}
return info.st_ino;
}
  • 说明:该函数为取某个文件的“索引节点”信息,相关函数都已经不陌生了,在课本上以及之前博客中都有介绍,不再赘述。

printpathto函数

void printpathto( ino_t this_inode )
{
ino_t my_inode ;
char its_name[BUFSIZ]; if ( get_inode("..") != this_inode )
{
chdir( ".." ); inum_to_name(this_inode,its_name,BUFSIZ); my_inode = get_inode( "." );
printpathto( my_inode );
printf("/%s", its_name ); }
}
  • 说明:

    • 该部分函数实现了递归调用,先不看其中的inum_to_name函数,结构还是很清晰的
    • 传入一个索引节点,并求得父目录的索引节点,判断两者是否相等,相等则说明已经到了根文件夹下,可以终止递归调用
    • 如若不相等,则进入父目录,然后通过inum_to_name函数功能,将之前的目录名拷贝到its_name字符数组中,准备输出打印
    • 紧接着将进入后的父目录当作当前目录,反复执行操作,指导“第2点”中说的终止条件

inum_to_name函数

void inum_to_name(ino_t inode_to_find , char *namebuf, int buflen)
{
DIR *dir_ptr;
struct dirent *direntp; dir_ptr = opendir( "." );
if ( dir_ptr == NULL ){
perror( "." );
exit(1);
} while ( ( direntp = readdir( dir_ptr ) ) != NULL )
if ( direntp->d_ino == inode_to_find )
{
strncpy( namebuf, direntp->d_name, buflen);
namebuf[buflen-1] = '\0';
closedir( dir_ptr );
return;
}
fprintf(stderr, "error looking for inum %d\n", (int) inode_to_find);
exit(1);
}
  • 说明:

    • 该部分是整个代码的关键,起着将索引节点转化为相应的文件名的过程
    • 首先我们得打开一个目录(opendir),只有打开目录后才能正常读取目录(readdir),才能获取到dirent结构体,才能将索引节点转化为相应的文件名
    • 读取的部分很有意思,类似于我们读取文件一样。
    • 注意的是我们已经在该函数的父函数中进入了之前目录的父目录,可是现在该目录下有这么多目录,怎样才能找到进之前的目录呢?
    • 为了能正确找到之前的目录,我们将一个个读取的目录的ino信息与传参进来的ino信息做比对,如果相同,则说明找到了正确目录,把文件名拷贝到字符数组就行;如果比对结果不相同,则继续读取下一个目录。

运行结果

Linux下C语言编程实现spwd函数的更多相关文章

  1. LINUX下C语言编程调用函数、链接头文件以及库文件

    LINUX下C语言编程经常需要链接其他函数,而其他函数一般都放在另外.c文件中,或者打包放在一个库文件里面,我需要在main函数中调用这些函数,主要有如下几种方法: 1.当需要调用函数的个数比较少时, ...

  2. Linux基础与Linux下C语言编程基础

    Linux基础 1 Linux命令 如果使用GUI,Linux和Windows没有什么区别.Linux学习应用的一个特点是通过命令行进行使用. 登录Linux后,我们就可以在#或$符后面去输入命令,有 ...

  3. LINUX下C语言编程基础

    实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用 ...

  4. Linux下C语言编程基础学习记录

    VIM的基本使用  LINUX下C语言编程 用gcc命令编译运行C语言文件 预处理阶段:将*.c文件转化为*.i预处理过的C程序. 编译阶段:将*.i文件编译为汇编代码*.s文件. 汇编阶段:将*.s ...

  5. 【转】Linux基础与Linux下C语言编程基础

    原文:https://www.cnblogs.com/huyufeng/p/4841232.html ------------------------------------------------- ...

  6. linux下C语言编程,include的默认搜索路径

    C语言编程时,发现细节的魅力很大.较为详细了看了一下关于include的知识,发现了几点新知: 1.include<头文件名>和include"头文件名" 如:incl ...

  7. Linux下C语言编程中库的使用

    零.问题 1. 为什么要用到库? 2. 我要用一个库,但是,尼玛命令行上该怎么写呢?或者说库文件如何使用? 3. Linux的库在那些地方? 4. 什么是静态库,什么是动态库,二者有啥区别? 5. 常 ...

  8. linux 下C语言编程库文件处理与Makefile编写

    做开发快3年了,在linux下编译安装软件算是家常便饭了.就拿gcc来说,都有不下10次了,可基本每次都会碰到些奇奇怪怪的问题.看来还是像vs.codeblocks这样的ide把人弄蠢了.便下定决心一 ...

  9. 实验二 Linux下C语言编程基础

    1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用gdb调试技术 6. 熟悉makefile基本原理 ...

随机推荐

  1. 分享php工作中遇到的一些探究和技巧【1】

    一 foreach的引用 $arr = range(,); //[1,2,3] foreach($arr as &$val) { } foreach($arr as $val) { } pri ...

  2. Android中的单例模式

    定义: 单例模式:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 使用场景: 确保某一个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一 ...

  3. CDC 2013 北京站手记

    受搜狐畅游的邀请,这次能够有机会参与2013中国开发者大会北京站的活动. 本次大会的主题是“游戏”和“移动”,因此上午的峰会安排了5个主讲,分别就搜索.云存储服务器.游戏媒体.移动应用和游戏渠道等多方 ...

  4. android Timer使用方法

    Timer属性:http://www.apihome.cn/api/java/Timer.html 声明创建: private Timer mTimer; protected void onCreat ...

  5. scp报错:not a regular file,解决方法:加参数 -r

    命令:scp  -P1234  /data/aa   root@192.0.0..0:/data 文件结构:/data/aa/yearmonth=2015-09 报错:not a regular fi ...

  6. 扫盲 BT Sync——不仅是同步利器,而且是【分布式】网盘

    先向大伙儿宣布个好消息-- 经过多位热心读者的大力支持,经过几天的努力,已经完成了"微软网盘"到"BitTorrent Sync"的迁移工作. 再次向这批热心读 ...

  7. 三维网格形变算法(Gradient-Based Deformation)

    将三角网格上的顶点坐标(x,y,z)看作3个独立的标量场,那么网格上每个三角片都存在3个独立的梯度场.该梯度场是网格的微分属性,相当于网格的特征,在形变过程中随控制点集的移动而变化.那么当用户拖拽网格 ...

  8. POJ1386Play on Words[有向图欧拉路]

    Play on Words Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11846   Accepted: 4050 De ...

  9. Linux下监听或绑定(bind)843端口失败

    问题:写了一个程序,尝试在843端口监听,结果在执行bind的时候失败了 原来,系统不允许用户程序在1-1024端口监听,因为他们是知名端口. 解决办法: 换成root用户,即可成功bind.(ubu ...

  10. Font Awesome使用指南

    Font Awesome介绍 Font Awesome是一款很流行的字体图标工具.随着Bootstrap的流行而逐渐被人所认识,现在FontAwesome不仅仅可以在bt上使用,还可以应用在各种web ...