summaryrefslogtreecommitdiff
path: root/README
blob: b8e48eda43e290008465cd413347052a177330a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
Libsqlfs

Copyright 2006, Palmsource, Inc., an ACCESS company.
Sunnyvale, California, USA

Libsqlfs is free/open source software distributed under the GNU Lesser
General Public License, version 2 or later versions as published by the Free
Software Foundation.  See the file COPYING for the complete licensing terms.

Introduction
============


The libsqlfs library implements a POSIX style file system on top of an
SQLite database.  It allows applications to have access to a full read/write
file system in a single file, complete with its own file hierarchy and name
space.  This is useful for applications which needs structured storage, such
as embedding documents within documents, or management of configuration
data or preferences.  Libsqlfs can be used as an shared library, or it can be
built as a FUSE (Linux File System in User Space) module to allow a libsqlfs
database to be accessed via OS level file system interfaces by normal
applications.
 

Rational
========

PalmSource software developers recently created libsqlfs.  This library is an
adjunct to the very popular open source SQLite database software.  Libsqlfs
was created as part of PalmSource's ALP mobile phone platform, but it is
useful in many other applications too.

The libsqlfs library provides an easy way for applications to put an
entire read/write file system into a relational database as a single file
in the host file system.  Such a file system can easily be moved around,
backed up or restored as a single file.  But the file system can also be
accessed as individual files.  This provides great flexibility and
convenience.

We concluded that a simpler way to meet our needs was to write a library
that supported  the POSIX file system semantics on an SQL database.  This
brings the benefits of a real database, such as transactions and
concurrency control, and allows us to have complete control over the
schema of the preferences, so we can allow additional metadata such as
value types, permissions and access control lists. Our libsqlfs registry
can accommodate small preference values such as a number, and large
binary objects such as an video clip.   The library provides a generic
file system layer that maps a file system onto a SQLite database, and
supports a POSIX file system semantics.

To speed development, we built our file system mapping layer as a File
System In User Space (FUSE) module.  FUSE is another open source
project.  It is a kernel module that supports user-level implementations
of file systems. Our design allows libsqlfs to implement a real file
system at the OS level, and apply real file system operations on it.  We 
tested the complete build process of gcc and the Linux kernel on top of
libsqlfs, and we successfully executed fsx.c, the Apple file system test
tool, against libsqlfs.

Today the ALP Global Settings component uses libsqlfs as the storage
back-end.  Libsqlfs provides an easy way for applications to support a
read/write file system totally contained in a relational database as a single
file in the host file system, without using SQL statements.  Libsqlfs
provides a superset of the storage features of GConf, and can be used as the
storage back end of other desktop preference services.  Libsqlfs is also
useful wherever developers need to organize data, and sometimes treat it as
one file, and at other times treat it as a collection of individually
writable files.


Installation
============

* As a Library

Libsqlfs provides a GNU autoconf/automake based build system for building as
an application library.  To build, please follow the normal GNU configure
conventions.  Normally, the following command is all what's needed:

./configure --prefix=<install dir>
make && make install

<install dir> defaults to /usr/local if not specified.

You have to be root for installing into system directories such as
/usr/local.

Both a static library and a shared library are built, unless you specify
otherwise via options to configure.

* As an FUSE module

Currently FUSE module build is not integrated with the configure script;
instead a script compile_fuse is supplied for building the module.  You may
need to edit the include paths to adjust for your particular environment. 

After running the script you shall have an executable called fuse_libsqlfs.
Run it as root to start a FUSE session on top of libsqlfs:

fuse_libsqlfs <mnt point> 

then you shall see the libsqlfs file space exposed, and
can be accessed by normal applications,  via the <mnt point>.

example:

fuse_libsqlfs /mnt/sqlfs &

ls /mnt/sqlfs

The location of the SQLite database is hard-coded in fuse_main.c.  Change the
argument to sqlfs_init() to suit your needs.

APIs
====

A libsqlfs session is represented by an object of type sqlfs_t.  All APIs
require an explicit reference to a valid sqlfs_t.

Each file is a "key" in the internal libsqlfs vocabulary.  File metadata are
represented as objects of the sturct key_attr.  File contents are represented
by the struct key_value. 

File metadata are the normal POSIX file attributes as expected except an
additional "type" which can not be visible via the normal file attribute
functions.  The "type" is used to support the specific needs of the setting
registry application and can be one of the following:

Null
Dir
Integer (32-bit)
Double (a C double)
String (a C zero-terminated string)
Sym_link (symbolic link)
Bool  (a boolean)
List (a Glib list of values)
Blob (a binary object)

Note all other file system primitives do not make use of the "type"; to them
all files are blobs. At this point the "type" is meant for use by higher up
application logic in applications using libsqlfs.

Libsqlfs started as an FUSE module so it implements the primitives as
defined by FUSE version 2.5.3.  Specifically, the following file system
primitives are implemented:


