lstat:无法访问另一个目录中的文件

2023-11-30

我正在尝试编写类似 ls 的程序,产生类似的输出ls -l包含文件的权限、所有者、时间和名称。 如果我通过的话效果很好.(或什么都没有),所以它适用于当前目录。但是如果我将任何其他目录传入或传出当前目录,perror说它“无法访问”文件。

请帮我找出是什么阻止了lstat访问另一个目录中的文件。

我使用 gcc 和文本编辑器,没有 IDE,开始学习使用 gdb (尝试调试但没有找到可以指出我应该寻找哪种解决方案的东西)。这就是为什么我决定将所有代码放在这里,以便任何人都可以运行它。也许我传递了错误的论点,也许这是某种lstat的错误行为,我不知道。我一直试图在网上找到有关它的信息,但没有结果。

这是我到目前为止所做的事情:

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>     // open()
#include <unistd.h>    // close()
#include <sys/param.h>
#include <string.h>
#include <limits.h>    // PATH_MAX
#include <pwd.h>       // structure for getpwuid()
#include <grp.h>       // structure for getgrgid()
#include <time.h>      // ctime()

static void ls(const char *dir);
void get_info(const char *name, int offset);
int get_maxsize(const char *name);


int main(int argc, char ** argv)
{
    if (argc == 1)
        ls(".");
    else
        while (--argc > 0)
            ls(*++argv);
    return 0;
}


static void ls(const char *dir)
{
    struct dirent * entry;
    DIR *d = opendir(dir);
    char pathbuf[PATH_MAX + 1];
    int offset = 0;

    if (d == 0) {
        perror("ls");
        return;
    }

    /* find max file size for better ls-alike output */
    while ((entry = readdir(d)) != NULL) {
        realpath(entry->d_name, pathbuf);
        /* pathbuf OR entry->d_name here: */
        if (get_maxsize(entry->d_name) > offset)
            offset = get_maxsize(pathbuf);
    }
    closedir(d);

    d = opendir(dir);
    while ((entry = readdir(d)) != NULL) {
        /* pathbuf OR entry->d_name here: */
        realpath(entry->d_name, pathbuf);
        get_info(entry->d_name, offset);
    }
    closedir(d);
}


void get_info(const char *name, int offset)
{
    struct stat statbuf;
    struct passwd *pwdPtr;
    struct group *grpPtr;
    int length = 0;
    char *time = NULL;

    /* skip . and .. dirs */
    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
        return;

    if (lstat(name, &statbuf) == -1) {
        fprintf(stderr, "can't access %s\n", name);
        perror("get_info");
        return;
    } 
    else
        switch (statbuf.st_mode & S_IFMT) {
            case S_IFREG: printf("-"); break;
            case S_IFDIR: printf("d"); break;
            case S_IFCHR: printf("c"); break;
            case S_IFBLK: printf("b"); break;
            case S_IFLNK: printf("l"); break;
            case S_IFSOCK: printf("s"); break;
            case S_IFIFO: printf("p"); break;
        }

    /* owner */
    if (statbuf.st_mode & S_IREAD) printf("r");
    else printf("-");
    if (statbuf.st_mode & S_IWRITE) printf("w");
    else printf("-");
    if (statbuf.st_mode & S_IEXEC) printf("x");
    else printf("-");

    /* group */
    if (statbuf.st_mode & S_IRGRP) printf("r");
    else printf("-");
    if (statbuf.st_mode & S_IWGRP) printf("w");
    else printf("-");
    if (statbuf.st_mode & S_IXGRP) printf("x");
    else printf("-");

    /* other users */
    if (statbuf.st_mode & S_IROTH) printf("r");
    else printf("-");
    if (statbuf.st_mode & S_IWOTH) printf("w");
    else printf("-");
    if (statbuf.st_mode & S_IXOTH) printf("x");
    else printf("-");

    /* hard links */
    printf(" %2zu", statbuf.st_nlink);

    /* owner name */
    if ((pwdPtr = getpwuid(statbuf.st_uid)) == NULL) {
        perror("getpwuid");
        exit(EXIT_FAILURE);
    } 
    else {
        printf(" %s", pwdPtr->pw_name);
    }

    /* gruop name */
    if ((grpPtr = getgrgid(statbuf.st_gid)) == NULL) {
        perror("getgrgid");
        exit(EXIT_FAILURE);
    } 
    else {
        printf(" %s", grpPtr->gr_name);
    }

    /* size in bytes */
    /* "C uses an asterisk in the position of the field
       width specifier to indicate to printf that it will
       find the variable that contains the value of the field
       width as an additional parameter." 
       http://www.eecs.wsu.edu/~cs150/reading/printf.htm */
    while(offset != 0)
    {
        offset /= 10;             /* n=n/10 */
        ++length;
    }
    printf(" %*d", length, (int)statbuf.st_size);

    /* last modifying time */
    time = ctime(&statbuf.st_mtime);
    time[strlen(time) - 1] = 0;
    printf(" %s", time);

    /* index */
    // ToDo

    /* filename */
    printf(" %s", name);

    printf("\n");
    // -,d,c,b,l,s,p
    //if ((statbuf.st_mode & S_IFMT) == S_IFREG)
    //    printf("- %8ld %s\n", statbuf.st_size, name);
}


