배경 디렉토리 항목을 나열하는 기존 응용 프로그램이 있습니다. strace는 단지 getdents를 호출하고 반환 된 순서대로 나열합니다. 인수없이 ls에 대한 호출과 동일한 순서로 표시하려고합니다. 이를 달성하기 위해 디렉토리 데이터를 업데이트 할 수 있습니까?getdents에 의해 주문 디렉토리 항목이 리턴되는 것을 결정하는 것은 무엇입니까?
FS가 ext4 일 경우 차이가 있습니다.
감사
배경 디렉토리 항목을 나열하는 기존 응용 프로그램이 있습니다. strace는 단지 getdents를 호출하고 반환 된 순서대로 나열합니다. 인수없이 ls에 대한 호출과 동일한 순서로 표시하려고합니다. 이를 달성하기 위해 디렉토리 데이터를 업데이트 할 수 있습니까?getdents에 의해 주문 디렉토리 항목이 리턴되는 것을 결정하는 것은 무엇입니까?
FS가 ext4 일 경우 차이가 있습니다.
감사
당신이 정말로가 (난 당신이 사용할 수있는 소스 코드가없는 가정있는)이 프로그램의 동작을 변경하기로 결정하는 경우 opendir
및 readdir
에 전화를 끼어로 교체 LD_PRELOAD
을 사용할 수 있습니다 자신의 정렬 래퍼.
#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
는 역순으로 항목을 반환하는 (너무 정렬이 적응할 수) : 같은 후크 모양을 수있는 방법을 예는이 다음이다.
$ 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
..
하 석 : 이것은 당신이 그들이받은 단순히 순서대로 디렉토리 항목을 나열하는 프로그램 test
와 함께 사용하는 방법입니다! 이 작동합니다. 방금 libc 함수를 연결했습니다.
제안 해 주셔서 감사합니다. 방금 여기에서 코드를 사용하여 동일한 작업을 수행했습니다. [LD_PRELOAD 라이브러리를 사용하여 디렉터리 통과 속도를 높입니다.] (http://www.redhat.com/archives/ext3-users/2008-May/msg00006.html) . 지금 당장은 해결책이 될 것 같습니다만, 원래 getdents가 사용하는 알고리즘이 무엇인지 궁금합니다. – Barney
아니, 당신은 파일 시스템의 메타 데이터 ls(1)
디렉터리 entires에 적용되는 정렬 순서와 같은 순서로 getdents(2)
반환 디렉토리 entires을 가지고 조작 할 수있는 방법이 없습니다.
ls(1)
과 동일한 알고리즘을 사용하여 항목을 정렬하도록 프로그램을 수정할 수 있습니다. N 항목이있는 디렉토리를 정렬하려면 적어도 O (N) 메모리와 O (NLog N) 시간이 필요합니다. ls(1)
과 같은 방식으로 정렬하려면 구현, 메모리 및 시간의 가치가 있는지 결정해야합니다.
ext4라는 사실이 차이를 만듭니다. vfat의 경우 디렉토리를 다른 파일 시스템으로 옮긴 다음 올바른 순서로 파일을 다시 복사 할 수 있습니다. 나는 휴대용 mp3 선수를 위해 그것을 항상한다. BTW, 셸 glob 또한 'ls'와 같은 정렬합니다. 그래서 - cp -r music/media/my_player는 잘못된 순서를 줄 것이지만'mkdir/media/my_player/music; cp -v music/*/media/my_player/music' - 파일을 올바르게 복사합니다! 하지만이 트릭은 ext4에서 도움이되지 않습니다! (어쩌면 해시 테이블 디렉토리 또는 뭔가가 있습니다 ...) –
글쎄, 난 여기에 같은 결론을 발견 : http://superuser.com/a/373621/269542 - 그래서 당신만을 정렬 할 수 있습니다. 해당 응용 프로그램의 소스가있는 경우 LD_PRELOAD를 사용하여 해킹하는 대신 정렬을 추가 할 수 있습니다. –