SchOS/cmd/schattr/main.c
Nexoniarz a1c965da1e include: one folder per subsystem, and includes that name it
Sixty-five headers sat side by side in include/, so `#include "irq.h"`
said nothing about where irq.h was or what it belonged to, and errno.h,
stat.h and fcntl.h at the top shadowed the system's for any host tool
built with -I./include. They are in folders now -- arch/ core/ fs/
dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and
every include names the folder, as Linux's do: "core/proc.h".

Done mechanically and checked the hard way: the kernel built from this
tree disassembles identically to the one built from the tree before
it. The full image boots, and userland is the same set of programs.
Paths in docs and comments follow; docs/guides/layout.md has a table
of what is where, and tools/fix-includes.py rewrites old-style
includes from the folders in the tree, for code written before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
2026-10-23 15:05:12 +02:00

116 lines
3.2 KiB
C

// schattr -- attach metadata to files, and ask the filesystem about it.
//
// schattr set <file> <name> <value> attach a value
// schattr get <file> <name> read it back
// schattr rm <file> <name> remove it
// schattr index <name> start indexing that attribute
// schattr find <name> <value> 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 <file> <name> [value]\n");
puts_(" schattr index <name>\n");
puts_(" schattr find <name> <value>\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();
}