使用C在POSIX中使用目录

我将继续说这是
Linux课程介绍的家庭作业.如果没有我自己的大量尝试,我不会发布它,并且看到我这个学期的远程学生,我无法进入校园进行辅导.我需要一些帮助来找出问题所在.

本质上,赋值要求我们创建一个与POSIX中的pwd命令具有相同基本功能的程序,以显示当前目录的绝对路径.我们将使用main和main三个函数.我们也不要使用getcwd命令.我会列出它们和它们的目的

> inum_to_filename:接受三个参数(要转换的inode编号,指向写入名称的缓冲区的指针,以及缓冲区的大小).什么都不返回它是:

>打开当前目录,
>读取第一个目录条目,
>如果当前目录的inode与传入的inode匹配,则将name复制到buffer并返回.
>否则,请阅读下一个目录条目并重复上一步.

> filename_to_inum:接受一个参数(表示文件名的char *).它返回相应的inode编号.它是:

>将文件inode中的信息读入内存中的结构.
>如果有任何问题,请显示相应的错误.
>从结构中返回inode编号.

> display_path:接受一个参数(当前工作目录中的inode).它什么都不返回.它是:

>创建一个字符数组,用作目录名称的缓冲区.
>使用filename_to_inode获取父目录的inode.
>如果父inode等于当前inode,我们已经到达root并且可以返回.
>否则,切换到父目录并使用inum_to_filename查找传递给函数的inode的名称.使用步骤1中的缓冲区来存储它.
>递归调用display_path以显示绝对路径.

这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>

void inum_to_filename (int inode_arg, char *pathBuffer, int size_arg) {
    DIR *dir_ptr = opendir(".");
    struct dirent *dirent_ptr = readdir(dir_ptr);
    int counter = 0;

    while (counter != 1) {
        if (inode_arg == dirent_ptr->d_ino) {

            strcat(pathBuffer, "/");
            strcat(pathBuffer, dirent_ptr->d_name);

            counter = counter + 1;
            return;

        } else {
            dirent_ptr = readdir(dir_ptr);
        }
    }

    closedir(dir_ptr);
}

int filename_to_inum (char *src) {
    int res = 0;
    struct stat info;
    int result = stat(src, &info);

    if (result != 0) {
        fprintf(stderr, "Cannot stat ");
        perror(src);
        exit(EXIT_FAILURE);
    } else {
        res = info.st_ino;
    }

    return res;
} 

void display_path (int ino_src) {
    int bufSize = 4096;
    char pathBuffer[bufSize];
    int ino_prnt = filename_to_inum("..");

    if (ino_src == ino_prnt) {
        //print for test
        inum_to_filename(ino_src, pathBuffer, bufSize);
        printf("%s", pathBuffer);
        return;
    } else {
        //print for test
        chdir("..");
        inum_to_filename(ino_src, pathBuffer, bufSize);
        display_path(ino_prnt);
        printf("%s", pathBuffer);
    }
}

int main (int argc, char *argv[]) {
    int c_ino = filename_to_inum(".");
    display_path(c_ino);
    printf("\n");
}

截至目前,它正在显示“/./MyName”,其中MyName是我在服务器上的个人命名目录.它是我运行程序的目录.使用pwd时,我返回“/ home / MyName”.我不确定我的下一步是什么让绝对路径正确.

最佳答案 代码主要设置为以正确的顺序一次打印一个名称,因此主要问题是使用strcat()而不是strcpy().此外,检测您何时在开始时位于根目录中很重要;如果你不这样做,你最终可以/.当前目录是根目录时,或类似的东西(具体取决于您如何协调打印).

此版本的代码具有:

>在inum_to_filename()中完成循环,但也添加了错误报告.请记住,进程可以在没有权限的目录中运行(通常需要setuid程序 – 尽管可以在程序启动后更改权限).在这种情况下,它可能无法打开..(或.).
>丢失变数;它没有达到有用的目的.使用assign-and-test惯用法允许代码包含对readdir()的单个调用.
>使用strcpy()而不是strcat().
>使用type ino_t存储inode编号.使用size_t表示大小.
>减少filename_to_inum()中的中间变量数量.
>请注意,if(ino_src == ino_prnt)语句体中的代码用于根目录;在没有测试打印的情况下,它什么都不做.
>请注意,else部分中的打印是操作的主要部分,而不仅仅是测试打印.
>错误检查chdir(“..”);
>检测main()中的root.
>观察到此代码不直接适合重写函数,因为它将进程的当前目录更改为/成功时.

修改后的代码:

#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

static void inum_to_filename(ino_t inode_arg, char *pathBuffer, size_t size_arg)
{
    assert(size_arg > 0);
    DIR *dir_ptr = opendir(".");
    if (dir_ptr == 0)
    {
        fprintf(stderr, "Failed to open directory '.' (%d: %s)\n", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }
    struct dirent *dirent_ptr;

    while ((dirent_ptr = readdir(dir_ptr)) != 0)
    {
        if (inode_arg == dirent_ptr->d_ino)
        {
            if (strlen(dirent_ptr->d_name) >= size_arg)
            {
                fprintf(stderr, "File name %s too long (%zu vs %zu max)\n",
                        dirent_ptr->d_name, strlen(dirent_ptr->d_name), size_arg);
                exit(EXIT_FAILURE);
            }
            strcpy(pathBuffer, dirent_ptr->d_name);
            break;
        }
    }

    closedir(dir_ptr);
}

static ino_t filename_to_inum(char *src)
{
    struct stat info;

    if (stat(src, &info) != 0)
    {
        fprintf(stderr, "Cannot stat ");
        perror(src);
        exit(EXIT_FAILURE);
    }
    return info.st_ino;
}

static void display_path(ino_t ino_src)
{
    size_t bufSize = 4096;
    char pathBuffer[bufSize];
    ino_t ino_prnt = filename_to_inum("..");

    if (ino_src == ino_prnt)
    {
        // print for test
        inum_to_filename(ino_src, pathBuffer, bufSize);
        printf("%s", "(root): /\n");
    }
    else
    {
        // print for real
        if (chdir("..") != 0)
        {
            fprintf(stderr, "Failed to chdir to .. (%d: %s)\n",
                    errno, strerror(errno));
        }
        inum_to_filename(ino_src, pathBuffer, bufSize);
        display_path(ino_prnt);
        printf("/%s", pathBuffer);
    }
}

int main(void)
{
    ino_t c_ino = filename_to_inum(".");
    ino_t r_ino = filename_to_inum("/");
    if (r_ino == c_ino)
        putchar('/');
    else
        display_path(c_ino);
    printf("\n");
}

毫无疑问,其他方法可以解决这个问题.

警告:在使用/ Volumes / CRUZER /子目录(这是一个记忆棒)时,这让我有些不安.扫描/卷时,它无法找到inode(1,这是令人惊讶的),而我还没有找到原因.我的一个程序 – 一个getpwd实现 – 工作正常;另一个是有一个不同的问题.我希望我能深究这一切.使用GCC 5.1.0在Mac OS X 10.10.5上进行测试.

点赞