af_retrieve(3)

πŸ’– af_retrieve(3) β€” the AtFS retrieve interface, but make it make sense πŸ’–

okay so this is the af_retrieve(3) page out of the Attribute Filesystem (AtFS) manual, and it's literally your backstage pass to pulling files back out of AtFS. no cap. ✨


πŸŽ€ NAME πŸŽ€

af_find, af_cachefind, af_initattrs, af_getkey, af_dropkey, af_dropset, af_dropall β€” the AtFS retrieve interface 🫢


🌸 SYNOPSIS 🌸

#include <atfs.h>

int af_find (Af_attrs *attrbuf, Af_set *resultset)

int af_cachefind (Af_attrs *attrbuf, Af_set *resultset)

int af_initattrs (Af_attrs *attrbuf)

int af_getkey (char *syspath, char *name, char *type, int gen, int rev,
Af_key *aso)

int af_dropkey (Af_key *key)

int af_dropset (Af_set *set)

int af_dropall (void)

πŸ¦‹ DESCRIPTION πŸ¦‹

so af_find and af_cachefind are the two besties that go get you ASOs by their attributes. af_find works on source objects only, and af_cachefind works on derived objects only. the keys of every ASO they find come back to you in resultset. lowkey important: the keys in resultset are returned in random order, so don't come for me about the ordering, it's not a thing. 🌈

both of them expect resultset to be a pointer to an empty set structure β€” like, empty empty, bestie. and both of them return the number of ASOs they found. slay.


πŸ’… the attribute buffer πŸ’…

your retrieve arguments get passed in an attribute buffer called attrbuf. you should initialize attrbuf with af_initattrs before you call af_find (or, resp., af_cachefind). what does af_initattrs do? it disables every field in the attribute buffer. periodt. then your application can switch individual fields back on by setting whatever attribute value it actually wants. the initial settings of each field are listed down below, right next to the structure of the attribute buffer.

if you set one of the Af_user fields in the attribute buffer to AF_NOUSER, you only get ASOs selected where the corresponding user attribute is not set. and ngl, this only makes sense for af_locker, like when you specifically want to select ASOs that are not locked.

on the af_mode field, it does a bitwise comparison. so every ASO gets selected that has at least all the required mode bits (the ones you gave in af_mode) set in its own mode field. an exact match is not required. it's giving "close enough is close enough." πŸ’…

the first two fields in the attribute buffer are the search space. generally the search space for a retrieve operation is a directory, and the directory name goes in the af_syspath field of the attribute buffer. if you don't give a system path at all? it searches the current directory. and heads up: the af_host field in the attribute buffer is ignored in the current implementation. πŸ™ˆ


🧚 the attribute buffer structure 🧚

here it is, exactly as it is, initial values and all:

typedef struct {                                  initial value
    char  af_host[MAXHOSTNAMELEN];                /* hostname (ignored) */""
    char  af_syspath[MAXPATHLEN+1];               /* system path */""
    char  af_name[MAXNAMLEN+1];                   /* filename */"*"
    char  af_type[MAXTYPLEN]; /* filename extension (type) */"*"
    int   af_gen;             /* generation number */-1
    int   af_rev;             /* revision number */-1
    int   af_state;           /* version state */ -1
    Af_user                   af_owner;           /* owner */{ "", "", "" }
    Af_user                   af_author;          /* author */{ "", "", "" }
    off_t af_size;            /* size of file */  -1
    u_short                   af_mode;            /* protection */0
    Af_user                   af_locker;          /* locker */{ "", "", "" }
    time_t                    af_mtime;           /* date of last modification */-1
    time_t                    af_atime;           /* date of last access */-1
    time_t                    af_ctime;           /* date of last status change*/-1
    time_t                    af_stime;           /* save date */-1
    time_t                    af_ltime;           /* date of last lock change */-1
    char  *af_udattrs[AF_MAXUDAS];                /* user defined attributes */
} Af_attrs;

πŸ“ user defined attributes as retrieve arguments πŸ“

you can absolutely pass a list of user defined attributes as retrieve arguments. the pointer list af_udattrs in the attribute buffer gets filled with strings of the form name[=value]. and the list must be terminated by a nil pointer. don't forget that part, bestie, it's non-negotiable. πŸ’€

the user defined attributes get interpreted like this:

  • empty list (first entry is a nil pointer) β€” matches every ASO. πŸ’–
  • "" (first entry is an empty string) β€” matches every ASO that has no user defined attributes.
  • name[=] β€” matches if a user defined attribute with the given name is present.
  • name=value β€” matches all ASOs that have a corresponding user defined attribute that has at least the given value.

πŸ‘‘ af_getkey and friends πŸ‘‘

af_getkey builds up an object key from a combination of attributes β€” pathname, name, type, generation number, revision number and variant name β€” that uniquely identifies a source ASO. on a successful completion, the found object key is returned in the buffer key. πŸ”₯

and here's a cute trick: instead of explicit version numbers, you can pass the pseudo-numbers AF_BUSYVERS, AF_FIRSTVERS or AF_LASTVERS to af_getkey. note that af_getkey works only on source objects.

so this call right here:

af_getkey ("", "otto", "c", AF_BUSYVERS, AF_BUSYVERS, key)

leads to the key of the file (busy version) named otto.c in the current directory. ✨

and this one:

af_getkey ("", "otto", "c", AF_LASTVERS, AF_LASTVERS, key)

delivers the last saved version (if present) of the history of otto.c. obsessed.


🫢 giving your keys back (yes, you have to) 🫢

once you've retrieved a key or a whole set of keys, the data for the corresponding object version(s) stays cached in memory for as long as your application doesn't explicitly hand the key back. it's giving "you borrowed my hoodie and i need it back." 😭

  • af_dropkey gives a key back and releases the object version.
  • a retrieved set of keys has to be given back with af_dropset.
  • af_dropall sets all reference counters for cached object versions to zero β€” which means it gives all formerly retrieved keys and sets back. it's the "everyone out of the pool" of AtFS. πŸ’€

⭐ DIAGNOSTICS ⭐

af_find returns the number of found ASOs. upon error, -1 is returned and af_errno is set to the corresponding error number. so like, if you see -1, go check af_errno, bestie, it's telling you what's wrong. πŸŽ€


and that's the whole page, fr fr. this was af_retrieve(3) from AtFS-1.71, dated Fri Jun 25 14:33:18 1993 β€” yes, 1993, she's vintage and she's iconic, we stan a legacy filesystem. πŸ’œβœ¨

πŸ“¦ where this page comes from