我将继续说这是Linux课程介绍的家庭作业。如果没有我自己的大量尝试,我不会发布它,并且看到我这个学期的远程学生,我无法进入校园进行辅导。我需要一些帮助来找出问题所在。
本质上,赋值要求我们创建一个与POSIX中的pwd
命令具有相同基本功能的程序,以显示当前目录的绝对路径。我们将使用main和main三个函数。我们也不要使用getcwd
命令。我将列出它们及其目的
inum_to_filename
:接受三个参数(要翻译的inode编号,指向写入名称的缓冲区的指针,以及缓冲区的大小)。什么都不返回它是:
filename_to_inum
:接受一个参数(表示文件名的char *
)。它返回相应的inode编号。它是:
display_path
:接受一个参数(来自当前工作目录的inode)。它什么都不返回。它是:
filename_to_inode
获取父目录的inode。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");
}
目前正在显示&#34; /./ MyName&#34; MyName是我在服务器上的个人命名目录。它是我运行程序的目录。当使用pwd时,我返回&#34; / home / MyName&#34;。我不确定下一步让绝对路径正确的是什么。
答案 0 :(得分:1)
这是非常好的任务:)。 我阅读并尝试了您的代码,这几乎是正确的。有两个小问题导致了错误的行为。
第一期
当display_path
到达根文件夹时,您不需要调用inum_to_filename
并打印文件夹的名称,因为您已经在上一次迭代中打印了路径的第一个文件夹。这可以防止您的代码显示&#34; ./"在路径的开头。
也就是说,if条件变为:
if (ino_src == ino_prnt) {
return;
} else {
chdir("..");
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("%s", pathBuffer);
}
第二期:
您没有在属性上初始化保存目录名称的缓冲区。这会导致显示随机值。要解决此问题,您只需使用memset
将缓冲区的初始值设置为零。
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;
memset(pathBuffer, 0, size_arg);
while (counter != 1) {
...
}
closedir(dir_ptr);
}
完整代码工作:
#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;
memset(pathBuffer, 0, size_arg);
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;
}
/*
- Create an array of characters to use as a buffer for the name of the directory.
- Get the inode for the parent directory using filename_to_inode.
- If the parent inode is equal to the current inode, we have reached root and can return.
- Otherwise, change to the parent directory and use inum_to_filename to find the name for
the inode that was passed into the function. Use the buffer from step 1 to store it.
- Recursively call display_path to display the absolute path.
*/
void display_path (int ino_src) {
int bufSize = 4096;
char pathBuffer[bufSize];
int ino_prnt = filename_to_inum("..");
if (ino_src == ino_prnt) {
return;
} else {
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");
}
输出:
ubuntu@ubuntu-VirtualBox:~/dev$ vi pwd.c
ubuntu@ubuntu-VirtualBox:~/dev$ gcc pwd.c
ubuntu@ubuntu-VirtualBox:~/dev$ ./a.out
/home/ubuntu/dev
ubuntu@ubuntu-VirtualBox:~/dev$ pwd
/home/ubuntu/dev
ubuntu@ubuntu-VirtualBox:~/dev$
答案 1 :(得分:1)
代码主要设置为按正确的顺序一次打印一个名称,因此主要问题是使用strcat()
而不是strcpy()
。此外,检测您何时在开始时位于根目录中很重要;如果不这样做,当当前目录是根目录时,您最终可以使用/.
或类似的东西(具体取决于您如何协调打印)。
此版本的代码包含:
在inum_to_filename()
中完成循环,但也添加了错误报告。请记住,进程可以在没有权限的目录中运行(通常需要setuid程序 - 尽管可以在程序启动后更改权限)。在这种情况下,它可能无法打开..
(或.
)。
丢失变量count
;它没有达到有用的目的。使用assign-and-test惯用法允许代码包含对readdir()
的单个调用。
使用strcpy()
代替strcat()
。
使用类型ino_t
存储inode编号。使用size_t
表示尺寸。
减少filename_to_inum()
中的中间变量数量。
请注意if (ino_src == ino_prnt)
语句体中的代码用于根目录;在没有测试印刷品的情况下,它什么都不做。
请注意,else
部分的打印是操作的主要部分,而不仅仅是测试打印。
错误检查chdir("..");
在main()
。
观察到此代码不直接适合重写函数,因为它在成功时将进程的当前目录更改为/
。
修订代码:
#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/Sub-Directory
工作时,这给了我一些悲伤。在扫描1
时,它无法找到inode(/Volumes
,这是令人惊讶的),而我没有找到原因。我的一个程序 - getpwd
实现 - 工作正常;另一个是有一个不同的问题。我希望我能深究这一切。使用GCC 5.1.0在Mac OS X 10.10.5上进行测试。