Apr
7
It’s been a while since I posted anything up here, so I’m going to try and cover a few topics now. I started a new job developing payments routing software with ACI Worldwide in February, so I’ve been busy enough over the last few weeks.
To start with, I’ll mention http://photos.jmadden.eu, which I’ve just set up. This is a Plogger install that I can fill up with our photos. At the moment, all that’s up there are photos of Lou’s hen night in Killarney this year.
That leads me nicely on to my stag weekend, which was this past weekend (4th, 5th & 6th of April). I had a brilliant weekend, really enjoyed it & it was brilliant to have such a great bunch of friends around for the few days celebration! Thanks to everyone who made it. When I get a few photos in from it, I’ll put them up too.
While on the topic of photos, I also grabbed PloggerPress to integrate Plogger with WordPress, so I could have pages & posts of just photos. It works perfectly, but I’ve made a few changes to make it work a bit better for what I want. Firstly, I found a minor bug in it that I notified the developer about this evening. On line 150 of plogger-press.php, change
$url=substr($path, $number);
to
$url=preg_replace(“/[ |(|)]/”, “_”, substr($path, $number));
Plogger replaces certain characters (the one’s I noticed for the above change were ‘ ‘, ‘(‘ and ‘)’) with underscores. This ended up with some of the thumbnails for photos not being shown because the link for the ‘img src’ was incorrect.
As well as this, I added an ‘add_filter(“wp_head”, “my_head_func”);’ so I could alter some styling. I put a ‘class=”image”‘ into the ‘<img>’ tags so I could style them (borders, padding etc.) just to look a bit better.
Lastly, I’ve had very little time to work on SvnFs lately. I’ve done a small bit of work on getting write support done, but if you want it any time soon, I’d advise grabbing it from http://www.jmadden.eu/svnrepos/svnfs/trunk. It’s available anonymously, so
svn co http://www.jmadden.eu/svnrepos/svnfs/trunk
That’s it for now. We’re only three and a half weeks away from the wedding, so I doubt there’ll be many more updates before that. I’ll put up the stag photos when I get them, but that’ll probably be it!!
Sep
19
I’ve just uploaded svnfs-0.4.tgz.
The major change in this version is to remove the requirement for a list of the repository at mount time, in favour of doing a list of the required directory when it’s needed. This slows down commands and tab completion, with the trade off of giving quicker mount times and always giving the latest contents of the repository.
As well as this, a few bugs were fixed.
- listing of files and directories in the root of the mounted filesystem
- segfault caused by an off-by-one in _svnclient_list_func()
- don’t return subdirectory files in svnfs_readdir()
As usual, any comments or patches welcome to john+svnfs@jmadden.eu.
Jun
28
I’ve updated SvnFs further to fix RHEL build problems (thanks to Niall Donegan for his help testing the numerous proposed fixes).
Version 0.3 and upwards require version 1.4 or higher of the Subversion development libraries to compile and run. I haven’t yet updated the configure script to check for this, so this is likely the problem if you get compile errors similar to
svnclient.c:48: error: syntax error before ‘*’ token
svnclient.c: In function `_svnclient_list_func’:
svnclient.c:53: error: `path’ undeclared (first use in this function)
svnclient.c:53: error: (Each undeclared identifier is reported only once
svnclient.c:53: error: for each function it appears in.)
svnclient.c:56: error: `dirent’ undeclared (first use in this function)
svnclient.c: In function `svnclient_readdir’:
svnclient.c:81: error: `SVN_DIRENT_KIND’ undeclared (first use in this
function)
svnclient.c:81: error: `SVN_DIRENT_SIZE’ undeclared (first use in this
function)
svnclient.c:102: warning: initialization makes pointer from integer
without a cast
svnclient.c: In function `svnclient_read’:
svnclient.c:134: warning: assignment makes pointer from integer without
a cast
make[2]: *** [svnclient.o] Error 1
make[2]: Leaving directory `/root/svnfs/src’
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/root/svnfs’
make: *** [all] Error 2
I’ve decided to work with the latest API, so I won’t be “fixing” these issues to work with older deprecated API functions.
As usual, this release is available from the SvnFs page.
Jun
24
I’ve uploaded the latest version of SvnFs. It’s available from the SvnFs page.
This provides read-only support for Subversion repositories. There are still some issues that need to be ironed out (design issues rather than bugs).
- Doing a recursive list of the repository at mount time is slow
- Reading large files is slow, due to lack of caching
Other than that, from my testing, it works pretty reliably.
I did come across an awkward bug though, which I now can’t reproduce! Basically, between the time I created the Subversion repository for SvnFs and now I’ve switched from en_IE@euro as my locale to en_IE.UTF8. Something in there caused Subversion to get mixed up and incorrectly report the filesize in the svn_dirent_t structure filled by svn_client_list(). This meant that the filesystem thought the files were smaller than they actually were, and was causing short reads. I worked around it by removing and re-adding all the files that were showing incorrect sizes, just for my own testing.
Jun
17
I’m still working, albeit slowly, on SvnFs. I’ve implemented open() and read() functions, but there are still bugs to be ironed out, so I’m not releasing it yet.
However, I’ve finally gotten around to setting up anonymous access to the code, so the latest development version can be gotten from the Subversion repository with
svn co http://www.jmadden.eu/svnrepos/svnfs/trunk
Testing reports and patches graciously accepted!
The two major bugs to be fixed are:
- Reading large files causes a segmentation fault
- The directory listing of a repository lists files that have been deleted or removed
Once those two are fixed, I think v0.3 should be ready for release, and should offer a complete readonly filesystem of a Subversion repository.
After that, I’ll need to move some code around. Doing a full listing of a Subversion repository at mount time is very slow, and probably not needed – particularly for large repositories. So that will have to change to be more scalable.
Mar
10
I’ve created this page to track releases of SvnFs. The first release, version 0.2 is now available.
Please let me know if you find it useful, and send any patches or bugs to john+svnfs@jmadden.eu.
I haven’t yet set up anonymous access to the Subversion repository for this project, but I’ll hopefully get it done during the week.
Mar
9
SvnFs has gotten to somewhat of a milestone! You can use it to mount a subversion repository, and browse it like a filesystem – ie. you can use cd and ls to look around the repository. There’s no auth support, so it’s pretty much only useful for anonymous or otherwise authenticated (eg. svn+ssh, file) repositories.
While the FUSE documentation isn’t great, the example programs are very easy to follow. In this case, the setup is the same as the hello.c setup.
#include <fuse.h>
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
fuse_opt_parse(&args, &svnfs, svnfs_opts, svnfs_parse_opts);
return(fuse_main(args.argc, args.argv, &svnfs_oper));
Here, I’m using svnfs as a global struct to hold specific SvnFs options (eg. debugging on or off); svnfs_opts are the possible command line options and svnfs_parse_opts is the function to parse SvnFs specific options.
To get started with Subversion, the first thing I needed was a client context and a memory pool. Subversion uses APR for portability. APR manages the allocation and deallocation (along with plenty of other stuff) of memory for you, and it uses a concept of pools of memory. So, to start with, I created a global memory pool, and I initialise it in a function called from main().
#include <apr_pools.h>
apr_pool_t *pool;
apr_initialize();
pool = svn_pool_create(pool);
Secondly, I created the client context.
#include <svn_client.h>
svn_client_ctx_t *ctx;
svn_auth_baton_t *auth_baton;
apr_array_header_t *providers;
svn_auth_provider_object_t *username_wc_provider;
svn_client_create_context(&ctx, pool);
svn_config_get_config(&(ctx->config), NULL, pool);
providers = apr_array_make(pool, 1, sizeof(svn_auth_provider_object_t *));
username_wc_provider = apr_pcalloc(pool, sizeof(*username_wc_provider));
svn_client_get_username_provider(&username_wc_provider, pool);
*(svn_auth_provider_object_t **)apr_array_push(providers) = username_wc_provider;
svn_auth_open(&auth_baton, providers, pool);
ctx->auth_baton = auth_baton;
This block of code loads up your configuration (currently not supported, the NULL in svn_config_get_config is the configuration file name), and sets up the authentication baton for the client context.
Lastly, I use a recursive svn ls to get the full list of files from the repository, and store this in a linked list. Getting the list of files from Subversion is done as follows.
apr_hash_t *dirents;
apr_array_header_t *array;
svn_opt_revision_t *rev = { 0 };
svn_sort__item_t *item;
svn_dirent_t *dirent;
char *fullpath;
SVN_ERR(svn_client_ls(&dirents, fullpath, rev, TRUE, ctx, pool));
array = svn_sort__hash(dirents, svn_sort_compare_items_as_paths, pool);
for( int i = 0; i < array->nelts; ++i ) {
item = &APR_ARRAY_IDX(array, i, svn_sort__item_t);
utf8_name = item->key;
dirent = apr_hash_get(dirents, utf8_name, item->klen);
}
I populate my linked list with the filename and a struct stat for each file. The struct stat is only used (at the moment) to store the mode – 0755 for directories, 0644 for files. Obviously, this will have to be updated in future to match real file permissions, or preferred permissions (eg. if you wanted to use SvnFs to store your email in Subversion, you don’t want world readable files).
The svn_dirent_t *dirent; above has a member called kind which can be svn_node_file or svn_node_dir. This is what I’m using to set the mode of the file.
Lastly, when a readdir() is called, svnfs_readdir get’s called. This simply returns all the elements in the current directory, but checking the filename in the linked list, and omitting any files in subdirectories. When getattr() is called, svnfs_getattr() gets run. This finds the entry in the linked list that matches the filename being looked for, and returns the struct stat for that element. This search needs to be optimised for larger repositories, but for now, it works! Pretty simple really, but functional!