diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 21f74b5f..be2a5f22 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -69,8 +69,9 @@ jobs: run: | tar xzf try-dist.tgz/try-*.tgz --strip-components=1 rm -r try-dist.tgz - ./configure + ./configure --disable-utils make all + sudo make install - name: Run tests with shell fallbacks run: | @@ -78,8 +79,15 @@ jobs: ! which try-commit scripts/run_tests.sh + - name: Clean up build + run: | + sudo make clean + - name: Install utilities run: | + autoconf + ./configure + make all sudo make install - name: Run tests with utilities @@ -116,8 +124,9 @@ jobs: - name: Configure and build utilities run: | autoconf - ./configure + ./configure --disable-utils make all + sudo make install - name: Run tests with shell fallbacks run: | @@ -125,8 +134,15 @@ jobs: ! which try-commit scripts/run_tests.sh + - name: Clean up build + run: | + sudo make clean + - name: Install utilities run: | + autoconf + ./configure + make all sudo make install - name: Run tests with utilities diff --git a/Makefile.in b/Makefile.in index 507b32d5..c08f7226 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,13 +16,14 @@ INSTALL=@INSTALL@ DISTDIR=@PACKAGE_TARNAME@-@PACKAGE_VERSION@ DISTTGZ=$(DISTDIR).tgz -TARGETS=$(if $(findstring yes,@enable_utils@),utils/try-summary utils/try-commit) man/try.1.gz +TARGETS=utils/make-socket $(if $(findstring yes,@enable_utils@),utils/try-summary utils/try-commit) man/try.1.gz all: $(TARGETS) install: $(TARGETS) $(INSTALL) -d $(bindir) $(INSTALL) -m 755 try $(bindir) + $(INSTALL) -m 755 utils/make-socket $(bindir) ifeq (@enable_utils@, yes) $(INSTALL) -m 755 utils/try-summary $(bindir) $(INSTALL) -m 755 utils/try-commit $(bindir) @@ -58,7 +59,10 @@ utils/try-summary: utils/ignores.o utils/try-summary.o utils/try-commit: utils/ignores.o utils/try-commit.o $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -g $^ -test: try $(if $(findstring yes,@enable_utils@),utils/try-summary utils/try-commit) +utils/make-socket: utils/make-socket.o + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -g $^ + +test: try $(if $(findstring yes,@enable_utils@),utils/try-summary utils/try-commit) utils/make-socket scripts/run_tests.sh lint: diff --git a/Vagrantfile b/Vagrantfile index 0119e767..20266d69 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -13,9 +13,14 @@ Vagrant.configure("2") do |config| sudo apt-get update sudo apt-get install -y git expect curl attr pandoc gcc make autoconf mergerfs sudo chown -R vagrant:vagrant try + sudo modprobe overlay cd try + autoconf && ./configure --disable-utils && make + sudo make install scripts/run_tests.sh + sudo make clean + autoconf && ./configure && make sudo make install which try-commit || exit 2 @@ -78,10 +83,15 @@ Vagrant.configure("2") do |config| # This is intentional, if we moved try to lv1 it'd work since itself does not contain a nested mount sudo mv /home/vagrant/try /mnt/lv0 sudo chown -R vagrant:vagrant /mnt/lv0/try + sudo modprobe overlay cd /mnt/lv0/try + autoconf && ./configure --disable-utils && make + sudo make install scripts/run_tests.sh + sudo make clean + autoconf && ./configure && make sudo make install which try-commit || exit 2 @@ -97,6 +107,7 @@ Vagrant.configure("2") do |config| sudo apt-get update sudo apt-get install -y curl attr pandoc gcc make autoconf mergerfs zsh sudo chown -R vagrant:vagrant try + sudo modprobe overlay cd try @@ -149,8 +160,15 @@ Vagrant.configure("2") do |config| wget https://github.com/trapexit/mergerfs/releases/download/2.40.2/mergerfs-2.40.2-1.el9.x86_64.rpm sudo rpm -i mergerfs-2.40.2-1.el9.x86_64.rpm sudo chown -R vagrant:vagrant try + sudo modprobe overlay cd try + + autoconf && ./configure --disable-utils && make + sudo make install TRY_TOP=$(pwd) scripts/run_tests.sh + + sudo make clean + autoconf && ./configure && make sudo make install which try-commit || exit 2 @@ -167,8 +185,15 @@ Vagrant.configure("2") do |config| wget https://github.com/trapexit/mergerfs/releases/download/2.40.2/mergerfs-2.40.2-1.fc39.x86_64.rpm sudo rpm -i mergerfs-2.40.2-1.fc39.x86_64.rpm sudo chown -R vagrant:vagrant try + sudo modprobe overlay cd try + + autoconf && ./configure --disable-utils && make + sudo make install TRY_TOP=$(pwd) scripts/run_tests.sh + + sudo make clean + autoconf && ./configure && make sudo make install which try-commit || exit 2 diff --git a/configure.ac b/configure.ac index 82841b5a..16882078 100644 --- a/configure.ac +++ b/configure.ac @@ -10,21 +10,21 @@ AC_ARG_ENABLE([utils], [don't compile C utilities for summarizing and committing changes (default is yes)])], [enable_utils=${enableval}], [enable_utils=yes]) + +AC_REQUIRE_AUX_FILE([utils/make-socket.c]) + +# build tools +AC_PROG_CC + +# CFLAGS AND CPPFLAGGS +AUTO_CFLAGS="" +AUTO_CPPFLAGS="" + if test "$enable_utils" = "yes" then AC_REQUIRE_AUX_FILE([utils/try-commit.c]) - # build tools - AC_PROG_CC - - # CFLAGS and CPPFLAGGS - if test -z "$CFLAGS" - then - AUTO_CFLAGS="-g -Wall -O2" - else - AUTO_CFLAGS="" - fi - AUTO_CPPFLAGS="" + AUTO_CPPFLAGS="" CFLAGS=${CFLAGS-"$AUTO_CFLAGS"} CPPFLAGS=${CPPFLAGS-"$AUTO_CPPFLAGS"} diff --git a/package.nix b/package.nix index 8bc594db..f2276dc1 100644 --- a/package.nix +++ b/package.nix @@ -35,6 +35,7 @@ stdenv.mkDerivation { install -Dt $out/bin try install -Dt $out/bin utils/try-commit install -Dt $out/bin utils/try-summary + install -Dt $out/bin utils/make-socket wrapProgram $out/bin/try --prefix PATH : ${ lib.makeBinPath [ coreutils diff --git a/scripts/check_trycase.sh b/scripts/check_trycase.sh index 6471a864..e34a4645 100755 --- a/scripts/check_trycase.sh +++ b/scripts/check_trycase.sh @@ -38,7 +38,7 @@ check_file() { lf="${lf%)}" case "$cf" in - (file|dir|symlink|nonexist|opaque|whiteout);; + (file|dir|symlink|nonexist|opaque|whiteout|fifo|socket);; (*) printf "ERROR: $1: invalid changed file: %s\n" "$cf" : $((ERRORS += 1)) ;; diff --git a/test/all-commit-cases.sh b/test/all-commit-cases.sh index 852efd1c..bdfef0e8 100755 --- a/test/all-commit-cases.sh +++ b/test/all-commit-cases.sh @@ -224,3 +224,90 @@ echo arrivederci >formerdir/it/file2 || fail [ -L formerdir ] || fail [ "$(readlink formerdir)" = "/this/is/a/broken/symlink" ] || fail rm formerdir || fail + +# // TRYCASE(fifo, file) + +: $((COUNT += 1)) + +! [ -e newpipe ] || fail +"$TRY" -y "touch newpipe; echo new >newpipe" +[ -f newpipe ] || fail +[ "$(cat newpipe)" = "new" ] || fail +"$TRY" -y "rm newpipe; mkfifo newpipe" +[ -p newpipe ] || fail +rm newpipe + +# // TRYCASE(fifo, dir) + +: $((COUNT += 1)) + +! [ -e newpipe ] || fail +"$TRY" -y "mkdir newpipe" +[ -d newpipe ] || fail +"$TRY" -y "rm -r newpipe; mkfifo newpipe" +[ -p newpipe ] || fail +rm newpipe + +# // TRYCASE(fifo, symlink) + +: $((COUNT += 1)) + +! [ -e newpipe ] || fail +ln -s "$TRY" newpipe +[ -L newpipe ] || fail +"$TRY" -y "rm newpipe; mkfifo newpipe" +[ -p newpipe ] || fail +rm newpipe + +# // TRYCASE(fifo, nonexist) + +: $((COUNT += 1)) + +! [ -e newpipe ] || fail +"$TRY" -y "mkfifo newpipe" +[ -p newpipe ] || fail +rm newpipe + +# // TRYCASE(socket, file) + +: $((COUNT += 1)) + +! [ -e newsock ] || fail +"$TRY" -y "touch newsock; echo hello> newsock" +[ -f newsock ] || fail +[ "$(cat newsock)" = "hello" ] || fail +"$TRY" -y "rm newsock; make-socket newsock" +[ -S newsock ] || fail +rm newsock + +# // TRYCASE(socket, dir) + +: $((COUNT += 1)) + +! [ -e newsock ] || fail +"$TRY" -y "mkdir newsock" +[ -d newsock ] || fail +"$TRY" -y "rm -r newsock; make-socket newsock" +[ -S newsock ] || fail +rm newsock + +# // TRYCASE(socket, symlink) + +: $((COUNT += 1)) + +! [ -e newsock ] || fail +ln -s "$TRY" newsock +[ -L newsock ] || fail +"$TRY" -y "rm newsock; make-socket newsock" +! [ -e newlink ] || fail +[ -S newsock ] || fail +rm newsock + +# // TRYCASE(socket, nonexist) + +: $((COUNT += 1)) + +! [ -e newsock ] +"$TRY" -y "make-socket newsock" +[ -S newsock ] || fail +rm newsock diff --git a/try b/try index de6ef4a3..75d321e8 100755 --- a/try +++ b/try @@ -45,7 +45,6 @@ set_TRY_SHELL() { export TRY_SHELL } - ################################################################################ # Run a command (in `$@`) in an overlay (in `$SANDBOX_DIR`) ################################################################################ @@ -249,7 +248,7 @@ do ## NB $mountpoint is the local directory to mount ## $merger_dir is where we'll put its merger "$UNION_HELPER" "$mountpoint" "$merger_dir" 2>>"$try_mount_log" || - printf "%s: Warning: Failed mounting $mountpoint via $UNION_HELPER, see \"$try_mount_log\"\n" "$TRY_COMMAND" >&2 + printf "%s: Warning: Failed mounting $mountpoint via $UNION_HELPER, see \"$try_mount_log\"\n" "$TRY_COMMAND" >&2 make_overlay "$SANDBOX_DIR" "$merger_dir" "$pure_mountpoint" 2>>"$try_mount_log" || printf "%s: Warning: Failed mounting $mountpoint as an overlay via $UNION_HELPER, see \"$try_mount_log\"\n" "$TRY_COMMAND" >&2 fi @@ -458,7 +457,7 @@ find_upperdir_changes() { sandbox_dir="$1" ignore_file="$2" - find "$sandbox_dir/upperdir/" -type f -o \( -type c -size 0 \) -o -type d -o -type l | ignore_changes "$ignore_file" + find "$sandbox_dir/upperdir/" | ignore_changes "$ignore_file" } ################################################################################ @@ -514,13 +513,12 @@ process_changes() { echo "rd $local_file" continue fi - # must be a directory, but not opaque---leave it! elif [ -c "$changed_file" ] && ! [ -s "$changed_file" ] && [ "$(stat -c %t,%T "$changed_file")" = "0,0" ] then # // TRYCASE(whiteout, *) echo "de $local_file" - elif [ -f "$changed_file" ] + elif [ -f "$changed_file" ] || [ -p "$changed_file" ] || [ -S "$changed_file" ] then if [ -f "$changed_file" ] && getfattr --absolute-names -d "$changed_file" 2>/dev/null | grep -q -e "user.overlay.whiteout" then @@ -534,11 +532,25 @@ process_changes() { # // TRYCASE(file, file) # // TRYCASE(file, dir) # // TRYCASE(file, symlink) + # // TRYCASE(fifo, file) + # // TRYCASE(fifo, dir) + # // TRYCASE(fifo, symlink) + # // TRYCASE(socket, file) + # // TRYCASE(socket, dir) + # // TRYCASE(socket, symlink) echo "mo $local_file" + continue else # // TRYCASE(file, nonexist) + # // TRYCASE(fifo, nonexist) + # // TRYCASE(socket, nonexist) echo "ad $local_file" + continue fi + # // TRYCASE(fifo, *) + # // TRYCASE(socket, *) + echo "ad $local_file" + continue fi done < +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + int sockfd; + struct sockaddr_un addr; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + const char *socket_name= argv[1]; + + sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (sockfd == -1) { + perror("socket"); + exit(EXIT_FAILURE); + } + + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path) - 1); + + if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) { + perror("bind"); + close(sockfd); + exit(EXIT_FAILURE); + } + + close(sockfd); + + return 0; +} + diff --git a/utils/try-commit.c b/utils/try-commit.c index 986c718a..b17dcd76 100644 --- a/utils/try-commit.c +++ b/utils/try-commit.c @@ -256,6 +256,25 @@ int main(int argc, char *argv[]) { break; case FTS_DEFAULT: + + if (S_ISFIFO(ent->fts_statp->st_mode) || (S_ISSOCK(ent->fts_statp->st_mode))) { + + if (local_exists) { + // TRYCASE(fifo, file) + // TRYCASE(fifo, dir) + // TRYCASE(fifo, symlink) + // TRYCASE(socket, file) + // TRYCASE(socket, dir) + // TRYCASE(socket, symlink) + remove_local(local_file, local_exists, &local_stat); + } + + // TRYCASE(fifo, nonexist) + // TRYCASE(socket, nonexist) + commit(ent->fts_path, local_file); + break; + } + if (S_ISCHR(ent->fts_statp->st_mode) && ent->fts_statp->st_size == 0) { struct statx statxp; if (statx(AT_FDCWD, ent->fts_path, 0, STATX_TYPE | STATX_INO, &statxp) == -1) { diff --git a/utils/try-summary.c b/utils/try-summary.c index 3bccf19c..d40e8a1c 100644 --- a/utils/try-summary.c +++ b/utils/try-summary.c @@ -145,6 +145,7 @@ int main(int argc, char *argv[]) { // nothing of interest! directory got made, but modifications must be inside break; + case FTS_F: // regular file if (getxattr(ent->fts_path, "user.overlay.whiteout", NULL, 0) != -1) { // TRYCASE(whiteout, *) @@ -171,6 +172,26 @@ int main(int argc, char *argv[]) { break; case FTS_DEFAULT: + + if (S_ISFIFO(ent->fts_statp->st_mode) || S_ISSOCK(ent->fts_statp->st_mode)) { + + if(local_exists) { + // TRYCASE(fifo, file) + // TRYCASE(fifo, dir) + // TRYCASE(fifo, symlink) + // TRYCASE(socket, file) + // TRYCASE(socket, dir) + // TRYCASE(socket, symlink) + show_change(local_file, "modified"); + break; + } + + // TRYCASE(fifo, nonexist) + // TRYCASE(socket, nonexist) + show_change(local_file, "added"); + break; + } + if (S_ISCHR(ent->fts_statp->st_mode) && ent->fts_statp->st_size == 0) { struct statx statxp; if (statx(AT_FDCWD, ent->fts_path, 0, STATX_TYPE | STATX_INO, &statxp) == -1) {