1

I am investigating different methods of maintaining state between sessions [of my application running].

One [non-portable] method that was suggested to me [from the #ubuntu IRC chat] was to take advantage of man xattr:

Extended attributes are name:value pairs associated permanently with files and directories, similar to the environment strings associated with a process.

Source Code: https://github.com/torvalds/linux/blob/master/fs/xattr.c

This would be extremely useful to me if I could get it to work. I am not much of a c or kernel developer though, and can not quite parse how I go about mapping key value pairs to a file.

What I have thus far:

#include <QApplication>
#include <QTextStream>
#include <stdio.h>
#include <sys/xattr.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    char key[] = "foo";
    char val[] = "bar";
    char dir[] = "/home/akiva/foobar.txt";
    ssize_t set = setxattr (dir, key, val, strlen(val), 0); // Returns -1[error]
    ssize_t get = listxattr(dir, key,      strlen(val)   ); // Returns  0
    QTextStream(stdout) << QString("SetError: %1 \n"
                                   "GetError: %2 \n"
                                   "     Key: %3 \n"
                                   "     Val: %4 \n").arg(set).arg(get).arg(key).arg(val);

    return a.exec();
}

I am not sure why setxattr is giving me an error, nor what I should expect from listxattr which seems to be functioning fine. I'd like to be able to set or create a key:value pair for my foobar.txt file. In this case, "foo":"bar". Subsequently, after setting it, I'd like to be able to get the value from the file /home/akiva/foobar.txt, something along the lines:

FileClass fc("/home/akiva/foobar.txt"); // A class I will make, similar to QMap
{
        fc.insert("foo", "bar");
        fc.insert("bow", "tie");
}
QString s   = fc["foo"];          // s == "bar"
bool hasFoo = fc.contains("foo"); // true
bool hasDoo = fc.contains("doo"); // false
QStringList keys = fc.keys  ();   // "foo", "bow"
QStringList vals = fc.values();   // "bar", "tie"

Within the class, I would handle all the limitations etc. In any case, I'd like to get a working example of just being able to set and get key value pairs from my files, but I can not find a single example anywhere.

  • How can I set Key:Value pairs to files using xattr?
  • How can I get Key:Value pairs from files using xattr?
  • Do files ordinarily have existing Extended Attributes?
Anon
  • 2,267
  • 3
  • 34
  • 51
  • 1
    Which error do you get ? Add `if (set == -1) { perror("setxattr"); }` at tne next line after your call to setxattr. – nos Dec 16 '19 at 15:25
  • 1
    Checkk `errno` for the cause and make sure your filesystem supports xattributes – Alan Birtles Dec 16 '19 at 15:26
  • @nos `setxattr: Operation not supported`, I am on ext4 – Anon Dec 16 '19 at 15:30
  • So from the [docs](http://man7.org/linux/man-pages/man2/setxattr.2.html) , your file system does not support extended attributes. See e.g. here https://askubuntu.com/questions/124102/how-do-i-enable-extended-attributes-on-ext4 for how you can enable it, though it depends on which filesystem you use and other things. – nos Dec 16 '19 at 15:32
  • @nos Are you sure? Here it seems to say its enabled by default: https://unix.stackexchange.com/a/428427/79280 – Anon Dec 16 '19 at 15:34
  • 1
    It also reports not supported for "The namespace prefix of name is not valid", see the comments on your link, you need "user." on the front of your keys – Alan Birtles Dec 16 '19 at 15:38
  • 1
    see [Extended attribute namespaces](http://man7.org/linux/man-pages/man7/xattr.7.html) – Alan Birtles Dec 16 '19 at 15:41
  • @AlanBirtles Appending `user.` worked. Now I am getting an error: `listxattr: Numerical result out of range` – Anon Dec 16 '19 at 15:43
  • 1
    you parameters to [listxattr](http://man7.org/linux/man-pages/man2/listxattr.2.html) are incorrect, I guess you wanted to call [getxattr](http://man7.org/linux/man-pages/man2/getxattr.2.html). Either way `char val[] = "bar"` is undefined behaviour and passing `val` into a function which will modify `val` will probably crash your application – Alan Birtles Dec 16 '19 at 15:52
  • @AlanBirtles That fixed it. I am now able to get the value from the file. However, strangely, it is giving me error 3 or 4, `getxattr: No such file or directory` – Anon Dec 16 '19 at 16:11

0 Answers0