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()
.
我正在尝试用它的一些标志重写 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()
.