Extended filesystem attributes support
François Revol <[email protected]> Thu, 3 Jun 2004 11:10:56 -0400
| Newsgroups | gmane.emacs.xemacs.design |
|---|---|
| Message-ID | <[email protected]> |
Hello,
BeOS has been using extended filesystem attributes for years,
and Linux has recently got some (weaker IMO) API to manipulate
attributes on filesystems that support it.
In BeOS for example, they are used to store the file's mimetype,
preferred application, folder's layouts for the file manager,
ID3s (which are then easily searchable by queries, which Linux
is far from able to do), mail data (from, to, subject, ...), and
even the whole datas for People files, which are 0-length files
with various attributes for contact informations, which a recent
IM_Kit (multi-protocol instant messenger) extended to contain
nicknames and networks. The default webbrowser (NetPositive) uses
0-length files as bookmark items as well, and BeIDE, the default
code editor, stores various things on files this way, including
the on-screen position, and the selection. Even file searches
(live updated) are stored as 0 length files with mimetype
application/x-vnd.Be-query.
I think (X)Emacs could benefit from attribute support.
Possible uses include saving current buffer selection
(as character range), cursor position, character encoding,
mimetype (and by extention editing mode), mode options
(tab-width, ...), ... and I'd prefer it to be cross-platform
instead of Linux or BeOS-specific. I might ultimately create
a library to encap various APIs.
I don't know much about POSIX attrs yet, what I know makes me
think it's not very featureful, but I hope I'm wrong.
The BeOS attributes differ from the POSIX ones on several points.
- they are typed. each attributes carry a 32 bit type, some of
which are defined by the system:
B_INT64_TYPE = 'LLNG',
B_INT32_TYPE = 'LONG',
B_INT16_TYPE = 'SHRT',
B_INT8_TYPE = 'BYTE',
B_STRING_TYPE = 'CSTR',
B_MIME_STRING_TYPE = 'MIMS', // used for mime-type
// a lot more ... and applications are free to use their own
types (4 caps are reserved for the system).
Note the type, even if required by read_attr(), is not part of
the key, and the filesystem can only have a single attribute
for the same file and name. (actually I believe it's up to the
filesystem kernel addon). So it is easy to emulate the BeOS API
from the POSIX one using 4 bytes at the start of the data, though
it might not be the cleanest way. Another option is to treat POSIX
attrs as strings, and use them with data like "int(3)", "str(foo)"...
- they are indexable (at least those of generic types, it's up to
the underlying filesystem)
- they are queryable (those indexed), the filesystem kernel addon
answers the query directly.
- the API (see later) works on file descriptors, while the posix
API seems to work on paths. I feel the former is more logical, for
example it works even if someone is mv-ing the file and other stuff,
besides it's called "extended _file_ attribute" (a directory being
just a weird file), and not a _path_ attribute. I think that point
isn't much of a problem, it's easy to get an fd from a path anyway :)
(for folders, the DIR struct has an fd field).
I don't think Emacs really needs query support
(though it could be funny), so it should be possible to find a common
denominator.
I think OS/2 has some form of attribute support too in HPFS, but
I don't know what kind. I don't know what NTFS is up to, appart
the ugly "file forks" stuff. I'll ask around about HFS+.
Has anyone attempted to add attribute support to XEmacs already ?
Any comment ?
Cheers,
François.
Here is how the C level API looks (the higher level is exposed
as methods on the BEntry class, which BFile, BDirectory and
BSymLink inherit from):
ssize_t fs_read_attr(int fd, const char *attribute, uint32 type, off_t pos, void *buf, size_t count);
ssize_t fs_write_attr(int fd, const char *attribute, uint32 type, off_t pos, const void *buf, size_t count);
int fs_remove_attr(int fd, const char *attr);
DIR * fs_open_attr_dir(const char *path);
DIR * fs_fopen_attr_dir(int fd);
int fs_close_attr_dir(DIR *dirp);
struct dirent *fs_read_attr_dir(DIR *dirp);
void fs_rewind_attr_dir(DIR *dirp);
typedef struct attr_info
{
uint32 type;
off_t size;
} attr_info;
int fs_stat_attr(int fd, const char *name, struct attr_info *ai);