我将继续说这是
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上进行测试.