问题描述
背景是我有一个列出目录条目的现有应用程序;strace显示它仅调用getdents并按返回的顺序列出它们.我希望它们以与不带参数的ls调用相同的顺序显示.是否可以通过某种方式更新目录数据来实现此目的?
Background is I have an existing application which lists directory entries; strace reveals it just calls getdents and lists them in the order returned. I would like them displayed in the same order as a call to ls with no arguments. Is it possible to update the directory data in some way to achieve this?
FS是ext4,如果有区别的话.
FS is ext4, if that makes any difference.
谢谢
推荐答案
如果您确实确实决定改变此程序的行为(我认为您没有可用的源代码),您可以使用 LD_PRELOAD
挂断电话到 opendir
和 readdir
并替换为您自己的排序包装器.下面是一个这样的钩子的示例:
If you really are determined to change this program's behaviour (of which I assume that you don't have the source code available), you can use LD_PRELOAD
to hook the call to opendir
and readdir
and replace it with your own, sorting wrapper. An example how such a hook could look like is the following:
#define _GNU_SOURCE 1
#include <stdio.h>
#include <dirent.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
struct __dirstream
{
int __fd;
char *__data;
size_t __allocation;
size_t __offset;
size_t __size;
struct dirent __entry;
};
typedef struct _dirent_list {
struct dirent *value;
struct _dirent_list *next;
} dirent_list;
typedef struct _my_DIR {
struct __dirstream orig;
dirent_list *first_entry;
int first_readdir;
} my_DIR;
DIR *opendir(const char *name) {
DIR *(*orig_opendir)(const char*) = dlsym(RTLD_NEXT, "opendir");
DIR *dir = orig_opendir(name);
// save additional information along with the
// original DIR structure
my_DIR *my_dir = calloc(1, sizeof(*my_dir));
my_dir->first_readdir = 1;
memcpy(my_dir, dir, sizeof(*dir));
return (DIR*)my_dir;
}
struct dirent *readdir(DIR *dir) {
struct dirent *(*orig_readdir)(DIR*) = dlsym(RTLD_NEXT, "readdir");
my_DIR *my_dir = (my_DIR*)dir;
dirent_list *item;
if (my_dir->first_readdir) {
struct dirent *entry;
while ((entry = orig_readdir(dir))) {
// exercise for the reader:
// implement insertion sort here
item = calloc(1, sizeof(*item));
item->value = entry;
item->next = my_dir->first_entry;
my_dir->first_entry = item;
}
my_dir->first_readdir = 0;
}
if (!my_dir->first_entry)
return NULL;
item = my_dir->first_entry;
struct dirent *result = item->value;
my_dir->first_entry = item->next;
free(item);
return result;
}
它将覆盖 opendir
和 readdir
以相反的顺序返回条目(您也可以将其用于排序).这就是将它与程序 test
一起使用的方式,该程序仅按接收顺序列出目录条目:
It overrides opendir
and readdir
to return the entries in reverse order (you can adapt this for sorting too). This is how you use it with a program test
that simply lists the directory entries in the order they are received:
$ gcc -Wall -shared -fPIC -o libhookdir.so hookdir.c -ldl
$ ./test
..
test
.
hookdir.c
libhookdir.so
test.c
$ LD_PRELOAD=./libhookdir.so ./test
test.c
libhookdir.so
hookdir.c
.
test
..
哈!这行得通.我们只是迷上了一个libc函数.
Hah! This works. We just hooked a libc function.
这篇关于什么决定了 getdents 返回的订单目录条目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!