M system-v2/nix-sys/.gitignore.do => system-v2/nix-sys/.gitignore.do +2 -0
@@ 5,6 5,8 @@ redo-targets | sed 's/..//' > $3
cat << EOF >> $3
.gitignore
.dep.*
+.depend.*
+.target.*
.lock.*
index.cdb
config.h
A system-v2/nix-sys/chattr/disable.c => system-v2/nix-sys/chattr/disable.c +2 -0
@@ 0,0 1,2 @@
+int immutable_on(const char *_path) { return 0; }
+int immutable_off(const char *_path) { return 0; }
A system-v2/nix-sys/chattr/enable.c => system-v2/nix-sys/chattr/enable.c +35 -0
@@ 0,0 1,35 @@
+#include <linux/fs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+static int fssetflags(int fd, unsigned int flags)
+{
+ return ioctl(fd, FS_IOC_SETFLAGS, (void*)&flags);
+}
+
+static int path_setattrs(const char *path, unsigned int flags)
+{
+ int fd;
+ int err;
+
+ fd = open(path, O_NONBLOCK|O_RDONLY);
+ if (fd < 0)
+ return 1;
+ err = fssetflags(fd, flags);
+ close(fd);
+
+ return err;
+}
+
+int immutable_on(const char *path)
+{
+ return path_setattrs(path, FS_IMMUTABLE_FL);
+}
+
+int immutable_off(const char *path)
+{
+ return path_setattrs(path, 0);
+}
A system-v2/nix-sys/default.h.do => system-v2/nix-sys/default.h.do +7 -0
@@ 0,0 1,7 @@
+#!/bin/sh -eu
+feature=$(cat conf/feature-$2)
+src="$2/$feature.c"
+
+redo-ifchange $src conf/feature-$2
+
+cproto -qe < $src > $3
M system-v2/nix-sys/default.nix => system-v2/nix-sys/default.nix +6 -4
@@ 1,12 1,13 @@
-{ stdenv, tinycdb, nix-sys-generate, redo-c, manifest ? {} }:
+{ stdenv, tinycdb, nix-sys-generate, manifest ? { }, redo-c, cproto
+, linuxHeaders ? null }:
assert manifest != null;
let
in stdenv.mkDerivation {
name = "nix-sys";
src = ./.;
outputs = [ "out" "cdb" ];
- nativeBuildInputs = [ nix-sys-generate redo-c ];
- buildInputs = [ tinycdb ];
+ nativeBuildInputs = [ nix-sys-generate redo-c cproto ];
+ buildInputs = [ tinycdb linuxHeaders ];
configurePhase = ''
mkdir conf
echo $out > conf/out
@@ 14,6 15,8 @@ in stdenv.mkDerivation {
echo "$manifest" > conf/manifest
echo "${stdenv.cc.targetPrefix}cc -static -O2" > conf/cc
echo "${stdenv.cc.targetPrefix}cc" > conf/ld
+ echo "${if linuxHeaders != null then "enable" else "disable"}" \
+ > conf/feature-chattr
'';
buildPhase = "redo";
installPhase = ''
@@ 24,4 27,3 @@ in stdenv.mkDerivation {
postFixup = "rm -fr $out/nix-support";
manifest = builtins.toJSON manifest;
}
-
M system-v2/nix-sys/default.o.do => system-v2/nix-sys/default.o.do +11 -2
@@ 1,4 1,13 @@
#!/bin/sh -eu
cc=$(cat conf/cc)
-redo-ifchange conf/cc generate $2.c
-$cc $2.c -c -o $3
+redo-ifchange conf/cc generate chattr.h
+
+if [ -e "$2.c" ] ; then
+ src="$2.c"
+else
+ redo-ifchange "conf/feature-$2"
+ src="$2/$(cat conf/feature-$2).c"
+fi
+
+redo-ifchange "$src"
+$cc "$src" -c -o $3
M system-v2/nix-sys/main.c => system-v2/nix-sys/main.c +11 -0
@@ 8,6 8,8 @@
#include <unistd.h>
#include <stdio.h>
+#include "chattr.h"
+
struct copy_a {
const char *source;
const char *tmp;
@@ 263,7 265,16 @@ int main(int argc, char **argv)
write2("renaming copy into ");
write2_s(obj->destination);
write2("... ");
+
+ /* Make file immutable (chattr +i) so it can't be
+ * modified by mistake. Linux-only.
+ *
+ * TODO: Check errors properly.
+ */
+ (void) immutable_off(obj->destination);
err = rename(obj->tmp, obj->destination);
+ (void) immutable_on(obj->destination);
+
if (err) {
write2("fail\n");
return 1;
M system-v2/nix-sys/nix-sys.do => system-v2/nix-sys/nix-sys.do +1 -1
@@ 1,5 1,5 @@
#!/bin/sh -eu
ld=$(cat conf/ld)
-objs="main.o"
+objs="main.o chattr.o"
redo-ifchange conf/ld $objs
$ld $objs -lcdb -o $3