msys2 / MSYS2-packages

Package scripts for MSYS2.

Home Page:https://packages.msys2.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

add a script to clean up files "binned" by msys2-runtime

jeremyd2019 opened this issue · comments

Updating core packages (specifically pacman.exe and msys-2.0.dll I think) results in oddly-named files in the "recycle bin" directory (see https://github.com/msys2/msys2-runtime/blob/abcb3c6c0f330ac7568956b2be6bf3376517bb56/winsup/cygwin/syscalls.cc#L342). These files don't ever seem to get cleaned up, or indeed result as showing anything in the UI recycle bin. Hence, there should be some way to clean them up.

I made a simple script to do this (https://gist.github.com/jeremyd2019/4984ff0fa1f6fd8c99d7b8b244c52088)

#!/bin/bash -e

shopt -s nullglob

root="$(cygpath -w /)"
root="$(cygpath -u "${root:0:2}")"

trash=("${root}/\$Recycle.Bin/S-1-"*/$'.\355\261\255'*)

if (( ${#trash[@]} )); then
  ls -la "${trash[@]}"
  read -r -p "Remove? (y/N) "

  if [[ "${REPLY^^}" == "Y" ]]; then
    rm -f "${trash[@]}"
  fi
fi

This script wouldn't work right if the root of the volume is not the drive letter (like, a volume mounted on a directory). Maybe some other edge cases

I don't know where this should live though (filesystem? maybe pacman-contrib just because I associate this with paccache for regular cleanup operations).

Another idea that I keep thinking of is, if the file absolutely cannot be deleted, maybe msys2-runtime could register it for deletion on reboot (with MoveFileEx with lpNewFileName NULL and MOVEFILE_DELAY_UNTIL_REBOOT flag). But I figure somebody would have tried that in cygwin at some point already...

Updating core packages results in oddly-named files in the "recycle bin" directory

I have not seen files in recycle bin related to msys2 or cygwin since first time using them.

Try the script (or the pattern from the script, usually ls -l /c/\$Recycle.Bin/S-1-*/$'.\355\261\255'*). They don't show up in the Windows UI for the recycle bin, so it's not at all obvious that they're there

Could you provide any example output of that command? I have only desktop.ini files in there and could try to reproduce the issue with a new msys2 installation.

I was actually just stepping through the cygwin code in gdb, so I have a bit of a standalone reproducer:

cp /usr/bin/sleep.exe .
./sleep 1000 &
rm -f sleep.exe
ls -la /d/\$Recycle.Bin/S-1-*/$'.\355\261\255'*
-rwxr-xr-x 1 XXX None 36003 May 26 23:05 '/d/$Recycle.Bin/S-1-5-21-XXX/.'$'\355\261\255\355\261\263\355\261\271\355\261\263''300000000017db0aa9908ed6033f1264'

I can reproduce the issue with that command. Here is an example of those weird file. /f is the partition where msys2 was installed for testing.

$ tree -a /f/\$RECYCLE.BIN/
/f/$RECYCLE.BIN/
└── S-1-5-21-1390408910-2694286881-1732342665-1001
    ├── .\156155\156163\156171\156163006e00000003d55a67694fe0c9892f4e
    ├── .\156155\156163\156171\156163006f0000000398cd92cba531c0fd489f
    ├── .\156155\156163\156171\15616300ba0000000383b3e888f6746f72d25f
    └── desktop.ini

Nice work btw, jeremy ❤️

Another idea that I keep thinking of is, if the file absolutely cannot be deleted, maybe msys2-runtime could register it for deletion on reboot (with MoveFileEx with lpNewFileName NULL and MOVEFILE_DELAY_UNTIL_REBOOT flag). But I figure somebody would have tried that in cygwin at some point already...

As I kind of expected, docs suggest MOVEFILE_DELAY_UNTIL_REBOOT only works from an elevated context. Maybe something in cygwin could try to delete these files on future startups? Or a script in /etc/profile.d to clean them up on future shell launches, but I am concerned that it could be impossible for a script to find the correct recycle.bin directory in every edge case that cygwin tries to handle.

I've been considering this more, and trying to figure out how to replicate what cygwin does to find the recycle bin. The hardest part to script seems to be to get a list of volume mount points. This is what I've come up with so far:

mountvol |
sed -ne '/^Possible values for VolumeName/,${/^\s\{8\}/{s///;/^\*\*\*/!p}}' |
cygpath -uf - |
xargs -i find '{}' -maxdepth 1 -iname '$Recycle.Bin' -print0 |
find -files0-from - -maxdepth 2 -name $'.\uDC6D\uDC73\uDC79\uDC73*' -o -name '.msys*'

Allowing for making a C utility to get the volume mount points as \0-delimited cygwin paths (https://gist.github.com/jeremyd2019/8e088a72dfef44ee29ed3442957c1e65), this becomes:

./volumes |
find -files0-from - -maxdepth 1 -iname '$Recycle.Bin' -print0 |
find -files0-from - -maxdepth 2 -name $'.\uDC6D\uDC73\uDC79\uDC73*' -o -name '.msys*'

(for the record, on upstream cygwin the names would be -name $'.\uDC63\uDC79\uDC67*' -o -name '.cyg*')