filed
Job queue using FUSE
git clone git://mccd.space/filed
| Log | Files | Refs | README | LICENSE |
commit ebd1b1342664e2d3f08d47a07558c6b479282af0 parent 1fbbb1875bc27b42e8f4608e46991c8932469479 Author: Marc Coquand <marc@coquand.email> Date: Mon, 15 Dec 2025 10:55:15 +0100 Add the start of file metadata Diffstat:
| A | setfattr.go | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
| A | store/filemeta.go | | | 44 | ++++++++++++++++++++++++++++++++++++++++++++ |
| M | store/jobs.go | | | 8 | +++++++- |
3 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/setfattr.go b/setfattr.go
@@ -0,0 +1,38 @@
+package main
+
+import (
+ "context"
+ "log/slog"
+ "os"
+ "qj/store"
+ "syscall"
+
+ "bazil.org/fuse"
+)
+
+func Setattr(store *store.Store, meta *store.FileMeta, content []byte, inode uint64, ctx context.Context, req *fuse.SetattrRequest, resp *fuse.SetattrResponse) error {
+ if req.Valid.Mode() {
+ meta.Mode = uint32(req.Mode)
+ }
+
+ if req.Valid.Uid() {
+ meta.UID = req.Uid
+ }
+
+ if req.Valid.Gid() {
+ meta.GID = req.Gid
+ }
+
+ if err := store.UpsertFileMeta(*meta); err != nil {
+ slog.Error("STORE: Failed to save metadata", "error", err)
+ return syscall.EIO
+ }
+
+ resp.Attr.Inode = meta.Inode
+ resp.Attr.Mode = os.FileMode(meta.Mode)
+ resp.Attr.Uid = meta.UID
+ resp.Attr.Gid = meta.GID
+ resp.Attr.Size = uint64(len(content))
+
+ return nil
+}
diff --git a/store/filemeta.go b/store/filemeta.go
@@ -0,0 +1,44 @@
+package store
+
+import (
+ "database/sql"
+)
+
+// FileMeta holds standard POSIX file attributes
+type FileMeta struct {
+ Inode uint64
+ Mode uint32
+ UID uint32
+ GID uint32
+}
+
+// Returns file metadata, if it exists.
+func (st *Store) GetFileMeta(inode uint64) (m *FileMeta, err error) {
+ query := `
+ SELECT inode, mode, uid, gid
+ FROM file_meta
+ WHERE inode = ?
+ `
+ err = st.db.QueryRow(query, inode).Scan(&m.Inode, &m.Mode, &m.UID, &m.GID)
+ if err == sql.ErrNoRows {
+ // No metadata exists, that's ok
+ return nil, nil
+ }
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (st *Store) UpsertFileMeta(meta FileMeta) error {
+ query := `
+ INSERT INTO file_meta (inode, mode, uid, gid)
+ VALUES (?, ?, ?, ?)
+ ON CONFLICT(inode) DO UPDATE SET
+ mode = excluded.mode,
+ uid = excluded.uid,
+ gid = excluded.gid
+ `
+ _, err := st.db.Exec(query, meta.Inode, meta.Mode, meta.UID, meta.GID)
+ return err
+}
diff --git a/store/jobs.go b/store/jobs.go
@@ -65,6 +65,7 @@ func (s *Store) initSchema() error {
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
+ CREATE INDEX IF NOT EXISTS idx_state ON jobs(state);
CREATE TABLE IF NOT EXISTS config (
id INTEGER PRIMARY KEY CHECK (id = 0),
max_attempts INTEGER DEFAULT 3,
@@ -80,8 +81,13 @@ func (s *Store) initSchema() error {
SET inode = (SELECT IFNULL(MAX(inode), 0) + 1 FROM jobs)
WHERE id = new.id;
END;
+ CREATE TABLE IF NOT EXISTS file_meta (
+ inode INTEGER PRIMARY KEY,
+ mode INTEGER,
+ uid INTEGER,
+ gid INTEGER
+ );
- CREATE INDEX IF NOT EXISTS idx_state ON jobs(state);
`
_, err := s.db.Exec(query)
return err