lstat 和 ls 权限输出在某种程度上有所不同

lstat and ls permissions output is somehow differs

我正在尝试用它的一些标志重写 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] = '[=10=]';
}

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

正如您从评论中建议的添加错误检查中发现的那样,您遇到了 'No such file or directory' 的问题。这是因为 lstat() 从当前工作目录开始解析 struct dirent 对象中的文件名之类的相对路径, 而不是 您要列出的目录

的文件

幸运的是,现代 unix/linux 系统有一个函数 fstatat() 可以让你指定一个目录作为相对路径的基础,你可以从 DIR 结构 dirfd().

使用它的简化示例:

#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().