【问题标题】:lstat and ls permissions output is somehow differslstat 和 ls 权限输出有些不同
【发布时间】:2022-01-18 16:09:25
【问题描述】:

我正在尝试用它的一些标志重写 ls 函数,目前我正在实现 [-l] 标志,但是关于原始 ls 和 lstat 权限的输出是不同的

这是我的代码

void mx_strmode(mode_t mode, char * buf) {
  const char chars[] = "rwxrwxrwx";
  for (size_t i = 0; i < 9; i++) {
    buf[i] = (mode & (1 << (8-i))) ? chars[i] : '-';
  }
  buf[9] = '\0';
}

int main(int ac, char **av) {
    t_flags flags = mx_get_flags(ac, av);
    char *dir_name = get_dir_name(ac, av);
    DIR *dir;
    struct dirent *entry;

    dir = opendir(dir_name);
    if (!dir) {
        perror("diropen");
        exit(1);
    };

    struct stat s_stat;
    while ((entry = readdir(dir)) != NULL) {
        lstat(entry->d_name, &s_stat);
        char buf_perm[10];
        mx_strmode(s_stat.st_mode, buf_perm);
        printf("%s  %s\n", buf_perm , entry->d_name);

    };

    closedir(dir);
}

这是我从 ls 和我的程序中得到的。我正在打开不包含我的可执行文件的目录(可能是问题的根源)

>drwxr-xr-x   3 fstaryk  4242   102 Jan  3 17:27 .
>drwxr-xr-x  11 fstaryk  4242   374 Jan 18 17:40 ..
>-rw-r--r--   1 fstaryk  4242  4365 Jan 18 17:40 main.c

>rwxr-xr-x    .
>rwx------    ..
>rwx------    main.c

【问题讨论】:

  • 检查lstat 的返回值(以及您可能未检查的任何其他库调用)
  • @Mat ,lstat 实际上在 main.c 上返回 -1 但我不知道为什么,“..”的信息仍然不正确
  • 打印出dentry-&gt;d_name(也许是当前目录以使其更清晰)。
  • @Mat 通过 perror 输出是 >lstat: No such file or directory NAME IS main.c

标签: c file unix permissions


【解决方案1】:

正如您通过添加 cmets 中建议的错误检查发现的那样,您遇到了“没有这样的文件或目录”的问题。这是因为 lstat() 从当前工作目录开始解析 struct dirent 对象中的文件名等相对路径,不是您要列出文件的目录。

幸运的是,现代 unix/linux 系统有一个函数 fstatat(),它可以让你指定一个目录作为相对路径的基础,你可以从带有 dirfd()DIR 结构中获取所需的目录描述符。

使用它的简化示例:

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>

int main(void) {
  DIR *d = opendir("test/");
  if (!d) {
    perror("opendir");
    return EXIT_FAILURE;
  }

  int dfd = dirfd(d); // Get the directory file descriptor for use with fstatat()
  if (dfd < 0) {
    perror("dirfd");
    closedir(d);
    return EXIT_FAILURE;
  }

  struct dirent *entry;
  while ((entry = readdir(d))) {
    if (entry->d_name[0] == '.') {
      // Skip dotfiles
      continue;
    }

    struct stat s;
    // Resolve filenames relative to the directory being scanned
    // and don't follow symlinks to emulate lstat()'s behavior
    if (fstatat(dfd, entry->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
      perror("fstatat");
      closedir(d);
      return EXIT_FAILURE;
    }
    printf("%s: %ld\n", entry->d_name, (long)s.st_size);
  }

  closedir(d);
  return 0;
}

在缺少*at() 函数的旧操作系统上,您必须求助于创建一个包含目录名+文件名的字符串(使用snprintf() 或其他)并将其用作lstat() 的参数。

【讨论】:

  • 谢谢!你的回答很有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 2020-07-07
  • 1970-01-01
  • 2013-12-28
  • 2013-06-13
  • 1970-01-01
相关资源
最近更新 更多