一 问题
实现pwd功能
二 分析
结合stat()函数和stat结构体,可根据目录名获得目标的i-节点号
使用chdir()函数可以改变用户的当前路径 结合readdir()函数和direntp结构体,可以根据i-节点号获得其对应的目录名称 1)获得当前目录A的i-节点号Ai 2)跳转到父目录,根据i-节点号Ai就能知道目录A的名称 3)依次倒退到根目录为止三 实现
1 头文件
#include#include #include #include #include #include
2 相关函数声明
ino_t get_inode(char *);void printpathto(ino_t);void inum_to_name(ino_t,char *,int);
3 根据目录名称获得其i-节点号
ino_t get_inode(char *fname){ struct stat info; /*根据目录名获得目录的stat结构信息*/ if(stat(fname,&info)==-1) { fprintf(stderr,"Cannot stat"); perror(fname); exit(1); } /*i-节点信息存储在stat结构的st_ino中*/ return info.st_ino;}
4 目录的跳转
使用chdir()函数即可
5 根据i-节点号获得目录名称
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); } /*用readdir函数打开目录并获得dirent结构体*/ while((direntp = readdir(dir_ptr))!=NULL) { /*目录内的文件节点号存储在dirent结构体的d_ino中*/ if(direntp->d_ino == inode_to_find) { /*比较两个i-节点号,一致的话就通过dirent结构体获得目录名称*/ strncpy(namebuf,direntp->d_name,buflen); namebuf[buflen-1] = '\0'; closedir(dir_ptr); return; } } fprintf(stderr,"error looking for inum \n"); exit(1);}
6 根据目录名,获得其路径
在任何目录下,“.”表示当前目录,“..”表示父目录
void printpathto(ino_t this_inode){ ino_t my_inode; char its_name[BUFSIZ]; /*首先判断父目录与当前目录的i-节点号是否一致(根目录的父目录与当前目录的i-节点号一致)*/ if (get_inode("..") != this_inode) { /*跳到父目录*/ chdir(".."); /*根据i-节点号查询当前目录的目录名*/ inum_to_name(this_inode,its_name,BUFSIZ); /*获得父目录的i-节点号*/ my_inode = get_inode("."); /*循环调用*/ printpathto(my_inode); /*当前目录的父目录为根目录时,结束循环调用并打印路径*/ printf("/%s",its_name); }}
7 主函数
int main(){ /*根据当前目录的i-节点号,获得当前路径*/ printpathto(get_inode(".")); putchar('\n'); return 0;}
四 相关函数与结构体
1 stat()函数
通过文件名获取文件信息,并保存在stat结构体中头文件:#include <sys/stat.h> #include <unistd.h>函数原型 int stat(const char *file_name, struct stat *buf)参数 file_name 指向文件名的指针 buf 指向stat结构体的指针返回值 0 执行成功 -1 执行失败,错误代码存于ermo中2 stat结构体
头文件:#include<sys/stat.h>struct stat{ mode_t st_mode; //文件对应的模式,文件,目录等 ino_t st_ino; //i-node节点号 dev_t st_dev; //设备号码 dev_t st_rdev; //特殊设备号码 nlink_t st_nlink; //文件的连接数 uid_t st_uid; //文件所有者 gid_t st_gid; //文件所有者对应的组 off_t st_size; //普通文件,对应的文件字节数 time_t st_atime; //文件最后被访问的时间 time_t st_mtime; //文件内容最后被修改的时间 time_t st_ctime; //文件状态(属性)改变时间 blksize_t st_blksize; //文件内容对应的块大小 blkcnt_t st_blocks; //文件内容对应的块数量}
3 DIR结构体
typedef struct _dirstream DIR;struct _dirstream{ void *_fd; /* `struct hurd_fd' pointer for descriptor. */ char *_data; /* Directory block. */ int _entry_data; /* Entry number `__data' corresponds to. */ char *_ptr; /* Current pointer into the block. */ int _entry_ptr; /* Entry number `__ptr' corresponds to. */ size_t _allocation; /* Space allocated for the block. */ size_t _size; /* Total valid data in the block. */ _libc_lock_define (, _lock) /* Mutex lock for this structure. */}4 opendir()函数
打开一个目录,失败时返回一个空指针头文件:#inculde<dirent.h>函数原型 DIR* opendir (const char * path );参数 path 目录的路径返回值 DIR* 一个用来保存目录信息结构体指针 NULL 打开失败5 dirent结构体
struct dirent{ long d_ino; /* inode number 索引节点号 */ off_t d_off; /* offset to this dirent 在目录文件中的偏移 */ unsigned short d_reclen; /* length of this d_name 文件名长 */ unsigned char d_type; /* the type of d_name 文件类型 */ char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */}6 readdir()函数
读取目录,然后返回dirent结构体指针头文件:#include<dirent.h>函数原型 struct dirent* readdir(DIR* dir_handle);参数 dir_handle 保存目录信息的DIR结构体指针返回值 dirent 结构体指针NULL 文件读取完毕7 closedir()函数
关闭参数dir所指的目录流,关闭成功返回0,失败返回-1头文件: #include<dirent.h>函数原型 int closedir(DIR *dir);参数 dir 指向要关闭的目录流返回值 0 成功 -1 失败,错误原因存于errno中8 strncpy()函数
将字符串src中最多n个字符复制到字符数组dest中,返回指向dest的指针头文件: #include <string.h>函数原型 char * strncpy(char *dest, char *src, n);参数 dest 指向目的的指针 src 指向源的指针返回值 char * 指向dest的指针9 chdir()函数
用于改变当前工作目录头文件: #include <unistd.h>函数原型 int chdir ( const char *path );参数 path 指定的目录返回值 0 成功 -1 失败