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.
Niklas B.
source share