123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- Caseless Filesystem
- ---------------------
- The caseless filesystem is designed to allow one to access files in a
- case insensitive manner on a case-sensitive filesystem. A particular
- example of the use of this is in trying to build code that's maintained
- on a case insensitive operating system (e.g. windows) on Linux without
- having to spend time correcting all the references.
- e.g. on the filesystem the file might be "inc/api.h" but c source code
- might contain '#include "INC\Api.h"' which is case-inconsistent and will
- fail on Linux.
- Usage:
- caseless-fuse path/to/mountpoint path/to/source
- the "source" is the location with the original files. The mountpoint is
- the place where the apparently case-insensitive version of those files
- will appear to be present.
- When you are finished you can unmount the filesystem like so:
- fusermount -u path/to/mountpoint
- Example:
- If there is a file called api.h in "myproject" and you mount "myproject"
- onto "uc_myproject" like so:
- mkdir uc_myproject
- caseless-fuse myproject uc_myproject
- ...then this command will fail:
- cat myproject/API.H
- cat: cannot access myproject/API.H: No such file or directory
- ...but this one will succeed:
- cat uc_myproject/API.H
- /* api.h */
- #ifndef _API_H_
- #define _API_H_
- ....
- #endif
- Design
- ------
- Caseless has a big hashtable - the key is a lowercased version of a
- filename with the full path and the value is the actual filename on the
- storage media.
- On startup it fills the hashtable with all the files that exist under
- the source directory and then as files are created/removed in the course
- of running it keeps this hashtable uptodate.
- A chained hastable is used with a compile-time constant number of chains.
- When some operation is contemplated on a file: if it's an operation
- that requires a file to already exist then the fs lowercases the name
- the application asked for, uses this as a key to lookup the "real"
- filename and opens that instead. If the file is not in the hash table
- then it doesn't exist and this is only ok if the operation is "create"
- or "open(ccc,"w+").
- Lookups on non-existent keys are expensive-ish in dictionaries so we
- also remember when a file doesn't exist by storing a null value into
- the dictionary for that key. Make does a lot of lookups for non-existant
- things, of course.
- There is code for handling the file operations (caseless-fuse.c) for
- managing the dictionary of lowercase filenames mapping to real names
- (pathcache.c) and code for looking after our "own home-grown filehandles"
- (filehandles.c). The filename mapping dictionary uses a generic string
- key/string value hashtable from hashtable.c.
- There are some little test programs (e.g. for the hashtable
- implementation) and some test scripts - test.sh is for basic correctness
- of operations and test_perf.sh tries to check performance on "stat"
- operations which make does a lot of.
- Known-Issues
- -------------
- Memory usage is not bounded in the face of many deletes since the
- filesystem tries to remember what files don't exist and has no way of
- recovering the storage that this requires. Future versions will.
- It's not as fast as direct access to the filesystem.
- Building:
- -----------
- You need to have the fuse libraries installed.
- Just type "make" to build.
- To debug the filesystem, build with debugging on:
- make CFLAGS="-g -DDEBUG"
- then run like so:
- ./caseless-fuse -o debug path/to/mountpoint path/to/source
- The filesystem will not become a daemon and will display debugging output
- on the console. You can use another terminal window to run whatever
- testing you wish while watching this output. Debugging slows the filesystem
- down greatly so for real world use run "make clean; make" to rebuild before
- using it.
|