int get_maxsize(const char *name)
{
    struct stat statbuf;

    if (lstat(name, &statbuf) == -1) {
        fprintf(stderr, "can't access %s\n", name);
        perror("get_maxsize");
        return -1;
    }
    return statbuf.st_size;
}

正常工作时的输出(仅适用于当前目录):

yulian@deb:~/programming/os$ ./readDir .
-rw-rw-rw-  1 yulian yulian  4387 Mon Nov 30 06:31:51 2015 readDir.c
-rw-rw-rw-  1 yulian yulian   282 Sun Nov 29 04:43:03 2015 sometext.txt
-rwxr-xr-x  1 yulian yulian 13792 Sat Nov 28 11:54:09 2015 readDir
drwxr-xr-x  2 yulian yulian  4096 Fri Nov 27 05:26:42 2015 testDir 
// there is test dir called `testDir` where it fails

失败时输出:

yulian@deb:~/programming/os$ ./readDir testDir/
can't access 2.jpg
get_maxsize: No such file or directory
can't access ETicket_edc7cb12cdc23e6c04a308f34fd31c28.pdf
get_maxsize: No such file or directory

update:使用我添加的建议解决方案get_info:

....
char *filemane = NULL;

filemane = strrchr(name, '/') + 1;
/* to prevent . and .. from output */
if (strcmp(filemane, ".") == 0 || strcmp(filemane, "..") == 0)
    return;
...
/* filename */
printf(" %s", filemane);          // and changed the argument here

所以输出现在产生的文件名与ls -l,而不是他们的完整路径。


你缺少的是添加dir您想要探索 pathbuf 变量。只需考虑使用以下 ls 实现

