Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ jobs:
# extra RAM for the mfs-backed TMPDIR, see the openbsd test step
memory: 12G
- os: haiku
version: 'r1beta5'
version: 'r1beta6'
display_name: Haiku
do_binaries: false

Expand All @@ -327,7 +327,7 @@ jobs:

- name: Test on ${{ matrix.display_name }}
id: cross_os
uses: cross-platform-actions/action@v1.4.0
uses: cross-platform-actions/action@v1.5.0
env:
DO_BINARIES: ${{ matrix.do_binaries }}
with:
Expand Down Expand Up @@ -442,24 +442,47 @@ jobs:
;;
haiku)
pkgman refresh
pkgman install -y git pkgconfig zstd lz4 xxhash
pkgman install -y openssl3
# already installed:
# pkgman install -y git pkgconfig lz4 openssl3
pkgman install -y lz4_devel zstd_devel xxhash_devel openssl3_devel
pkgman install -y rust_bin
pkgman install -y python3.10
pkgman install -y cffi
pkgman install -y lz4_devel zstd_devel xxhash_devel openssl3_devel libffi_devel

# there is no pkgman package for tox, so we install it into a venv
python3 -m ensurepip --upgrade
python3 -m pip install --upgrade pip wheel
python3 -m venv .venv
. .venv/bin/activate

export PKG_CONFIG_PATH="/system/develop/lib/pkgconfig:/system/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
export BORG_LIBLZ4_PREFIX=/system/develop
export BORG_LIBZSTD_PREFIX=/system/develop
export BORG_LIBXXHASH_PREFIX=/system/develop
export BORG_OPENSSL_PREFIX=/system/develop
pip install -r requirements.d/development.txt
pip install -e .

# this VM corrupts data every now and then: rustc crashed on crate metadata it
# had written itself ("assertion failed: bytes[len] == STR_SENTINEL") and pip
# found sha256 mismatches reading big wheels back from its own cache. Build
# outside /boot/system/cache/tmp (haiku's /tmp) and run one rustc at a time,
# in case that corruption comes from disk or memory pressure.
export TMPDIR=/boot/home/borg-tmp
mkdir -p "$TMPDIR"
export CARGO_TARGET_DIR="$TMPDIR/cargo-target"
export CARGO_BUILD_JOBS=1

# retry a pip install that hit a corrupted file, dropping the cached (possibly
# corrupted) files first, so one of them does not fail the whole job.
pip_install() {
for attempt in 1 2 3; do
pip install "$@" && return 0
echo "*** pip install failed (attempt $attempt), purging the pip cache and retrying ***"
pip cache purge || true
done
return 1
}

pip_install -r requirements.d/development.txt
pip_install -e .

# troubles with either tox or pytest xdist, so we run pytest manually:
pytest -v -rs --benchmark-skip -k "not remote and not socket"
;;
Expand Down
27 changes: 16 additions & 11 deletions src/borg/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -868,17 +868,22 @@ def extract_item(self, item, restore_attrs=True, dry_run=False, stdout=False, sp
# overwrite files outside the extraction directory (e.g. /etc/passwd).
self.safe_dirs.discard(path) # path is about to be (re)created; never trust a stale entry for it
self._check_safe_parent(item.path)
# Attempt to remove existing files, ignore errors on failure
try:
st = os.stat(path, follow_symlinks=False)
if stat.S_ISDIR(st.st_mode):
os.rmdir(path)
else:
os.unlink(path)
except UnicodeEncodeError:
raise self.IncompatibleFilesystemEncodingError(path, sys.getfilesystemencoding()) from None
except OSError:
pass
# Attempt to remove existing files, ignore errors on failure.
# A trailing "." component means the extraction directory itself (the archive's
# "." item, as created by "borg create ARCHIVE ."). posix requires rmdir() to
# refuse such a path with EINVAL, but haiku strips the "." and would remove the
# extraction directory (if empty), so do not even try to remove it.
if os.path.basename(path) != '.':
try:
st = os.stat(path, follow_symlinks=False)
if stat.S_ISDIR(st.st_mode):
os.rmdir(path)
else:
os.unlink(path)
except UnicodeEncodeError:
raise self.IncompatibleFilesystemEncodingError(path, sys.getfilesystemencoding()) from None
except OSError:
pass

def make_parent(path):
parent_dir = os.path.dirname(path)
Expand Down
5 changes: 5 additions & 0 deletions src/borg/locking.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ def kill_stale_lock(self):
names = os.listdir(self.path)
except FileNotFoundError: # another process did our job in the meantime.
pass
except OSError:
# we can not read the lock directory - e.g. haiku fails this with EBUSY or
# "bad data" while the directory is concurrently replaced via rename().
# Not being able to look at the lock means we can not call it stale.
return False
else:
for name in names:
try:
Expand Down
2 changes: 2 additions & 0 deletions src/borg/testsuite/checksums.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from ..algorithms import checksums
from ..helpers import bin_to_hex, hex_to_bin
from ..platformflags import is_haiku

crc32_implementations = [checksums.crc32_slice_by_8]
if checksums.have_clmul:
Expand Down Expand Up @@ -118,6 +119,7 @@ def test_crc32_short_slices(implementation):

@pytest.mark.skipif(not checksums.have_clmul, reason='needs CLMUL support')
@pytest.mark.skipif(sys.platform == 'win32', reason='needs POSIX mmap/mprotect')
@pytest.mark.skipif(is_haiku, reason='the overread check does not work on haiku')
def test_crc32_clmul_no_overread():
# crc32_clmul used to load 16 bytes unconditionally for inputs of 4..15 bytes,
# reading up to 12 bytes past the end of the buffer. That is a SIGSEGV whenever
Expand Down
Loading