我正在尝试使用来自c的linux api来模拟linux命令ls。查看代码它确实有意义,但是当我运行它时,我得到“stat error:没有这样的文件或目录”。我检查过opendir工作正常。我认为问题在于stat,即使我认为它应该返回0,它仍返回-1。
我错过了什么?
感谢您的帮助。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
int main(int argc, char *argv[])
{
DIR *dirp;
struct dirent *direntp;
struct stat stat_buf;
char *str;
if (argc != 2)
{
fprintf( stderr, "Usage: %s dir_name\n", argv[0]);
exit(1);
}
if ((dirp = opendir( argv[1])) == NULL)
{
perror(argv[1]);
exit(2);
}
while ((direntp = readdir( dirp)) != NULL)
{
if (stat(direntp->d_name, &stat_buf)==-1)
{
perror("stat ERROR");
exit(3);
}
if (S_ISREG(stat_buf.st_mode)) str = "regular";
else if (S_ISDIR(stat_buf.st_mode)) str = "directory";
else str = "other";
printf("%-25s - %s\n", direntp->d_name, str);
}
closedir(dirp);
exit(0);
}
答案 0 :(得分:3)
这是因为您没有说明实际文件。它在不同的目录中。如果您想要真实的文件名,请将argv[1]
和direntp->d_name
合并为一个'/'。
另外,匈牙利语的命名很蹩脚,即使是最后的“p”这个小小的一点。如果你有这么多变量,你需要在他们的名字中跟踪他们的类型,你做错了。
以下是您的计划的修订版本:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <sys/param.h>
int main(int argc, char *argv[])
{
DIR *dirp;
struct dirent *direntp;
struct stat stat_buf;
char *str;
char fullpath[MAXPATHLEN + 1];
size_t dirnamelen;
if (argc != 2)
{
fprintf( stderr, "Usage: %s dir_name\n", argv[0]);
exit(1);
}
strncpy(fullpath, argv[1], MAXPATHLEN - 1); /* account for trailing '/' */
fullpath[MAXPATHLEN - 1] = '\0';
dirnamelen = strlen(fullpath);
if (strlen(argv[1]) > dirnamelen) {
fprintf( stderr, "Directory name is too long: %s", argv[1] );
exit(2);
}
fullpath[dirnamelen++] = '/';
fullpath[dirnamelen] = '\0';
if ((dirp = opendir( argv[1])) == NULL)
{
perror(argv[1]);
exit(2);
}
while ((direntp = readdir( dirp)) != NULL)
{
fullpath[dirnamelen] = '\0';
if ((dirnamelen + strlen(direntp->d_name)) > MAXPATHLEN) {
fprintf(stderr, "File %s + directory %s is too long.", direntp->d_name, fullpath);
continue;
} else {
/* strncpy is mild overkill because the if statement has verified that
there's enough space. */
strncpy(fullpath + dirnamelen, direntp->d_name, MAXPATHLEN - dirnamelen);
fullpath[MAXPATHLEN] = '\0';
}
if (stat(fullpath, &stat_buf)==-1)
{
perror("stat ERROR");
exit(3);
}
if (S_ISREG(stat_buf.st_mode)) str = "regular";
else if (S_ISDIR(stat_buf.st_mode)) str = "directory";
else str = "other";
printf("%-25s - %s\n", direntp->d_name, str);
}
closedir(dirp);
exit(0);
}
请注意,我使用MAXPATHLEN
(来自<limits.h>
)并仔细检查以确保没有任何缓冲区溢出。您应该在代码中执行相同的操作。
修改:更改了代码以使用strn
系列函数以增加安全性。
答案 1 :(得分:2)
添加
#include <unistd.h>
...
chdir(argv[1]);
或使用如此
的完整路径名调用stat...
char fullpath[MAXPATHLEN];
snprintf(fullpath, sizeof(fullpath), "%s/%s", argv[1], direntp->d_name);
if (stat(fullpath, &stat_buf) == -1)
...
答案 2 :(得分:1)
为什么不尝试这个?只需像argv[1]
/home/sabri/Desktop/Test
的路径
int main(int argc, char *argv[])
{
struct dirent *direntp;
DIR *dirp;
if (argc != 2)
{
fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
return 1;
}
if ((dirp = opendir(argv[1])) == NULL)
{
perror ("Failed to open directory");
return 1;
}
while ((direntp = readdir(dirp)) != NULL)
printf("%s\n", direntp->d_name);
while ((closedir(dirp) == -1) && (errno == EINTR)) ;
return 0;
}
答案 3 :(得分:0)
其他人建议为stat()
建立完整路径,或使用chdir()
。这两个都可以工作(虽然它们受到竞争条件的影响,如果目录在你正在阅读时被重命名)。
另一种不受竞争条件限制的替代方案是使用fstatat()
,因此可以说更“正确”。只需将您现有的stat()
电话替换为:
fstatat(dirfd(dirp), direntp->d_name, &stat_buf, 0)
(chdir()
方法也可以无竞争条件:使用fchdir(dirfd(dirp))
代替chdir()
,或者将目录更改为argv[1]
然后打开"."
与opendir()
。路径名构造方法不能无竞争条件。)
答案 4 :(得分:-2)
如果您在unix上使用,则可以使用系统命令。
system("ls -ltr | grep -d");