• Linux getcwd()的实现【转】


    转自:http://www.cnblogs.com/alan-forever/p/3721908.html

    通过getcwd()可以获取当前工作目录。

    1 #include <unistd.h>
    2 
    3 char *getcwd(char *cwdbuf, size_t size);

    成功调用返回指向cwdbuf的指针,失败返回NULL。

    getcwd()的实现是《Linux/Unix系统编程手册》的练习18.5,题目如下:

    实现一个功能与getcwd()相当的函数。提示:要获取当前工作目录的名称,可调用opendir()和readdir()来遍历其父目录(..)中的各个条目,查找其中与当前工作目录具有相同i-node编号及设备号的一项。如此这般,沿着目录树层层拾级而上(chdir(..))并进行扫描,就能构建出完整的目录路径。当前目录与当前工作目录相同时,就结束遍历。无论调用该函数成功与否,都应将调用者遣回其起始目录(使用open()和fchdir()能方便地实现这一功能)

    1、通过stat获取文件信息,根据文件信息中的i-node编号和设备号来找到正确的目录

    2、运用opendir()、readdir()来获取目录的信息,目录不能通过read()来获取信息。

    PS:tlpi_hdr.h头文件为《Linux/Unix系统编程手册》的头文件,可以去作者的网站下载,其中的errExit()为错误处理函数。。。。

    复制代码
      1 /*
      2  * =====================================================================================
      3  *
      4  *       Filename:  18.5.c
      5  *
      6  *    Description:  
      7  *
      8  *        Version:  1.0
      9  *        Created:  2014年05月11日 14时04分35秒
     10  *       Revision:  none
     11  *       Compiler:  gcc
     12  *
     13  *         Author:  alan (), alan19920626@gmail.com
     14  *   Organization:  
     15  *
     16  * =====================================================================================
     17  */
     18 
     19 #include <sys/stat.h>
     20 #include <fcntl.h>
     21 #include <dirent.h>
     22 #include <sys/types.h>
     23 #include "tlpi_hdr.h"
     24 
     25 #define BUF_MAX 4096
     26 
     27 extern int errno; 
     28 
     29 char *Getcwd(char *cwdbuf, size_t size){
     30     char path[BUF_MAX], cwd[BUF_MAX];
     31     DIR *dirp;
     32     struct dirent *dp;
     33     struct stat sb, sb_d, sb_1;
     34     dev_t dev;
     35     ino_t ino;
     36 
     37     while(1){
     38         //获取当前目录的文件信息
     39         if(stat(".", &sb) == -1)
     40             errExit("stat");
     41         dev = sb.st_dev;
     42         ino = sb.st_ino;
     43 
     44         //获取父目录的对应的目录流和父目录的文件信息
     45         if((dirp = opendir("..")) == NULL)
     46             errExit("opendir");
     47         if(stat("..", &sb_1) == -1)
     48             errExit("stat");
     49 
     50         //判断当前目录是否与父目录相同
     51         if(sb_1.st_dev == dev && sb_1.st_ino == ino)
     52             break;
     53 
     54         errno = 0;
     55         
     56         //在父目录对应的目录流读取条目
     57         while((dp = readdir(dirp)) != NULL){
     58             snprintf(path, BUF_MAX, "../%s", dp->d_name);
     59 
     60             if(stat(path, &sb_d) == -1)
     61                 errExit("stat");
     62 
     63             //得到当前目录对应的条目并将目录逐渐完善
     64             if(dev == sb_d.st_dev && ino == sb_d.st_ino){
     65                 memset(cwd, 0, sizeof(cwd));
     66                 if(strcat(cwd, "/") == NULL)
     67                     errExit("strcat");
     68                 if(strcat(cwd, dp->d_name) == NULL)
     69                     errExit("strcat");
     70                 if(strcat(cwd, cwdbuf) == NULL)
     71                     errExit("strcat");
     72 
     73                 if(strncpy(cwdbuf, cwd, BUF_MAX) == NULL)
     74                     errExit("strncpy");
     75                 break;
     76             }
     77             
     78         }
     79 
     80         if(dp == NULL && errno != 0)
     81             errExit("readdir");
     82 
     83         closedir(dirp);
     84         chdir("..");      //改变当前目录
     85     }
     86 
     87     return cwdbuf;
     88 }
     89 
     90 int main(int argc, char *argv[]){
     91     char buf[BUF_MAX];
     92     char t_buf[BUF_MAX];
     93     char *p;
     94     int fd;
     95 
     96     if((fd = open(".", O_RDONLY)) == -1)
     97         errExit("open");
     98 
     99     if(argc != 1)
    100         usageErr("%s", argv[0]);
    101 
    102     p = Getcwd(buf, BUF_MAX);
    103     if(p == NULL)
    104         errExit("My getcwd");
    105     printf("My getcwd: %s
    ", p);
    106     fchdir(fd);    //遣回最初的目录
    107 
    108     p = getcwd(t_buf, BUF_MAX);
    109     if(p == NULL)
    110         errExit("getcwd");
    111     printf("getcwd: %s
    ", p);
    112 
    113     exit(EXIT_SUCCESS);
    114 }
    复制代码

    测试结果:

    lancelot@debian:~/Code/tlpi$ pwd
    /home/lancelot/Code/tlpi
    lancelot@debian:~/Code/tlpi$ ./18.5 
    My getcwd: /home/lancelot/Code/tlpi
    getcwd: /home/lancelot/Code/tlpi
  • 相关阅读:
    装饰者模式
    代理模式
    享元模式
    模板模式
    命令模式
    建造者模式
    单例模式
    观察者模式
    迭代器模式
    访问者模式
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/5649248.html
Copyright © 2020-2023  润新知