您好,欢迎来到99网。
搜索
您的当前位置:首页C语言实现linux pwd命令

C语言实现linux pwd命令

来源:99网

实验内容

通过实现Linux的pwd命令,以理解Linux文件系统的基本概念一集内部实现,并熟悉Linux系统与文件系统相关的系统调用接口。


知识点:

  • 列表内容
  • Linux pwd命令
  • Linux文件系统中文件及目录的实现方式
  • Linux文件及目录系统调用接口的使用

pwd命令

1.0版本的pwd

/*
 * 文件名: mypwd1.c
 * 描述:通过系统函数getcwd实现pwd命令
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void)
{   
    char buf[1024];

    char *cwd =getcwd(buf, sizeof(buf));

    if (NULL == cwd) {
        perror("Get cerrent working directory fail.\n");
        exit(-1);
    } else {
        printf("Current working directory is : %s\n", cwd);
    }

    return 0;
}

虽然这段代码实现了pwd的功能,但是却依然无法为我们解答pwd是如何工作的。

Linux中的文件

在Linux中的文件系统中,文件=N(N>=1)个inode+M(M>=1)个数据块

数据块,存放文件的内容数据,数据块的数目根据文件内容大小而定。

inode成为信息节点,有两个作用:

在一个文件系统中,一个inode代表一个文件,并使用一个整数值来表示该inode,成为inode-number,该值对于一个文件系统而言是唯一的,即通过该值可以找到其对应的inode。一般情况下,一个文件只有一个inode信息来描述它。

下面通过一段程序来获取某个文件的inode信息:

*  文件名:filestat.c
*  描述:打印指定文件名的inode信息
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

struct stat file_stat;

void print_file_stat(struct stat *fs)
{
    printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
    printf("inode: \t\t\t\t%ld\n", fs->st_ino);
    printf("protection: \t\t\t%o\n", fs->st_mode);
    printf("number of hard links: \t\t%lu\n", fs->st_nlink);
    printf("user ID of owner: \t\t%d\n", fs->st_uid);
    printf("group ID of owner: \t\t%d\n", fs->st_gid);
    printf("file size in bytes: \t\t%ld\n", fs->st_size);
    printf("time of last access: \t\t%s", ctime(&fs->st_atime));
    printf("time of last modification: \t%s", ctime(&fs->st_mtime));
    printf("time of last change: \t\t%s", ctime(&fs->st_ctime));
}   

int main(int argc, char* argv[])
{   

    if (2 != argc) {
        fprintf(stderr, "Usage: %s filename...\n", argv[0]);
        exit(-1);
    }

    if (0 != stat(argv[1], &file_stat)) {
        perror("stat"); 
        exit(-1);
    }

    print_file_stat(&file_stat);

    return 0;
}

Linux中的目录

/*
* 文件名:directorylist.c
* 描述:打印指定目录的内容列表
*/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
    if (2 != argc) {
        fprintf(stderr, "Usage: %s directory...\n", argv[0]);
        exit(-1);
    }

    DIR *dp = NULL;
    struct dirent *dptr = NULL;
    if (NULL == (dp = opendir(argv[1]))) {
        fprintf(stderr, "Can not open Input Directory [%s]\n", argv[1]);
        exit(-1);
    } else {
        printf("Directory [%s] Content List: \n", argv[1]);
        while (NULL != (dptr = readdir(dp))) {
            printf("inode-number: %-10ld \t filename: %s\n", dptr->d_ino, dptr->d_name);
        }

        closedir(dp);
    }

    return 0;
}

实现pwd命令

实现代码:

/*
* 文件名:mypwd.c
* 描述:实现简单的pwd命令
*/
#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;

    for(;;) {
        /*1.通过特殊的文件名“.”获取当前目录的inode-number*/
        ino_t current_ino = get_ino_byname(".");
        /*2.通过特殊的文件名“..”获取当前目录的父级目录的inode-number*/
        ino_t parent_ino = get_ino_byname("..");

        /*3.判断当前目录和上级目录的inode-number是否一样*/
        if (current_ino == parent_ino)
            break; /*4.如果两个inode-number一样说明到达根目录*/

        /*5.如果两个inode-number不一样*/
        /*切换至父级目录,根据步骤1获取的inode-number,在父级目录中搜索对应的文件名并记录下来, 重新回到步骤1*/
        chdir("..");
        dir_stack[current_depth++] = find_name_byino(current_ino);
        if (current_depth>=MAX_DIR_DEPTH) { /*路径名太深*/
             fprintf(stderr, "Directory tree is too deep.\n");
             exit(-1);
        }
    }

    /*输出完整路径名*/
    int i = current_depth-1;
    for (i = current_depth-1; i>=0; i--) {
       fprintf(stdout, "/%s", dir_stack[i]);
    }
    fprintf(stdout, "%s\n", current_depth==0?"/":"");

    return 0;
}

参考资料

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 99spj.com 版权所有 湘ICP备2022005869号-5

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务