What determines the elements of the order catalog returned by getdents?

Background - I have an existing application that lists directory entries; strace shows that it simply calls getdents and lists them in the returned order. I would like them to appear in the same order as calling ls with no arguments. Is it possible to update the catalog data in any way for this?

FS is ext4 if that matters.

thanks

+7
source share
2 answers

If you decide to really change the behavior of this program (from which I assume that you do not have source code), you can use LD_PRELOAD to intercept the opendir and readdir and replace it with your own sorting shell. An example of how such a hook might look like this:

 #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; } 

It overrides opendir and readdir to return records in reverse order (you can also set this to sort). So you use it with the test program, which simply lists the directory entries in the order in which 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 .. 

Huh! It works. We just hooked up the libc function.

+6
source

No, you cannot manipulate file system metadata so that the getdents(2) return directory is returned in the same order as the sort order that ls(1) applies to the directory.

You can always change your program for sorting records using the same algorithms as ls(1) , although this requires at least O (N) memory and O (N Log N) time to sort the directory with N elements . You will need to decide whether to implement, memory and time, sort in the same way as ls(1) .

+1
source

All Articles