Elixir Xattr v0.3.1 Xattr View Source
API module for accessing custom extended filesystem attributes.
Attributes managed by this module are stored in isolation, in custom namespace. Because implementation concepts of extended attributes differ in supported platforms, it would not be possible to provide unified API which could cover specific use cases.
Some kernels and filesystems may place various limits on extended attributes functionality, and so it is to use them only to store few, short metadata which is not crucial to application functionality.
Implementation
Elixir Xattr is implemented as NIF library with two platform-dependent backends:
- Xattr - Unix extended attributes supported by Linux and macOS
- Windows - alternate data streams available in Windows/NTFS
Xattr
This backed works as an Erlang wrapper for xattr(7)
functionality available in Unix world. Attributes are always prefixed with
user.ElixirXattr
namespace.
Windows
On Windows, NTFS has a feature called Alternate Data Streams. Briefly: a file can have many contents.
Attributes are stored in ElixirXattr
data stream, which is automatically
created when setting an attribute and the stream does not exist. They are
saved in simple binary format, as a contiguous list of size:data cells:
v - name C-string size v - value binary size
+---+------------+---+-----------+---+----------+---+-------+
| 5 | n a m e \0 | 5 | v a l u e | 4 | f o o \0 | 3 | b a r | ...
+---+------------+---+-----------+---+----------+---+-------+
^ - name C-string, note \0 suffix ^ - value binary data
Unicode
Unicode filenames are supported (and as such proper encoding conversions are performed when needed).
Both names nor values are not processed and stored as-is.
Attribute name types
Because attribute names can be represented by various Erlang types, they are prefixed with type tags during serialization:
a$
- atomss$
- name
For example, given Xattr backend, call Xattr.set("foo.txt", "example", "value")
will create user.ElixirXattr.s$example
extended attribute on file foo.txt
.
Extended attributes & file system links
On both Unix and Windows implementations, attribute storage is attached to file system data, not file/link entries. Therefore attributes are shared between all hard links / file and its symlinks.
Errors
Because of the nature of error handling on both Unix and Windows, only specific
error codes are translated to atoms. Other codes are stringified to some human
readable name, on Unix using strerror
and on Windows to form 'Windows Error {hexadecimal error code}'
(Windows
version of strerror returns localized messages on non-English installations).
Following errors are represented as atoms and as such can be pattern matched:
:enoattr
- attribute was not found:enotsup
- extended attributes are not supported for this file:enoent
- file does not exist:invalfmt
- attribute storage is corrupted and should be regenerated
Link to this section Summary
Functions
Gets extended attribute value
The same as get/2
, but raises an exception if it fails
Checks whether path
has extended attribute name
The same as has/2
, but raises an exception if it fails
Lists names of all extended attributes of path
Removes extended attribute
The same as rm/2
, but raises an exception if it fails
Sets extended attribute value
The same as set/3
, but raises an exception if it fails
Link to this section Types
name_t() View Source
Link to this section Functions
get(path, name) View Source
Gets extended attribute value.
If attribute name
does not exist, {:error, :enoattr}
is returned.
Example
Xattr.set("foo.txt", "hello", "world")
Xattr.get("foo.txt", "hello") == {:ok, "world"}
Xattr.get("foo.txt", :foo) == {:error, :enoattr}
get!(path, name) View Source
The same as get/2
, but raises an exception if it fails.
has(path, name) View Source
Checks whether path
has extended attribute name
.
Example
Xattr.set("foo.txt", "hello", "world")
Xattr.has("foo.txt", "hello") == {:ok, true}
Xattr.has("foo.txt", :foo) == {:ok, false}
has!(path, name) View Source
The same as has/2
, but raises an exception if it fails.
ls(path) View Source
Lists names of all extended attributes of path
.
The order of items in returned list is unspecified. If given path
has no
attributes, {:ok, []}
is returned.
Example
Xattr.set("foo.txt", "hello", "world")
Xattr.set("foo.txt", :foo, "bar")
{:ok, list} = Xattr.ls("foo.txt")
# list should be permutation of ["hello", :foo]
ls!(path) View Source
The same as ls/1
, but raises an exception if it fails.
rm(path, name) View Source
Removes extended attribute.
If attribute name
does not exist, {:error, :enoattr}
is returned.
Example
Xattr.set("foo.txt", "hello", "world")
Xattr.set("foo.txt", :foo, "bar")
Xattr.rm("foo.txt", "foo")
{:ok, ["hello"]} = Xattr.ls("foo.txt")
rm!(path, name) View Source
The same as rm/2
, but raises an exception if it fails.
set(path, name, value) View Source
Sets extended attribute value.
If attribute name
does not exist, it is created.
Example
Xattr.set("foo.txt", "hello", "world")
Xattr.get("foo.txt", "hello") == {:ok, "world"}
set!(path, name, value) View Source
The same as set/3
, but raises an exception if it fails.