static void ls(const char *dir)
{
    struct dirent * entry;
    DIR *d = opendir(dir);
    char pathbuf[PATH_MAX + 1];
    char tmp[PATH_MAX+1];
    int offset = 0;

    if (d == 0) {
        perror("ls");
        return;
    }

    /* find max file size for better ls-alike output */
    while ((entry = readdir(d)) != NULL) {
        /* pathbuf OR entry->d_name here: */
        // realpath(entry->d_name, pathbuf);
        snprintf (tmp, PATH_MAX, "%s/%s", dir, entry->d_name);
        if (get_maxsize(tmp) > offset)
            offset = get_maxsize(tmp);
    }
    closedir(d);

    d = opendir(dir);
    while ((entry = readdir(d)) != NULL) {
        /* pathbuf OR entry->d_name here: */
        // realpath(entry->d_name, pathbuf);
        snprintf (tmp, PATH_MAX, "%s/%s", dir, entry->d_name);
        get_info(tmp, offset);
    }
    closedir(d);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

lstat:无法访问另一个目录中的文件 的相关文章

随机推荐

  • 我的 librosa MFCC 输出正确吗?我认为使用 librosa MFCC 时得到的帧数错误

    result librosa feature mfcc signal 16000 n mfcc 13 n fft 2048 hop length 400 result shape 信号长 1 秒 采样率为 16000 我计算出 13 MFC
  • MSVCRT 中“创建硬链接”函数的名称是什么?

    修复一个错误这个答案 在 MSVCRT 中创建硬链接的函数的正确名称是什么 奇怪的是 有一个函数叫做CreateHardLink 但它并不存在于 MSVCRT 中 而是存在于 MSVCRT 中 它是 Kernel32 的一部分
  • 返回到程序顶部重试

    我正在自学 C 当前章节的挑战要求我 以您的上一个项目为例 创建其他方法来对传入其中的两个数字进行减法 乘法或除法 在除法中 检查第二个数字是否不为0 因为除以0是一个非法的数学概念 如果第二个数字是 0 则返回 0 现在我写了下面的内容
  • 在 Azure SQL 数据库中创建外部文件格式时出错

    在 Azure SQL DB 中创建外部文件格式时出现错误 EXTERNAL 附近的语法不正确 我正在使用以下命令 使用 Microsoft 文档链接中的 T SQL 语法 但仍然出现语法错误 Example 1 CREATE EXTERN
  • 使用 matplotlib 在 python 中使用字典的条形图

    我有两本词典 A 2018 23 2019 30 B 2018 26 2019 35 现在我想绘制 A 和 B 2018 2019 年的趋势 但是在绘制条形图时 我得到以下结果 岁月不断膨胀 填满了空间 b 完全隐藏了 A 请建议如何绘制图
  • 快速发送 MIME 类型错误的资产

    Using Express to serve a Vue js webpack app I am receiving the following error after deploy Is my code for serving the a
  • 由未知权威机构签署的 x509 证书 - go-pingdom

    我正在使用 Go 包pingdom go查询 Pingdom 该应用程序容器化如下 FROM alpine 3 8 USER nobody ADD build output bin app usr local bin app 但是我收到以下
  • android - 导入 - 与开发人员 google com games

    我按照这里的指南进行操作https developers google com games 我完成了步骤 1 中的所有说明 步骤 1 下载示例应用程序 但该项目未编译 导入 google play services lib 项目和 Base
  • 将图例添加到 ggplot2

    我一直在尝试向我的 ggplot 添加图例 但惨败 我确实遇到了与手动添加图例相关的其他问题 例如1 2但无法将答案应用到我的 ggplot 上 我尝试了该功能scale colour manual但传说并没有出现 任何帮助将非常感激 p
  • 欧拉计划 17

    我一直在尝试解决欧拉 17 问题 但遇到了一些麻烦 该问题的定义是 如果数字 1 到 5 用单词写成 一 二 三 四 五 那么总共使用了 3 3 5 4 4 19 个字母 如果从 1 到 1000 一千 的所有数字都用文字写出来 需要使用多
  • “必需”验证属性在 asp.net mvc 3 中不起作用,而其他属性则有效

    我有一个奇怪的情况 我为我的实体对象创建了一个单独的验证类 MetadataType typeof TopTenFav Validation public partial class TopTenFav public class TopTe
  • 为什么我的代码块仅显示输出不到一秒......?

    我一周前安装了 Codeblock 没有更改任何设置 我创建了一个简单的控制台应用程序 当我单击 构建 并运行它时 它会显示我的输出大约几毫秒然后消失 它过去会永远保留 直到我退出它 有谁知道为什么会发生这种情况 在 构建日志 选项卡中显示
  • 紧急安装并与 Orion Context Broker 集成

    在 Rush 中运行监听器和一次消费者之后 我运行 contextBroker rush localhost 5001 我确保使用 Orion 0 17 而不是 0 14 输入 version url 后显示的是
  • 添加CombinedResourceHandler后pe:ckEditor不再工作

    I added OmniFaces使用CombinedResourceHandler 但现在PrimeFaces 扩展
  • 如何将协议定义为 @ObservedObject 属性的类型?

    我有一个依赖于视图模型的 swiftui 视图 视图模型有一些已发布的属性 我想为视图模型层次结构定义一个协议和默认实现 并使视图依赖于协议而不是具体类 我希望能够写出以下内容 protocol ItemViewModel Observab
  • 导入 .p12 文件中包含的所有证书

    我有一个 p12我的 ASP NET 应用程序通过 HTTPS 连接到 Web 服务的文件 我正在尝试导入 p12文件保存到本地计算机 我的商店中 这 p12 file 包含多个证书 一个包含私钥 另一个是 CA 证书以完成链 目前 我正在
  • Prestashop - 如何写入日志文件?

    我应该在 Prestashop 模块中使用什么 php 代码来写入日志文件 我用过 Logger addLog something 1 但它不起作用 您还可以使用以下代码将日志存储在文件中 logger new FileLogger 0 0
  • HTML5 拖放 拖动时更改图标/光标

    我想知道当我拖动 dragover dragenter 图标 光标时如何更改例如拒绝或允许部分 当然 我可以用光标移动绝对定位的 DOM 部分 但我对原生 HTML5 解决方案感兴趣 Thanks 你在追寻掉落效果 在dragstart中初
  • 按模式递归添加文件

    如何通过位于不同目录中的模式 或全局 递归添加文件 例如 我想添加A B C foo java and D E F bar java 以及其他几个 java 文件 使用一个命令 git add java 不幸的是 这并没有按预期工作 您可以
  • lstat:无法访问另一个目录中的文件

    我正在尝试编写类似 ls 的程序 产生类似的输出ls l包含文件的权限 所有者 时间和名称 如果我通过的话效果很好 或什么都没有 所以它适用于当前目录 但是如果我将任何其他目录传入或传出当前目录 perror说它 无法访问 文件 请帮我找出