int sqlfs_proc_getattr(sqlfs_t *, const char *path, struct stat *stbuf);
int sqlfs_proc_access(sqlfs_t *, const char *path, int mask);
int sqlfs_proc_readlink(sqlfs_t *, const char *path, char *buf, size_t size);
int sqlfs_proc_readdir(sqlfs_t *, const char *path, void *buf, fuse_fill_dir_t filler, 
                  off_t offset, struct fuse_file_info *fi);
int sqlfs_proc_mknod(sqlfs_t *, const char *path, mode_t mode, dev_t rdev);
int sqlfs_proc_mkdir(sqlfs_t *, const char *path, mode_t mode);
int sqlfs_proc_unlink(sqlfs_t *, const char *path);
int sqlfs_proc_rmdir(sqlfs_t *, const char *path);
int sqlfs_proc_symlink(sqlfs_t *, const char *path, const char *to);
int sqlfs_proc_rename(sqlfs_t *, const char *from, const char *to);
int sqlfs_proc_link(sqlfs_t *, const char *from, const char *to);
int sqlfs_proc_chmod(sqlfs_t *, const char *path, mode_t mode);
int sqlfs_proc_chown(sqlfs_t *, const char *path, uid_t uid, gid_t gid);
int sqlfs_proc_truncate(sqlfs_t *, const char *path, off_t size);
int sqlfs_proc_utime(sqlfs_t *, const char *path, struct utimbuf *buf);
int sqlfs_proc_open(sqlfs_t *, const char *path, struct fuse_file_info *fi);
int sqlfs_proc_read(sqlfs_t *, const char *path, char *buf, size_t size, off_t offset, struct
    fuse_file_info *fi);
int sqlfs_proc_write(sqlfs_t *, const char *path, const char *buf, size_t size, off_t offset,
    struct fuse_file_info *fi);
int sqlfs_proc_statfs(sqlfs_t *, const char *path, struct statvfs *stbuf);
int sqlfs_proc_release(sqlfs_t *, const char *path, struct fuse_file_info *fi);
int sqlfs_proc_fsync(sqlfs_t *, const char *path, int isfdatasync, struct fuse_file_info *fi);


Their semantics are as defined by the FUSE documentation and the
corresponding Unix file system calls.  Following the FUSE conventions, all
file or key paths must be absolute and start with a '/'.  Applications can
provide their own logic for relative paths before passing the "normalized"
absolute paths to these FUSE primitive routines.

Extended attributes are not yet supported in this version.

In addition, other APIs provide environment setup, support for
transaction and convenience functions: 

int sqlfs_init(const char *)
    initialize the libsqlfs library and sets the default database file name.

int sqlfs_open(const char *db, sqlfs_t **);
    creates a new connection to the libsqlfs database.  The first argument,
    if not NULL,specifies a different database file from the default.

int sqlfs_close(sqlfs_t *);
    closes and frees a libsqlfs connection.
    

int sqlfs_del_tree(sqlfs_t *sqlfs, const char *key);
    deletes a whole subtree.

int sqlfs_get_value(sqlfs_t *sqlfs, const char *key, key_value *value, 
    size_t begin, size_t end); 
    reads contents of a file contained in a range
    (between offsets begin and end)

int sqlfs_set_value(sqlfs_t *sqlfs, const char *key, const key_value *value, 
    size_t begin,  size_t end);
    writes contents of a file contained in a range
    (between offsets begin and end)

int sqlfs_get_attr(sqlfs_t *sqlfs, const char *key, key_attr *attr);
    reads the metadata of a file
    
int sqlfs_set_attr(sqlfs_t *sqlfs, const char *key, const key_attr *attr);
    write the metadata of a file

int sqlfs_set_type(sqlfs_t *sqlfs, const char *key, const char *type);
    sets the "type" of the file content. 
      
int sqlfs_begin_transaction(sqlfs_t *sqlfs);
    begins a SQLite transaction
    
int sqlfs_complete_transaction(sqlfs_t *sqlfs, int i);
    ends a SQLite transaction
    
Note the transaction supports "levels"; that is, transaction calls can be
nested and libsqlfs maintains an internal level count of the current
transaction level.  The actual SQLite transaction are only started when the
level goes above 0 and only ended when the level falls to zero.    

For a sample application showing the usage of libsqlfs, see the test
program test.c in the test directory.
    
Supported Platforms
===================

To date, libsqlfs is tested on 32-bit i386 and StrongArm (Treo 650
phone) GNU/Linux (Ubnutu).

Currently libsqlfs, when used as a library, only has been tested on GNU/Linux
(Ubnutu and Red Hat  Fedora 5) although it shall be usable on any Unix like
platforms where SQLite runs with at most minor changes.   It shall also work
on the Cygwin enviroment but this is not tested.  Patches for different
platform support are welcome.

For use at the OS level, libsqlfs only supports the FUSE on the Linux kernel
on both 32-bit i386 and StrongArm.

Supported Database
==================

To date, only SQLite is supported.



For more information, please contact:

Peter van der Linden  peter.vanderlinden@palmsource.com 
Andy Tai, andy.tai@palmsource.com