/* ------------------------------------------------------------ filemap.h - Simple Portable File Path Mapper ------------------------------------------------------------ * © David Olofson, 2001 * This code is released under the terms of the GNU LGPL. */ /* * Path syntax: * All filemapper_t functions but exepath() * and sys2unix() (obviously!) expect paths in the * native system format. * * ALL OTHER PATHS SHOULD BE IN UNIX FORMAT. * * All arguments that are expected to be in system * format are named along the lines of "syspath". * * Classes: * The 'class>>' construct expands to one of the * paths registered for 'class', or makes the mapping * fail (NULL is returned), if the object doesn't * exist or cannot be created as applicable. * * Class references are recursive, and are resolved * late, at mapping time. (That is, they are resolved * when someone asks for it, not when registering * paths.) * * Class "HOME>>" is built-in, and resolves to the * root of the user home directory. (Currently * looks only at the environment variable "HOME", * which may not be defined on all platforms.) * * Class "EXE>>" is another built-in, and refers to * the path extracted from exepath(). */ #ifndef _FILEMAP_H_ #define _FILEMAP_H_ #include "aconfig.h" #define FM_DEREF_TOKEN ">>" #include #include #define FM_BUFFERS 16 #define FM_BUFFER_SIZE 512 struct fm_key_t { fm_key_t *next; char key[10]; char *path; }; enum { FM_ERROR = 0, FM_FILE, FM_DIR, FM_ANY, FM_FILE_CREATE, FM_DIR_CREATE }; // Not a great name - but fm_path_t would just be confusing, // and an fm_object_t can actually be either a dir or a file. struct fm_object_t { fm_object_t *next; char *path; int kind; ~fm_object_t(); }; class filemapper_t { // For get_(first|next)() fm_object_t *objects; fm_object_t *current_obj; DIR *current_dir; // File mapper keys fm_key_t *keys; // Application executable path char *app_path; // Silly/safe/string alloc :-) char buffers[FM_BUFFERS][FM_BUFFER_SIZE]; int next_buffer; char *salloc(); // Various private funcs void no_double_slashes(char *buf); void unix_slashes(char *buf); void sys_slashes(char *buf); int probe(const char *syspath); int test_file_create(const char *syspath); int test_file_dir_any(const char *syspath, int kind); int try_get(const char *path, int kind); void add_object(const char *path, int kind); int recurse_get(char *result, const char *ref, int kind, int level, int build); public: filemapper_t(); ~filemapper_t(); // Set/get path to exe file. // Note that exepath() expects a // path in the *native system* format, // while exepath() returns a Unix path. void exepath(const char *syspath); const char *exepath() { return app_path; } // Add 'path' to class 'key'. // Key should be given *without* the '::'. void addpath(const char *key, const char *path, int first = 0); // key == NULL, ref == NULL or "*": // Get first key. // key == NULL, ref == : // Get first key of class 'ref'. // key == , ref == NULL: // Get next key of same class as 'key'. // key == , ref == : // Get next key of class 'ref'. // The "*" wildcard for 'ref' is allowed. // Returns NULL if no key was found. fm_key_t *getkey(fm_key_t *key = NULL, const char *ref = NULL); // Get object path (returns path in system format!) const char *get(const char *ref, int kind = FM_FILE); /* FIXME: Do these really handle the 'kind' argument properly...? FIXME: When looking for files, they should return only files FIXME: matching the 'ref' path, while when looking for dirs, FIXME: every file inside each matching dir should be returned. */ // Initialize path scan. Use get_next() to get the // paths to all matches. void get_all(const char *ref, int kind = FM_FILE); // Get next object (returns path in system format!) const char *get_next(); // Open/create file/dir. FILE *fopen(const char *ref, const char *mode); DIR *opendir(const char *ref); int mkdir(const char *ref, int perm); // Print out all registered paths of class 'ref' // to stream 'f'. (ref == '*') ==> All classes. void print(FILE *f, const char *ref); // Translate to and from the internal Unix-like path format char *sys2unix(const char *syspath); char *unix2sys(const char *path); }; #endif