metropolis/node/build: prepare fsspec for use in initramfs

This moves fsspec up into the node build directory as it's going to be
used in multiple tools (like mkinitcpio) in the future. It also adds
special files support to it as that's going to be required at least for
initramfs support but it may prove useful for erofs as well.

Change-Id: I8d559bb761b4da350c0070b23b5ab393ba6e9872
Reviewed-on: https://review.monogon.dev/c/monogon/+/521
Reviewed-by: Sergiusz Bazanski <serge@monogon.tech>
diff --git a/metropolis/node/build/mkerofs/fsspec/BUILD.bazel b/metropolis/node/build/fsspec/BUILD.bazel
similarity index 60%
rename from metropolis/node/build/mkerofs/fsspec/BUILD.bazel
rename to metropolis/node/build/fsspec/BUILD.bazel
index bd0f036..3a65d97 100644
--- a/metropolis/node/build/mkerofs/fsspec/BUILD.bazel
+++ b/metropolis/node/build/fsspec/BUILD.bazel
@@ -8,23 +8,16 @@
     visibility = ["//visibility:public"],
 )
 
-go_proto_library(
-    name = "spec_go_proto",
-    importpath = "source.monogon.dev/metropolis/node/build/mkerofs/spec",
-    proto = ":spec_proto",
-    visibility = ["//visibility:public"],
-)
-
 go_library(
     name = "go_default_library",
     embed = [":fsspec_go_proto"],
-    importpath = "source.monogon.dev/metropolis/node/build/mkerofs/fsspec",
+    importpath = "source.monogon.dev/metropolis/node/build/fsspec",
     visibility = ["//visibility:public"],
 )
 
 go_proto_library(
     name = "fsspec_go_proto",
-    importpath = "source.monogon.dev/metropolis/node/build/mkerofs/fsspec",
+    importpath = "source.monogon.dev/metropolis/node/build/fsspec",
     proto = ":spec_proto",
     visibility = ["//visibility:public"],
 )
diff --git a/metropolis/node/build/mkerofs/fsspec/spec.proto b/metropolis/node/build/fsspec/spec.proto
similarity index 74%
rename from metropolis/node/build/mkerofs/fsspec/spec.proto
rename to metropolis/node/build/fsspec/spec.proto
index 3d6e8dc..712de1c 100644
--- a/metropolis/node/build/mkerofs/fsspec/spec.proto
+++ b/metropolis/node/build/fsspec/spec.proto
@@ -16,8 +16,8 @@
 
 syntax = "proto3";
 
-package metropolis.node.build.mkerofs.fsspec;
-option go_package = "source.monogon.dev/metropolis/node/build/mkerofs/fsspec";
+package metropolis.node.build.fsspec;
+option go_package = "source.monogon.dev/metropolis/node/build/fsspec";
 
 // FSSpec is the spec from which a filesystem is generated. It consists of files, directories and symbolic
 // links. Directories are also automatically inferred when required for the placement of files or symbolic
@@ -27,6 +27,7 @@
   repeated File file = 1;
   repeated Directory directory = 2;
   repeated SymbolicLink symbolic_link = 3;
+  repeated SpecialFile special_file = 4;
 }
 
 // For internal use only. Represents all supported inodes in a oneof.
@@ -35,6 +36,7 @@
     File file = 1;
     Directory directory = 2;
     SymbolicLink symbolic_link = 3;
+    SpecialFile special_file = 4;
   }
 }
 
@@ -67,4 +69,30 @@
   string path = 1;
   // The path to which the symbolic link resolves to.
   string target_path = 2;
+}
+
+message SpecialFile {
+  // The path where the special file ends up in the filesystem.
+  string path = 1;
+
+  enum Type {
+    CHARACTER_DEV = 0;
+    BLOCK_DEV = 1;
+    FIFO = 2;
+  }
+
+  // Type of special file.
+  Type type = 2;
+
+  // The major device number of the special file.
+  uint32 major = 3;
+  // The minor number of the special file. Ignored for FIFO-type special files.
+  uint32 minor = 4;
+
+  // Unix permission bits
+  uint32 mode = 5;
+  // Owner uid
+  uint32 uid = 6;
+  // Owner gid
+  uint32 gid = 7;
 }
\ No newline at end of file
diff --git a/metropolis/node/build/mkerofs/BUILD.bazel b/metropolis/node/build/mkerofs/BUILD.bazel
index 6de1c73..3cbcbde 100644
--- a/metropolis/node/build/mkerofs/BUILD.bazel
+++ b/metropolis/node/build/mkerofs/BUILD.bazel
@@ -6,7 +6,7 @@
     importpath = "source.monogon.dev/metropolis/node/build/mkerofs",
     visibility = ["//visibility:public"],
     deps = [
-        "//metropolis/node/build/mkerofs/fsspec:go_default_library",
+        "//metropolis/node/build/fsspec:go_default_library",
         "//metropolis/pkg/erofs:go_default_library",
         "@com_github_golang_protobuf//proto:go_default_library",
     ],
diff --git a/metropolis/node/build/mkerofs/main.go b/metropolis/node/build/mkerofs/main.go
index d4e9d4d..651096b 100644
--- a/metropolis/node/build/mkerofs/main.go
+++ b/metropolis/node/build/mkerofs/main.go
@@ -30,7 +30,7 @@
 
 	"github.com/golang/protobuf/proto"
 
-	"source.monogon.dev/metropolis/node/build/mkerofs/fsspec"
+	"source.monogon.dev/metropolis/node/build/fsspec"
 	"source.monogon.dev/metropolis/pkg/erofs"
 )
 
@@ -161,6 +161,10 @@
 		entryRef.data.Type = &fsspec.Inode_SymbolicLink{SymbolicLink: symlink}
 	}
 
+	if len(spec.SpecialFile) > 0 {
+		log.Fatalf("special files are currently unimplemented in mkerofs")
+	}
+
 	fs, err := os.Create(*outPath)
 	if err != nil {
 		log.Fatalf("failed to open output file: %v", err)