// schattr -- attach metadata to files, and ask the filesystem about it. // // schattr set attach a value // schattr get read it back // schattr rm remove it // schattr index start indexing that attribute // schattr find every object carrying that value // // `find` is the point of the rest. Without an index it is refused rather than // answered by walking every file, because a query that silently degrades into a // full scan is worse than one that says it cannot help: the first teaches you to // use it on a filesystem where it will not scale. // // Indexing covers values written *after* the index is declared. There is no // reindexing pass, so declare the index first. #include "core/types.h" #include "uapi/user.h" static void puts_(const char *s) { int n = 0; while (s[n]) n++; write(1, (void *)s, n); } static void putn_(unsigned long long v) { char buf[24]; int i = 0; if (v == 0) { write(1, "0", 1); return; } while (v > 0 && i < (int)sizeof(buf)) { buf[i++] = '0' + (int)(v % 10); v /= 10; } while (i--) write(1, &buf[i], 1); } static int streq(const char *a, const char *b) { while (*a && *a == *b) { a++; b++; } return *a == *b; } int main(int argc, char *argv[]) { if (argc < 2) { puts_("usage: schattr set|get|rm [value]\n"); puts_(" schattr index \n"); puts_(" schattr find \n"); exit(); } if (streq(argv[1], "set") && argc == 5) { int len = 0; while (argv[4][len]) len++; if (setxattr(argv[2], argv[3], argv[4], len, 0) < 0) { puts_("schattr: set failed\n"); exit(); } exit(); } if (streq(argv[1], "get") && argc == 4) { char val[256]; int n = getxattr(argv[2], argv[3], val, sizeof(val) - 1); if (n < 0) { puts_("schattr: no such attribute\n"); exit(); } val[n] = '\0'; puts_(val); puts_("\n"); exit(); } if (streq(argv[1], "rm") && argc == 4) { if (removexattr(argv[2], argv[3]) < 0) { puts_("schattr: remove failed\n"); exit(); } exit(); } if (streq(argv[1], "index") && argc == 3) { if (schfs_index(argv[2]) < 0) { puts_("schattr: could not create the index\n"); exit(); } puts_("schattr: indexing "); puts_(argv[2]); puts_(" from now on\n"); exit(); } if (streq(argv[1], "find") && argc == 4) { unsigned long long ids[64]; int n = schfs_query(argv[2], argv[3], ids, 64); if (n < 0) { puts_("schattr: no index on "); puts_(argv[2]); puts_(" -- declare one with `schattr index` first\n"); exit(); } putn_((unsigned long long)n); puts_(n == 1 ? " object:\n" : " objects:\n"); for (int i = 0; i < n; i++) { puts_(" #"); putn_(ids[i]); puts_("\n"); } exit(); } puts_("schattr: bad usage\n"); exit(); }