mirror of
https://github.com/Llewellynvdm/Tomb.git
synced 2024-09-28 04:39:02 +00:00
Compare commits
139 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ff692999de | ||
|
4783456814 | ||
|
653609a4b9 | ||
|
284fb4a3cd | ||
|
0ef195dff0 | ||
|
48c08c0086 | ||
|
29098f356c | ||
|
447817de6c | ||
|
b7fa057e48 | ||
|
963a0cc321 | ||
|
117bd9bd6e | ||
|
c1b5e1b310 | ||
|
afe0390d93 | ||
|
32eab3beec | ||
|
11a5776456 | ||
|
ef1541f7a2 | ||
|
73950fe3d8 | ||
|
41b899e4e1 | ||
|
33f7878a22 | ||
|
42e233d2b0 | ||
|
6df1cdeab9 | ||
|
0b25ba6d68 | ||
|
89283a06b7 | ||
|
c83068c03a | ||
|
be533b3995 | ||
|
75aafc0c8c | ||
|
45c4616110 | ||
|
7016515ce6 | ||
|
97c61dc513 | ||
|
4523823c48 | ||
|
cb997eec2c | ||
|
857895a750 | ||
|
891fa80c7a | ||
|
431f1c6647 | ||
|
2b75962e54 | ||
|
bae8af351b | ||
|
2082198b36 | ||
|
552dc82fe3 | ||
|
7ebcfc767e | ||
|
c72432d640 | ||
|
4a277c97f2 | ||
|
735d540fe7 | ||
|
b715917b31 | ||
|
0d06c994cf | ||
|
6c383ffd64 | ||
|
ddb2de6072 | ||
|
3398b7bf89 | ||
|
abe5704658 | ||
|
d0b84d78a0 | ||
|
91adbbe183 | ||
|
766cd27c1b | ||
|
dee2b0f8c4 | ||
|
13eeef7c6c | ||
|
194d60fe9a | ||
|
7f91cc917d | ||
|
09d981f0fc | ||
|
e1afecb832 | ||
|
e97c088a26 | ||
|
9385ddee43 | ||
27792f4421 | |||
8be3163022 | |||
|
21da75adab | ||
|
a0b633fb77 | ||
|
f9ec17d126 | ||
|
dcdf4cb3bb | ||
|
0c8d4cf477 | ||
|
51452e4e6a | ||
|
58035cf14a | ||
|
06ea734878 | ||
|
347462cb0c | ||
|
cd9fa46964 | ||
|
d8989e1955 | ||
|
59d7331cb0 | ||
|
4d72a2180a | ||
|
7249afe98e | ||
|
0eed3cf321 | ||
|
e316ef22cc | ||
|
82e5342334 | ||
|
4e3221e937 | ||
|
364a457fbc | ||
|
571cdeafbf | ||
|
b9cf58054a | ||
|
646d2c33fd | ||
|
713cfd3071 | ||
|
5eaa92e614 | ||
|
d65a3f1586 | ||
|
b5eae55c8b | ||
|
0130fcf86d | ||
|
30d2e92a77 | ||
|
0d004f312d | ||
|
b14be5022e | ||
|
ed841b9f32 | ||
|
6e8ef0a29a | ||
|
5772d39e19 | ||
|
1ae5845c61 | ||
|
fce89023a5 | ||
|
be911b1e16 | ||
|
12684e6740 | ||
|
42390b78c0 | ||
|
3639b2e0ec | ||
|
8502bdc722 | ||
|
e463a6e600 | ||
|
6af298e15f | ||
|
1655fd5a99 | ||
|
8782dab9ed | ||
|
3b44a6be3a | ||
|
7a1b699cea | ||
|
85af9459aa | ||
|
f4e2ae2f97 | ||
|
62806769af | ||
|
8be3e7d2a0 | ||
|
97343cf590 | ||
|
60034b0b55 | ||
|
b7822afaf0 | ||
|
6955719f04 | ||
|
8ceeca8769 | ||
|
03c93ef976 | ||
|
5a5eb6ddcf | ||
|
9323c1caf8 | ||
|
f7046c5941 | ||
|
b6ffe1a2f1 | ||
|
84ef4bef4b | ||
|
e0ba8c5f4d | ||
|
90eec3d830 | ||
|
930b414889 | ||
|
61a9d1a420 | ||
|
d2d35bc8db | ||
|
585af6a61b | ||
|
2a744fe89d | ||
|
b235f16ce4 | ||
|
ce521ed2e2 | ||
|
087ecd25a2 | ||
|
24a89b680d | ||
|
3860487a0b | ||
|
61386ca646 | ||
|
ae21619d04 | ||
|
7f2e22c517 | ||
|
fb3ffcec03 | ||
|
815b8f4218 |
4
.github/FUNDING.yml
vendored
Normal file
4
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
github: dyne
|
||||
patreon: dyneorg
|
||||
open_collective: dyne
|
||||
|
76
.github/workflows/hugo.yml
vendored
Normal file
76
.github/workflows/hugo.yml
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
# Sample workflow for building and deploying a Hugo site to GitHub Pages
|
||||
name: Deploy Hugo site to Pages
|
||||
|
||||
on:
|
||||
# Runs on pushes targeting the default branch
|
||||
push:
|
||||
branches: ["website"]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
# Default to bash
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
# Build job
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HUGO_VERSION: 0.124.1
|
||||
steps:
|
||||
- name: Install Hugo CLI
|
||||
run: |
|
||||
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
|
||||
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
|
||||
- name: Install Dart Sass
|
||||
run: sudo snap install dart-sass
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Setup Pages
|
||||
id: pages
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Install Node.js dependencies
|
||||
run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
|
||||
- name: Build with Hugo
|
||||
env:
|
||||
# For maximum backward compatibility with Hugo modules
|
||||
HUGO_ENVIRONMENT: production
|
||||
HUGO_ENV: production
|
||||
run: |
|
||||
hugo \
|
||||
--minify \
|
||||
--source docs \
|
||||
## breaks URL building ## --baseURL "${{ steps.pages.outputs.base_url }}/"
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: ./docs/public
|
||||
|
||||
# Deployment job
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
56
.github/workflows/linux.yml
vendored
Normal file
56
.github/workflows/linux.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
name:
|
||||
💀 Linux Tomb
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'doc/**'
|
||||
- 'extras/portable/**'
|
||||
- '*.md'
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'doc/**'
|
||||
- 'extras/portable/**'
|
||||
- '*.md'
|
||||
branches:
|
||||
- master
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-matrix:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04, ubuntu-24.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Install tomb dependencies
|
||||
run: |
|
||||
sudo apt-get update -y -q
|
||||
sudo apt-get install -y -q zsh cryptsetup gpg gawk libgcrypt20-dev steghide qrencode python3-pip python3-dev libssl-dev make gcc sudo gettext bsdmainutils file pinentry-curses xxd libsodium23 libsodium-dev argon2
|
||||
- name: Install python2 on ubuntu 20
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
run: sudo apt-get install -y -q python2
|
||||
- name: Install python2 on ubuntu 22
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: sudo apt-get install -y -q python2
|
||||
- name: Install doas where found
|
||||
if: matrix.os == 'ubuntu-24.04'
|
||||
run: |
|
||||
sudo apt-get install -y -q opendoas
|
||||
echo "permit nopass root" | sudo tee /etc/doas.conf
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build the pbkdf2 extras
|
||||
run: |
|
||||
make --directory=extras/kdf-keys
|
||||
sudo make --directory=extras/kdf-keys install
|
||||
- name: Run pbkdf2 tests
|
||||
run: sudo make -C extras/kdf-keys test
|
||||
- name: Disable swap
|
||||
run: sudo swapoff -a
|
||||
- name: Run main tests
|
||||
run: sudo make test
|
28
AUTHORS.md
28
AUTHORS.md
@ -2,27 +2,28 @@ Cryptsetup was originally written in 2004 by Jana Saout
|
||||
|
||||
LUKS extensions are written in 2006 by Clemens Fruhwirth
|
||||
|
||||
Tomb is written and maintained since 2007 by Denis Roio <J@dyne.org>
|
||||
Tomb is written and maintained since 2007 by [Denis "Jaromil" Roio](https://jaromil.dyne.org)
|
||||
|
||||
Tomb includes code and advices by Anathema, Boyska, Hellekin O. Wolf,
|
||||
Daniel Rodriguez, Parazyd, Alexandre Pujol, AitorATuin, Narrat and
|
||||
Artur Malimonov.
|
||||
Daniel Rodriguez, Parazyd, Alexandre Pujol, AitorATuin, Narrat, Artur
|
||||
Malimonov and Chris Vogel.
|
||||
|
||||
The 'gtomb' GUI based on Zenity is written by Parazyd.
|
||||
The 'gtomb' GUI based on Zenity is written by Parazyd and Daniel Dias Rodrigues.
|
||||
|
||||
The Qt5 desktop tray GUI is written by Gianluca Montecchi.
|
||||
|
||||
Python Tomb wrappers are contributed by Reiven and Boyska.
|
||||
|
||||
The Docker Tomb wrapper is contributed by Greg Tczap
|
||||
The Docker Tomb wrapper is contributed by Greg Tczap and Jens Rischbieth.
|
||||
|
||||
Artwork is contributed by Jordi aka Mon Mort and Logan VanCuren.
|
||||
|
||||
Gettext internationalization and Spanish translation is contributed by
|
||||
Daniel Rodriguez. French translation by Hellekin and Roy Lockhart,
|
||||
Russian translation by fsLeg, German translation by Jerry Polfer,
|
||||
Italian translation by Massimiliano Augello and Swedish translation by
|
||||
PLJ / Kosovoper.
|
||||
Daniel Rodriguez and Francisco Serrador. French translation by
|
||||
Hellekin and Roy Lockhart, Russian translation by fsLeg and AHOHNMYC,
|
||||
German translation by Jerry Polfer, Italian translation by
|
||||
Massimiliano Augello and Swedish translation by PLJ / Kosovoper,
|
||||
general fixes contributed by Daniel Dias Rodrigues.
|
||||
|
||||
Testing, reviews and documentation contributed by Dreamer, Vlax,
|
||||
Shining the Translucent, Mancausoft, Asbesto Molesto, Nignux, TheJH,
|
||||
@ -31,13 +32,12 @@ Polfer, Jim Turner, Maxime Arthaud, RobertMX, mhogomchungu Mandeep
|
||||
Bhutani, Emil Lundberg, Joel Montes de Oca, Armin Mesbah, Arusekk,
|
||||
Stephan Schindel, Asbjørn Apeland, Victor Calvert, bjonnh, SargoDevel,
|
||||
AitorATuin, Alexis Danizan, Sven Geuer, Greg Tczap, Aaron Janse, Mark
|
||||
Mykkanen, Alexis Danizan, Steve Litt, James R, Matthieu Crapet and...
|
||||
the Linux Action Show!
|
||||
Mykkanen, Alexis Danizan, Steve Litt, James R, Matthieu Crapet, Selene
|
||||
ToyKeeper, Valentin Heidelberg and... the Linux Action Show!
|
||||
|
||||
Tomb includes an implementation of the "Password-Based Key Derivation
|
||||
Function v2" based on GCrypt and written by Anthony Thyssen, with
|
||||
fixes contributed by AitorATuin.
|
||||
|
||||
Tomb developers can be contacted via GitHub issues on
|
||||
https://www.github.com/dyne/Tomb or over IRC https://irc.dyne.org
|
||||
channel **#dyne** (or directly over port 9999 with SSL)
|
||||
Some of the Tomb developers can be contacted via [GitHub discussions](https://github.com/dyne/Tomb/discussions)
|
||||
or over Telegram via the [Dyne.org Chat Channel](https://t.me/dyne_chat).
|
||||
|
23
ChangeLog.md
23
ChangeLog.md
@ -1,5 +1,28 @@
|
||||
# Tomb ChangeLog
|
||||
|
||||
## 2.11
|
||||
### July 2024
|
||||
|
||||
Search engine is upgraded to use recoll, based on xapian backend:
|
||||
offers a GUI and is more up to date, replaces swish-e. Various fixes
|
||||
include a better default of 3 rounds for Argon2 KDF, improved support
|
||||
for cloakify which is now shipped in tomb/extras, new support for
|
||||
pinentry-tty useful for some headless systems and terminals over
|
||||
serial port, improved usage on machines without sudo and support
|
||||
bind-hooks on folders containing spaces in their names. Also the
|
||||
translations to some other languages were improved. All documentation
|
||||
was revisited and reorganized, manpage corrected in some parts and a
|
||||
new homepage is up at https://dyne.org/tomb
|
||||
|
||||
## 2.10
|
||||
### Sep 2023
|
||||
|
||||
This release adds optional support for Argon2 KDF brute-force
|
||||
protection and introduces support for doas as an alternative to sudo
|
||||
for privilege escalation. It also improves support for BTRFS formatted
|
||||
Tombs, adds zram detection as swap memory, updates documentation and
|
||||
translations and cleans up the script code.
|
||||
|
||||
## 2.9
|
||||
### Jan 2021
|
||||
|
||||
|
@ -51,7 +51,7 @@ The key can also be hidden in an image, to be used as key later
|
||||
tomb bury -k secrets.tomb.key nosferatu.jpg (hide the key in a jpeg image)
|
||||
tomb open -k nosferatu.jpg secrets.tomb (use the jpeg image to open the tomb)
|
||||
|
||||
Or backupped to a QRCode that can be printed on paper and hidden in
|
||||
Or backed up to a QRCode that can be printed on paper and hidden in
|
||||
books. QRCodes can be scanned with any mobile application, resulting
|
||||
into a block of text that can be used with `-k` just as a normal key.
|
||||
|
||||
@ -72,8 +72,8 @@ executable | function
|
||||
steghide | bury and exhume keys inside images
|
||||
resizefs | extend the size of existing tomb volumes
|
||||
qrencode | engrave keys into printable qrcode sheets
|
||||
mlocate | fast search of file names inside tombs
|
||||
swish++ | fast search of file contents inside tombs
|
||||
plocate | fast search of file names inside tombs
|
||||
recoll | fast search of file contents inside tombs
|
||||
unoconv | fast search of contents in PDF and DOC files
|
||||
lesspipe | fast search of contents in compressed archives
|
||||
haveged | fast entropy generation for key forging
|
||||
|
@ -22,16 +22,16 @@ cryptsetup v2.1 a new default has been introduced (luks2) and the
|
||||
Using Tomb version 2.6 (and future releases) the problem opening tombs
|
||||
using recent GNU/Linux distributions is fixed.
|
||||
|
||||
# Whitespaces in KDF passwords
|
||||
# Whitespace in KDF passwords
|
||||
## Issue affecting passwords used with PBKDF2 keys (<2.6)
|
||||
|
||||
Up until and including Tomb's version 2.5 the PBKDF2 wrapper for keys
|
||||
in Tomb has a bug affecting passwords that contain whitespaces. Since
|
||||
in Tomb has a bug affecting passwords that contain whitespace. Since
|
||||
the passwords are trimmed at the first whitespace, this makes them
|
||||
weaker, while fortunately the KDF transformation still applies.
|
||||
|
||||
This issue is fixed in Tomb version 2.6: all users adopting KDF keys
|
||||
that have passwords containing whitespaces should change them,
|
||||
that have passwords containing whitespace should change them,
|
||||
knowing that their "old password" is trimmed until the whitespace.
|
||||
|
||||
Users adopting GPG keys or plain (without KDF wrapper) can ignore
|
||||
|
10
Makefile
10
Makefile
@ -2,6 +2,14 @@ PROG = tomb
|
||||
PREFIX ?= /usr/local
|
||||
MANDIR ?= ${PREFIX}/share/man
|
||||
|
||||
deps:
|
||||
@if [ -r /etc/debian_version ]; then \
|
||||
apt-get install -qy zsh cryptsetup file gnupg pinentry-curses; fi
|
||||
@if [ -r /etc/fedora-release ]; then \
|
||||
yum install -y zsh cryptsetup file gnupg pinentry-curses; fi
|
||||
@if [ -r /etc/alpine-release ]; then \
|
||||
apk add zsh cryptsetup file gpg pinentry-tty e2fsprogs findmnt; fi
|
||||
|
||||
all:
|
||||
@echo
|
||||
@echo "Tomb is a script and does not need compilation, it can be simply executed."
|
||||
@ -26,4 +34,4 @@ test:
|
||||
make -C extras/test
|
||||
|
||||
lint:
|
||||
shellcheck -s zsh -e SC1073,SC1027,SC1072,SC1083,SC1009 tomb
|
||||
shellcheck -s bash -e SC1058,SC1073,SC1072,SC1009 tomb
|
||||
|
305
README.md
305
README.md
@ -1,309 +1,58 @@
|
||||
..... ..
|
||||
.H8888888h. ~-. . uW8"
|
||||
888888888888x `> u. .. . : `t888
|
||||
X~ `?888888hx~ ...ue888b .888: x888 x888. 8888 .
|
||||
' x8.^"*88*" 888R Y888r ~`8888~'888X`?888f` 9888.z88N
|
||||
`-:- X8888x 888R I888> X888 888X '888> 9888 888E
|
||||
488888> 888R I888> X888 888X '888> 9888 888E
|
||||
.. `"88* 888R I888> X888 888X '888> 9888 888E
|
||||
x88888nX" . u8888cJ888 X888 888X '888> 9888 888E
|
||||
!"*8888888n.. : "*888*P" "*88%""*88" '888!` .8888 888"
|
||||
' "*88888888* 'Y" `~ " `"` `%888*%"
|
||||
^"***"` "`
|
||||
# Tomb: The Linux Crypto Undertaker
|
||||
|
||||
*A minimalistic commandline tool to manage encrypted volumes* aka **The Crypto Undertaker**
|
||||
[![Build Status](https://github.com/dyne/tomb/actions/workflows/linux.yml/badge.svg)](https://github.com/dyne/Tomb/actions)
|
||||
<!-- [![Build Status](https://github.com/dyne/tomb/actions/workflows/portable.yml/badge.svg)](https://github.com/dyne/Tomb/actions) -->
|
||||
|
||||
[![software by Dyne.org](https://files.dyne.org/software_by_dyne.png)](http://www.dyne.org)
|
||||
Minimalistic command line tool based on Linux dm-crypt and LUKS, trusted by hackers since 2007.
|
||||
|
||||
More information and updates on website: https://www.dyne.org/software/tomb
|
||||
|
||||
Get the stable .tar.gz signed release for production use!
|
||||
|
||||
Download it from https://files.dyne.org/tomb
|
||||
|
||||
For the instructions on how to get started using Tomb, see [INSTALL](INSTALL.md).
|
||||
You can keep your volumes secure and easily manageable with simple commands.
|
||||
|
||||
![tomb's logo](https://github.com/dyne/Tomb/blob/master/extras/images/monmort.png)
|
||||
|
||||
[![Build Status](https://travis-ci.org/dyne/Tomb.svg?branch=master)](https://travis-ci.org/dyne/Tomb)
|
||||
|
||||
# What is Tomb, the crypto undertaker?
|
||||
|
||||
Tomb aims to be a free and open source system for easy encryption and
|
||||
backup of personal files, written in code that is easy to review and
|
||||
links well reliable GNU/Linux components.
|
||||
|
||||
Tomb's ambition is to improve safety by way of:
|
||||
|
||||
- a minimalist design consisting in small and well readable code
|
||||
- facilitation of good practices, i.e: key/storage physical separation
|
||||
- adoption of a few standard and well tested implementations.
|
||||
|
||||
At present, Tomb consists of a simple shell script (Zsh) using
|
||||
standard filesystem tools (GNU) and the cryptographic API of the Linux
|
||||
kernel (cryptsetup and LUKS). Tomb can also produce machine parsable
|
||||
output to facilitate its use inside graphical applications.
|
||||
|
||||
# How does it work?
|
||||
|
||||
To create a Tomb, do:
|
||||
Create a new 120MiB `secret.tomb` folder and lock it with a new `secret.tomb.key` file.
|
||||
```
|
||||
$ tomb dig -s 100 secret.tomb
|
||||
$ tomb forge secret.tomb.key
|
||||
$ tomb lock secret.tomb -k secret.tomb.key
|
||||
$ tomb dig -s 120 secret.tomb
|
||||
$ tomb forge -k secret.tomb.key
|
||||
$ tomb lock -k secret.tomb.key secret.tomb
|
||||
```
|
||||
To open it, do
|
||||
```
|
||||
$ tomb open secret.tomb -k secret.tomb.key
|
||||
$ tomb open -k secret.tomb.key secret.tomb
|
||||
```
|
||||
and after you are done
|
||||
And after you are done
|
||||
```
|
||||
$ tomb close
|
||||
```
|
||||
or if you are in a hurry
|
||||
Or, if you are in a hurry, kill all processes with open files inside your tomb and close it.
|
||||
```
|
||||
$ tomb slam all
|
||||
$ tomb slam
|
||||
```
|
||||
## 📖 [Get started on dyne.org/tomb](https://dyne.org/tomb)
|
||||
|
||||
```
|
||||
Syntax: tomb [options] command [arguments]
|
||||
<a href="https://dyne.org/tomb"><img src="https://files.dyne.org/software_by_dyne.png" width="30%"></a>
|
||||
|
||||
Commands:
|
||||
More information in `man tomb` and on [dyne.org/docs/tomb](https://dyne.org/docs/tomb).
|
||||
|
||||
// Creation:
|
||||
dig create a new empty TOMB file of size -s in MiB
|
||||
forge create a new KEY file and set its password
|
||||
lock installs a lock on a TOMB to use it with KEY
|
||||
### 💾 [Download from files.dyne.org/tomb](https://files.dyne.org/tomb/)
|
||||
|
||||
// Operations on tombs:
|
||||
open open an existing TOMB (-k KEY file or - for stdin)
|
||||
index update the search indexes of tombs
|
||||
search looks for filenames matching text patterns
|
||||
list list of open TOMBs and information on them
|
||||
ps list of running processes inside open TOMBs
|
||||
close close a specific TOMB (or 'all')
|
||||
slam slam a TOMB killing all programs using it
|
||||
resize resize a TOMB to a new size -s (can only grow)
|
||||
Use only stable and signed releases in production!
|
||||
|
||||
// Operations on keys:
|
||||
passwd change the password of a KEY (needs old pass)
|
||||
setkey change the KEY locking a TOMB (needs old key and pass)
|
||||
Tomb's development is community-based!
|
||||
|
||||
// Backup on paper:
|
||||
engrave makes a QR code of a KEY to be saved on paper
|
||||
## 🤏🏽 How can you help
|
||||
|
||||
// Steganography:
|
||||
bury hide a KEY inside a JPEG image (for use with -k)
|
||||
exhume extract a KEY from a JPEG image (prints to stdout)
|
||||
cloak transform a KEY into a TEXT using CIPHER (for use with -k)
|
||||
uncloak extract a KEY from a TEXT file using CIPHER (prints to stdout)
|
||||
Donations are very welcome on [dyne.org/donate](https://www.dyne.org/donate)
|
||||
|
||||
Options:
|
||||
Translations are also welcome: see our simple [translation guide](https://github.com/dyne/Tomb/blob/master/extras/translations/README.md)
|
||||
|
||||
-s size of the tomb file when creating/resizing one (in MiB)
|
||||
-k path to the key to be used ('-k -' to read from stdin)
|
||||
-n don't process the hooks found in tomb
|
||||
-o options passed to commands: open, lock, forge (see man)
|
||||
-f force operation (i.e. open even if swap is active)
|
||||
-g use a GnuPG key to encrypt a tomb key
|
||||
-r provide GnuPG recipients (separated by comma)
|
||||
-R provide GnuPG hidden recipients (separated by comma)
|
||||
--kdf forge keys armored against dictionary attacks
|
||||
Tomb's code is short and readable: don't be afraid to inspect it! If you plan to submit a PR, please remember that this is a minimalist tool, and the code should be short and readable. Also, first, read our small intro to [Tomb's coding style](doc/HACKING.txt).
|
||||
|
||||
-h print this help
|
||||
-v print version, license and list of available ciphers
|
||||
-q run quietly without printing informations
|
||||
-D print debugging information at runtime
|
||||
```
|
||||
We have a [space for issues](https://github.com/dyne/Tomb/issues) open for detailed bug reports. Always include the Tomb version being used when filing a case, please.
|
||||
|
||||
# What is this for, exactly?
|
||||
|
||||
This tool can be used to dig .tomb files (LUKS volumes), forge keys
|
||||
protected by a password (GnuPG encryption) and use the keys to lock
|
||||
the tombs. Tombs are like single files whose contents are inaccessible
|
||||
in the absence of the key they were locked with and its password.
|
||||
|
||||
Once open, the tombs are just like normal folders and can contain
|
||||
different files, plus they offer advanced functionalities like bind
|
||||
and execution hooks and fast search, or they can be slammed close even
|
||||
if busy. Keys can be stored on separate media like USB sticks, NFC,
|
||||
on-line SSH servers or bluetooth devices to make the transport of data
|
||||
safer: one always needs both the tomb and the key, plus its password,
|
||||
to access it.
|
||||
|
||||
The tomb script takes care of several details to improve user's
|
||||
behaviour and the security of tombs in everyday usage: protects the
|
||||
typing of passwords from keyloggers, facilitates hiding keys inside
|
||||
images, indexes and search a tomb's contents, mounts directories in
|
||||
place, lists open tombs and selectively closes them, warns the user
|
||||
about free space and last time usage, etc.
|
||||
|
||||
# How secure is this?
|
||||
|
||||
Death is the only sure thing in life. That said, Tomb is a pretty
|
||||
secure tool especially because it is kept minimal, its source is
|
||||
always open to review (even when installed) and its code is easy to
|
||||
read with a bit of shell script knowledge.
|
||||
|
||||
All encryption tools being used in Tomb are included as default in
|
||||
many GNU/Linux operating systems and therefore are regularly peer
|
||||
reviewed: we don't add anything else to them really, just a layer of
|
||||
usability.
|
||||
|
||||
The file [KNOWN_BUGS.md](KNOWN_BUGS.md) contains some notes on known
|
||||
vulnerabilities and threat model analysis.
|
||||
|
||||
In absence or malfunction of the Tomb script it is always possible to
|
||||
access the contents of a Tomb only using a dm-crypt enabled Linux
|
||||
kernel, cryptsetup, GnuPG and any shell interpreter issuing the
|
||||
following commands as root:
|
||||
```
|
||||
lo=$(losetup -f)
|
||||
losetup -f secret.tomb
|
||||
pass="$(gpg -d secret.key)"
|
||||
echo -n -e "$pass" | cryptsetup --key-file - luksOpen $lo secret
|
||||
mount /dev/mapper/secret /mnt
|
||||
unset pass
|
||||
```
|
||||
One can change the last argument `/mnt` to where the Tomb has to be
|
||||
mounted and made accessible. To close the tomb then use:
|
||||
```
|
||||
umount /mnt
|
||||
cryptsetup luksClose /dev/mapper/secret
|
||||
```
|
||||
|
||||
# Stage of development
|
||||
|
||||
Tomb is an evolution of the 'mknest' tool developed for the
|
||||
[dyne:bolic](http://www.dynebolic.org) 100% Free GNU/Linux
|
||||
distribution in 2001: its 'nesting' mechanism allowed the liveCD users
|
||||
to encrypt and make persistent home directories. Since then the same
|
||||
shell routines kept being maintained and used for dyne:bolic until
|
||||
2007, when they were ported to work on more GNU/Linux distributions.
|
||||
|
||||
As of today, Tomb is a very stable tool also used in mission critical
|
||||
situations by a number of activists in dangerous zones. It has been
|
||||
reviewed by forensics analysts and it can be considered safe for
|
||||
adoption where the integrity of information stored depends on the
|
||||
user's behaviour and the strength of a standard AES-256 (XTS plain)
|
||||
encryption algorithm (current default) or, at one's option, other
|
||||
equivalent standards supported by the Linux kernel.
|
||||
|
||||
## Compatibility
|
||||
|
||||
Tomb can be used in conjunction with some other software applications,
|
||||
some are developed by Dyne.org, but some also by third parties.
|
||||
|
||||
### Included extra applications
|
||||
|
||||
These auxiliary applications are found in the extras/ subdirectory of
|
||||
distributed Tomb's sourcecode:
|
||||
|
||||
- [GTomb](extras/gtomb) is a graphical interface using zenity
|
||||
- [gtk-tray](extras/gtk-tray) is a graphical tray icon for GTK panels
|
||||
- [qt-tray](extras/qt-tray) is a graphical tray icon for QT panels
|
||||
- [tomber](extras/tomber) is a wrapper to use Tomb in Python scripts
|
||||
- [docker](extras/docker) is a wrapper to use Tomb through Docker
|
||||
|
||||
![skulls and pythons](https://github.com/dyne/Tomb/blob/master/extras/images/python_for_tomb.png)
|
||||
|
||||
### External applications
|
||||
|
||||
The following applications are not included in Tomb's distributed
|
||||
sourcecode, but are known and tested to be compatible with Tomb:
|
||||
|
||||
- [Secrets](https://secrets.dyne.org) is a software that can be operated on-line and on-site to split a Tomb key in shares to be distributed to peers: some of them have to agree to combine back the shares in order to retrieve the key.
|
||||
|
||||
- [zuluCrypt](https://mhogomchungu.github.io/zuluCrypt/) is a graphical application to manage various types of encrypted volumes on GNU/Linux, among them also Tombs, written in C++.
|
||||
|
||||
- [Mausoleum](https://github.com/mandeep/Mausoleum) is a graphical interface to facilitate the creation and management of tombs, written in Python.
|
||||
|
||||
|
||||
- [pass-tomb](https://github.com/roddhjav/pass-tomb) is a console based wrapper of the excellent password keeping program [pass](https://www.passwordstore.org) that helps to keep the whole tree of password encrypted inside a tomb. It is written in Bash.
|
||||
|
||||
If you are writing a project supporting Tomb volumes or wrapping Tomb, let us know!
|
||||
|
||||
|
||||
## Compliancy
|
||||
|
||||
Tomb qualifies as sound for use on information rated as "top secret"
|
||||
when used on an underlying stack of carefully reviewed hardware
|
||||
(random number generator and other components) and software (Linux
|
||||
kernel build, crypto modules, device manager, compiler used to built,
|
||||
shell interpreter and packaged dependencies).
|
||||
|
||||
Tomb volumes are fully compliant with the FIPS 197 advanced encryption
|
||||
standard published by NIST and with the following industry standards:
|
||||
|
||||
- Information technology -- Security techniques -- Encryption algorithms
|
||||
- [ISO/IEC 18033-1:2015](http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=54530) -- Part 1: General
|
||||
- [ISO/IEC 18033-3:2010](http://www.iso.org/iso/home/store/catalogue_ics/catalogue_detail_ics.htm?csnumber=54531) -- Part 3: Block ciphers
|
||||
|
||||
Tomb implementation is known to address at least partially issues raised in:
|
||||
|
||||
- Information technology -- Security techniques -- Key management
|
||||
- [ISO/IEC 11770-1:2010](http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=53456) -- Part 1: Framework
|
||||
- [ISO/IEC 11770-2:2008](http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=46370) -- Part 2: Mechanisms using symmetric techniques
|
||||
- [ISO/IEC 27005:2011](http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=56742) Information technology -- Security techniques -- Information security risk management
|
||||
- [ISO/IEC 24759:2014](http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=59142) Information technology -- Security techniques -- Test requirements for cryptographic modules
|
||||
|
||||
Any help on further verification of compliancy is very welcome, as the
|
||||
access to ISO/IEC document is limited due to its expensive nature.
|
||||
|
||||
|
||||
# Use stable releases in production!
|
||||
|
||||
Anyone planning to use Tomb to store and access secrets should not use
|
||||
the latest development version in Git, but use instead the .tar.gz
|
||||
release on https://files.dyne.org/tomb . The stable version will
|
||||
always ensure backward compatibility with older tombs: we make sure it
|
||||
creates sane tombs and keys by running various tests before releasing
|
||||
it. The development version in Git might introduce sudden bugs and is
|
||||
not guaranteed to produce backward- or forward-compatible tombs and keys.
|
||||
The development version in Git should be used to report bugs, test new
|
||||
features and develop patches.
|
||||
|
||||
So be warned: do not use the latest Git version in production
|
||||
environments, but use a stable release versioned and packed as
|
||||
tarball on https://files.dyne.org/tomb
|
||||
|
||||
![Day of the dead](https://github.com/dyne/Tomb/blob/master/extras/images/DayOfTheDead.jpg)
|
||||
|
||||
# How can you help
|
||||
|
||||
Donations are very welcome, please go to https://www.dyne.org/donate
|
||||
|
||||
Translations are also welcome: they can be contributed editing sending
|
||||
the .po files in [extras/translations](extras/translations).
|
||||
|
||||
The code is pretty short and readable. There is also a collection of
|
||||
specifications and design materials in the [doc](doc) directory.
|
||||
|
||||
To contribute code and reviews visit https://github.com/dyne/Tomb
|
||||
|
||||
If you plan to commit code into Tomb, please keep in mind this is a
|
||||
minimalist tool and its code should be readable. Guidelines on the
|
||||
coding style are illustrated in [doc/HACKING.txt](doc/HACKING.txt).
|
||||
|
||||
Tomb's developers can be contacted using the issues on GitHub or over
|
||||
IRC on https://irc.dyne.org channel **#dyne** (or direct port 9999 SSL)
|
||||
There is also a [space for discussion](https://github.com/dyne/Tomb/discussions) of new features, desiderata and whatnot on github.
|
||||
|
||||
# Licensing
|
||||
|
||||
Tomb is Copyright (C) 2007-2021 by the Dyne.org Foundation and
|
||||
maintained by Denis Roio <J@dyne.org>. More information on all
|
||||
the developers involved is found in the [AUTHORS](AUTHORS.md) file.
|
||||
Tomb is Copyright (C) 2007-2024 by the Dyne.org Foundation and maintained by [Jaromil](https://github.com/jaromil). The [AUTHORS](AUTHORS.md) file contains more information on all the developers involved. The license is GNU Public License v3.
|
||||
|
||||
This source code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please refer
|
||||
to the GNU Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Public License along with
|
||||
this source code; if not, write to: Free Software Foundation, Inc.,
|
||||
675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
## [More info on dyne.org/tomb](https://dyne.org/tomb)
|
||||
|
@ -1,13 +1,11 @@
|
||||
Overview
|
||||
=========
|
||||
|
||||
|
||||
What's a key?
|
||||
It basicly is a gpg simmetrically encrypted, ascii-armored file.
|
||||
It's encryption key is a function (see below, on KDF section) of your tomb
|
||||
What is a key?
|
||||
It is a gpg symmetrically encrypted, ascii-armored file.
|
||||
The encryption key is a function (see below, on KDF section) of your tomb
|
||||
passphrase.
|
||||
|
||||
|
||||
Layout
|
||||
======
|
||||
|
||||
|
@ -31,11 +31,11 @@ Linux hard disk encryption settings
|
||||
and LRW for standardisation. EME along with it's cousin CMC seems to
|
||||
provide the best security level, but imposes additional encryption
|
||||
steps. Plumb-IV is discussed only for reference, because it has the
|
||||
same performance penalty as CMC, but in constrast suffers from
|
||||
same performance penalty as CMC, but in contrast suffers from
|
||||
weaknesses of CBC encryption.
|
||||
|
||||
As convention, this document will use the term "blocks", when it
|
||||
referes to a single block of plain or cipher text (usually 16 byte),
|
||||
refers to a single block of plain or cipher text (usually 16 byte),
|
||||
and will use the term "sectors", when it refers to a 512-byte wide hard
|
||||
disk block.
|
||||
|
||||
@ -171,8 +171,8 @@ Content leaks
|
||||
cipher blocks. But how does this number grow in n? Obviously
|
||||
exponentially. Plotting a few a decimal powers shows that the chance
|
||||
for finding at least on identical cipher pair flips to 1 around n =
|
||||
10^20 (n = 10^40 for a 256-bit cipher). This inflexion point is reached
|
||||
for a 146 million TB storage (or a hundered thousand trillion trillions
|
||||
10^20 (n = 10^40 for a 256-bit cipher). This inflection point is reached
|
||||
for a 146 million TB storage (or a hundred thousand trillion trillions
|
||||
TB storage for a 256-bit cipher).
|
||||
|
||||
^1The blocks with available preceding cipher blocks is 62/1KB for all
|
||||
|
207
doc/tomb.1
207
doc/tomb.1
@ -1,4 +1,4 @@
|
||||
.TH tomb 1 "Jan 4, 2021" "tomb"
|
||||
.TH tomb 1 "Jun 25, 2023" "tomb"
|
||||
|
||||
.SH NAME
|
||||
Tomb \- the Crypto Undertaker
|
||||
@ -32,23 +32,24 @@ Generates a file that can be used as a tomb and will occupy as much
|
||||
space as its desired initial size, the unlocked \fI.tomb\fR file can
|
||||
then be locked using a \fIkey\fR. It takes a mandatory \fI-s\fR option
|
||||
which is the size in megabytes (MiB). Tombs are digged using random
|
||||
data gathered from a non-blocking source (/dev/urandom).
|
||||
data gathered from a non-blocking source (/dev/urandom). For very
|
||||
large tombs this may take up too much time and entropy, then it is
|
||||
possible to use \fIfallocate(1)\fR being aware it does not pre-fill
|
||||
with random data, decreasing the tomb's security.
|
||||
|
||||
.B
|
||||
.IP "forge"
|
||||
Creates a new \fIkey\fR and prompts the user for a \fIpassword\fR to
|
||||
protect its usage using symmetric encryption. This operation uses
|
||||
random data from a non-blocking source (/dev/urandom) and it may take
|
||||
long only in some cases; to switch using a blocking source the
|
||||
\fI--use-random\fR flag can be used. The \fI-g\fR option switches on
|
||||
the use of a GPG key instead of a password (asymmetric encryption),
|
||||
then the \fI-r\fR option indicates the recipient key; more recipient
|
||||
GPG ids can be indicated (comma separated). The default cipher to
|
||||
protect the key is AES256, a custom one can be specified using the
|
||||
\fI-o\fR option, for a list of supported ciphers use \fI-v\fR. For
|
||||
additional protection against dictionary attacks on keys, the
|
||||
\fI--kdf\fR option can be used when forging a key, making sure that
|
||||
the \fItomb-kdb-pbkdf2\fR binaries in \fIextras/kdf\fR were compiled
|
||||
Creates a new \fIkey\fR and prompts the user for a \fIpassword\fR to protect
|
||||
its usage using symmetric encryption. This operation uses random data from a
|
||||
non-blocking source (/dev/urandom) and it may take long only in some cases; to
|
||||
switch using a blocking source the \fI--use-random\fR flag can be used. The
|
||||
\fI-g\fR option switches on the use of a GPG key instead of a password
|
||||
(asymmetric encryption), then the \fI-r\fR option indicates the recipient key;
|
||||
more recipient GPG ids can be indicated (comma separated). The default cipher
|
||||
to protect the key is AES256, a custom one can be specified using the \fI-o\fR
|
||||
option, for a list of supported ciphers use \fI-v\fR. For additional protection
|
||||
against dictionary attacks on keys, the \fI--kdf\fR option can be used when
|
||||
forging a key, making sure that the binaries in \fIextras/kdf\fR were compiled
|
||||
and installed on the system.
|
||||
|
||||
.B
|
||||
@ -65,11 +66,29 @@ option can be used to specify the cipher specification: default is
|
||||
If you are looking for something exotic, also try
|
||||
"serpent-xts-plain64". More options may be found in cryptsetup(8) and
|
||||
Linux documentation. The \fI--filesystem\fR option can be used to
|
||||
specify "btrfs" as an alternative filesystem used to format the tomb,
|
||||
specify an alternative filesystem used to format the tomb,
|
||||
in place of the default "ext4". This operation requires root
|
||||
privileges to loopback mount, format the tomb (using LUKS and Ext4),
|
||||
privileges to loopback mount, format the tomb (using LUKS and mkfs),
|
||||
then set the key in its first LUKS slot.
|
||||
|
||||
.RS
|
||||
Supported filesystems for \fI--filesystem\fR:
|
||||
.PD 0
|
||||
.IP "ext3" 15
|
||||
using operating system defaults
|
||||
.IP "ext4"
|
||||
using operating system defaults
|
||||
.IP "btrfs"
|
||||
for tombs >= 47MB using operating system defaults
|
||||
.IP "btrfsmixedmode"
|
||||
for tombs >=18MB btrfs mixed mode (see mkfs.btrfs(8))
|
||||
.IP "ext3maxinodes"
|
||||
ext3 with a maximum of inodes (for many small files)
|
||||
.IP "ext4maxinodes"
|
||||
ext4 with a maximum of inodes (for many small files)
|
||||
.PD
|
||||
.RE
|
||||
|
||||
.B
|
||||
.IP "open"
|
||||
Opens an existing \fItomb file\fR (first argument) using a key
|
||||
@ -103,19 +122,21 @@ internally to enumerate processes running in one or all tombs.
|
||||
.IP "index"
|
||||
Creates or updates the search indexes of all tombs currently open:
|
||||
enables use of the \fIsearch\fR command using simple word patterns on
|
||||
file names. Indexes are created using mlocate's updatedb(8) and
|
||||
swish-e(1) if they are found on the system. Indexes allow one to search
|
||||
file names. Indexes are created using plocate's updatedb(8) and
|
||||
recoll(1) if they are found on the system. Indexes allow one to search
|
||||
very fast for filenames and contents inside a tomb, they are stored
|
||||
inside it and are not accessible if the Tomb is closed. To avoid
|
||||
indexing a specific tomb simply touch a \fI.noindex\fR file in it.
|
||||
Useful tools to have: poppler-utils, aspell, xdg-utils, plocate.
|
||||
|
||||
.B
|
||||
.IP "search"
|
||||
Takes any string as argument and searches for them through all tombs
|
||||
currently open and previously indexed using the \fIindex\fR command.
|
||||
The search matches filenames if mlocate is installed and then also
|
||||
file contents if swish++ is present on the system, results are listed
|
||||
on the console.
|
||||
The search matches filenames if plocate is installed and then also
|
||||
file contents if recoll is installed, all results are listed on the
|
||||
console.
|
||||
One can also run recoll's GUI using \fIrecoll -c /media/tomb\fR
|
||||
|
||||
.B
|
||||
.IP "close"
|
||||
@ -198,22 +219,19 @@ key is buried in any image or not.
|
||||
|
||||
.B
|
||||
.IP "cloak"
|
||||
Hides a tomb key (\fI-k\fR) inside a \fIlong plain-text file\fR (first
|
||||
argument) using \fIsteganography\fR: the text will change in a way
|
||||
that can hardly be noticed by human eye and hardly detected by data
|
||||
analysis. This option is useful to backup tomb keys in unsuspected
|
||||
places; it depends from the availability of \fIcloakify\fR and
|
||||
consequently \fIpython2\fR. This function does not support asymmetric
|
||||
encryption using the \fI-g\fR flag.
|
||||
Cloaks a tomb key (\fI-k\fR) disguising it as a text file using a
|
||||
cipher from \fIextras/cloak/ciphers\fR (second argument) using
|
||||
\fIcloakify\fR. This option is useful to backup tomb keys in
|
||||
unsuspected places; it needs \fIextras/cloak\fR installed and
|
||||
\fIpython3\fR.
|
||||
|
||||
.B
|
||||
.IP "uncloak"
|
||||
This command recovers from long plain-text files the keys that were
|
||||
previously hidden into them using \fIcloak\fR. Cloak requires a key
|
||||
filename (\fI-k\fR) and a \fIplain-text\fR file (first argument) known
|
||||
to be containing a key. If the right key password is given, the key
|
||||
will be exhumed. If the password is not known, it is quite hard to
|
||||
verify if a key is buried in a text or not.
|
||||
Recovers a tomb key from a cloaked text file. Uncloak requires a text
|
||||
file (first argument), a cipher file (second argument) and optionally
|
||||
an output file (third argument). If the first two parameters are
|
||||
correct then the output will be a valid tomb key file restored from
|
||||
cloak.
|
||||
|
||||
.SH OPTIONS
|
||||
.B
|
||||
@ -257,7 +275,8 @@ the \fIsize\fR of the new file to be created. Units are megabytes (MiB).
|
||||
.B
|
||||
.IP "-g"
|
||||
Tell tomb to use a asymmetric GnuPG key encryption instead of a
|
||||
symmetric passphrase to protect a tomb key. This option can be followed by \fI-r\fR when the command needs to specify recipient(s).
|
||||
symmetric passphrase to protect a tomb key. This option can be
|
||||
followed by \fI-r\fR when the command needs to specify recipient(s).
|
||||
.B
|
||||
.IP "-r \fI<gpg_id>[,<gpg_id2>]\fR"
|
||||
Provide a new set of recipient(s) to encrypt a tomb key. \fIgpg_ids\fR
|
||||
@ -265,22 +284,28 @@ can be one or more GPG key ID, comma separated. All GPG keys must be
|
||||
trusted keys in GPG.
|
||||
.B
|
||||
.IP "--kdf \fI<itertime>\fR"
|
||||
Activate the KDF feature against dictionary attacks when creating a
|
||||
key: forces a delay of \fI<itertime>\fR times every time this key is
|
||||
used. The actual time to wait depends on the CPU speed of the
|
||||
computer where the key is used. Using 5 or 10 is a sane amount for
|
||||
modern computers, the value is multiplied by 1 million.
|
||||
Activate the KDF feature against dictionary attacks when creating a key: forces
|
||||
a delay of \fI<itertime>\fR times every time this key is used. The actual time
|
||||
to wait depends on the CPU speed (default) or the RAM size (argon2) of the
|
||||
computer where the key is used. Using 5 or 10 is a sane amount for modern
|
||||
computers, the value is multiplied by 1 million.
|
||||
.B
|
||||
.IP "--sphx-user \fI<username>\fR"
|
||||
Activate the SPHINX feature for password-authenticated key agreement.
|
||||
This option indicates the \fI<username>\fR used to retrieve the
|
||||
password from a sphinx oracle key reachable via TCP/IP.
|
||||
|
||||
.IP "--sphx-host \fI<domain>\fR"
|
||||
Activate the SPHINX feature for password-authenticated key agreement.
|
||||
This option indicates the \fI<domain>\fR used to retrieve the password
|
||||
from a sphinx oracle daemon reachable via TCP/IP. This is not the
|
||||
network address of the daemon, which is configured in /etc/sphinx
|
||||
.IP "--kdftype \fIargon2 | pbkdf2\fR"
|
||||
Adopt the \fIargon2\fR algorithm for KDF, stressing the RAM capacity rather
|
||||
than the CPU speed of the computer decrypting the tomb. Requires the
|
||||
\fIargon2\fR binary by P-H-C to be installed, as packaged by most distros.
|
||||
Default is \fIpbkdf2\fR.
|
||||
.B
|
||||
.IP "--kdfmem \fI<memory>\fR"
|
||||
In case of \fIargon2\fR KDF algorithm, this value specifies the size of RAM
|
||||
used: it consists of a number which is the elevated power of two in kilobytes.
|
||||
Default is 18 which is 250 MiB (2^18 = 262,144 kilobytes).
|
||||
.B
|
||||
.IP "--sudo \fI<executable>\fR"
|
||||
Select a different tool than sudo for privilege escalation.
|
||||
Alternatives supported so far are: pkexec, doas, sup, sud. For any
|
||||
alternative to work the executable must be included in the current
|
||||
PATH.
|
||||
|
||||
.B
|
||||
.IP "-h"
|
||||
@ -338,7 +363,7 @@ base root of the tomb.
|
||||
.IP "bind-hooks"
|
||||
This hook file consists of a simple text file named \fIbind-hooks\fR
|
||||
containing a two column list of paths to files or directories inside
|
||||
the tomb. The files and directories will be be made directly
|
||||
the tomb. The files and directories will be made directly
|
||||
accessible by the tomb \fIopen\fR command inside the current user's
|
||||
home directory. Tomb uses internally the "mount \-o bind" command to
|
||||
bind locations inside the tomb to locations found in $HOME. In the
|
||||
@ -346,10 +371,10 @@ first column are indicated paths relative to the tomb and in the
|
||||
second column are indicated paths relative to $HOME contents, for
|
||||
example:
|
||||
.EX
|
||||
mail mail
|
||||
.gnupg .gnupg
|
||||
.fmrc .fetchmailrc
|
||||
.mozilla .mozilla
|
||||
mail mail
|
||||
.gnupg .gnupg
|
||||
.fmrc .fetchmailrc
|
||||
.mozilla .mozilla
|
||||
.EE
|
||||
|
||||
.B
|
||||
@ -365,9 +390,9 @@ command.
|
||||
.SH PRIVILEGE ESCALATION
|
||||
|
||||
The tomb commandline tool needs to acquire super user rights to
|
||||
execute most of its operations: to do so it uses sudo(8), while
|
||||
pinentry(1) is adopted to collect passwords from the user. Tomb
|
||||
executes as super user only when required.
|
||||
execute most of its operations: so it uses sudo(8) or other configured
|
||||
tools, while pinentry(1) is adopted to collect passwords from the
|
||||
user. Tomb executes as super user only when required.
|
||||
|
||||
To be made available on multi user systems, the superuser execution of
|
||||
the tomb script can be authorized for users without jeopardizing the
|
||||
@ -380,20 +405,20 @@ whole system's security: just add such a line to \fI/etc/sudoers\fR:
|
||||
To avoid that tomb execution is logged by \fIsyslog\fR also add:
|
||||
|
||||
.EX
|
||||
Cmnd_Alias TOMB = /usr/local/bin/tomb
|
||||
Defaults!TOMB !syslog
|
||||
Cmnd_Alias TOMB = /usr/local/bin/tomb
|
||||
Defaults!TOMB !syslog
|
||||
.EE
|
||||
|
||||
.SH PASSWORD INPUT
|
||||
|
||||
Password input is handled by the pinentry program: it can be text
|
||||
based or graphical and is usually configured with a symlink. When
|
||||
using Tomb in X11 it is better to use a graphical pinentry-gtk2 or
|
||||
pinentry-qt because it helps preventing keylogging by other X
|
||||
clients. When using it from a remote ssh connection it might be
|
||||
necessary to force use of pinentry-curses for instance by unsetting
|
||||
the DISPLAY environment var.
|
||||
|
||||
using Tomb in a graphical environment (X11 or Wayland) it is better
|
||||
to use either pinentry-gtk2 (deprecated), pinentry-gnome or
|
||||
pinentry-qt because it helps preventing keylogging by other clients.
|
||||
When using it from a remote ssh connection it might be necessary to
|
||||
force use of pinentry-tty for instance by unsetting the DISPLAY (X11)
|
||||
or WAYLAND_DISPLAY (Wayland) environment var.
|
||||
|
||||
.SH SWAP
|
||||
|
||||
@ -432,20 +457,10 @@ prefix all invocations of tomb with a blank space, including two lines
|
||||
in ".zshrc":
|
||||
|
||||
.EX
|
||||
export HISTIGNORESPACE=1
|
||||
alias tomb=' tomb'
|
||||
export HISTIGNORESPACE=1
|
||||
alias tomb=' tomb'
|
||||
.EE
|
||||
|
||||
.SH PASSWORD INPUT
|
||||
|
||||
Tomb uses the external program "pinentry" to let users type the key password into a terminal or a graphical window. This program works in conjunction with "gpg-agent", a daemon running in background to facilitate secret key management with gpg. It is recommended one runs "gpg-agent" launching it from the X session initialization ("~/.xsession" or "~/.xinitrc" files) with this command:
|
||||
|
||||
.EX
|
||||
eval $(gpg-agent --daemon --write-env-file "${HOME}/.gpg-agent-info")
|
||||
.EE
|
||||
|
||||
In the future it may become mandatory to run gpg-agent when using tomb.
|
||||
|
||||
.SH SHARE A TOMB
|
||||
A tomb key can be encrypted with more than one recipient. Therefore, a
|
||||
tomb can be shared between different users. The recipients are given
|
||||
@ -458,24 +473,6 @@ its copies are destroyed. The \fI-r\fR option can be used in the tomb
|
||||
commands: \fIopen\fR, \fIforge\fR \fIsetkey\fR, \fIpasswd\fR,
|
||||
\fIbury\fR, \fIexhume\fR and \fIresize\fR.
|
||||
|
||||
.SH SPHINX (PAKE)
|
||||
|
||||
Using the package libsphinx
|
||||
.UR https://github.com/stef/libsphinx
|
||||
.UE
|
||||
and its python client/daemon implementation pwdsphinx
|
||||
.UR https://github.com/stef/pwdsphinx
|
||||
.UE
|
||||
is possible to store and retrieve safely the password that locks the
|
||||
tomb. Using this feature will make it impossible to retrieve the
|
||||
password without the oracle sphinx server running and reachable. Each
|
||||
key entry needs a username and a domain specified on creation and
|
||||
a password that locks it.
|
||||
|
||||
SPHINX makes it impossible to maliciously retrieve the password
|
||||
locking the tomb key without an attacker accessing both the
|
||||
server, the sphinx password and the tomb key file.
|
||||
|
||||
.SH EXAMPLES
|
||||
|
||||
.IP \(bu
|
||||
@ -528,11 +525,11 @@ keeping all its profile data inside it:
|
||||
cat <<EOF > /media/FOX.tomb/exec-hooks
|
||||
#!/bin/sh
|
||||
if [ "$1" = "open" ]; then
|
||||
firefox -no-remote -profile "$2"/firefox-pro &
|
||||
firefox -no-remote -profile "$2"/firefox-pro &
|
||||
fi
|
||||
EOF
|
||||
chmod +x /media/FOX.tomb/exec-hooks
|
||||
mkdir /media/FOX.tomb/firefox-pro
|
||||
chmod +x /media/FOX.tomb/exec-hooks
|
||||
mkdir /media/FOX.tomb/firefox-pro
|
||||
.EE
|
||||
|
||||
.IP \(bu
|
||||
@ -543,13 +540,13 @@ Script a tomb to archive Pictures using Shotwell, launching it on open:
|
||||
cat <<EOF > /media/Pictures.tomb/bind-hooks
|
||||
Pictures Pictures
|
||||
EOF
|
||||
cat <<EOF > /media/Pictures.tomb/exec-hooks
|
||||
cat <<EOF > /media/Pictures.tomb/exec-hooks
|
||||
#!/bin/sh
|
||||
if [ "$1" = "open" ]; then
|
||||
which shotwell > /dev/null
|
||||
if [ "$?" = "0" ]; then
|
||||
shotwell -d "$2"/Pictures/.shotwell &
|
||||
fi
|
||||
which shotwell > /dev/null
|
||||
if [ "$?" = "0" ]; then
|
||||
shotwell -d "$2"/Pictures/.shotwell &
|
||||
fi
|
||||
fi
|
||||
EOF
|
||||
chmod +x /media/Pictures.tomb/exec-hooks
|
||||
|
Binary file not shown.
@ -1647,7 +1647,7 @@ change_tomb_key() {
|
||||
|
||||
_sudo cryptsetup luksClose "${mapper}" || _failure "Unexpected error in luksClose."
|
||||
|
||||
_success "Succesfully changed key for tomb: ::1 tomb file::" $TOMBFILE
|
||||
_success "Successfully changed key for tomb: ::1 tomb file::" $TOMBFILE
|
||||
_message "The new key is: ::1 new key::" $TOMBKEYFILE
|
||||
|
||||
return 0
|
||||
|
5
extras/cloak/Makefile
Normal file
5
extras/cloak/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
install:
|
||||
install -Dm755 cloakify.py ${DESTDIR}${PREFIX}/bin/cloakify
|
||||
install -Dm755 decloakify.py ${DESTDIR}${PREFIX}/bin/decloakify
|
3
extras/cloak/README.md
Normal file
3
extras/cloak/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Cloakify steganography into text files
|
||||
|
||||
Original repo: https://github.com/asrabon/Cloakify-3
|
66
extras/cloak/ciphers/amphibians
Normal file
66
extras/cloak/ciphers/amphibians
Normal file
@ -0,0 +1,66 @@
|
||||
Allophrynidae
|
||||
Pipidae
|
||||
Dicroglossidae
|
||||
Myobatrachidae
|
||||
Mavortium
|
||||
Indotyphlidae
|
||||
Elongatus
|
||||
Croceater
|
||||
Xanthoptica
|
||||
Telmatobiidae
|
||||
Arthroleptidae
|
||||
Phrynobatrachidae
|
||||
Hynobiidae
|
||||
Rivularis
|
||||
Torosa
|
||||
Ranidae
|
||||
Leptodactylidae
|
||||
Dendrobatidae
|
||||
Alsodidae
|
||||
Eleutherodactylidae
|
||||
Bufonidae
|
||||
Craugastoridae
|
||||
Ambystomatidae
|
||||
Hylodidae
|
||||
Croceum
|
||||
Sierrae
|
||||
Ambystoma
|
||||
Micrixalidae
|
||||
Nyctibatrachidae
|
||||
Taricha
|
||||
Typhlonectidae
|
||||
Attenuatus
|
||||
Brachycephalidae
|
||||
Dicamptodon
|
||||
Platycephalus
|
||||
Ichthyophiidae
|
||||
Centrolenidae
|
||||
Plethodontidae
|
||||
Oregonensis
|
||||
Hyperoliidae
|
||||
Batrachoseps
|
||||
Hylidae
|
||||
Rhacophoridae
|
||||
Diabolicus
|
||||
Ensatina
|
||||
Gavilanensis
|
||||
Nigriventris
|
||||
Californiense
|
||||
Rhyacotritonidae
|
||||
Salamandridae
|
||||
Altasierrae
|
||||
Plethodon
|
||||
Megophryidae
|
||||
Sigillatum
|
||||
Variegatus
|
||||
Tenebrosus
|
||||
Microhylidae
|
||||
Pacificus
|
||||
Odontobatrachidae
|
||||
Ceratobatrachidae
|
||||
Odontophrynidae
|
||||
Strabomantidae
|
||||
Mantellidae
|
||||
Hydromantes
|
||||
Siphonopidae
|
||||
Pyxicephalidae
|
66
extras/cloak/ciphers/belgianBeers
Normal file
66
extras/cloak/ciphers/belgianBeers
Normal file
@ -0,0 +1,66 @@
|
||||
Nondedju
|
||||
St. Paul Double
|
||||
Lesage Dubbel
|
||||
La Namuroise
|
||||
Saint-Monon Ambrée
|
||||
Belle-Vue Kriek Classique
|
||||
Floris Framboise
|
||||
Corsendonk Triple 11.11.11
|
||||
Keizer Karel Robijn Rood
|
||||
Waase Wolf
|
||||
Horst bier
|
||||
Morpheus Tripel
|
||||
Mageleno
|
||||
Gordon Finest Copper
|
||||
St. Benoit Blonde
|
||||
Waterloo Tripel 7 Blond
|
||||
Totentrekker
|
||||
Molse Tripel
|
||||
Geuze Mariage Parfait
|
||||
Quest
|
||||
Limerick
|
||||
Buffalo Bitter
|
||||
Mongozo Palmnut
|
||||
La Waterlootoise
|
||||
Serafijn Tripel
|
||||
Lindemans Apple
|
||||
Sint-Gummarus Tripel
|
||||
Steendonk
|
||||
Chimay Wit
|
||||
Podge Oak Aged Stout
|
||||
Liefmans Frambozenbier
|
||||
Louwaege Faro
|
||||
Ypres
|
||||
Hapkin
|
||||
Affligem 950 Cuvee
|
||||
Caulier Brune
|
||||
Hoppe
|
||||
Joseph
|
||||
Florilège de Rose
|
||||
Saison de Dottignies
|
||||
Shark Pants
|
||||
Pikkeling Tripel
|
||||
Den Twaalf
|
||||
Antiek Blond
|
||||
Belgoo Luppoo
|
||||
Cambrinus
|
||||
Adelardus
|
||||
La Rulles Blonde
|
||||
Kapel van Viven Blond
|
||||
Montagnarde Altitude 6
|
||||
Ramée Triple Blond
|
||||
Abbay d'Aulne Triple Blonde
|
||||
't Smisje Calva Reserva
|
||||
De Koninck Winter
|
||||
Holger
|
||||
Zonderik 100
|
||||
Elliot Brew
|
||||
Abbay d'Aulne Val de Sambre
|
||||
Sur-les-Bois Blonde
|
||||
Schaarbeekse Oude Kriek 3 Fonteinen
|
||||
Lustem
|
||||
Rodenbach
|
||||
Vossen met de Meynen Blond
|
||||
Xenophon’s Wine
|
||||
Westhoek XX
|
||||
Brussels Fruit Beer "Red Fruit"
|
107
extras/cloak/ciphers/desserts
Normal file
107
extras/cloak/ciphers/desserts
Normal file
@ -0,0 +1,107 @@
|
||||
honey
|
||||
jelly
|
||||
lollipop
|
||||
spumoni
|
||||
milkshake
|
||||
shortcake
|
||||
souffle
|
||||
flower
|
||||
fondant
|
||||
crunch
|
||||
pineapple
|
||||
marionberry
|
||||
lime
|
||||
pudding
|
||||
sugar
|
||||
caramel
|
||||
granita
|
||||
zest
|
||||
brittle
|
||||
liquer
|
||||
bun
|
||||
toffee
|
||||
ginger
|
||||
custard
|
||||
cookie
|
||||
sucker
|
||||
pistachio
|
||||
meringue
|
||||
eggs
|
||||
peach
|
||||
buttermilk
|
||||
turnover
|
||||
biscuits
|
||||
turtle
|
||||
puffs
|
||||
doughnut
|
||||
apricot
|
||||
nutmeg
|
||||
gingerbread
|
||||
cherry
|
||||
truffle
|
||||
turnovers
|
||||
licorice
|
||||
mousse
|
||||
muffins
|
||||
raspberry
|
||||
sorbet
|
||||
streusel
|
||||
candy
|
||||
torte
|
||||
syrup
|
||||
terrine
|
||||
curd
|
||||
hazelnut
|
||||
brownie
|
||||
strawberries
|
||||
blueberry
|
||||
coconut
|
||||
butterscotch
|
||||
cookies
|
||||
huckleberry
|
||||
icing
|
||||
walnut
|
||||
pie
|
||||
snickerdoodles
|
||||
cannoli
|
||||
marzipan
|
||||
cake
|
||||
compote
|
||||
bonbon
|
||||
glaze
|
||||
flan
|
||||
cane
|
||||
foster
|
||||
sherbet
|
||||
ganache
|
||||
cream
|
||||
buttercream
|
||||
jam
|
||||
cobbler
|
||||
tirimisu
|
||||
creme
|
||||
cupcake
|
||||
cinnamon
|
||||
mint
|
||||
vanilla
|
||||
éclair
|
||||
taffy
|
||||
orange
|
||||
almond
|
||||
rhubarb
|
||||
pastry
|
||||
brulee
|
||||
lemon
|
||||
cheesecake
|
||||
chocolate
|
||||
donut
|
||||
sundae
|
||||
peach pie
|
||||
shortbread
|
||||
frosting
|
||||
parfaits
|
||||
blackberry
|
||||
popsicle
|
||||
confection
|
||||
crepe
|
||||
macaroon
|
100
extras/cloak/ciphers/dessertsArabic
Normal file
100
extras/cloak/ciphers/dessertsArabic
Normal file
@ -0,0 +1,100 @@
|
||||
سلحفاة
|
||||
كاب كيك
|
||||
ترين
|
||||
معجنات
|
||||
مرزبانية حلوى لوز وسكر
|
||||
اللبن المخفوق
|
||||
مخيض اللبن
|
||||
كعكة فواكه
|
||||
القاناش
|
||||
مصاصة
|
||||
ايكلير
|
||||
زهرة
|
||||
أقراص سكرية
|
||||
دوران
|
||||
بروليه
|
||||
عرق السوس
|
||||
المصاصة
|
||||
بقلمي
|
||||
مشمش
|
||||
نفث
|
||||
الإسكافي
|
||||
تبرع
|
||||
تيريميسو
|
||||
كلس
|
||||
تلذذ
|
||||
.توت
|
||||
لوز
|
||||
كعكة الغريبة
|
||||
فراولة
|
||||
كرز
|
||||
جنية سمراء صغيرة
|
||||
تحولات
|
||||
خبز الزنجبيل
|
||||
سطح أملس
|
||||
فستق
|
||||
تورتى
|
||||
كومبوت
|
||||
نعناع
|
||||
نبات
|
||||
شوكولاتة
|
||||
قصب
|
||||
كعكة
|
||||
كريم
|
||||
كريب
|
||||
مرنغ
|
||||
نفيخة
|
||||
الكعك
|
||||
البون بون
|
||||
كاسترد
|
||||
أناناس
|
||||
الكرمل
|
||||
يكر
|
||||
عسل
|
||||
الزبد
|
||||
شراب مركز
|
||||
السكر
|
||||
شربات
|
||||
خوخ
|
||||
جوزة الطيب
|
||||
الموسية
|
||||
سكريات الطوفي حلوى
|
||||
راوند
|
||||
بندق
|
||||
تخثر
|
||||
فطيرة الجبن
|
||||
سبوموني
|
||||
الحاضنة
|
||||
زنجبيل
|
||||
فطيرة
|
||||
كوكي
|
||||
البسكويت
|
||||
بسكويت
|
||||
جرانيتا
|
||||
صقيع
|
||||
البرتقالي
|
||||
جوزة الهند
|
||||
بودنغ
|
||||
حلوى
|
||||
الكمأة
|
||||
توت العُليق
|
||||
معكرون نوع حلوي
|
||||
كانولي
|
||||
فطيرة الخوخ
|
||||
سحق
|
||||
هش
|
||||
قرفة
|
||||
ليمون
|
||||
هلام
|
||||
جوز
|
||||
الفانيليا
|
||||
بارفيتس
|
||||
مثلجات
|
||||
إبله
|
||||
بلاك بيري
|
||||
[ستريوسل]
|
||||
حلوى من سكر أسمر وزبدة
|
||||
الكعك المحلى بالسكر
|
||||
مربى
|
||||
بيض
|
||||
تثليج
|
94
extras/cloak/ciphers/dessertsChinese
Normal file
94
extras/cloak/ciphers/dessertsChinese
Normal file
@ -0,0 +1,94 @@
|
||||
蛋糕
|
||||
甜甜圈
|
||||
草莓
|
||||
橙
|
||||
焦糖
|
||||
糖浆
|
||||
越橘
|
||||
姜
|
||||
酥皮
|
||||
蛋白杏仁饼干
|
||||
榛子
|
||||
乳蛋糕
|
||||
果仁蛋糕
|
||||
皮匠
|
||||
香草
|
||||
培育
|
||||
周转
|
||||
糖粉奶油细末
|
||||
杯形饼
|
||||
棒糖
|
||||
软糖
|
||||
酸橙
|
||||
脆
|
||||
酥
|
||||
棒冰
|
||||
核桃
|
||||
覆盆子
|
||||
包子
|
||||
杏
|
||||
果盘
|
||||
樱桃
|
||||
乳酪蛋糕
|
||||
紧缩
|
||||
糖
|
||||
糖果
|
||||
柠檬
|
||||
松露
|
||||
失误
|
||||
奶油曲奇
|
||||
巧克力
|
||||
龟
|
||||
奶糖
|
||||
桃子馅饼
|
||||
甘草
|
||||
桃
|
||||
凝乳
|
||||
杂音
|
||||
太妃糖
|
||||
热情
|
||||
圣代
|
||||
冻糕
|
||||
布朗尼
|
||||
格兰尼塔
|
||||
果酱
|
||||
果冻
|
||||
布丁
|
||||
鸡蛋
|
||||
黑莓
|
||||
开心果
|
||||
奶昔
|
||||
肉桂
|
||||
甘蔗
|
||||
薄荷
|
||||
酪
|
||||
糕点
|
||||
杏仁
|
||||
釉
|
||||
肉豆蔻
|
||||
冰糕
|
||||
松饼
|
||||
果子露
|
||||
花
|
||||
绉
|
||||
菠萝
|
||||
大黄
|
||||
蓝莓
|
||||
沙锅
|
||||
结霜
|
||||
邦邦
|
||||
蜜饯
|
||||
吸盘
|
||||
姜饼
|
||||
香炸奶酪卷
|
||||
奶油
|
||||
伽纳彻
|
||||
曲奇饼
|
||||
椰子
|
||||
果馅饼
|
||||
馅饼
|
||||
摩丝
|
||||
积冰
|
||||
泡芙
|
||||
蜂蜜
|
||||
饼干
|
84
extras/cloak/ciphers/dessertsHindi
Normal file
84
extras/cloak/ciphers/dessertsHindi
Normal file
@ -0,0 +1,84 @@
|
||||
केक
|
||||
बादाम का मीठा हलुआ
|
||||
टुकड़े
|
||||
कुचले हुए फल
|
||||
जायफल
|
||||
कलाकंद
|
||||
कुकी
|
||||
कप केक
|
||||
दालचीनी
|
||||
क्रेप
|
||||
कारोबार
|
||||
चीज़केक
|
||||
खुबानी
|
||||
बटरस्कॉच
|
||||
सिरप
|
||||
टाफ़ी
|
||||
जाम
|
||||
जिंजरब्रेड
|
||||
नारंगी
|
||||
कुकीज़
|
||||
ठंडा करना
|
||||
ब्राउनी
|
||||
पाई
|
||||
शहद
|
||||
क्रीम
|
||||
एक प्रकार का फल
|
||||
बिस्कुट
|
||||
आड़ू
|
||||
चीनी
|
||||
अदरक
|
||||
मिठाई
|
||||
टोफ़ी
|
||||
नद्यपान
|
||||
नाज़ुक
|
||||
चेरी
|
||||
चूसने की मिठाई
|
||||
वनीला
|
||||
दही
|
||||
दिलचस्पी
|
||||
गन्ना
|
||||
पिस्ता
|
||||
चॉकलेट
|
||||
मोची
|
||||
गनाचे
|
||||
अंडे
|
||||
शीशे का आवरण
|
||||
कचौड़ी
|
||||
पेस्ट्री
|
||||
छाछ
|
||||
जेली
|
||||
नारियल
|
||||
बन
|
||||
चूना
|
||||
कश
|
||||
की कमी
|
||||
फ़्लान
|
||||
कारमेल
|
||||
नींबू
|
||||
शर्बत
|
||||
आड़ु पाई
|
||||
मिल्कशेक
|
||||
फूल
|
||||
डोनट
|
||||
स्ट्रॉबेरीज
|
||||
पालक
|
||||
अखरोट
|
||||
ब्लूबेरी
|
||||
पुदीना
|
||||
मलाई
|
||||
मानसिक शांति
|
||||
हेज़लनट
|
||||
ब्लैकबेरी
|
||||
बादाम
|
||||
रसभरी
|
||||
कैंडी
|
||||
मूस
|
||||
टर्नओवर
|
||||
बॉन बॉन
|
||||
कछुआ
|
||||
चूसने वाला
|
||||
कस्टर्ड
|
||||
कुकुरमुत्ता
|
||||
पुडिंग
|
||||
अनानास
|
92
extras/cloak/ciphers/dessertsPersian
Normal file
92
extras/cloak/ciphers/dessertsPersian
Normal file
@ -0,0 +1,92 @@
|
||||
آناناس
|
||||
تخم مرغ
|
||||
بستنی چوبی
|
||||
حجم معاملات
|
||||
بستنی و مغز گردو
|
||||
نان شیرینی مرکب از شکر و زرده تخم مرغ و بادام
|
||||
فندق
|
||||
زنجبیل
|
||||
ژله
|
||||
گردو
|
||||
دونات
|
||||
پینه دوز
|
||||
لاک پشت
|
||||
مستی
|
||||
زغال اخته
|
||||
پسته
|
||||
سرخ
|
||||
طفل شیرخوار
|
||||
گل
|
||||
میلک شیک
|
||||
شیرینی زنجفیلی
|
||||
شکننده
|
||||
جوز
|
||||
نارگیل
|
||||
پودینگ
|
||||
نارنجی
|
||||
ابدوغ
|
||||
کلوچه
|
||||
کمپوت
|
||||
بحران
|
||||
شکلات
|
||||
هلو
|
||||
شربت
|
||||
کرپ
|
||||
کیک تخم مرغ و شکر و مغز گردو
|
||||
تمشک
|
||||
لیمو شیرین
|
||||
عسل
|
||||
گردش
|
||||
زردالو
|
||||
کیک میوه
|
||||
پای
|
||||
کیک
|
||||
بستنی میوه
|
||||
تافی
|
||||
کرم رنگ
|
||||
کوکی
|
||||
اب نبات چوبی
|
||||
نوعی کیک میوه دار
|
||||
توت سیاه
|
||||
ریواس
|
||||
فاستر
|
||||
وانیل
|
||||
نبات
|
||||
بیسکویت
|
||||
قارچ خوراکی دنبلان
|
||||
لیکور
|
||||
شیرینی
|
||||
شکر و تخم مرغ
|
||||
بستنی میوه و مغز بادام و میوه جات ایتالیایی
|
||||
یکجور دوربین عکاسی
|
||||
شیرین بیان
|
||||
کماج
|
||||
فوندانت
|
||||
نیشکر
|
||||
کرم
|
||||
پاف
|
||||
قند
|
||||
نعناع
|
||||
موس
|
||||
گرانیت
|
||||
دارچین
|
||||
اهک
|
||||
پوشش
|
||||
گراوند
|
||||
بادام
|
||||
فیالبداهه
|
||||
پای هلو
|
||||
شیرینی خامهدار و بستنی دار
|
||||
کیک پنیر
|
||||
نوعی کیک کوچک
|
||||
توت فرنگی
|
||||
رنگ زرد
|
||||
مربا
|
||||
سوفله
|
||||
کاستارد
|
||||
درخت زغال اخته
|
||||
کشک
|
||||
گیلاس
|
||||
مزه
|
||||
نان روغنی
|
||||
لعاب
|
90
extras/cloak/ciphers/dessertsRussian
Normal file
90
extras/cloak/ciphers/dessertsRussian
Normal file
@ -0,0 +1,90 @@
|
||||
присоска
|
||||
праздничный торт
|
||||
малина
|
||||
трюфель
|
||||
лесной орех
|
||||
леденец
|
||||
кремовый
|
||||
песочное печенье
|
||||
ананас
|
||||
мускатный орех
|
||||
лайм
|
||||
печенье
|
||||
сироп
|
||||
абрикос
|
||||
лимон
|
||||
кондитерские изделия
|
||||
миндальное печенье
|
||||
эклер
|
||||
конфета
|
||||
имбирный пряник
|
||||
чизкейк
|
||||
ваниль
|
||||
крем
|
||||
сапожник
|
||||
флан
|
||||
цветок
|
||||
мусс
|
||||
творог
|
||||
шоколад
|
||||
брюле
|
||||
хруст
|
||||
кексы
|
||||
черепаха
|
||||
карамель
|
||||
имбирь
|
||||
обороты
|
||||
иней
|
||||
желе
|
||||
пирог
|
||||
яйца
|
||||
домовой
|
||||
фисташковый
|
||||
парфе
|
||||
варенье
|
||||
сахар
|
||||
кекс
|
||||
грецкий орех
|
||||
глазурь
|
||||
мята
|
||||
обледенение
|
||||
затяжек
|
||||
булочка
|
||||
эскимо
|
||||
конфеты
|
||||
тростник
|
||||
ликер
|
||||
вишня
|
||||
кокос
|
||||
суфле
|
||||
персиковый пирог
|
||||
корица
|
||||
помадка
|
||||
молочный коктейль
|
||||
пудинг
|
||||
черника
|
||||
ежевика
|
||||
ревень
|
||||
меренга
|
||||
ириски
|
||||
персик
|
||||
ломкий
|
||||
пломбир
|
||||
ириска
|
||||
пончик
|
||||
миндальный
|
||||
блюдо из дичи
|
||||
марципан
|
||||
лакрица
|
||||
способствовать
|
||||
заварной крем
|
||||
мед
|
||||
компот
|
||||
пахта
|
||||
цедра
|
||||
оборот
|
||||
канноли
|
||||
оранжевый
|
||||
шербет
|
||||
клубника
|
||||
креп
|
104
extras/cloak/ciphers/dessertsSwedishChef
Normal file
104
extras/cloak/ciphers/dessertsSwedishChef
Normal file
@ -0,0 +1,104 @@
|
||||
boon
|
||||
meelksheke-a
|
||||
brooneee-a
|
||||
mooffffeens
|
||||
coosterd
|
||||
bleckberry
|
||||
ceennemun
|
||||
tureemisoo
|
||||
teffffy
|
||||
cubbler
|
||||
guneche-a
|
||||
fundunt
|
||||
pooddeeng
|
||||
perffeeets
|
||||
shurtbreed
|
||||
meceruun
|
||||
syroop
|
||||
flooer
|
||||
meent
|
||||
suooffffle-a
|
||||
cuukeee-a
|
||||
merzeepun
|
||||
bootterscutch
|
||||
creme-a
|
||||
soondee-a
|
||||
streoosel
|
||||
creem
|
||||
ceremel
|
||||
cherry
|
||||
sooger
|
||||
shurtceke-a
|
||||
hoockleberry
|
||||
hezelnoot
|
||||
geenger
|
||||
oorunge-a
|
||||
tuffffee-a
|
||||
muoosse-a
|
||||
cunnulee
|
||||
sherbet
|
||||
jelly
|
||||
cheeseceke-a
|
||||
chuculete-a
|
||||
cune-a
|
||||
coopceke-a
|
||||
cuukeees
|
||||
surbet
|
||||
crepe-a
|
||||
iceeng
|
||||
duooghnoot
|
||||
pestry
|
||||
toortle-a
|
||||
mereengooe-a
|
||||
gruneeta
|
||||
leeme-a
|
||||
epreecut
|
||||
sneeckerduudles
|
||||
toornufers
|
||||
beescooits
|
||||
gleze-a
|
||||
rhooberb
|
||||
huney
|
||||
coord
|
||||
lulleepup
|
||||
bunbun
|
||||
dunoot
|
||||
ceke-a
|
||||
breettle-a
|
||||
croonch
|
||||
leeqooer
|
||||
frusteeng
|
||||
pupseecle-a
|
||||
spoomunee
|
||||
cundy
|
||||
pooffffs
|
||||
soocker
|
||||
blooeberry
|
||||
toornufer
|
||||
nootmeg
|
||||
broolee-a
|
||||
lemun
|
||||
cunffecshun
|
||||
terreene-a
|
||||
respberry
|
||||
elmund
|
||||
turte-a
|
||||
velnoot
|
||||
mereeunberry
|
||||
fuster
|
||||
peee-a
|
||||
peech
|
||||
trooffffle-a
|
||||
cumpute-a
|
||||
leecurice-a
|
||||
cucunoot
|
||||
peeneepple-a
|
||||
jem
|
||||
geengerbreed
|
||||
iggs
|
||||
flun
|
||||
zest
|
||||
peestechiu
|
||||
strevberreees
|
||||
écleur
|
||||
funeella
|
86
extras/cloak/ciphers/dessertsThai
Normal file
86
extras/cloak/ciphers/dessertsThai
Normal file
@ -0,0 +1,86 @@
|
||||
นมผสมไอศกรีม
|
||||
ไข่
|
||||
แห้ว
|
||||
เปลือกน้ำฅาล
|
||||
ครีม
|
||||
ผลไม้ชนิดหนึ่ง
|
||||
ผลไม้แช่อิ่ม
|
||||
ขนมเมอร์แรง
|
||||
ฉาบ
|
||||
ความเอร็ดอร่อย
|
||||
คุกกี้
|
||||
โดนัท
|
||||
ลูกจันทน์เทศ
|
||||
นมเปรี้ยว
|
||||
พาย
|
||||
ขนมชนิดร่วน
|
||||
ไอติม
|
||||
ราสเบอร์รี่
|
||||
ทอฟฟี่
|
||||
เฮเซลนัท
|
||||
ขนมปิ้ง
|
||||
อ้อย
|
||||
ทำเหรียญ
|
||||
น้ำผึ้ง
|
||||
มะพร้าว
|
||||
กาละแม
|
||||
อุปถัมภ์
|
||||
บัตเตอร์
|
||||
อาหารตีให้เป็นฟอง
|
||||
ขนมปังขิง
|
||||
เชอร์รี่
|
||||
พุดดิ้ง
|
||||
ผักชนิดหนึ่ง
|
||||
มวย
|
||||
ผลประกอบการ
|
||||
สีส้ม
|
||||
ต้นมันฮ่อ
|
||||
ลูกอม
|
||||
อัลมอนด์
|
||||
ขนมแมคะรูน
|
||||
สตรอเบอร์รี่
|
||||
เครื่องปรุงอาหารมาร์ซิปัน
|
||||
มะนาว
|
||||
ขนมปังกรอบ
|
||||
ลูกกวาด
|
||||
คัพเค้ก
|
||||
ฅกประหม่า
|
||||
ผี
|
||||
อบเชย
|
||||
ขนมชนิดหนึ่ง
|
||||
น้ำเชื่อม
|
||||
เต่า
|
||||
แอปริคอท
|
||||
ขนมเค้กเนยแข็ง
|
||||
พาย ลูกพีช
|
||||
เครื่องดื่มเชอร์เบ็ท
|
||||
วุ้น
|
||||
เค้ก
|
||||
กระทืบ
|
||||
ช็อคโกแลต
|
||||
มูสส์
|
||||
แพรย่น
|
||||
ผลไม้ดำนำ้เงินลูเล็ก ๆ
|
||||
ขิง
|
||||
คัสตาร์
|
||||
ไอศกรีมใส่ผลไม้
|
||||
แยม
|
||||
เครื่องดูด
|
||||
มัฟฟิน
|
||||
ขนมที่ติดกับปลายไม้
|
||||
ดอกไม้
|
||||
น้ำตาล
|
||||
หลากสี
|
||||
บลูเบอร์รี่
|
||||
พีช
|
||||
วานิลลา
|
||||
เชอร์เบท
|
||||
คุ้กกี้
|
||||
พิสตาเชีย
|
||||
เคลือบน้ำแข็ง
|
||||
เปราะ
|
||||
พัฟ
|
||||
พายผลไม้
|
||||
พืชชะเอ็ม
|
||||
สับปะรด
|
||||
บัตเตอร์ครีม
|
70
extras/cloak/ciphers/emoji
Normal file
70
extras/cloak/ciphers/emoji
Normal file
@ -0,0 +1,70 @@
|
||||
😀
|
||||
😴
|
||||
😜
|
||||
😝
|
||||
😩
|
||||
😃
|
||||
😛
|
||||
😕
|
||||
😏
|
||||
👊
|
||||
🙉
|
||||
😿
|
||||
😅
|
||||
😁
|
||||
😭
|
||||
🐱
|
||||
😸
|
||||
🙌
|
||||
😓
|
||||
🙈
|
||||
🐨
|
||||
😽
|
||||
🐵
|
||||
😮
|
||||
😈
|
||||
😆
|
||||
😑
|
||||
😶
|
||||
🐔
|
||||
😂
|
||||
😪
|
||||
😥
|
||||
🙆
|
||||
😲
|
||||
🙇
|
||||
😾
|
||||
😹
|
||||
🙍
|
||||
😗
|
||||
😳
|
||||
😼
|
||||
😧
|
||||
🐸
|
||||
🙀
|
||||
🖖
|
||||
😌
|
||||
😟
|
||||
🙅
|
||||
😬
|
||||
🙊
|
||||
🐼
|
||||
😄
|
||||
😣
|
||||
🐻
|
||||
😻
|
||||
😱
|
||||
😯
|
||||
😷
|
||||
😊
|
||||
🐂
|
||||
🐰
|
||||
😵
|
||||
😰
|
||||
🙏
|
||||
🙎
|
||||
😺
|
||||
🙋
|
||||
😫
|
||||
😡
|
||||
😙
|
65
extras/cloak/ciphers/evadeAV
Normal file
65
extras/cloak/ciphers/evadeAV
Normal file
@ -0,0 +1,65 @@
|
||||
4
|
||||
v
|
||||
q
|
||||
m
|
||||
0
|
||||
B
|
||||
j
|
||||
u
|
||||
E
|
||||
e
|
||||
g
|
||||
J
|
||||
w
|
||||
y
|
||||
Y
|
||||
Q
|
||||
D
|
||||
H
|
||||
t
|
||||
x
|
||||
i
|
||||
3
|
||||
6
|
||||
f
|
||||
O
|
||||
C
|
||||
9
|
||||
N
|
||||
a
|
||||
T
|
||||
Z
|
||||
F
|
||||
A
|
||||
5
|
||||
G
|
||||
M
|
||||
h
|
||||
s
|
||||
o
|
||||
7
|
||||
l
|
||||
U
|
||||
k
|
||||
R
|
||||
L
|
||||
X
|
||||
n
|
||||
r
|
||||
W
|
||||
d
|
||||
P
|
||||
K
|
||||
S
|
||||
I
|
||||
c
|
||||
=
|
||||
+
|
||||
/
|
||||
8
|
||||
V
|
||||
2
|
||||
1
|
||||
p
|
||||
b
|
||||
z
|
199
extras/cloak/ciphers/geoCoordsWorldCapitals
Normal file
199
extras/cloak/ciphers/geoCoordsWorldCapitals
Normal file
@ -0,0 +1,199 @@
|
||||
18°21'N 64°56'W
|
||||
05°50'N 55°10'W
|
||||
00°15'S 78°35'W
|
||||
12°06'N 86°20'W
|
||||
13°50'S 171°50'W
|
||||
14°36'N 61°02'W
|
||||
59°55'N 10°45'E
|
||||
43°52'N 18°26'E
|
||||
50°30'N 30°28'E
|
||||
37°31'N 126°58'E
|
||||
29°18'S 27°30'E
|
||||
06°55'N 158°09'E
|
||||
51°40'S 59°51'W
|
||||
37°58'N 23°46'E
|
||||
01°59'S 30°04'E
|
||||
25°10'S 57°30'W
|
||||
04°00'N 73°28'E
|
||||
35°10'N 33°25'E
|
||||
05°35'N 00°06'W
|
||||
22°35'S 17°04'E
|
||||
03°16'S 29°18'E
|
||||
14°40'N 121°03'E
|
||||
02°02'N 45°25'E
|
||||
52°23'N 04°54'E
|
||||
09°24'S 147°08'E
|
||||
18°40'N 72°20'W
|
||||
46°04'N 14°33'E
|
||||
12°00'S 77°00'W
|
||||
35°54'N 14°31'E
|
||||
27°31'N 89°45'E
|
||||
23°08'N 82°22'W
|
||||
15°31'N 32°35'E
|
||||
17°20'N 61°48'W
|
||||
21°05'N 105°55'E
|
||||
09°00'N 79°25'W
|
||||
33°40'N 73°10'E
|
||||
49°26'N 02°33'W
|
||||
14°00'S 33°48'E
|
||||
59°22'N 24°48'E
|
||||
53°00'S 74°00'E
|
||||
24°45'S 25°57'E
|
||||
18°28'N 66°07'W
|
||||
15°28'S 28°16'E
|
||||
53°52'N 27°30'E
|
||||
42°01'N 21°26'E
|
||||
25°58'S 32°32'E
|
||||
09°05'N 07°32'E
|
||||
11°40'S 43°16'E
|
||||
00°25'N 09°26'E
|
||||
22°17'S 166°30'E
|
||||
25°05'N 77°20'W
|
||||
19°20'N 99°10'W
|
||||
36°30'S 60°00'W
|
||||
45°50'N 15°58'E
|
||||
09°02'N 38°42'E
|
||||
31°57'N 35°52'E
|
||||
17°32'S 149°34'W
|
||||
12°10'N 14°59'E
|
||||
14°16'S 170°43'W
|
||||
35°15'S 149°08'E
|
||||
01°17'S 36°48'E
|
||||
06°23'N 02°42'E
|
||||
12°15'N 01°30'W
|
||||
41°19'S 174°46'E
|
||||
04°23'N 18°35'E
|
||||
46°46'N 56°12'W
|
||||
24°28'N 54°22'E
|
||||
18°00'N 76°50'W
|
||||
40°25'N 03°45'W
|
||||
14°05'N 87°14'W
|
||||
15°02'N 23°34'W
|
||||
13°28'N 16°40'W
|
||||
23°43'N 90°26'E
|
||||
42°45'N 23°20'E
|
||||
09°55'N 84°02'W
|
||||
12°05'N 69°00'W
|
||||
49°37'N 06°09'E
|
||||
48°12'N 16°22'E
|
||||
41°43'N 44°50'E
|
||||
40°10'N 44°31'E
|
||||
04°34'N 74°00'W
|
||||
41°20'N 69°10'E
|
||||
13°10'N 61°10'W
|
||||
41°54'N 12°29'E
|
||||
41°18'N 19°49'E
|
||||
39°55'N 116°20'E
|
||||
44°27'N 26°10'E
|
||||
46°57'N 07°28'E
|
||||
08°31'S 179°13'E
|
||||
24°41'N 46°42'E
|
||||
50°51'N 04°21'E
|
||||
35°44'N 51°30'E
|
||||
12°34'N 07°55'W
|
||||
04°52'N 115°00'E
|
||||
40°29'N 49°56'E
|
||||
27°45'N 85°20'E
|
||||
21°10'S 174°00'W
|
||||
43°55'N 12°30'E
|
||||
42°31'N 01°32'E
|
||||
18°30'N 69°59'W
|
||||
33°20'N 44°30'E
|
||||
05°05'N 52°18'W
|
||||
04°20'S 15°15'E
|
||||
53°21'N 06°15'W
|
||||
00°10'N 06°39'E
|
||||
17°17'N 62°43'W
|
||||
54°38'N 25°19'E
|
||||
32°49'N 13°07'E
|
||||
47°02'N 28°50'E
|
||||
30°01'N 31°14'E
|
||||
14°34'N 17°29'W
|
||||
34°28'N 69°11'E
|
||||
15°47'S 47°55'W
|
||||
13°45'N 100°35'E
|
||||
08°50'S 13°15'E
|
||||
20°10'S 57°30'E
|
||||
00°20'N 32°30'E
|
||||
16°45'N 96°20'E
|
||||
64°10'N 51°35'W
|
||||
12°48'S 45°14'E
|
||||
11°08'N 42°20'E
|
||||
64°10'N 21°57'W
|
||||
55°45'N 37°35'E
|
||||
28°37'N 77°13'E
|
||||
03°09'N 101°41'E
|
||||
60°15'N 25°03'E
|
||||
03°45'N 08°50'E
|
||||
15°12'N 145°45'E
|
||||
15°19'N 38°55'E
|
||||
09°29'N 13°49'W
|
||||
56°53'N 24°08'E
|
||||
29°30'N 48°00'E
|
||||
17°43'S 1°02'E
|
||||
16°20'S 68°10'W
|
||||
08°30'N 13°17'W
|
||||
31°47'N 35°12'E
|
||||
45°20'S 168°43'E
|
||||
48°10'N 17°07'E
|
||||
06°49'N 05°17'W
|
||||
22°12'N 113°33'E
|
||||
06°18'N 10°47'W
|
||||
25°44'S 28°12'E
|
||||
38°33'N 68°48'E
|
||||
48°50'N 02°20'E
|
||||
10°30'N 66°55'W
|
||||
18°27'N 64°37'W
|
||||
36°50'N 10°11'E
|
||||
17°45'S 168°18'E
|
||||
11°33'N 104°55'E
|
||||
08°29'S 125°34'E
|
||||
52°13'N 21°00'E
|
||||
51°36'N 00°05'W
|
||||
33°30'N 36°18'E
|
||||
62°05'N 06°56'W
|
||||
26°10'N 50°30'E
|
||||
15°20'N 61°24'W
|
||||
42°54'N 74°46'E
|
||||
39°91'N 77°02'W
|
||||
06°50'N 58°12'W
|
||||
01°30'N 173°00'E
|
||||
39°57'N 32°54'E
|
||||
44°50'N 20°37'E
|
||||
16°00'N 61°44'W
|
||||
47°29'N 19°05'E
|
||||
17°58'N 102°36'E
|
||||
18°55'S 47°31'E
|
||||
06°09'N 01°20'E
|
||||
11°45'N 15°45'W
|
||||
33°53'N 35°31'E
|
||||
13°40'N 89°10'W
|
||||
34°50'S 56°11'W
|
||||
17°18'N 88°30'W
|
||||
06°09'S 106°49'E
|
||||
47°08'N 09°31'E
|
||||
51°10'N 71°30'E
|
||||
45°27'N 75°42'W
|
||||
52°30'N 13°25'E
|
||||
13°27'N 02°06'E
|
||||
38°00'N 57°50'E
|
||||
50°05'N 14°22'E
|
||||
14°02'N 60°58'W
|
||||
14°40'N 90°22'W
|
||||
03°50'N 11°35'E
|
||||
13°05'N 59°30'W
|
||||
33°24'S 70°40'W
|
||||
07°20'N 134°28'E
|
||||
36°42'N 03°08'E
|
||||
38°42'N 09°10'W
|
||||
12°32'N 70°02'W
|
||||
18°06'S 178°30'E
|
||||
06°08'S 35°45'E
|
||||
59°20'N 18°03'E
|
||||
09°27'S 159°57'E
|
||||
04°09'S 15°12'E
|
||||
23°37'N 58°36'E
|
||||
25°15'N 51°35'E
|
||||
39°09'N 125°30'E
|
||||
19°20'N 81°24'W
|
||||
26°18'S 31°06'E
|
82
extras/cloak/ciphers/geocache
Normal file
82
extras/cloak/ciphers/geocache
Normal file
@ -0,0 +1,82 @@
|
||||
Carley State Park N 44 º 06.717 W 092 º 10.390
|
||||
Scenic State Park N 47 º 42.700 W 093 º 34.167
|
||||
Lake Bronson State Park N 48 º 43.472 W 096 º 37.545
|
||||
Myre-Big Island State Park N 43 º 38.226 W 093 º 18.541
|
||||
Interstate State Park N 45 º 23.518 W 092 º 40.199
|
||||
Tettegouche State Park N 47 º 21.592 W 091 º 16.939
|
||||
Garden Island State Recreation Area N 49 º 10.537 W 094 º 50.031
|
||||
Nerstrand Big Woods State Park N 44 º 20.533 W 093 º 06.339
|
||||
Bear Head Lake State Park N 47o 47.787 W 092o 03.858
|
||||
Cascade River State Park. N 47 º 42.660 W 090 º 30.643
|
||||
Mille Lacs Kathio State Park N 46 º 08.132 W 093 º 43.520
|
||||
Schoolcraft State Park N 47 º 13.390 W 093 º 48.252
|
||||
Frontenac State Park N 44 º 31.428 W 092 º 20.467
|
||||
Temperance River State Park N 47 º 33.241 W 090 º 52.498
|
||||
Cuyuna Country State Recreation Area N 46 º 28.724 W 093 º 58.598
|
||||
Brown’s Creek State Trail N 45 º 04.531 W 092 º 49.776
|
||||
Minnesota Valley State Trail N 44 º 46.901 W 093 º 35.350
|
||||
Lake Louise State Park N 43 º 31.739 W 092 º 31.452
|
||||
Itasca State Park N 47 º 11.488 W 095 º 10.199
|
||||
Split Rock Creek State Park N 43 º 53.664 W 096 º 21.941
|
||||
Kilen Woods State Park N 43 º 43.858 W 095 º 04.101
|
||||
Zippel Bay State Park N 48 º 50.891 W 094 º 50.859
|
||||
Split Rock Lighthouse State Park N 47 º 11.912 W 091 º 22.479
|
||||
George H. Crosby Manitou State Park N 47 º 28.732 W 091 º 06.703
|
||||
Glendalough State Park N 46 º 19.233 W 095 º 40.287
|
||||
Gateway State Trail N 45 º 03.522 W 092 º 55.627
|
||||
Sakatah Lake State Park N 44 º 13.504 W 093 º 31.181
|
||||
Hill Annex Mine State Park N 47 º 19.585 W 093 º 16.697
|
||||
Root River State Trail N 43 º 46.298 W 091 º 38.153
|
||||
Lake Bemidji State Park N 47 º 32.079 W 094 º 49.590
|
||||
La Salle Lake State Recreation Area N 47 º 20.697 W 095 º 09.507
|
||||
Franz Jevne State Park N 48 º 38.526 W 094 º 03.773
|
||||
Minnesota Valley State Recreation Area N 44 º 39.144 W 093 º 42.849
|
||||
Sibley State Park N 45 º 18.865 W 095 º 02.355
|
||||
Blazing Star State Trail N 43 º 38.226 W 093 º 18.541
|
||||
Judge C.R. Magney State Park N 47 º 49.082 W 090 º 03.173
|
||||
Iron Range Off-Highway Vehicle State Recreation Area N 47 º 28.721 W 092 º 26.319
|
||||
Upper Sioux Agency State Park N 44o 44.203 W 095 º 27.571
|
||||
Blue Mounds State Park N 43 º 41.474 W 096 º 11.807
|
||||
Luce Line State Trail N 44 º 59.163 W 093 º 29.651
|
||||
Fort Snelling State Park N 44o 53.349 W 093o 11.014
|
||||
Fort Ridgely State Park N 44 º 27.193 W 094 º 43.607
|
||||
Hayes Lake State Park N 48 º 38.257 W 095 º 32.739
|
||||
Charles A. Lindbergh State Park N 45 º 57.548 W 094 º 23.337
|
||||
Lake Maria State Park N 45 º 19.070 W 093 º 56.139
|
||||
Gooseberry Falls State Park N 47 º 08.463 W 091 º 28.207
|
||||
Savanna Portage State Park N 46 º 49.716 W 093 º 09.031
|
||||
Grand Portage State Park N 48 º 00.200 W 089 º 35.657
|
||||
Greenleaf Lake State Recreation Area N 45 º 00.536 W 094 º 28.491
|
||||
Forestville/Mystery Cave State Park N 43 º 38.425 W 092 º 13.110
|
||||
Big Stone Lake State Park N 45 º 23.126 W 096 º 32.099
|
||||
Lake Vermilion-Soudan Underground Mine State Park N 47 º 49.197 W 092 º 14.320
|
||||
Red River State Recreation Area N 47 º 55.743 W 097 º 01.723
|
||||
Great River Bluffs State Park N 46 º 51.919 W 096 º 28.031
|
||||
Crow Wing State Park N 46 º 16.389 W 094 º 19.972
|
||||
Beaver Creek Valley State Park N 43 º 38.571 W 091 º 34.872
|
||||
Shooting Star State Trail N 43 º 31.547 W 092 º 30.986
|
||||
Glacial Lakes State Park N 45 º 32.438 W 095 º 31.430
|
||||
Flandrau State Park N 44 º 17.596 W 094 º 28.065
|
||||
Lac Qui Parle State Park N 45 º 02.620 W 095 º 53.025
|
||||
Wild River State Park N 45 º 32.139 W 092 º 43.947
|
||||
Lake Shetek State Park N 44 º 06.248 W 095 º 41.103
|
||||
Maplewood State Park N 46 º 32.361 W 095 º 59.151
|
||||
Old Mill State Park N 48 º 21.691 W 096 º 34.011
|
||||
Banning State Park N 46 º 09.869 W 092 º 50.373
|
||||
Jay Cooke State Park N 46 º 39.271 W 092 º 22.270
|
||||
Camden State Park N 44 º 20.787 W 095 º 55.735
|
||||
Afton State Park N 44 º 51.336 W 092 º 46.484
|
||||
Minneopa State Park N 44 º 08.879 W 094 º 05.540
|
||||
Rice Lake State Park N 44 º 05.576 W 093 º 03.849
|
||||
McCarthy Beach State Park N 47 º 40.200 W 093 º 01.830
|
||||
Whitewater State Park N 44 º 03.206 W 092 º 02.703
|
||||
Monson Lake State Park N 45 º 19.164 W 095 º 16.493
|
||||
Father Hennepin State Park N 46 º 08.614 W 093 º 28.948
|
||||
Lake Carlos State Park N 46 º 00.052 W 095 º 20.073
|
||||
Moose Lake State Park N 46 º 26.109 W 092 º 43.949
|
||||
John A. Latsch State Park N 44 º 10.310 W 091 º 50.319
|
||||
St. Croix State Park N 45 º 57.048 W 092 º 34.198
|
||||
Big Bog State Recreation Area N 48 º 10.203 W 094 º 30.901
|
||||
Garden Island State Recreation Area Alternate N 48 º 52.073 W 094 º 50.896
|
||||
William O’Brien State Park N 45 º 13.373 W 092 º 46.047
|
||||
Buffalo River State Park N 46 º 51.919 W 096 º 28.031
|
113
extras/cloak/ciphers/hashesMD5
Normal file
113
extras/cloak/ciphers/hashesMD5
Normal file
@ -0,0 +1,113 @@
|
||||
033698705E420DD71634D5C8A861DE7E
|
||||
0566F25FC73E4ACC826C84FF521EDAF7
|
||||
05D5668D5CF9A65FAABE2186C0B19001
|
||||
0991756FBCC2D438CDDD07E7BA996C4F
|
||||
0A12376A0B0A65C39299D94EB02FE799
|
||||
0A26C74B6012B5BBBF715B9327C00C44
|
||||
0BF2D9B8F392C853EE41F15006A38839
|
||||
0F5F49305B40F326674AD23AED0554BC
|
||||
0F82D00A63498CCE8982D5608B759F9E
|
||||
10515EC6CF372232E995602BB7A70046
|
||||
1080418C171BB86F202DA3EB234C74A1
|
||||
108B7B6D86873256A1958916035872E9
|
||||
10B43971A8295F3720F38FBCDD9D6AC6
|
||||
137609CBF5410CFDC487FC2118FB16AE
|
||||
13D1261EFBCEAE62EC6B65F3257769A4
|
||||
15BB21591BE151CAADCC264D3602E522
|
||||
1ACC555ADC3E731133EEAA80154BB886
|
||||
1B4E227142C24B81C9EAA61122B12CB1
|
||||
1C63129AE9DB9C60C3E8AA94D3E00495
|
||||
1D1E60D5E0B698FF150DCAB24DF184D5
|
||||
1F7A1132D93837D2A83E4CA8FABA9941
|
||||
2345F10BB948C5665EF91F6773B3E455
|
||||
236B922AEA10AF085C5206E4D5DBCC85
|
||||
26B580B0AEDE3B3E8B58BC761E09577C
|
||||
26E059C26592E4A078CCB31AFEDF213C
|
||||
26FEE1830A3552695A975E509B289F0D
|
||||
2902A7FD778812E75F953779B67BE83C
|
||||
2AAE667514F164221A71E9CEB734E31A
|
||||
2B92AD5136C0C171DF9B02A24D3D9C82
|
||||
332D114301906A70E56EDB1325B192E3
|
||||
3362E5D0E467010F8FFAFE6E079B3FCC
|
||||
35E656E1FCF2FC8FBCAC23EA148E7BD0
|
||||
3B287E2F82D9B57BD0801638A21B6EB6
|
||||
40068DCA5800AD8BC5E1EA749B5A968F
|
||||
447CC066DE9703C5AEE3FDD3AF0AD5E0
|
||||
45C311F94E075EF1F15EFBA7B5084A10
|
||||
498A8A3364A43A8E9D880E441043E33F
|
||||
4AAEA6397CFA277E4433FA325FA396F7
|
||||
4DC642D0E0881B63072691C194F99B7E
|
||||
51951570A66679F7B5C21A83E3385D13
|
||||
5263DC84FFBA8FA607754CACCE3E65FD
|
||||
57AC36ADC5258C1B8048A7D7BD966A73
|
||||
5836CAD35828419B754B684A9DA147A0
|
||||
596BFF793A503D75B68B760A9BF70AA3
|
||||
5E5B18D4681B24F342F89A19DA2D4699
|
||||
604E708741886E3D922D26CE1A7B2835
|
||||
618206DD0078A5740373C161D7570989
|
||||
64B9469496B3012D4E19F626AC068233
|
||||
64F4AE7B5A81F0EB65316410581047C0
|
||||
6676E7D0995EBD8DBD136869A9358D14
|
||||
69BDBA2238286ED674D2DBD66319B629
|
||||
69F3EEC589EFF77854287AF84E0258FE
|
||||
6FC4B922446021AD57578E4E281D7965
|
||||
722EF044BF1D7A293440B68A6E7B6721
|
||||
744CE343D3FAF9FBFA81116688714F3B
|
||||
791701316B125F94CC61F8C2D9FF9C58
|
||||
7989D7CFAF00CAB7D0B6A58324EB63E9
|
||||
7A2D09AF8F40467DDDAF0F946960ADE3
|
||||
7AD7E9A563E9F3CA7175DE3668C85654
|
||||
7BCD03390834DFF914740E27D826C2DA
|
||||
7E5FAF44E6D49A0000135A9D5D59EF76
|
||||
7EDEB90A6ED6E0141E9F28FACA7F3AF6
|
||||
8350ADB55BAA13F09BFB53B0D51CAF2D
|
||||
859C7547DF3CA77B07D4ECD3B0F42F57
|
||||
865BDF0F2727792BCD77C7BE5B36C6CA
|
||||
8745BA34F93696B1165C36A52FAC0FDF
|
||||
8904646023577F9746BADE425D317ABE
|
||||
8911BFAF73444B67B000B3D3EDB55E6D
|
||||
8A548185B6A6A873D9243072B13D04AB
|
||||
8B0EE5A501CEF4A5699FD3B2D4549E8F
|
||||
8BD2DB1BE8AABBC2CE9AE757D0302707
|
||||
939E652393234AE78B511092C5B3A0B6
|
||||
93FE91EB27123C4927105753C4DB4B7D
|
||||
9536637DF923B3AAD6DDE0A80D7CD7E4
|
||||
9684C7747527BFA45DE2D0E733058D9F
|
||||
970796E057AD9284F16AF55E19BDCE7F
|
||||
9A0711EC9F302EDE9C07731208553E69
|
||||
9FEA03AA1B4293B8566B1B5AEAE12D8F
|
||||
A304C99480E027B2D2AE5A9D10021335
|
||||
A33B929706F3280EC6D46BE67E569915
|
||||
A402080405F59AAD7E3C66B2339B1311
|
||||
A4DC1273708D83FCF39355AFA587E2EC
|
||||
A5484EEFDBC11797A293DA331B31C62B
|
||||
A59D3A8442AD87289D6891238CD9C7DD
|
||||
A8A4C199766A66EA54079F19F819EE8D
|
||||
A8EA4070D693DB509DECA6676DE675E9
|
||||
AA13ABDB56EA5FD37B133F96EB3E3B6A
|
||||
AB6A89F36224022B8A954316C55137DC
|
||||
AEBA8FB7353C9C4F9B27F015FB9DC5AD
|
||||
B13A1C9325803C9258F868EF97F04F8D
|
||||
B32FD22E4BFAD91974A40D08EBC7D8B1
|
||||
B55549D6177C833E55DFA04F6A3650DC
|
||||
B79313B4FE11BF40EA80915AD676BE5E
|
||||
B80370360E1E0D5F7BA9709B12A01DEA
|
||||
BAE0168A5446D0B00D13B5CEC4D6F905
|
||||
BBA3BAFE548581C53B933B7DCCE620AB
|
||||
C03AA55846E82AEEADF1879065BAF7ED
|
||||
C44A471BD78CC6C2FEA32B9FE028D30A
|
||||
C5B68394786DF93CF7AD7366D3D5807C
|
||||
CD00B006870EABFBB56135FFAF2AC444
|
||||
CD8032768CFBD94F5C5876BA56EB78CD
|
||||
D27E2ABDB7A8F23407B803E04EB5AD90
|
||||
DB99B1E9EE0E4BB159F9256820214634
|
||||
E0F79190404F264B77DEA125D5FC8304
|
||||
E12B91EF812074FFD54663280739B825
|
||||
F0B2231D462E970D954AA661122D1034
|
||||
F55893FDF4409E1C6C2574C8D3005A6E
|
||||
F5E852552DEB0FF9A3899938E77CCCDE
|
||||
F89684B8DD9E68E3261E617D772ECF0E
|
||||
FA767CDB99CE06491731B69DDEEFBD69
|
||||
FCC96DF2D80B43831F5926BE58F63574
|
||||
FDB8250C494E39F3820B7C81DA1418A7
|
||||
FE4CEEB01D43A6C29D8F4FE93313C6C1
|
77
extras/cloak/ciphers/ipAddressesTop100
Normal file
77
extras/cloak/ciphers/ipAddressesTop100
Normal file
@ -0,0 +1,77 @@
|
||||
198.78.201.252
|
||||
209.200.154.225
|
||||
69.171.224.11
|
||||
144.198.29.112
|
||||
69.65.13.216
|
||||
208.87.33.151
|
||||
209.31.22.39
|
||||
69.63.181.15
|
||||
69.63.187.17
|
||||
65.55.72.135
|
||||
208.94.146.80
|
||||
74.125.157.99
|
||||
69.63.181.12
|
||||
178.162.238.136
|
||||
64.208.126.67
|
||||
72.247.244.88
|
||||
69.10.25.46
|
||||
178.17.165.74
|
||||
69.63.176.13
|
||||
97.107.137.164
|
||||
131.253.13.32
|
||||
98.124.248.77
|
||||
199.59.148.10
|
||||
195.191.207.40
|
||||
194.71.107.15
|
||||
31.7.57.13
|
||||
69.63.187.18
|
||||
212.58.241.131
|
||||
208.80.152.201
|
||||
80.94.76.5
|
||||
93.158.65.211
|
||||
89.238.130.247
|
||||
173.231.140.219
|
||||
199.7.177.218
|
||||
216.239.113.172
|
||||
95.211.149.7
|
||||
174.121.194.34
|
||||
173.0.84.3
|
||||
74.125.224.72
|
||||
207.97.227.239
|
||||
95.211.143.200
|
||||
91.220.176.248
|
||||
199.59.149.230
|
||||
174.140.154.20
|
||||
74.125.65.91
|
||||
65.39.178.43
|
||||
62.149.24.66
|
||||
74.125.224.181
|
||||
69.63.181.11
|
||||
199.47.217.179
|
||||
72.233.56.138
|
||||
97.107.132.144
|
||||
84.22.170.149
|
||||
62.149.24.67
|
||||
69.174.244.50
|
||||
109.163.226.240
|
||||
23.21.142.179
|
||||
216.52.208.187
|
||||
69.63.187.19
|
||||
98.139.183.24
|
||||
76.74.254.126
|
||||
205.196.120.13
|
||||
98.137.149.56
|
||||
65.55.175.254
|
||||
199.9.249.21
|
||||
69.63.184.142
|
||||
216.52.242.86
|
||||
184.173.141.231
|
||||
208.223.219.206
|
||||
194.71.107.50
|
||||
67.201.54.151
|
||||
64.191.203.30
|
||||
174.140.154.32
|
||||
72.21.211.176
|
||||
67.21.232.223
|
||||
23.23.130.59
|
||||
69.171.234.21
|
76
extras/cloak/ciphers/pokemonGo
Normal file
76
extras/cloak/ciphers/pokemonGo
Normal file
@ -0,0 +1,76 @@
|
||||
Bellsprout
|
||||
Zubat
|
||||
Doduo
|
||||
Rhyhorn
|
||||
Dratini
|
||||
Snorlax
|
||||
Krabby
|
||||
Onix
|
||||
Ponyta
|
||||
Paras
|
||||
Lapras
|
||||
Drowzee
|
||||
Zapdos
|
||||
Diglett
|
||||
Sandshrew
|
||||
Ekans
|
||||
Lickitung
|
||||
Tangela
|
||||
Scyther
|
||||
Oddish
|
||||
Geodude
|
||||
Slowpoke
|
||||
Voltorb
|
||||
Magmar
|
||||
Pidgey
|
||||
Caterpie
|
||||
Nidoran
|
||||
Poliwag
|
||||
Shellder
|
||||
Koffing
|
||||
Seel
|
||||
Mew
|
||||
Growlithe
|
||||
Machop
|
||||
Vulpix
|
||||
Porygon
|
||||
Mankey
|
||||
Hitmonchan
|
||||
Farfetchd
|
||||
Kabuto
|
||||
Tauros
|
||||
Venonat
|
||||
Articuno
|
||||
Clefairy
|
||||
Psyduck
|
||||
Jynx
|
||||
Squirtle
|
||||
Horsea
|
||||
Jigglypuff
|
||||
Mewtwo
|
||||
Pinsir
|
||||
Hitmonlee
|
||||
Goldeen
|
||||
Kangaskhan
|
||||
Moltres
|
||||
Cubone
|
||||
Magnemite
|
||||
Staryu
|
||||
Weedle
|
||||
Charmander
|
||||
Pikachu
|
||||
Omanyte
|
||||
Tentacool
|
||||
Spearow
|
||||
Grimer
|
||||
Gastly
|
||||
Abra
|
||||
Magikarp
|
||||
Rattata
|
||||
Aerodactyl
|
||||
Bulbasaur
|
||||
Electabuzz
|
||||
Meowth
|
||||
Ditto
|
||||
Chansey
|
||||
Exeggcute
|
67
extras/cloak/ciphers/rickrollYoutube
Normal file
67
extras/cloak/ciphers/rickrollYoutube
Normal file
@ -0,0 +1,67 @@
|
||||
https://bit.ly/1bu2Ruu
|
||||
https://bit.ly/1ijxdRx
|
||||
https://bit.ly/1FQbMVt
|
||||
https://bit.ly/2nQmPXd
|
||||
https://bit.ly/2oq4DYI
|
||||
https://bit.ly/2Kb9fsx
|
||||
https://bit.ly/1f9lqAP
|
||||
https://bit.ly/IqT6zt
|
||||
https://bit.ly/2HjNryg
|
||||
https://bit.ly/2efiE68
|
||||
https://bit.ly/2geoqTg
|
||||
https://bit.ly/2xZrYlX
|
||||
https://bit.ly/29wawO1
|
||||
https://bit.ly/2IvdUsg
|
||||
https://bit.ly/2Guggqi
|
||||
https://bit.ly/1p9Gf4X
|
||||
https://bit.ly/2jQX9JX
|
||||
https://bit.ly/2KT5CbZ
|
||||
https://bit.ly/2gkkzU2
|
||||
https://bit.ly/2ItVvMx
|
||||
https://bit.ly/2I9RflR
|
||||
https://bit.ly/2FFZyE3
|
||||
https://bit.ly/2uGlEgu
|
||||
https://bit.ly/2jP0U2S
|
||||
https://bit.ly/2IvQJOs
|
||||
https://bit.ly/2lqrm1G
|
||||
https://bit.ly/R0z0jZ
|
||||
https://bit.ly/1yA76u9
|
||||
https://bit.ly/1zTtQZr
|
||||
https://bit.ly/2Iwbcmh
|
||||
https://bit.ly/2I92hnl
|
||||
https://bit.ly/2IcYpC2
|
||||
https://bit.ly/2I5fm56
|
||||
https://bit.ly/2KcvsXq
|
||||
https://bit.ly/2KRVKPD
|
||||
https://bit.ly/2jN3VjX
|
||||
https://bit.ly/2KS8mqi
|
||||
https://bit.ly/1QasgsE
|
||||
https://bit.ly/2ryu1eN
|
||||
https://bit.ly/2ff2sPq
|
||||
https://bit.ly/2I5eIVr
|
||||
https://bit.ly/2G472wA
|
||||
https://bit.ly/2rxYokQ
|
||||
https://bit.ly/2eO3vYp
|
||||
https://bit.ly/2jLbl7w
|
||||
https://bit.ly/2rxVPQq
|
||||
https://bit.ly/1UisbYb
|
||||
https://bit.ly/2ry3luH
|
||||
https://bit.ly/2G3vWNb
|
||||
https://bit.ly/1iegU5b
|
||||
https://bit.ly/2G3wnHj
|
||||
https://bit.ly/2I6dYPX
|
||||
https://bit.ly/2rxWXn8
|
||||
https://bit.ly/2wxIYCQ
|
||||
https://bit.ly/2jO8lY8
|
||||
https://bit.ly/2jQbuXg
|
||||
https://bit.ly/29yCC7s
|
||||
https://bit.ly/2KOGFyi
|
||||
https://bit.ly/2KTRv6q
|
||||
https://bit.ly/2IvLePW
|
||||
https://bit.ly/2jP6ylA
|
||||
https://bit.ly/2KcD3VQ
|
||||
https://bit.ly/1NistpZ
|
||||
https://bit.ly/1Qz4NnI
|
||||
https://bit.ly/2Ib66bT
|
||||
https://bit.ly/2Bj7825
|
||||
https://bit.ly/2rzRuLR
|
68
extras/cloak/ciphers/skiResorts
Normal file
68
extras/cloak/ciphers/skiResorts
Normal file
@ -0,0 +1,68 @@
|
||||
Niseko, Japan
|
||||
Jackson Hole, Wyoming
|
||||
Squaw Valley, California
|
||||
Kirkwood, California
|
||||
Alpine Meadows, California
|
||||
Grand Targhee Resort, Wyoming
|
||||
Red Mountain Resort, British Columbia
|
||||
Big Bear, California
|
||||
Alagna, Italy
|
||||
Grand Targhee, Wyoming
|
||||
La Hoya, Chile
|
||||
Mountain High, California
|
||||
Meribel, France
|
||||
Kitzbühel, Austria
|
||||
Breckenridge, Colorado
|
||||
Heavenly, California & Nevada
|
||||
Taos, New Mexico
|
||||
Canyons, Utah
|
||||
Murren, Switzerland
|
||||
Snowbasin, Utah
|
||||
Incline Village, Nevada
|
||||
Winter Park, Colorado
|
||||
Shiga Kogen, Japan
|
||||
Park City, Utah
|
||||
Smuggler’s Notch, Vermont
|
||||
Mt. Schweitzer, Idaho
|
||||
Bernese Oberland, Switzerland
|
||||
Sierra-at-Tahoe, California
|
||||
Aspen-Snowmass, Colorado
|
||||
Riksgransen, Sweden
|
||||
Telluride, Colorado
|
||||
Solitude, Utah
|
||||
Mammoth Mountain, California
|
||||
Wolf Creek Ski Area
|
||||
Stowe, Vermont
|
||||
Craigieburn, New Zealand
|
||||
Big Sky, Montana
|
||||
Crested Butte, Colorado
|
||||
Jay Peak, Vermont
|
||||
Tremblant, Quebec
|
||||
Verbier, Switzerland
|
||||
Cortina d’Ampezzo, Italy
|
||||
Mount Snow, Vermont
|
||||
Vail, Colorado
|
||||
Keystone, Colorado
|
||||
Sun Valley, Idaho
|
||||
Timberline, Mt Hood Oregon
|
||||
Silverton, Colorado
|
||||
Wanaka, New Zealand
|
||||
Brighton, Utah
|
||||
St. Anton, Austria
|
||||
Mt. Rose, Nevada
|
||||
Okemo Mountain Resort, Vermont
|
||||
Copper Mountain, Colorado
|
||||
Northstar, California
|
||||
Beaver Creek, Colorado
|
||||
Whistler-Blackcomb, British Columbia
|
||||
Sundance, Utah
|
||||
Nozawa Onsen, Japan
|
||||
Deer Valley, Utah
|
||||
Whiteface Mountain, New York
|
||||
Purgatory, Colorado
|
||||
Mt. Bachelor, Oregon
|
||||
Killington, Vermont
|
||||
Snowbird, Utah
|
||||
Revelstoke, British Columbia
|
||||
Treble Cone, New Zealand
|
||||
Alta, Utah
|
147
extras/cloak/ciphers/starTrek
Normal file
147
extras/cloak/ciphers/starTrek
Normal file
@ -0,0 +1,147 @@
|
||||
Ishka
|
||||
Nog
|
||||
Charles Tucker
|
||||
William Riker
|
||||
Dolim
|
||||
Lon Suder
|
||||
Brunt
|
||||
Hogan
|
||||
J. M. Colt
|
||||
Winn Adami
|
||||
Leonardo da Vinci
|
||||
Jake Sisko
|
||||
Azan
|
||||
Amanda Grayson
|
||||
Weyoun
|
||||
Ayala
|
||||
Nyota Uhura
|
||||
Tuvok
|
||||
Saavik
|
||||
Lwaxana Troi
|
||||
Gowron
|
||||
José Tyler
|
||||
Miles O'Brien
|
||||
Kashimuro Nozawa
|
||||
Soval
|
||||
William Ross
|
||||
Shakaar Edon
|
||||
Kathryn Janeway
|
||||
Jonathan Archer
|
||||
Keiko O'Brien
|
||||
Kimara Cretak
|
||||
Julian Bashir
|
||||
Dukat
|
||||
Spock
|
||||
Alexander Rozhenko
|
||||
Seska
|
||||
Evek
|
||||
Sonya Gomez
|
||||
Tora Ziyal
|
||||
Damar
|
||||
Chakotay
|
||||
Mezoti
|
||||
Hugh of Borg
|
||||
Sela
|
||||
Thy'lek Shran
|
||||
Leonard McCoy
|
||||
Michael Rostov
|
||||
Jennifer Sisko
|
||||
Janice Rand
|
||||
Daniels
|
||||
Degra
|
||||
Beverly Crusher
|
||||
Kasidy Yates
|
||||
Reginald Barclay
|
||||
The Doctor
|
||||
Kes
|
||||
Jal Culluh
|
||||
Rom
|
||||
Mallora
|
||||
Elim Garak
|
||||
Silik
|
||||
Neelix
|
||||
Michael Jonas
|
||||
Phlox
|
||||
The Borg Queen
|
||||
Benjamin Sisko
|
||||
Kurn
|
||||
Hoshi Sato
|
||||
Mot
|
||||
K'Ehleyr
|
||||
Guinan
|
||||
Erika Hernandez
|
||||
B'Etor
|
||||
Leeta
|
||||
Harry Kim
|
||||
James T. Kirk
|
||||
Joseph Sisko
|
||||
Tal Celes
|
||||
The Traveler
|
||||
Samantha Wildman
|
||||
Rebi
|
||||
Morn
|
||||
Lursa
|
||||
Luther Sloan
|
||||
Female Changeling
|
||||
Susan Nicoletti
|
||||
Naomi Wildman
|
||||
Mr. Homn
|
||||
Katherine Pulaski
|
||||
Phillip Boyce
|
||||
Ezri Dax
|
||||
Christopher Pike
|
||||
Carol Marcus
|
||||
Mora Pol
|
||||
Kira Nerys
|
||||
Vash
|
||||
T'Pol
|
||||
Hikaru Sulu
|
||||
Jean-Luc Picard
|
||||
Bareil Antos
|
||||
Wesley Crusher
|
||||
Number One
|
||||
Geordi La Forge
|
||||
Montgomery Scott
|
||||
Lore
|
||||
Garrison
|
||||
Jannar
|
||||
Ro Laren
|
||||
Zek
|
||||
Icheb
|
||||
Tomalak
|
||||
Vorik
|
||||
Elizabeth Cutler
|
||||
Maxwell Forrest
|
||||
Maihar'du
|
||||
Vic Fontaine
|
||||
Owen Paris
|
||||
Michael Eddington
|
||||
Malcolm Reed
|
||||
Li Nalas
|
||||
Pavel Chekov
|
||||
Travis Mayweather
|
||||
B'Elanna Torres
|
||||
Worf
|
||||
Tom Paris
|
||||
Sarah Sisko
|
||||
Jadzia Dax
|
||||
Mila
|
||||
Data
|
||||
Q
|
||||
Seven of Nine
|
||||
Christine Chapel
|
||||
Alyssa Ogawa
|
||||
Joseph Carey
|
||||
Molly O'Brien
|
||||
Sarek
|
||||
Martok
|
||||
J. Hayes
|
||||
Kor
|
||||
Enabran Tain
|
||||
Robin Lefler
|
||||
Deanna Troi
|
||||
Quark
|
||||
Chell
|
||||
Tasha Yar
|
||||
Opaka Sulan
|
||||
Odo
|
77
extras/cloak/ciphers/statusCodes
Normal file
77
extras/cloak/ciphers/statusCodes
Normal file
@ -0,0 +1,77 @@
|
||||
Status code: 60
|
||||
Status code: 612
|
||||
Status code: 299
|
||||
Status code: 725
|
||||
Status code: 974
|
||||
Status code: 472
|
||||
Status code: 182
|
||||
Status code: 256
|
||||
Status code: 203
|
||||
Status code: 619
|
||||
Status code: 915
|
||||
Status code: 746
|
||||
Status code: 77
|
||||
Status code: 857
|
||||
Status code: 865
|
||||
Status code: 488
|
||||
Status code: 115
|
||||
Status code: 159
|
||||
Status code: 782
|
||||
Status code: 500
|
||||
Status code: 962
|
||||
Status code: 333
|
||||
Status code: 938
|
||||
Status code: 395
|
||||
Status code: 320
|
||||
Status code: 821
|
||||
Status code: 894
|
||||
Status code: 898
|
||||
Status code: 287
|
||||
Status code: 871
|
||||
Status code: 870
|
||||
Status code: 575
|
||||
Status code: 867
|
||||
Status code: 216
|
||||
Status code: 116
|
||||
Status code: 937
|
||||
Status code: 662
|
||||
Status code: 593
|
||||
Status code: 423
|
||||
Status code: 748
|
||||
Status code: 647
|
||||
Status code: 62
|
||||
Status code: 817
|
||||
Status code: 452
|
||||
Status code: 212
|
||||
Status code: 946
|
||||
Status code: 471
|
||||
Status code: 401
|
||||
Status code: 527
|
||||
Status code: 935
|
||||
Status code: 131
|
||||
Status code: 119
|
||||
Status code: 868
|
||||
Status code: 776
|
||||
Status code: 762
|
||||
Status code: 706
|
||||
Status code: 268
|
||||
Status code: 331
|
||||
Status code: 106
|
||||
Status code: 787
|
||||
Status code: 89
|
||||
Status code: 134
|
||||
Status code: 681
|
||||
Status code: 793
|
||||
Status code: 971
|
||||
Status code: 355
|
||||
Status code: 28
|
||||
Status code: 31
|
||||
Status code: 559
|
||||
Status code: 715
|
||||
Status code: 501
|
||||
Status code: 385
|
||||
Status code: 197
|
||||
Status code: 709
|
||||
Status code: 344
|
||||
Status code: 205
|
||||
Status code: 892
|
71
extras/cloak/ciphers/topWebsites
Normal file
71
extras/cloak/ciphers/topWebsites
Normal file
@ -0,0 +1,71 @@
|
||||
office.com
|
||||
imgur.com
|
||||
microsoft.com
|
||||
outbrain.com
|
||||
amazon.com
|
||||
reddit.com
|
||||
aol.com
|
||||
netflix.com
|
||||
bankofamerica.com
|
||||
force.com
|
||||
wordpress.com
|
||||
bing.com
|
||||
foxnews.com
|
||||
wellsfargo.com
|
||||
google.com
|
||||
blogspot.com
|
||||
cnet.com
|
||||
homedepot.com
|
||||
instagram.com
|
||||
live.com
|
||||
etsy.com
|
||||
stackoverflow.com
|
||||
imdb.com
|
||||
github.com
|
||||
facebook.com
|
||||
huffingtonpost.com
|
||||
craiglist.org
|
||||
walmart.com
|
||||
diply.com
|
||||
quora.com
|
||||
wikia.com
|
||||
pinterest.com
|
||||
groupon.com
|
||||
bestbuy.com
|
||||
pandora.com
|
||||
tripadvisor.com
|
||||
msn.com
|
||||
amazonaws.com
|
||||
indeed.com
|
||||
tumblr.com
|
||||
apple.com
|
||||
xfinity.com
|
||||
comcast.net
|
||||
capitalone.com
|
||||
citi.com
|
||||
ebay.com
|
||||
go.com
|
||||
espn.go.com
|
||||
yelp.com
|
||||
zillow.com
|
||||
vice.com
|
||||
salesforce.com
|
||||
washingtonpost.com
|
||||
chase.com
|
||||
forbes.com
|
||||
buzzfeed.com
|
||||
cnn.com
|
||||
microsoftonline.com
|
||||
twitter.com
|
||||
americanexpress.com
|
||||
paypal.com
|
||||
target.com
|
||||
wikipedia.com
|
||||
nytimes.com
|
||||
dropbox.com
|
||||
weather.com
|
||||
youtube.com
|
||||
usps.com
|
||||
bbc.com
|
||||
yahoo.com
|
||||
linkedin.com
|
100
extras/cloak/ciphers/worldBeaches
Normal file
100
extras/cloak/ciphers/worldBeaches
Normal file
@ -0,0 +1,100 @@
|
||||
Balos Beach, Greece
|
||||
Oludeniz Beach, Turkey
|
||||
Hanalei Bay, Hawaii, United States
|
||||
Ffryes Beach, Antigua
|
||||
Wineglass Bay, Tasmania
|
||||
Sunrise Beach, Koh Lipe, Thailand
|
||||
Coffee Bay, Wild Coast, South Africa
|
||||
Hot Water Beach, Coromandel Peninsula, New Zealand
|
||||
Bandon, Oregon, United States
|
||||
Little Corn beaches, Nicaragua
|
||||
Lover's Beach, Baja California Sur, Mexico
|
||||
Pulau Derawan, Indonesia
|
||||
Akajima, Okinawa, Japan
|
||||
Trunk Bay, St. John, U.S. Virgin Islands
|
||||
Navagio Beach, Greece
|
||||
Flamenco Beach, Puerto Rico
|
||||
Plage de Piémanson, France
|
||||
Natadola Beach, Fiji
|
||||
Cayo Paraiso, Dominican Republic
|
||||
Unawatuna, Sri Lanka
|
||||
Los Roques, Venezuela
|
||||
Champagne Beach, Vanuatu
|
||||
Kaiteriteri Beach, Nelson, New Zealand
|
||||
Matira Beach, Bora Bora, Tahiti
|
||||
Anse de Grande Saline, St. Barths
|
||||
Puka Beach, Boracay, Philippines
|
||||
Laughing Bird Caye, Belize
|
||||
El Nido, Palawan, Philippines
|
||||
Anse Source d'Argent, La Digue, Seychelles
|
||||
Beidaihe, China
|
||||
Arashi Beach, Aruba
|
||||
An Bang Beach, Hoi An, Vietnam
|
||||
Juara Beach, Tioman Island, Malaysia
|
||||
D-Day beaches, Normandy, France
|
||||
Rarotonga, Cook Islands
|
||||
West Bay Beach, Roatan, Honduras
|
||||
Cavendish Beach, Prince Edward Island, Canada
|
||||
Ifaty Beach, Madagascar
|
||||
Grande Anse Beach, La Digue Island, Seychelles
|
||||
Diani Beach, Kenya
|
||||
Dominical Beach, Costa Rica
|
||||
Bahia Solano, Colombia
|
||||
Patnem Beach, Goa, India
|
||||
Tanjung Rhu, Langkawi, Malaysia
|
||||
Essaouira, Morocco
|
||||
Tulum, Mexico
|
||||
Belle Mare, Mauritius
|
||||
Long Beach, Phu Quoc, Vietnam
|
||||
Egremni Beach, Greece
|
||||
Bondi Beach, Sydney, Australia
|
||||
Isshiki Beach, Hayama, Japan
|
||||
Paradise Beach, Rab, Croatia
|
||||
Grace Bay, Providenciales, Turks & Caicos
|
||||
Abaka Bay, Haiti
|
||||
Warwick Long Bay, Bermuda
|
||||
Phra Nang Beach, Railay, Thailand
|
||||
Karekare, West Auckland, New Zealand
|
||||
Gardner Bay, Espanola Island, Ecuador
|
||||
Meads Bay, Anguilla
|
||||
Panama City Beach, Florida, United States
|
||||
Boulders Beach, Cape Town, South Africa
|
||||
La Concha, Spain
|
||||
Rabbit Beach, Lampedusa, Italy
|
||||
Byron Bay, Australia
|
||||
Cape Maclear, Malawi
|
||||
Southwestern Beach, Koh Rong, Cambodia
|
||||
Canggu Beach, Bali, Indonesia
|
||||
Capo Sant'Andrea, Elba, Italy
|
||||
Cabbage Beach, Paradise Island, Bahamas
|
||||
Margaret River Beach, Australia
|
||||
Crane Beach, Barbados
|
||||
Radhanagar Beach, Andaman Islands, India
|
||||
Jeffreys Bay, South Africa
|
||||
Luskentyre Beach, Scotland
|
||||
Maya Bay, Ko Phi Phi, Thailand
|
||||
Long Bay, Saint-Martin
|
||||
Portstewart Strand, Northern Ireland
|
||||
Vilanculos Beach, Mozambique
|
||||
Las Salinas, Ibiza, Spain
|
||||
Grand Anse, Grenada
|
||||
Sun Island Beach, Maldives
|
||||
Whitehaven Beach, Queensland, Australia
|
||||
Placenia Beach, Belize
|
||||
Pigeon Point, Tobago, Trinidad and Tobago
|
||||
Punalu'u, Hawaii, United States
|
||||
The Baths, Virgin Gorda, British Virgin Islands
|
||||
Porto da Barra, Salvador, Brazil
|
||||
Nungwi, Zanzibar, Tanzania
|
||||
Skagen Beach, Denmark
|
||||
Palaui Island, Cagayan Valley, Philippines
|
||||
Negril Beach, Jamaica
|
||||
Falassarna Beach, Crete, Greece
|
||||
Nihiwatu Beach, Sumba, Indonesia
|
||||
Playa Paraiso, Cayo Largo, Cuba
|
||||
Bottom Bay, Barbados
|
||||
Na'ama Bay, Sharm el Sheikh, Egypt
|
||||
Haad Rin, Ko Pha Ngan, Thailand
|
||||
Pulau Perhentian Kecil, Malaysia
|
||||
Praia do Sancho, Fernando de Noronha, Brazil
|
||||
Venice Beach, California, United States
|
100
extras/cloak/ciphers/worldFootballTeams
Normal file
100
extras/cloak/ciphers/worldFootballTeams
Normal file
@ -0,0 +1,100 @@
|
||||
Celta Vigo Spain
|
||||
Rangers Scotland
|
||||
Rosario Central Argentina
|
||||
Roma Italy
|
||||
Santos FC Brazil
|
||||
Dinamo Zagreb Croatia
|
||||
Málaga Spain
|
||||
Liverpool FC England
|
||||
FC Porto Portugal
|
||||
Sevilla Spain
|
||||
Al-Ahli Saudi Arabia
|
||||
Feyenoord Netherlands
|
||||
Saint-Étienne France
|
||||
Corinthians Brazil
|
||||
Borussia Mönchengladbach Germany
|
||||
Sport Recife Brazil
|
||||
Everton FC England
|
||||
Lyon France
|
||||
Sassuolo Italy
|
||||
Schalke 04 Germany
|
||||
Internacional Brazil
|
||||
Ajax Netherlands
|
||||
Valencia Spain
|
||||
Lille France
|
||||
Villarreal Spain
|
||||
Real Sociedad Spain
|
||||
Levadia Tallinn Estonia
|
||||
Leicester City England
|
||||
Nice France
|
||||
Flora Tallinn Estonia
|
||||
Ludogorets Razgrad Bulgaria
|
||||
Atlético Madrid Spain
|
||||
BATE Borisov Belarus
|
||||
Club Brugge Belgium
|
||||
Köln Germany
|
||||
Arsenal England
|
||||
APOEL Nicosia Cyprus
|
||||
Anderlecht Belgium
|
||||
São Paulo Brazil
|
||||
Salzburg Austria
|
||||
Dynamo Kyiv Ukraine
|
||||
América Mexico
|
||||
Maribor Slovenia
|
||||
PSV Eindhoven Netherlands
|
||||
Barcelona Spain
|
||||
Monaco France
|
||||
West Ham United England
|
||||
Wolfsburg Germany
|
||||
SSC Napoli Italy
|
||||
Guangzhou Evergrande China PR
|
||||
Paris Saint Germain France
|
||||
Crvena Zvezda Serbia
|
||||
Fenerbahçe Turkey
|
||||
Boca Juniors Argentina
|
||||
FC Sheriff Moldova
|
||||
CSKA Moskva Russia
|
||||
Manchester United England
|
||||
AZ Alkmaar Netherlands
|
||||
Lazio Italy
|
||||
Inter Milan Italy
|
||||
Zenit St. Petersburg Russia
|
||||
Benfica Portugal
|
||||
Basel Switzerland
|
||||
Tottenham Hotspur England
|
||||
Bayer Leverkusen Germany
|
||||
Estudiantes Argentina
|
||||
Sporting Portugal
|
||||
Augsburg Germany
|
||||
Swansea City England
|
||||
Genoa Italy
|
||||
Celtic Scotland
|
||||
Racing Club Argentina
|
||||
Olympiakos Greece
|
||||
Juventus Italy
|
||||
Grêmio Brazil
|
||||
Mainz 05 Germany
|
||||
Sparta Prague Czech Republic
|
||||
Nomme JK Kalju Estonia
|
||||
The New Saints Wales
|
||||
Fiorentina Italy
|
||||
Borussia Dortmund Germany
|
||||
Dnipro Dnipropetrovsk Ukraine
|
||||
Beşiktaş Turkey
|
||||
Olympique Marseille France
|
||||
Atlético Mineiro Brazil
|
||||
Manchester City England
|
||||
Athletic Bilbao Spain
|
||||
Viktoria Plzeň Czech Republic
|
||||
FC Krasnodar Russia
|
||||
AC Milan Italy
|
||||
Southampton England
|
||||
Chelsea England
|
||||
San Lorenzo Argentina
|
||||
Independiente Argentina
|
||||
Atlético Nacional Colombia
|
||||
Lanús Argentina
|
||||
Real Madrid Spain
|
||||
Cruzeiro Brazil
|
||||
Bayern München Germany
|
||||
Shakhtar Donetsk Ukraine
|
111
extras/cloak/cloakify.py
Normal file
111
extras/cloak/cloakify.py
Normal file
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Filename: cloakify.py
|
||||
#
|
||||
# Version: 1.1.0
|
||||
#
|
||||
# Author: Joe Gervais (TryCatchHCF)
|
||||
#
|
||||
# Summary: Exfiltration toolset (see decloakify.py) that transforms any filetype (binaries,
|
||||
# archives, images, etc.) into lists of words / phrases / Unicode to ease exfiltration of
|
||||
# data across monitored networks, hiding the data in plain sight. Also facilitates social
|
||||
# engineering attacks against human analysts and their workflows. Bonus Feature: Defeats
|
||||
# signature-based malware detection tools (cloak your other tools during an engagement).
|
||||
#
|
||||
# Used by cloakifyFactory.py, can be used as a standalone script as well (example below).
|
||||
#
|
||||
# Description: Base64-encodes the given payload and translates the output using a list
|
||||
# of words/phrases/Unicode provided in the cipher. This is NOT a secure encryption tool,
|
||||
# the output is vulnerable to frequency analysis attacks. Use the Noise Generator scripts
|
||||
# to add entropy to your cloaked file. You should encrypt the file before cloaking if
|
||||
# secrecy is needed.
|
||||
#
|
||||
# Prepackaged ciphers include: lists of desserts in English, Arabic, Thai, Russian,
|
||||
# Hindi, Chinese, Persian, and Muppet (Swedish Chef); PokemonGo creatures; Top 100 IP
|
||||
# Addresses; Top Websites; GeoCoords of World Capitols; MD5 Password Hashes; An Emoji
|
||||
# cipher; Star Trek characters; Geocaching Locations; Amphibians (Scientific Names);
|
||||
# evadeAV cipher (simple cipher that minimizes size of the resulting obfuscated data).
|
||||
#
|
||||
# To create your own cipher:
|
||||
#
|
||||
# - Generate a list of at least 66 unique words (Unicode-16 accepted)
|
||||
# - Remove all duplicate entries and blank lines
|
||||
# - Randomize the list (see 'randomizeCipherExample.txt' in Cloakify directory)
|
||||
# - Provide the file as the cipher argument to the script.
|
||||
# - ProTip: Place your cipher in the "ciphers/" directory and cloakifyFactory
|
||||
# will pick it up automatically as a new cipher
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# $ ./cloakify.py payload.txt ciphers/desserts > exfiltrate.txt
|
||||
#
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
|
||||
array64 = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/+=")
|
||||
|
||||
def Cloakify(payloadPath:str, cipherPath:str, outputPath:str="", password:str=None):
|
||||
"""Payload file's binary contents will be read and converted into base64.
|
||||
Cipher file will be read into a list that will be used for the payload's obfuscation.
|
||||
If an output path is defined the obfuscated content will be written to that otherwise,
|
||||
it will print it out to the console.
|
||||
|
||||
Args:
|
||||
payloadPath (str): Path to the file that will be encoded
|
||||
cipherPath (str): Path to the file used as the base64 cipher
|
||||
outputPath (str): Path to write out the obfuscated payload
|
||||
"""
|
||||
|
||||
try:
|
||||
with open(payloadPath, 'rb') as payloadFile:
|
||||
payloadRaw = payloadFile.read()
|
||||
payloadB64 = base64.encodebytes(payloadRaw)
|
||||
payloadB64 = payloadB64.decode("ascii").replace("\n", "")
|
||||
except Exception as e:
|
||||
print("Error reading payload file {}: {}".format(payloadPath, e))
|
||||
|
||||
payloadOrdering = None
|
||||
if password:
|
||||
random.seed(password)
|
||||
# Get a list of each line number in the cloaked file
|
||||
payloadOrdering = [i for i in range(len(payloadB64))]
|
||||
# Shuffle the order of the lines
|
||||
random.shuffle(payloadOrdering)
|
||||
|
||||
try:
|
||||
with open(cipherPath, encoding="utf-8") as file:
|
||||
cipherArray = file.readlines()
|
||||
except Exception as e:
|
||||
print("Error reading cipher file {}: {}".format(cipherPath, e))
|
||||
|
||||
if outputPath:
|
||||
try:
|
||||
with open(outputPath, "w+", encoding="utf-8") as outFile:
|
||||
if payloadOrdering:
|
||||
# Iterate through the randomized line order and write each line to the file
|
||||
for randomLoc in payloadOrdering:
|
||||
outFile.write(cipherArray[array64.index(payloadB64[randomLoc])])
|
||||
else:
|
||||
for char in payloadB64:
|
||||
outFile.write(cipherArray[array64.index(char)])
|
||||
except Exception as e:
|
||||
print("Error writing to output file {}: {}".format(outputPath, e))
|
||||
|
||||
else:
|
||||
for char in payloadB64:
|
||||
print(cipherArray[array64.index(char)].strip())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Transform file into obfuscated text file.')
|
||||
parser.add_argument('-i', "--input", type=str, help='Payload File Path', required=True)
|
||||
parser.add_argument('-c', "--cipher", type=str, help='Cipher File Path', required=True)
|
||||
parser.add_argument('-o', "--output", type=str, help='Output File Path', default="")
|
||||
parser.add_argument('-p', "--password", type=str, help='Password', default=None)
|
||||
args = parser.parse_args()
|
||||
|
||||
Cloakify(args.input, args.cipher, args.output, args.password)
|
84
extras/cloak/decloakify.py
Normal file
84
extras/cloak/decloakify.py
Normal file
@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Filename: decloakify.py
|
||||
#
|
||||
# Author: Joe Gervais (TryCatchHCF)
|
||||
#
|
||||
# Summary: Exfiltration toolset (see cloakify.py) that transforms data into lists
|
||||
# of words / phrases / Unicode to ease exfiltration of data across monitored networks,
|
||||
# essentially hiding the data in plain sight, and facilitate social engineering attacks
|
||||
# against human analysts and their workflows. Bonus Feature: Defeats signature-based
|
||||
# malware detection tools (cloak your other tools).
|
||||
#
|
||||
# Used by cloakifyFactory.py, can be used as a standalone script as well (example below).
|
||||
#
|
||||
# Description: Decodes the output of cloakify.py into its underlying Base64 format,
|
||||
# then does Base64 decoding to unpack the cloaked payload file. Requires the use of the
|
||||
# same cipher that was used to cloak the file prior to exfitration, of course.
|
||||
#
|
||||
# Prepackaged ciphers include: lists of desserts in English, Arabic, Thai, Russian,
|
||||
# Hindi, Chinese, Persian, and Muppet (Swedish Chef); Top 100 IP Addresses; GeoCoords of
|
||||
# World Capitols; MD5 Password Hashes; An Emoji cipher; Star Trek characters; Geocaching
|
||||
# Locations; Amphibians (Scientific Names); and evadeAV cipher, a simple cipher that
|
||||
# minimizes the size of the resulting obfuscated data.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# $ ./decloakify.py cloakedPayload.txt ciphers/desserts.ciph
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import random
|
||||
import sys
|
||||
|
||||
array64 = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/+=")
|
||||
|
||||
def Decloakify(cloakedPath:str, cipherPath:str, outputPath:str="", password:str=""):
|
||||
"""Cipher file will be read into a list that will be used for the payload's deobfuscation.
|
||||
Cloaked file's contents will be read in line by line mapping the line to a base64 character.
|
||||
If an output path is defined the base64 contents will be decoded and written to the output
|
||||
file otherwise it will be written to the console.
|
||||
|
||||
Args:
|
||||
cloakedPath (str): Path to the file that is encoded
|
||||
cipherPath (str): Path to the file used as the base64 cipher
|
||||
outputPath (str): Path to write out the decoded
|
||||
"""
|
||||
with open(cipherPath, encoding="utf-8") as file:
|
||||
arrayCipher = file.readlines()
|
||||
|
||||
clear64 = ""
|
||||
with open(cloakedPath, encoding="utf-8") as file:
|
||||
if password:
|
||||
random.seed(password)
|
||||
lines = file.readlines()
|
||||
# Get a list of each line number in the cloaked file
|
||||
decodeOrdering = [i for i in range(len(lines))]
|
||||
# Shuffle the order of the lines to what they were during encoding
|
||||
random.shuffle(decodeOrdering)
|
||||
# Map the index of the original payload to the index in the cloaked file
|
||||
decodeOrdering = {k: v for v, k in enumerate(decodeOrdering)}
|
||||
# Iterate through the proper line order and reconstruct the unshuffled base64 payload
|
||||
for i in range(len(lines)):
|
||||
clear64 += array64[arrayCipher.index(lines[decodeOrdering[i]])]
|
||||
else:
|
||||
for line in file:
|
||||
clear64 += array64[arrayCipher.index(line)]
|
||||
|
||||
payload = base64.b64decode(clear64)
|
||||
if outputPath:
|
||||
with open(outputPath, "wb") as outFile:
|
||||
outFile.write(payload)
|
||||
else:
|
||||
print(payload)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description='Transform file into unobfuscated text file.')
|
||||
parser.add_argument('-i', "--input", type=str, help='Cloaked File Path', required=True)
|
||||
parser.add_argument('-c', "--cipher", type=str, help='Cipher File Path', required=True)
|
||||
parser.add_argument('-o', "--output", type=str, help='Output File Path', default="")
|
||||
parser.add_argument('-p', "--password", type=str, help='Password', default=None)
|
||||
args = parser.parse_args()
|
||||
|
||||
Decloakify(args.input, args.cipher, args.output, args.password)
|
@ -1,31 +1,33 @@
|
||||
##
|
||||
# gregtzar/tomb
|
||||
#
|
||||
# This creates an Ubuntu derived base image and installs the tomb libarary
|
||||
# This creates an Ubuntu derived base image and installs the tomb library
|
||||
# along with it's dependencies.
|
||||
|
||||
FROM ubuntu:bionic
|
||||
FROM dyne/devuan:chimaera
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG TOMB_VERSION=2.5
|
||||
ARG TOMB_VERSION=2.9
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y \
|
||||
apt-get install -y -q --no-install-recommends\
|
||||
make \
|
||||
sudo \
|
||||
curl \
|
||||
rsync \
|
||||
build-essential \
|
||||
gettext \
|
||||
zsh \
|
||||
gnupg \
|
||||
cryptsetup \
|
||||
pinentry-curses \
|
||||
steghide
|
||||
file xxd \
|
||||
steghide \
|
||||
plocate \
|
||||
recoll
|
||||
|
||||
# Build and install Tomb from remote repo
|
||||
RUN curl https://files.dyne.org/tomb/Tomb-$TOMB_VERSION.tar.gz -o /tmp/Tomb-$TOMB_VERSION.tar.gz && \
|
||||
RUN curl https://files.dyne.org/tomb/releases/Tomb-$TOMB_VERSION.tar.gz -o /tmp/Tomb-$TOMB_VERSION.tar.gz && \
|
||||
cd /tmp && \
|
||||
tar -zxvf /tmp/Tomb-$TOMB_VERSION.tar.gz && \
|
||||
cd /tmp/Tomb-$TOMB_VERSION && \
|
||||
make install
|
||||
make install
|
||||
|
@ -18,15 +18,18 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this source code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
ver="0.8"
|
||||
TOMBPATH="/usr/local/bin/tomb" # Set this to your tomb executable's path
|
||||
KDFPATH="/usr/local/bin/" # Set this to the path of your KDF binaries (if you're using them)
|
||||
# {{{ SETTINGS
|
||||
ver="0.9.1"
|
||||
KDFPATH="/usr/libexec/tomb" # Path of your KDF binaries (if you're using them).
|
||||
SWAPOFF="false" # Set to "true" to swapoff, or "false" to use -f (force) flag.
|
||||
# The ones below should not need changing
|
||||
TOMBPATH="$(which tomb)" # Tomb executable's path
|
||||
HEXENC="$KDFPATH/tomb-kdb-hexencode"
|
||||
GENSALT="$KDFPATH/tomb-kdb-pbkdf2-gensalt"
|
||||
GETITER="$KDFPATH/tomb-kdb-pbkdf2-getiter"
|
||||
PBKDF="$KDFPATH/tomb-kdb-pbkdf2"
|
||||
_DD=/bin/dd
|
||||
_DD="$(which dd)"
|
||||
# }}}
|
||||
|
||||
# {{{ monmort icon
|
||||
MONMORT="/tmp/monmort.png"
|
||||
@ -41,337 +44,165 @@ b2RpZnkAMjAxMS0wMS0xMlQwOTozNDoyNCswMTowMNKiZVMAAAAASUVORK5CYII="
|
||||
echo -e "$ICONB64" | base64 --decode > $MONMORT
|
||||
# }}}
|
||||
|
||||
# {{{ sudo functions
|
||||
function _sudo {
|
||||
sudoassword=$(ask_password "Insert sudo password for user $USER")
|
||||
echo -e "$sudoassword\n" | sudo -S -v
|
||||
_sudowrong
|
||||
}
|
||||
|
||||
function _sudowrong {
|
||||
[[ $? = 0 ]] || {
|
||||
sudoassword=$(ask_password "Wrong password. Insert sudo password for user $USER")
|
||||
echo -e "$sudoassword\n" | sudo -S -v
|
||||
_sudowrong
|
||||
}
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ Zenity dialogs
|
||||
Icon="--window-icon="$MONMORT""
|
||||
function _zenques {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--question \
|
||||
--text="$1"
|
||||
zenity \
|
||||
$Icon \
|
||||
--question \
|
||||
--text="$1"
|
||||
}
|
||||
function _fsel {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--file-selection \
|
||||
--title="$1"
|
||||
zenity \
|
||||
$Icon \
|
||||
--file-selection \
|
||||
--title="$1"
|
||||
}
|
||||
function _fsave {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--file-selection \
|
||||
--save \
|
||||
--title="$1" \
|
||||
--filename="$2"
|
||||
zenity \
|
||||
$Icon \
|
||||
--file-selection \
|
||||
--save \
|
||||
--title="$1" \
|
||||
--filename="$2"
|
||||
}
|
||||
function _zenwarn {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--warning \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
zenity \
|
||||
$Icon \
|
||||
--warning \
|
||||
--title="Warning" \
|
||||
--text="$1"
|
||||
}
|
||||
function _info {
|
||||
which notify-send > /dev/null
|
||||
if [[ $? == "0" ]]; then
|
||||
_zenotif $*
|
||||
else
|
||||
_zeninfo $*
|
||||
fi
|
||||
which notify-send > /dev/null
|
||||
if [[ $? == "0" ]]; then
|
||||
_zenotif $*
|
||||
else
|
||||
_zeninfo $*
|
||||
fi
|
||||
}
|
||||
function _zenotif {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--notification \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
zenity \
|
||||
$Icon \
|
||||
--notification \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
}
|
||||
function _zeninfo {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--info \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
zenity \
|
||||
$Icon \
|
||||
--info \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
}
|
||||
function _zenerr {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--error \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
zenity \
|
||||
$Icon \
|
||||
--error \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
}
|
||||
function _zenprog {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--progress \
|
||||
--auto-close \
|
||||
--pulsate \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
zenity \
|
||||
$Icon \
|
||||
--progress \
|
||||
--auto-close \
|
||||
--pulsate \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
}
|
||||
function _zenprognc {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--progress \
|
||||
--auto-close \
|
||||
--no-cancel \
|
||||
--pulsate \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
zenity \
|
||||
$Icon \
|
||||
--progress \
|
||||
--auto-close \
|
||||
--no-cancel \
|
||||
--pulsate \
|
||||
--title="$1" \
|
||||
--text="$2"
|
||||
}
|
||||
function _zenentry {
|
||||
zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--entry \
|
||||
--title="$1" \
|
||||
--text="$2" \
|
||||
--entry-text="$3"
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ Some pinentry code shamelessly stolen from tomb
|
||||
# Ask user for a password
|
||||
# Wraps around the pinentry command, from the GnuPG project, as it
|
||||
# provides better security and conveniently use the right toolkit.
|
||||
ask_password() {
|
||||
local description="$1"
|
||||
local title="${2:-Enter tomb password.}"
|
||||
local output
|
||||
local password
|
||||
local gtkrc
|
||||
local theme
|
||||
|
||||
# Distributions have broken wrappers for pinentry: they do
|
||||
# implement fallback, but they disrupt the output somehow. We are
|
||||
# better off relying on less intermediaries, so we implement our
|
||||
# own fallback mechanisms. Pinentry supported: curses, gtk-2, qt4
|
||||
# and x11.
|
||||
|
||||
# make sure LANG is set, default to C
|
||||
LANG=${LANG:-C}
|
||||
|
||||
_verbose "asking password with tty=$TTY lc-ctype=$LANG"
|
||||
|
||||
if [[ "$DISPLAY" = "" ]]; then
|
||||
|
||||
if _is_found "pinentry-curses"; then
|
||||
_verbose "using pinentry-curses"
|
||||
output=`cat <<EOF | pinentry-curses
|
||||
OPTION ttyname=$TTY
|
||||
OPTION lc-ctype=$LANG
|
||||
SETTITLE $title
|
||||
SETDESC $description
|
||||
SETPROMPT Password:
|
||||
GETPIN
|
||||
EOF`
|
||||
else
|
||||
_failure "Cannot find pinentry-curses and no DISPLAY detected."
|
||||
fi
|
||||
|
||||
else # a DISPLAY is found to be active
|
||||
|
||||
# customized gtk2 dialog with a skull (if extras are installed)
|
||||
if _is_found "pinentry-gtk-2"; then
|
||||
_verbose "using pinentry-gtk2"
|
||||
|
||||
gtkrc=""
|
||||
theme=/share/themes/tomb/gtk-2.0-key/gtkrc
|
||||
for i in /usr/local /usr; do
|
||||
[[ -r $i/$theme ]] && {
|
||||
gtkrc="$i/$theme"
|
||||
break
|
||||
}
|
||||
done
|
||||
[[ "$gtkrc" = "" ]] || {
|
||||
gtkrc_old="$GTK2_RC_FILES"
|
||||
export GTK2_RC_FILES="$gtkrc"
|
||||
}
|
||||
output=`cat <<EOF | pinentry-gtk-2
|
||||
OPTION ttyname=$TTY
|
||||
OPTION lc-ctype=$LANG
|
||||
SETTITLE $title
|
||||
SETDESC $description
|
||||
SETPROMPT Password:
|
||||
GETPIN
|
||||
EOF`
|
||||
[[ "$gtkrc" = "" ]] || export GTK2_RC_FILES="$gtkrc_old"
|
||||
|
||||
# TODO QT4 customization of dialog
|
||||
elif _is_found "pinentry-qt4"; then
|
||||
_verbose "using pinentry-qt4"
|
||||
|
||||
output=`cat <<EOF | pinentry-qt4
|
||||
OPTION ttyname=$TTY
|
||||
OPTION lc-ctype=$LANG
|
||||
SETTITLE $title
|
||||
SETDESC $description
|
||||
SETPROMPT Password:
|
||||
GETPIN
|
||||
EOF`
|
||||
|
||||
# TODO X11 customization of dialog
|
||||
elif _is_found "pinentry-x11"; then
|
||||
_verbose "using pinentry-x11"
|
||||
|
||||
output=`cat <<EOF | pinentry-x11
|
||||
OPTION ttyname=$TTY
|
||||
OPTION lc-ctype=$LANG
|
||||
SETTITLE $title
|
||||
SETDESC $description
|
||||
SETPROMPT Password:
|
||||
GETPIN
|
||||
EOF`
|
||||
|
||||
else
|
||||
|
||||
if _is_found "pinentry-curses"; then
|
||||
_verbose "using pinentry-curses"
|
||||
|
||||
_warning "Detected DISPLAY, but only pinentry-curses is found."
|
||||
output=`cat <<EOF | pinentry-curses
|
||||
OPTION ttyname=$TTY
|
||||
OPTION lc-ctype=$LANG
|
||||
SETTITLE $title
|
||||
SETDESC $description
|
||||
SETPROMPT Password:
|
||||
GETPIN
|
||||
EOF`
|
||||
else
|
||||
_failure "Cannot find any pinentry: impossible to ask for password."
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
fi # end of DISPLAY block
|
||||
|
||||
# parse the pinentry output
|
||||
for i in ${(f)output}; do
|
||||
[[ "$i" =~ "^ERR.*" ]] && {
|
||||
_warning "Pinentry error: ::1 error::" ${i[(w)3]}
|
||||
print "canceled"
|
||||
return 1 }
|
||||
|
||||
# here the password is found
|
||||
[[ "$i" =~ "^D .*" ]] && password="${i##D }"
|
||||
done
|
||||
|
||||
[[ "$password" = "" ]] && {
|
||||
_warning "Empty password"
|
||||
print "empty"
|
||||
return 1 }
|
||||
|
||||
print "$password"
|
||||
return 0
|
||||
}
|
||||
|
||||
_is_found() {
|
||||
# returns 0 if binary is found in path
|
||||
[[ "$1" = "" ]] && return 1
|
||||
command -v "$1" 1>/dev/null 2>/dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
function _warning no() {
|
||||
option_is_set -q || _msg warning $@
|
||||
return 1
|
||||
}
|
||||
|
||||
function _verbose xxx() {
|
||||
option_is_set -D && _msg verbose $@
|
||||
return 0
|
||||
}
|
||||
|
||||
function _failure die() {
|
||||
typeset -i exitcode=${exitv:-1}
|
||||
option_is_set -q || _msg failure $@
|
||||
# be sure we forget the secrets we were told
|
||||
exit $exitcode
|
||||
zenity \
|
||||
$Icon \
|
||||
--entry \
|
||||
--title="$1" \
|
||||
--text="$2" \
|
||||
--entry-text="$3"
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ _clean - Clean function, removes sensitive stuff from memory
|
||||
function _clean {
|
||||
unset $?
|
||||
local rr="$RANDOM"
|
||||
while [[ ${#rr} -lt 500 ]]; do
|
||||
rr+="$RANDOM"
|
||||
done
|
||||
unset $?
|
||||
local rr="$RANDOM"
|
||||
while [[ ${#rr} -lt 500 ]]; do
|
||||
rr+="$RANDOM"
|
||||
done
|
||||
|
||||
cmnd="$rr"; unset cmnd
|
||||
tombname="$rr"; unset tombname
|
||||
tombsize="$rr"; unset tombsize
|
||||
keyfile="$rr"; unset keyfile
|
||||
sudoassword="$rr"; unset sudoassword
|
||||
tombtmp="/tmp/tombtmp"
|
||||
if [ -f $tombtmp ]; then
|
||||
dd if=/dev/urandom of=$tombtmp bs=800 count=1
|
||||
rm -f $tombtmp
|
||||
fi
|
||||
tombtmp="$rr"; unset tombtmp
|
||||
newkey="$rr"; unset newkey
|
||||
jpegfile="$rr"; unset jpegfile
|
||||
cmnd="$rr"; unset cmnd
|
||||
tombname="$rr"; unset tombname
|
||||
tombsize="$rr"; unset tombsize
|
||||
keyfile="$rr"; unset keyfile
|
||||
tombtmp="/tmp/tombtmp"
|
||||
if [ -f $tombtmp ]; then
|
||||
dd if=/dev/urandom of=$tombtmp bs=800 count=1
|
||||
rm -f $tombtmp
|
||||
fi
|
||||
tombtmp="$rr"; unset tombtmp
|
||||
newkey="$rr"; unset newkey
|
||||
jpegfile="$rr"; unset jpegfile
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ _main - Main window
|
||||
function _main {
|
||||
_clean
|
||||
cmnd=`zenity \
|
||||
--window-icon="$MONMORT" \
|
||||
--title="gtomb" \
|
||||
--width=640 \
|
||||
--height=420 \
|
||||
--list \
|
||||
--hide-header \
|
||||
--text="gtomb v$ver\nThe GUI wrapper for Tomb, the crypto undertaker." \
|
||||
--separator=" & " \
|
||||
--column=Function \
|
||||
--column=Description \
|
||||
"dig" "Dig a new tomb of chosen size" \
|
||||
"forge" "Forge a new key used to lock tombs" \
|
||||
"lock" "Lock a non-locked tomb using an existing key" \
|
||||
"open" "Open an existing tomb" \
|
||||
"index" "Index the contents of all tombs." \
|
||||
"search" "Search the content of indexed tombs." \
|
||||
"list" "List all open tombs and information on them" \
|
||||
"close" "Close a specific tomb (or all)" \
|
||||
"slam" "Slam a tomb (or all) killing all programs using it" \
|
||||
"resize" "Resize a tomb to a new size (can only grow)" \
|
||||
"passwd" "Change the passphrase of a key" \
|
||||
"setkey" "Change the key of an existing tomb" \
|
||||
"engrave" "Generates a QR code of a key to be saved on paper" \
|
||||
"bury" "Hide a key inside a JPEG image" \
|
||||
"exhume" "Extract a key from a JPEG image"`
|
||||
eval "_$cmnd"
|
||||
_clean
|
||||
cmnd=`zenity \
|
||||
$Icon \
|
||||
--title="gtomb" \
|
||||
--width=400 \
|
||||
--height=445 \
|
||||
--list \
|
||||
--hide-header \
|
||||
--text="gtomb v$ver\nThe GUI wrapper for Tomb, the crypto undertaker." \
|
||||
--separator=" & " \
|
||||
--column=Function \
|
||||
--column=Description \
|
||||
"dig" "Dig a new tomb of chosen size" \
|
||||
"forge" "Forge a new key used to lock tombs" \
|
||||
"lock" "Lock a non-locked tomb using an existing key" \
|
||||
"open" "Open an existing tomb" \
|
||||
"index" "Index the contents of all tombs." \
|
||||
"search" "Search the content of indexed tombs." \
|
||||
"list" "List all open tombs and information on them" \
|
||||
"close" "Close a specific tomb (or all)" \
|
||||
"slam" "Slam a tomb (or all) killing all programs using it" \
|
||||
"resize" "Resize a tomb to a new size (can only grow)" \
|
||||
"passwd" "Change the passphrase of a key" \
|
||||
"setkey" "Change the key of an existing tomb" \
|
||||
"engrave" "Generates a QR code of a key to be saved on paper" \
|
||||
"bury" "Hide a key inside a JPEG image" \
|
||||
"exhume" "Extract a key from a JPEG image"`
|
||||
if [[ "$?" = 1 && $SWAPOFF = "true" ]]; then
|
||||
zenity --password --title="sudo swapon -a" | sudo swapon -a
|
||||
unset $?
|
||||
fi
|
||||
eval "_$cmnd"
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ dig - Dig a new tomb
|
||||
function _dig {
|
||||
tombname=`_fsave "Choose where to dig your tomb" "secret.tomb"`
|
||||
res=$?
|
||||
tombname=`_fsave "Choose where to dig your tomb" "secret.tomb"`
|
||||
res=$?
|
||||
|
||||
if [[ -f "$tombname" ]]; then
|
||||
_zenerr "Error" "This tomb already exists. I am not digging here."
|
||||
exec _main
|
||||
elif [[ -z "$tombname" ]]; then
|
||||
_info "gtomb" "Cancelled"
|
||||
exec _main
|
||||
fi
|
||||
if [[ -f "$tombname" ]]; then
|
||||
_zenerr "Error" "This tomb already exists. I am not digging here."
|
||||
exec _main
|
||||
elif [[ -z "$tombname" ]]; then
|
||||
_info "gtomb" "Cancelled"
|
||||
exec _main
|
||||
fi
|
||||
|
||||
[[ $res = 0 ]] || exec _main
|
||||
|
||||
@ -387,7 +218,7 @@ function _dig {
|
||||
exec _main
|
||||
fi
|
||||
|
||||
[[ $res = 0 ]] || { _zenwarn "Warning" "Tomb digging canceled." ; exec _main }
|
||||
[[ $res = 0 ]] || { _zenwarn "Tomb digging cancelled." ; exec _main }
|
||||
|
||||
"$TOMBPATH" dig -s "$tombsize" "$tombname" | \
|
||||
_zenprog "Digging new tomb" "Please wait while your tomb is being dug..." &
|
||||
@ -401,10 +232,12 @@ function _dig {
|
||||
|
||||
[[ -n "$PID_DD" && -z "$PID_ZEN" ]] && {
|
||||
kill -9 $PID_DD
|
||||
_zenwarn "Warning" "Tomb digging cancelled."
|
||||
_zenwarn "Tomb digging cancelled."
|
||||
rm -f "$tombname"
|
||||
exec _main
|
||||
}
|
||||
|
||||
wait
|
||||
|
||||
_info "Success" "Your tomb has been dug in $tombname"
|
||||
exec _main
|
||||
@ -413,42 +246,42 @@ function _dig {
|
||||
|
||||
# {{{ forge - Forge a new key
|
||||
function _forge {
|
||||
keyfile=`_fsave "Choose where to forge your key" "secret.tomb.key"`
|
||||
res=$?
|
||||
keyfile=`_fsave "Choose where to forge your key" "secret.tomb.key"`
|
||||
res=$?
|
||||
|
||||
if [[ -f $keyfile ]]; then
|
||||
_zenerr "Error" "This key already exists. I am not overwriting."
|
||||
exec _main
|
||||
elif [[ -z $keyfile ]]; then
|
||||
_info "gtomb" "Canceled"
|
||||
exec _main
|
||||
fi
|
||||
if [[ -f $keyfile ]]; then
|
||||
_zenerr "Error" "This key already exists. I am not overwriting."
|
||||
exec _main
|
||||
elif [[ -z $keyfile ]]; then
|
||||
_info "gtomb" "Cancelled"
|
||||
exec _main
|
||||
fi
|
||||
|
||||
kdf=""
|
||||
kdfiter=""
|
||||
if [[ -x $HEXENC ]] && [[ -x $GENSALT ]] && [[ -x $GETITER ]] && [[ -x $PBKDF ]]; then
|
||||
_zenques "Do you want to use KDF? (Generates passwords armored against dictionary attacks)"
|
||||
[[ $? == "0" ]] && {
|
||||
kdf="--kdf"
|
||||
kdfiter=`_zenentry "Iterations" "Enter the delay (itertime) in seconds for each time \n\
|
||||
kdf=""
|
||||
kdfiter=""
|
||||
if [[ -x $GENSALT ]] && [[ -x $GETITER ]] && [[ -x $PBKDF ]]; then
|
||||
_zenques "Do you want to use KDF? (Generates passwords armored against dictionary attacks)"
|
||||
if [[ $? == "0" ]]; then
|
||||
kdf="--kdf"
|
||||
kdfiter=`_zenentry "Iterations" "Enter the delay (itertime) in seconds for each time \n\
|
||||
this key is used:" "2"`
|
||||
|
||||
re='^[0-9]+$'
|
||||
if ! [[ $kdfiter =~ $re ]]; then
|
||||
_zenerr "Error" "Please choose a valid number."
|
||||
exec _main
|
||||
elif [[ -z $kdfiter ]]; then
|
||||
_info "gtomb" "Canceled"
|
||||
exec _main
|
||||
fi
|
||||
}
|
||||
else
|
||||
_zenotif "gtomb" "KDF binaries not found."
|
||||
fi
|
||||
re='^[0-9]+$'
|
||||
if ! [[ $kdfiter =~ $re ]]; then
|
||||
_zenerr "Error" "Please choose a valid number."
|
||||
exec _main
|
||||
elif [[ -z $kdfiter ]]; then
|
||||
_info "gtomb" "Cancelled"
|
||||
exec _main
|
||||
fi
|
||||
fi
|
||||
else
|
||||
_zenotif "gtomb" "KDF binaries not found."
|
||||
fi
|
||||
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
"$TOMBPATH" forge "$keyfile" "$kdf" "$kdfiter" | \
|
||||
"$TOMBPATH" forge "$keyfile" "$kdf" "$kdfiter" "$FLAG" | \
|
||||
_zenprog "Forging key" "Please wait while your key is being forged...\n\
|
||||
You can move your mouse around and use your computer to speed up the process." &
|
||||
|
||||
@ -460,10 +293,12 @@ You can move your mouse around and use your computer to speed up the process." &
|
||||
done
|
||||
[[ -n "$PID_DD" && -z "$PID_ZEN" ]] && {
|
||||
kill -9 $PID_DD
|
||||
_zenwarn "Warning" "Forging cancelled."
|
||||
_zenwarn "Forging cancelled."
|
||||
rm -f $keyfile
|
||||
exec _main
|
||||
}
|
||||
|
||||
wait
|
||||
|
||||
_info "Success" "Your key is now forged in $keyfile"
|
||||
exec _main
|
||||
@ -472,17 +307,19 @@ You can move your mouse around and use your computer to speed up the process." &
|
||||
|
||||
# {{{ lock - Lock a non-locked tomb
|
||||
function _lock {
|
||||
tombname=`_fsel "Select a tomb to lock"`
|
||||
[[ -n $tombname ]] || { _zenotif "gtomb" "Cancelled" ; exec _main }
|
||||
tombname=`_fsel "Select a tomb to lock"`
|
||||
[[ -n $tombname ]] || { _zenotif "gtomb" "Cancelled" ; exec _main }
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
keyfile=`_fsel "Choose the key for your tomb"`
|
||||
[[ -n $keyfile ]] || { _zenotif "gtomb" "Cancelled" ; exec _main }
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
_sudo
|
||||
"$TOMBPATH" lock "$tombname" -k "$keyfile" | \
|
||||
_zenprognc "Locking your tomb" "Please wait while your tomb is being locked..."
|
||||
|
||||
wait
|
||||
|
||||
_info "Success" "Your tomb is now locked."
|
||||
exec _main
|
||||
}
|
||||
@ -490,14 +327,16 @@ function _lock {
|
||||
|
||||
# {{{ open - Open an existing tomb
|
||||
function _open {
|
||||
tombname=`_fsel "Choose a tomb to open"`
|
||||
tombname=`_fsel "Choose a tomb to open"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
keyfile=`_fsel "Choose the key for your tomb"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
_sudo
|
||||
"$TOMBPATH" open "$tombname" -k "$keyfile"
|
||||
"$TOMBPATH" open "$tombname" -k "$keyfile" "$FLAG"
|
||||
|
||||
wait
|
||||
|
||||
_info "Success" "Your tomb is now open."
|
||||
exec _main
|
||||
}
|
||||
@ -505,33 +344,33 @@ function _open {
|
||||
|
||||
# {{{ list - list all open tombs, along with their mountpoint
|
||||
function _list {
|
||||
tombtmp="/tmp/tombtmp"
|
||||
"$TOMBPATH" list --get-mountpoint > $tombtmp
|
||||
tombname=`cat $tombtmp | \
|
||||
sed 's/.*\/\([^\/]*\)$/\1\n &/' | \
|
||||
zenity \
|
||||
--title="Currently open tombs" \
|
||||
--window-icon="$MONMORT" \
|
||||
--width=640 --height=380 --list \
|
||||
--separator=" & " \
|
||||
--text="Here are your open tombs" \
|
||||
--column=Tomb \
|
||||
--column=Path `
|
||||
tombtmp="/tmp/tombtmp"
|
||||
"$TOMBPATH" list --get-mountpoint > $tombtmp
|
||||
tombname=`cat $tombtmp | \
|
||||
sed 's/.*\/\([^\/]*\)$/\1\n &/' | \
|
||||
zenity \
|
||||
--title="Currently open tombs" \
|
||||
$Icon \
|
||||
--width=400 --height=380 --list \
|
||||
--separator=" & " \
|
||||
--text="Here are your open tombs" \
|
||||
--column="Tomb" \
|
||||
--column="Path" `
|
||||
|
||||
tombname=`echo "$tombname" | cut -c1-16`
|
||||
tombname=`echo "$tombname" | cut -c1-16`
|
||||
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
listchoice=`zenity \
|
||||
--title="Choose action" \
|
||||
--window-icon="$MONMORT" \
|
||||
--width=640 --height=400 --list \
|
||||
$Icon \
|
||||
--width=400 --height=380 --list \
|
||||
--separator=" & " \
|
||||
--text="What do you want to do with this tomb?" \
|
||||
--column=Command \
|
||||
--column=Description \
|
||||
--column="Command" \
|
||||
--column="Description" \
|
||||
"disindex" "Disable indexing of this tomb." \
|
||||
"enindex" "Enable indexing of this tomb." \
|
||||
"enindex" "Enable indexing of this tomb." \
|
||||
"close" "Close the selected tomb." \
|
||||
"slam" "Slam the selected tomb." \
|
||||
"binds" "Edit current bind-hooks." \
|
||||
@ -541,13 +380,11 @@ function _list {
|
||||
|
||||
case $listchoice in
|
||||
close)
|
||||
_sudo
|
||||
"$TOMBPATH" close "$tombname"
|
||||
_zeninfo "Success" "Tomb closed successfully!"
|
||||
exec _main
|
||||
;;
|
||||
slam)
|
||||
_sudo
|
||||
"$TOMBPATH" slam "$tombname"
|
||||
_info "Success" "$tombname slammed successfully!"
|
||||
exec _main
|
||||
@ -595,22 +432,21 @@ function _list {
|
||||
|
||||
# {{{ close - Close open tomb(s)
|
||||
function _close {
|
||||
tombtmp="/tmp/tombtmp"
|
||||
"$TOMBPATH" list --get-mountpoint > $tombtmp
|
||||
echo "/all" >> $tombtmp
|
||||
tombname=`cat $tombtmp | \
|
||||
sed 's/.*\/\([^\/]*\)$/\1\n &/' | \
|
||||
zenity \
|
||||
--title="Choose a tomb to close" \
|
||||
--window-icon="$MONMORT" \
|
||||
--width=640 --height=380 --list \
|
||||
--separator=" & " \
|
||||
--column=Tomb \
|
||||
--column=Path `
|
||||
tombtmp="/tmp/tombtmp"
|
||||
"$TOMBPATH" list --get-mountpoint > $tombtmp
|
||||
echo "/all" >> $tombtmp
|
||||
tombname=`cat $tombtmp | \
|
||||
sed 's/.*\/\([^\/]*\)$/\1\n &/' | \
|
||||
zenity \
|
||||
--title="Choose a tomb to close" \
|
||||
$Icon \
|
||||
--width=640 --height=380 --list \
|
||||
--separator=" & " \
|
||||
--column=Tomb \
|
||||
--column=Path `
|
||||
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
_sudo
|
||||
tombname=`echo "$tombname" | cut -c1-16`
|
||||
"$TOMBPATH" close "$tombname"
|
||||
_info "Success" "Closed successfully!"
|
||||
@ -620,22 +456,21 @@ function _close {
|
||||
|
||||
# {{{ slam - Slam open tombs
|
||||
function _slam {
|
||||
tombtmp="/tmp/tombtmp"
|
||||
"$TOMBPATH" list --get-mountpoint > $tombtmp
|
||||
echo "/all" >> $tombtmp
|
||||
tombname=`cat $tombtmp | \
|
||||
sed 's/.*\/\([^\/]*\)$/\1\n &/' | \
|
||||
zenity \
|
||||
--title="Choose a tomb to slam" \
|
||||
--window-icon="$MONMORT" \
|
||||
--width=640 --height=380 --list \
|
||||
--separator=" & " \
|
||||
--column=Tomb \
|
||||
--column=Path `
|
||||
tombtmp="/tmp/tombtmp"
|
||||
"$TOMBPATH" list --get-mountpoint > $tombtmp
|
||||
echo "/all" >> $tombtmp
|
||||
tombname=`cat $tombtmp | \
|
||||
sed 's/.*\/\([^\/]*\)$/\1\n &/' | \
|
||||
zenity \
|
||||
--title="Choose a tomb to slam" \
|
||||
$Icon \
|
||||
--width=640 --height=380 --list \
|
||||
--separator=" & " \
|
||||
--column=Tomb \
|
||||
--column=Path `
|
||||
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
_sudo
|
||||
tombname=`echo "$tombname" | cut -c1-16`
|
||||
"$TOMBPATH" slam "$tombname"
|
||||
_info "Success" "Slammed successfully!"
|
||||
@ -645,11 +480,11 @@ function _slam {
|
||||
|
||||
# {{{ resize - Resize an existing *closed* tomb
|
||||
function _resize {
|
||||
tombname=`_fsel "Choose a tomb to resize"`
|
||||
res=$?
|
||||
_zenques "Is your tomb closed?"
|
||||
tombname=`_fsel "Choose a tomb to resize"`
|
||||
res=$?
|
||||
_zenques "Is your tomb closed?"
|
||||
|
||||
[[ $? = 0 ]] || { _zenwarn "gtomb" "Please close the tomb before resizing." ; exec _main }
|
||||
[[ $? = 0 ]] || { _zenwarn "Please close the tomb before resizing." ; exec _main }
|
||||
|
||||
[[ $res = 0 ]] || exec _main
|
||||
|
||||
@ -670,7 +505,6 @@ function _resize {
|
||||
keyfile=`_fsel "Choose according keyfile"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
_sudo
|
||||
"$TOMBPATH" resize "$tombname" -s "$tombsize" -k "$keyfile" | \
|
||||
_zenprognc "Resizing tomb." "Please wait while your tomb is being resized..."
|
||||
_info "Success" "Tomb resized successfully!"
|
||||
@ -680,10 +514,10 @@ function _resize {
|
||||
|
||||
# {{{ passwd - Change existing key's passphrase
|
||||
function _passwd {
|
||||
keyfile=`_fsel "Choose a keyfile"`
|
||||
keyfile=`_fsel "Choose a keyfile"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
"$TOMBPATH" passwd -k "$keyfile" | \
|
||||
"$TOMBPATH" passwd -k "$keyfile" "$FLAG" | \
|
||||
_zenprognc "Changing passphrase" "Please wait while your key's passphrase is being changed..."
|
||||
|
||||
_info "Success" "$keyfile passphrase changed successfully!"
|
||||
@ -693,7 +527,7 @@ function _passwd {
|
||||
|
||||
# {{{ setkey - Change a tomb's keyfile
|
||||
function _setkey {
|
||||
tombname=`_fsel "Choose a tomb to change its keyfile"`
|
||||
tombname=`_fsel "Choose a tomb to change its keyfile"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
keyfile=`_fsel "Chosse your tomb's old keyfile"`
|
||||
@ -702,19 +536,18 @@ function _setkey {
|
||||
newkey=`_fsel "Choose your tomb's new keyfile"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
_sudo
|
||||
"$TOMBPATH" setkey -k "$newkey" "$keyfile" "$tombname" | \
|
||||
"$TOMBPATH" setkey -k "$newkey" "$keyfile" "$tombname" "$FLAG" | \
|
||||
_zenprognc "Changing key" "Please wait while your tomb's key is being changed..."
|
||||
|
||||
_info "Success" "$tombname keyfile successfully changed! Now using $newkey"
|
||||
exec _main
|
||||
exec _main
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ engrave - generate QR code of a key
|
||||
function _engrave {
|
||||
which qrencode || _zenwarn "Warning" "qrencode is not installed. Install it and try again"
|
||||
keyfile=`_fsel "Choose a keyfile to engrave"`
|
||||
which qrencode || _zenwarn "qrencode is not installed. Install it and try again."
|
||||
keyfile=`_fsel "Choose a keyfile to engrave"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
jpegfile=`_fsave "Choose where to save your keyfile (PNG format)"`
|
||||
@ -730,8 +563,8 @@ function _engrave {
|
||||
|
||||
# {{{ bury - hide a keyfile in a JPEG image
|
||||
function _bury {
|
||||
which steghide || _zenwarn "Warning" "steghide is not installed. Install it and try again"
|
||||
keyfile=`_fsel "Choose keyfile"`
|
||||
which steghide || _zenwarn "steghide is not installed. Install it and try again."
|
||||
keyfile=`_fsel "Choose keyfile"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
jpegfile=`_fsel "Choose JPEG file"`
|
||||
@ -745,8 +578,8 @@ function _bury {
|
||||
|
||||
# {{{ exhume - extract keyfile from JPEG
|
||||
function _exhume {
|
||||
which steghide || _zenwarn "Warning" "steghide is not installed. Install it and try again"
|
||||
jpegfile=`_fsel "Choose JPEG file"`
|
||||
which steghide || _zenwarn "steghide is not installed. Install it and try again."
|
||||
jpegfile=`_fsel "Choose JPEG file"`
|
||||
[[ $? = 0 ]] || exec _main
|
||||
|
||||
keyfile=`_fsave "Choose where to extract your key"`
|
||||
@ -760,18 +593,18 @@ function _exhume {
|
||||
|
||||
# {{{ index - index the contents of open tombs
|
||||
function _index {
|
||||
which locate || _zenwarn "Warning" "mlocate is not installed. Install it and try again"
|
||||
"$TOMBPATH" index | _zenprognc "Indexing" "Please wait while the open tombs are being indexed..."
|
||||
_info "Success" "Tombs indexed!"
|
||||
exec _main
|
||||
which locate || _zenwarn "mlocate is not installed. Install it and try again."
|
||||
"$TOMBPATH" index | _zenprognc "Indexing" "Please wait while the open tombs are being indexed..."
|
||||
_info "Success" "Tombs indexed!"
|
||||
exec _main
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ search - searches the contents of indexed tombs
|
||||
function _search {
|
||||
strings=""
|
||||
_searchstring
|
||||
exec _main
|
||||
strings=""
|
||||
_searchstring
|
||||
exec _main
|
||||
}
|
||||
|
||||
function _searchstring {
|
||||
@ -799,7 +632,16 @@ function _searchstring {
|
||||
function _ { _clean } # I like cleaning :)
|
||||
|
||||
[[ -x $TOMBPATH ]] || {
|
||||
_zenwarn "Warning" "Tomb binary is not executable or doesn't exist in the current path. Install it or edit the script to point to the correct path."
|
||||
_zenwarn "Tomb binary is not executable or doesn't exist in the current path. Install it or edit the script to point to the correct path."
|
||||
exit 1 }
|
||||
|
||||
if [[ $SWAPOFF = "true" ]]; then
|
||||
FLAG=""
|
||||
zenity --password --title="sudo swapoff -a" | sudo swapoff -a
|
||||
unset $?
|
||||
else
|
||||
FLAG="-f"
|
||||
fi
|
||||
|
||||
_main
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
git clone https://github.com/stef/libsphinx
|
||||
cd libsphinx
|
||||
git submodule update --init --recursive --remote
|
||||
cd src
|
||||
sed -i 's|/usr/local|/usr|' makefile
|
||||
make
|
||||
sudo make install
|
||||
ldconfig
|
||||
pip3 install pwdsphinx
|
||||
sudo mkdir -p /etc/sphinx
|
@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
|
||||
} else {
|
||||
while( (read_bytes=fread(buf, sizeof(char), 2, stdin)) != 0) {
|
||||
if(read_bytes == 1) buf[1]='\0';
|
||||
sscanf(buf, "%x", &c);
|
||||
sscanf(buf, "%s", &c);
|
||||
printf("%c", c);
|
||||
}
|
||||
return 0;
|
||||
|
46
extras/portable/GNUmakefile
Normal file
46
extras/portable/GNUmakefile
Normal file
@ -0,0 +1,46 @@
|
||||
.PHONY: test
|
||||
|
||||
system := $(shell uname -s)
|
||||
# if [ ${system} == "FreeBSD" ]; then sudo kldload fusefs; fi
|
||||
|
||||
TOMB ?= test.tomb
|
||||
|
||||
#########
|
||||
## BUILD
|
||||
#########
|
||||
test: create-open-close check-random-data
|
||||
|
||||
########
|
||||
## TEST
|
||||
########
|
||||
create-open-close:
|
||||
TOMB=${TOMB} ./test/bats/bin/bats ./test/create_open_close.bats
|
||||
chmod a+r ${TOMB}
|
||||
|
||||
# arg: TOMB='path to tomb containing random.data'
|
||||
# assumes $TOMB.hash is the pre-calculated hash on creation
|
||||
check-random-data:
|
||||
TOMB=${TOMB} ./test/bats/bin/bats test/check-random-data.bats
|
||||
|
||||
########
|
||||
## LINT
|
||||
########
|
||||
shellcheck:
|
||||
shellcheck -s sh tomb -e SC2006,SC2059,SC2034
|
||||
|
||||
########
|
||||
## DEPS
|
||||
########
|
||||
download-deps-ubuntu22:
|
||||
curl https://files.dyne.org/tomb3/third-party/veracrypt-ubuntu22-amd64 -o /usr/local/bin/veracrypt && chmod +x /usr/local/bin/veracrypt
|
||||
curl https://files.dyne.org/zenroom/nightly/zenroom-linux-amd64 -o /usr/local/bin/zenroom && chmod +x /usr/local/bin/zenroom
|
||||
|
||||
download-deps-ubuntu20:
|
||||
curl https://files.dyne.org/tomb3/third-party/veracrypt-ubuntu20-amd64 -o /usr/local/bin/veracrypt && chmod +x /usr/local/bin/veracrypt
|
||||
curl https://files.dyne.org/zenroom/nightly/zenroom-linux-amd64 -o /usr/local/bin/zenroom && chmod +x /usr/local/bin/zenroom
|
||||
|
||||
download-deps-freebsd13:
|
||||
curl https://files.dyne.org/tomb3/third-party/veracrypt-freebsd13-amd64 -o /usr/local/bin/veracrypt && chmod +x /usr/local/bin/veracrypt
|
||||
curl https://files.dyne.org/tomb3/third-party/zenroom-freebsd13-amd64 -o /usr/local/bin/zenroom && chmod +x /usr/local/bin/zenroom
|
||||
|
||||
#curl https://files.dyne.org/zenroom/nightly/zenroom-freebsd13-amd64 -o /usr/local/bin/zenroom && chmod +x /usr/local/bin/zenroom
|
69
extras/portable/README.md
Normal file
69
extras/portable/README.md
Normal file
@ -0,0 +1,69 @@
|
||||
|
||||
# Portable Tomb :: the crypto undertaker runs everywhere
|
||||
|
||||
[![continuous integration tests badge](https://github.com/dyne/tomb/actions/workflows/portable.yml/badge.svg)](https://github.com/dyne/Tomb/actions) test coverage status for portability
|
||||
|
||||
## ⚠️ WORK IN PROGRESS 🛠️
|
||||
|
||||
This is the portable version of [Tomb](https://github.com/dyne/tomb)
|
||||
|
||||
[![software by Dyne.org](https://files.dyne.org/software_by_dyne.png)](http://www.dyne.org)
|
||||
|
||||
# Purpose
|
||||
|
||||
Portable tomb achieves direct **interoperable access to tomb volumes** between:
|
||||
|
||||
- GNU base Linux (Ubuntu)
|
||||
- Busybox based Linux (Alpine)
|
||||
- MS/Windows using WSL2 (Ubuntu)
|
||||
- FreeBSD (WIP using libluksde)
|
||||
- ~~Apple/OSX using [MacFUSE](https://osxfuse.github.io/)~~
|
||||
|
||||
After some extensive testing during 2022, __adoption of Veracrypt in portable Tomb has been dropped__ because of unreliability and bad performance.
|
||||
|
||||
Portable tomb stays as an experimental branch that aims to reduce dependencies and in particular uses only the **POSIX sh interpreter**.
|
||||
|
||||
# Status
|
||||
|
||||
Portable tomb development is in progress and tracked via issues and the [portable milestone](https://github.com/dyne/Tomb/milestone/9).
|
||||
|
||||
## Features
|
||||
|
||||
The following features will be implemented where possible:
|
||||
|
||||
- mount bind (Linux only)
|
||||
- ps / slam
|
||||
- resize (pending investigation)
|
||||
- index & search ([recoll based](https://github.com/dyne/Tomb/issues/211))
|
||||
- bury / exhume
|
||||
|
||||
## Dependencies
|
||||
|
||||
- FreeBSD: `fusefs-libs3 fusefs-lkl e2fsprogs util-linux libluksde`
|
||||
- Linux: `fuse3 util-linux`
|
||||
- crossplatform [Veracrypt binaries](https://files.dyne.org/tomb3/third-party) console-only
|
||||
|
||||
## Note on Veracrypt
|
||||
|
||||
The way upstream developers distribute Veracrypt is far from meeting our minimalist needs, but the console-only binary once installed has a few library dependencies and is all what we need.
|
||||
|
||||
I setup [my own build](https://github.com/jaromil/veracrypt) and provide binary builds of Veracrypt v1.25.9 for download on Tomb's file repository for testing purposes.
|
||||
|
||||
# Disclaimer
|
||||
|
||||
Tomb is Copyright (C) 2007-2023 by the Dyne.org Foundation and
|
||||
developed by [Jaromil](https://github.com/jaromil).
|
||||
|
||||
This source code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This source code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please refer
|
||||
to the GNU Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Public License along with
|
||||
this source code; if not, write to: Free Software Foundation, Inc.,
|
||||
675 Mass Ave, Cambridge, MA 02139, USA.
|
97
extras/portable/gh-ci-portable.yml
Normal file
97
extras/portable/gh-ci-portable.yml
Normal file
@ -0,0 +1,97 @@
|
||||
name: ☠️ Portable tomb
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'extras/portable/**'
|
||||
- '.github/workflows/portable.yml'
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
paths:
|
||||
- 'extras/portable/**'
|
||||
- '.github/workflows/portable.yml'
|
||||
branches:
|
||||
- master
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
ubuntu-20:
|
||||
name: 🐧 test Ubuntu-20
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install portable tomb dependencies
|
||||
run: |
|
||||
sudo apt-get install -q -y make openssl wget fuse3 util-linux
|
||||
sudo make -C portable download-deps-ubuntu20
|
||||
- name: Run portable tomb test
|
||||
run: sudo make -C extras/portable create-open-close
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ubuntu-test.tomb
|
||||
path: extras/portable/test.tomb*
|
||||
retention-days: 1
|
||||
|
||||
freebsd:
|
||||
runs-on: macos-12
|
||||
name: 😈 test FreeBSD-13
|
||||
needs: [ubuntu-20]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Download portable tomb volume built on Ubuntu
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ubuntu-test.tomb
|
||||
path: extras/portable
|
||||
- name: Test in FreeBSD
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
with:
|
||||
usesh: true
|
||||
prepare: |
|
||||
pkg install -y sudo gmake bash fusefs-libs3 fusefs-lkl e2fsprogs wget
|
||||
wget https://files.dyne.org/tomb3/third-party/veracrypt-freebsd13-amd64
|
||||
mv veracrypt-freebsd13-amd64 /usr/bin/veracrypt
|
||||
wget https://files.dyne.org/tomb3/third-party/zenroom-freebsd13-amd64
|
||||
mv zenroom-freebsd13-amd64 /usr/bin/zenroom
|
||||
chmod a+x /usr/bin/veracrypt /usr/bin/zenroom
|
||||
kldload fusefs
|
||||
run: |
|
||||
sudo gmake -C extras/portable
|
||||
sudo gmake -C portable check-random-data
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: freebsd-test.tomb
|
||||
path: extras/portable/test.tomb*
|
||||
retention-days: 1
|
||||
|
||||
ubuntu-last-cleanup:
|
||||
name: 🎯 final Ubuntu tests and cleanup
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [freebsd]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install compiler and dependencies
|
||||
run: |
|
||||
sudo apt-get install -q -y make openssl wget fuse3 util-linux
|
||||
sudo make -C extras/portable download-deps-ubuntu20
|
||||
- name: Download tomb built on FreeBSD
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: freebsd-test.tomb
|
||||
path: extras/portable
|
||||
- name: Check integrity FreeBSD->Ubuntu
|
||||
run: sudo make -C extras/portable check-random-data
|
||||
- name: delete FreeBSD tomb artifacts
|
||||
uses: geekyeggo/delete-artifact@v2
|
||||
with:
|
||||
name: freebsd-test.tomb
|
||||
- name: delete Ubuntu tomb artifacts
|
||||
uses: geekyeggo/delete-artifact@v2
|
||||
with:
|
||||
name: ubuntu-test.tomb
|
59
extras/portable/test/bats/bin/bats
Executable file
59
extras/portable/test/bats/bin/bats
Executable file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if command -v greadlink >/dev/null; then
|
||||
bats_readlinkf() {
|
||||
greadlink -f "$1"
|
||||
}
|
||||
else
|
||||
bats_readlinkf() {
|
||||
readlink -f "$1"
|
||||
}
|
||||
fi
|
||||
|
||||
fallback_to_readlinkf_posix() {
|
||||
bats_readlinkf() {
|
||||
[ "${1:-}" ] || return 1
|
||||
max_symlinks=40
|
||||
CDPATH='' # to avoid changing to an unexpected directory
|
||||
|
||||
target=$1
|
||||
[ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes
|
||||
[ -d "${target:-/}" ] && target="$target/"
|
||||
|
||||
cd -P . 2>/dev/null || return 1
|
||||
while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do
|
||||
if [ ! "$target" = "${target%/*}" ]; then
|
||||
case $target in
|
||||
/*) cd -P "${target%/*}/" 2>/dev/null || break ;;
|
||||
*) cd -P "./${target%/*}" 2>/dev/null || break ;;
|
||||
esac
|
||||
target=${target##*/}
|
||||
fi
|
||||
|
||||
if [ ! -L "$target" ]; then
|
||||
target="${PWD%/}${target:+/}${target}"
|
||||
printf '%s\n' "${target:-/}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n",
|
||||
# <file mode>, <number of links>, <owner name>, <group name>,
|
||||
# <size>, <date and time>, <pathname of link>, <contents of link>
|
||||
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
|
||||
link=$(ls -dl -- "$target" 2>/dev/null) || break
|
||||
target=${link#*" $target -> "}
|
||||
done
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
if ! BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}" 2>/dev/null); then
|
||||
fallback_to_readlinkf_posix
|
||||
BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}")
|
||||
fi
|
||||
|
||||
export BATS_ROOT=${BATS_PATH%/*/*}
|
||||
export -f bats_readlinkf
|
||||
exec env BATS_ROOT="$BATS_ROOT" "$BATS_ROOT/libexec/bats-core/bats" "$@"
|
98
extras/portable/test/bats/lib/bats-core/common.bash
Normal file
98
extras/portable/test/bats/lib/bats-core/common.bash
Normal file
@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
bats_prefix_lines_for_tap_output() {
|
||||
while IFS= read -r line; do
|
||||
printf '# %s\n' "$line" || break # avoid feedback loop when errors are redirected into BATS_OUT (see #353)
|
||||
done
|
||||
if [[ -n "$line" ]]; then
|
||||
printf '# %s\n' "$line"
|
||||
fi
|
||||
}
|
||||
|
||||
function bats_replace_filename() {
|
||||
local line
|
||||
while read -r line; do
|
||||
printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}"
|
||||
done
|
||||
if [[ -n "$line" ]]; then
|
||||
printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}"
|
||||
fi
|
||||
}
|
||||
|
||||
bats_quote_code() { # <var> <code>
|
||||
printf -v "$1" -- "%s%s%s" "$BATS_BEGIN_CODE_QUOTE" "$2" "$BATS_END_CODE_QUOTE"
|
||||
}
|
||||
|
||||
bats_check_valid_version() {
|
||||
if [[ ! $1 =~ [0-9]+.[0-9]+.[0-9]+ ]]; then
|
||||
printf "ERROR: version '%s' must be of format <major>.<minor>.<patch>!\n" "$1" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# compares two versions. Return 0 when version1 < version2
|
||||
bats_version_lt() { # <version1> <version2>
|
||||
bats_check_valid_version "$1"
|
||||
bats_check_valid_version "$2"
|
||||
|
||||
local -a version1_parts version2_parts
|
||||
IFS=. read -ra version1_parts <<< "$1"
|
||||
IFS=. read -ra version2_parts <<< "$2"
|
||||
|
||||
for i in {0..2}; do
|
||||
if (( version1_parts[i] < version2_parts[i] )); then
|
||||
return 0
|
||||
elif (( version1_parts[i] > version2_parts[i] )); then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
# if we made it this far, they are equal -> also not less then
|
||||
return 2 # use other failing return code to distinguish equal from gt
|
||||
}
|
||||
|
||||
# ensure a minimum version of bats is running or exit with failure
|
||||
bats_require_minimum_version() { # <required version>
|
||||
local required_minimum_version=$1
|
||||
|
||||
if bats_version_lt "$BATS_VERSION" "$required_minimum_version"; then
|
||||
printf "BATS_VERSION=%s does not meet required minimum %s\n" "$BATS_VERSION" "$required_minimum_version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if bats_version_lt "$BATS_GUARANTEED_MINIMUM_VERSION" "$required_minimum_version"; then
|
||||
BATS_GUARANTEED_MINIMUM_VERSION="$required_minimum_version"
|
||||
fi
|
||||
}
|
||||
|
||||
bats_binary_search() { # <search-value> <array-name>
|
||||
if [[ $# -ne 2 ]]; then
|
||||
printf "ERROR: bats_binary_search requires exactly 2 arguments: <search value> <array name>\n" >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
local -r search_value=$1 array_name=$2
|
||||
|
||||
# we'd like to test if array is set but we cannot distinguish unset from empty arrays, so we need to skip that
|
||||
|
||||
local start=0 mid end mid_value
|
||||
# start is inclusive, end is exclusive ...
|
||||
eval "end=\${#${array_name}[@]}"
|
||||
|
||||
# so start == end means empty search space
|
||||
while (( start < end )); do
|
||||
mid=$(( (start + end) / 2 ))
|
||||
eval "mid_value=\${${array_name}[$mid]}"
|
||||
if [[ "$mid_value" == "$search_value" ]]; then
|
||||
return 0
|
||||
elif [[ "$mid_value" < "$search_value" ]]; then
|
||||
# This branch excludes equality -> +1 to skip the mid element.
|
||||
# This +1 also avoids endless recursion on odd sized search ranges.
|
||||
start=$((mid + 1))
|
||||
else
|
||||
end=$mid
|
||||
fi
|
||||
done
|
||||
|
||||
# did not find it -> its not there
|
||||
return 1
|
||||
}
|
116
extras/portable/test/bats/lib/bats-core/formatter.bash
Normal file
116
extras/portable/test/bats/lib/bats-core/formatter.bash
Normal file
@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# reads (extended) bats tap streams from stdin and calls callback functions for each line
|
||||
# bats_tap_stream_plan <number of tests> -> when the test plan is encountered
|
||||
# bats_tap_stream_begin <test index> <test name> -> when a new test is begun WARNING: extended only
|
||||
# bats_tap_stream_ok [--duration <milliseconds] <test index> <test name> -> when a test was successful
|
||||
# bats_tap_stream_not_ok [--duration <milliseconds>] <test index> <test name> -> when a test has failed
|
||||
# bats_tap_stream_skipped <test index> <test name> <skip reason> -> when a test was skipped
|
||||
# bats_tap_stream_comment <comment text without leading '# '> <scope> -> when a comment line was encountered,
|
||||
# scope tells the last encountered of plan, begin, ok, not_ok, skipped, suite
|
||||
# bats_tap_stream_suite <file name> -> when a new file is begun WARNING: extended only
|
||||
# bats_tap_stream_unknown <full line> <scope> -> when a line is encountered that does not match the previous entries,
|
||||
# scope @see bats_tap_stream_comment
|
||||
# forwards all input as is, when there is no TAP test plan header
|
||||
function bats_parse_internal_extended_tap() {
|
||||
local header_pattern='[0-9]+\.\.[0-9]+'
|
||||
IFS= read -r header
|
||||
|
||||
if [[ "$header" =~ $header_pattern ]]; then
|
||||
bats_tap_stream_plan "${header:3}"
|
||||
else
|
||||
# If the first line isn't a TAP plan, print it and pass the rest through
|
||||
printf '%s\n' "$header"
|
||||
exec cat
|
||||
fi
|
||||
|
||||
ok_line_regexpr="ok ([0-9]+) (.*)"
|
||||
skip_line_regexpr="ok ([0-9]+) (.*) # skip( (.*))?$"
|
||||
not_ok_line_regexpr="not ok ([0-9]+) (.*)"
|
||||
|
||||
timing_expr="in ([0-9]+)ms$"
|
||||
local test_name begin_index ok_index not_ok_index index scope
|
||||
begin_index=0
|
||||
index=0
|
||||
scope=plan
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
'begin '*) # this might only be called in extended tap output
|
||||
((++begin_index))
|
||||
scope=begin
|
||||
test_name="${line#* "$begin_index" }"
|
||||
bats_tap_stream_begin "$begin_index" "$test_name"
|
||||
;;
|
||||
'ok '*)
|
||||
((++index))
|
||||
if [[ "$line" =~ $ok_line_regexpr ]]; then
|
||||
ok_index="${BASH_REMATCH[1]}"
|
||||
test_name="${BASH_REMATCH[2]}"
|
||||
if [[ "$line" =~ $skip_line_regexpr ]]; then
|
||||
scope=skipped
|
||||
test_name="${BASH_REMATCH[2]}" # cut off name before "# skip"
|
||||
local skip_reason="${BASH_REMATCH[4]}"
|
||||
bats_tap_stream_skipped "$ok_index" "$test_name" "$skip_reason"
|
||||
else
|
||||
scope=ok
|
||||
if [[ "$line" =~ $timing_expr ]]; then
|
||||
bats_tap_stream_ok --duration "${BASH_REMATCH[1]}" "$ok_index" "$test_name"
|
||||
else
|
||||
bats_tap_stream_ok "$ok_index" "$test_name"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
printf "ERROR: could not match ok line: %s" "$line" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
'not ok '*)
|
||||
((++index))
|
||||
scope=not_ok
|
||||
if [[ "$line" =~ $not_ok_line_regexpr ]]; then
|
||||
not_ok_index="${BASH_REMATCH[1]}"
|
||||
test_name="${BASH_REMATCH[2]}"
|
||||
if [[ "$line" =~ $timing_expr ]]; then
|
||||
bats_tap_stream_not_ok --duration "${BASH_REMATCH[1]}" "$not_ok_index" "$test_name"
|
||||
else
|
||||
bats_tap_stream_not_ok "$not_ok_index" "$test_name"
|
||||
fi
|
||||
else
|
||||
printf "ERROR: could not match not ok line: %s" "$line" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
'# '*)
|
||||
bats_tap_stream_comment "${line:2}" "$scope"
|
||||
;;
|
||||
'#')
|
||||
bats_tap_stream_comment "" "$scope"
|
||||
;;
|
||||
'suite '*)
|
||||
scope=suite
|
||||
# pass on the
|
||||
bats_tap_stream_suite "${line:6}"
|
||||
;;
|
||||
*)
|
||||
bats_tap_stream_unknown "$line" "$scope"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
normalize_base_path() { # <target variable> <base path>
|
||||
# the relative path root to use for reporting filenames
|
||||
# this is mainly intended for suite mode, where this will be the suite root folder
|
||||
local base_path="$2"
|
||||
# use the containing directory when --base-path is a file
|
||||
if [[ ! -d "$base_path" ]]; then
|
||||
base_path="$(dirname "$base_path")"
|
||||
fi
|
||||
# get the absolute path
|
||||
base_path="$(cd "$base_path" && pwd)"
|
||||
# ensure the path ends with / to strip that later on
|
||||
if [[ "${base_path}" != *"/" ]]; then
|
||||
base_path="$base_path/"
|
||||
fi
|
||||
printf -v "$1" "%s" "$base_path"
|
||||
}
|
22
extras/portable/test/bats/lib/bats-core/preprocessing.bash
Normal file
22
extras/portable/test/bats/lib/bats-core/preprocessing.bash
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BATS_TMPNAME="$BATS_RUN_TMPDIR/bats.$$"
|
||||
BATS_PARENT_TMPNAME="$BATS_RUN_TMPDIR/bats.$PPID"
|
||||
# shellcheck disable=SC2034
|
||||
BATS_OUT="${BATS_TMPNAME}.out" # used in bats-exec-file
|
||||
|
||||
bats_preprocess_source() {
|
||||
# export to make it visible to bats_evaluate_preprocessed_source
|
||||
# since the latter runs in bats-exec-test's bash while this runs in bats-exec-file's
|
||||
export BATS_TEST_SOURCE="${BATS_TMPNAME}.src"
|
||||
bats-preprocess "$BATS_TEST_FILENAME" >"$BATS_TEST_SOURCE"
|
||||
}
|
||||
|
||||
bats_evaluate_preprocessed_source() {
|
||||
if [[ -z "${BATS_TEST_SOURCE:-}" ]]; then
|
||||
BATS_TEST_SOURCE="${BATS_PARENT_TMPNAME}.src"
|
||||
fi
|
||||
# Dynamically loaded user files provided outside of Bats.
|
||||
# shellcheck disable=SC1090
|
||||
source "$BATS_TEST_SOURCE"
|
||||
}
|
107
extras/portable/test/bats/lib/bats-core/semaphore.bash
Normal file
107
extras/portable/test/bats/lib/bats-core/semaphore.bash
Normal file
@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# setup the semaphore environment for the loading file
|
||||
bats_semaphore_setup() {
|
||||
export -f bats_semaphore_get_free_slot_count
|
||||
export -f bats_semaphore_acquire_while_locked
|
||||
export BATS_SEMAPHORE_DIR="$BATS_RUN_TMPDIR/semaphores"
|
||||
|
||||
if command -v flock >/dev/null; then
|
||||
bats_run_under_lock() {
|
||||
flock "$BATS_SEMAPHORE_DIR" "$@"
|
||||
}
|
||||
elif command -v shlock >/dev/null; then
|
||||
bats_run_under_lock() {
|
||||
local lockfile="$BATS_SEMAPHORE_DIR/shlock.lock"
|
||||
while ! shlock -p $$ -f "$lockfile"; do
|
||||
sleep 1
|
||||
done
|
||||
# we got the lock now, execute the command
|
||||
"$@"
|
||||
local status=$?
|
||||
# free the lock
|
||||
rm -f "$lockfile"
|
||||
return $status
|
||||
}
|
||||
else
|
||||
printf "ERROR: flock/shlock is required for parallelization within files!\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# $1 - output directory for stdout/stderr
|
||||
# $@ - command to run
|
||||
# run the given command in a semaphore
|
||||
# block when there is no free slot for the semaphore
|
||||
# when there is a free slot, run the command in background
|
||||
# gather the output of the command in files in the given directory
|
||||
bats_semaphore_run() {
|
||||
local output_dir=$1
|
||||
shift
|
||||
local semaphore_slot
|
||||
semaphore_slot=$(bats_semaphore_acquire_slot)
|
||||
bats_semaphore_release_wrapper "$output_dir" "$semaphore_slot" "$@" &
|
||||
printf "%d\n" "$!"
|
||||
}
|
||||
|
||||
# $1 - output directory for stdout/stderr
|
||||
# $@ - command to run
|
||||
# this wraps the actual function call to install some traps on exiting
|
||||
bats_semaphore_release_wrapper() {
|
||||
local output_dir="$1"
|
||||
local semaphore_name="$2"
|
||||
shift 2 # all other parameters will be use for the command to execute
|
||||
|
||||
# shellcheck disable=SC2064 # we want to expand the semaphore_name right now!
|
||||
trap "status=$?; bats_semaphore_release_slot '$semaphore_name'; exit $status" EXIT
|
||||
|
||||
mkdir -p "$output_dir"
|
||||
"$@" 2>"$output_dir/stderr" >"$output_dir/stdout"
|
||||
local status=$?
|
||||
|
||||
# bash bug: the exit trap is not called for the background process
|
||||
bats_semaphore_release_slot "$semaphore_name"
|
||||
trap - EXIT # avoid calling release twice
|
||||
return $status
|
||||
}
|
||||
|
||||
bats_semaphore_acquire_while_locked() {
|
||||
if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then
|
||||
local slot=0
|
||||
while [[ -e "$BATS_SEMAPHORE_DIR/slot-$slot" ]]; do
|
||||
(( ++slot ))
|
||||
done
|
||||
if [[ $slot -lt $BATS_SEMAPHORE_NUMBER_OF_SLOTS ]]; then
|
||||
touch "$BATS_SEMAPHORE_DIR/slot-$slot" && printf "%d\n" "$slot" && return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# block until a semaphore slot becomes free
|
||||
# prints the number of the slot that it received
|
||||
bats_semaphore_acquire_slot() {
|
||||
mkdir -p "$BATS_SEMAPHORE_DIR"
|
||||
# wait for a slot to become free
|
||||
# TODO: avoid busy waiting by using signals -> this opens op prioritizing possibilities as well
|
||||
while true; do
|
||||
# don't lock for reading, we are fine with spuriously getting no free slot
|
||||
if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then
|
||||
bats_run_under_lock bash -c bats_semaphore_acquire_while_locked && break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
bats_semaphore_release_slot() {
|
||||
# we don't need to lock this, since only our process owns this file
|
||||
# and freeing a semaphore cannot lead to conflicts with others
|
||||
rm "$BATS_SEMAPHORE_DIR/slot-$1" # this will fail if we had not acquired a semaphore!
|
||||
}
|
||||
|
||||
bats_semaphore_get_free_slot_count() {
|
||||
# find might error out without returning something useful when a file is deleted,
|
||||
# while the directory is traversed -> only continue when there was no error
|
||||
until used_slots=$(find "$BATS_SEMAPHORE_DIR" -name 'slot-*' 2>/dev/null | wc -l); do :; done
|
||||
echo $(( BATS_SEMAPHORE_NUMBER_OF_SLOTS - used_slots ))
|
||||
}
|
357
extras/portable/test/bats/lib/bats-core/test_functions.bash
Normal file
357
extras/portable/test/bats/lib/bats-core/test_functions.bash
Normal file
@ -0,0 +1,357 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BATS_TEST_DIRNAME="${BATS_TEST_FILENAME%/*}"
|
||||
BATS_TEST_NAMES=()
|
||||
|
||||
# shellcheck source=lib/bats-core/warnings.bash
|
||||
source "$BATS_ROOT/lib/bats-core/warnings.bash"
|
||||
|
||||
# find_in_bats_lib_path echoes the first recognized load path to
|
||||
# a library in BATS_LIB_PATH or relative to BATS_TEST_DIRNAME.
|
||||
#
|
||||
# Libraries relative to BATS_TEST_DIRNAME take precedence over
|
||||
# BATS_LIB_PATH.
|
||||
#
|
||||
# Library load paths are recognized using find_library_load_path.
|
||||
#
|
||||
# If no library is found find_in_bats_lib_path returns 1.
|
||||
find_in_bats_lib_path() { # <return-var> <library-name>
|
||||
local return_var="${1:?}"
|
||||
local library_name="${2:?}"
|
||||
|
||||
local -a bats_lib_paths
|
||||
IFS=: read -ra bats_lib_paths <<< "$BATS_LIB_PATH"
|
||||
|
||||
for path in "${bats_lib_paths[@]}"; do
|
||||
if [[ -f "$path/$library_name" ]]; then
|
||||
printf -v "$return_var" "%s" "$path/$library_name"
|
||||
# A library load path was found, return
|
||||
return 0
|
||||
elif [[ -f "$path/$library_name/load.bash" ]]; then
|
||||
printf -v "$return_var" "%s" "$path/$library_name/load.bash"
|
||||
# A library load path was found, return
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# bats_internal_load expects an absolute path that is a library load path.
|
||||
#
|
||||
# If the library load path points to a file (a library loader) it is
|
||||
# sourced.
|
||||
#
|
||||
# If it points to a directory all files ending in .bash inside of the
|
||||
# directory are sourced.
|
||||
#
|
||||
# If the sourcing of the library loader or of a file in a library
|
||||
# directory fails bats_internal_load prints an error message and returns 1.
|
||||
#
|
||||
# If the passed library load path is not absolute or is not a valid file
|
||||
# or directory bats_internal_load prints an error message and returns 1.
|
||||
bats_internal_load() {
|
||||
local library_load_path="${1:?}"
|
||||
|
||||
if [[ "${library_load_path:0:1}" != / ]]; then
|
||||
printf "Passed library load path is not an absolute path: %s\n" "$library_load_path" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# library_load_path is a library loader
|
||||
if [[ -f "$library_load_path" ]]; then
|
||||
# shellcheck disable=SC1090
|
||||
if ! source "$library_load_path"; then
|
||||
printf "Error while sourcing library loader at '%s'\n" "$library_load_path" >&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf "Passed library load path is neither a library loader nor library directory: %s\n" "$library_load_path" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# bats_load_safe accepts an argument called 'slug' and attempts to find and
|
||||
# source a library based on the slug.
|
||||
#
|
||||
# A slug can be an absolute path, a library name or a relative path.
|
||||
#
|
||||
# If the slug is an absolute path bats_load_safe attempts to find the library
|
||||
# load path using find_library_load_path.
|
||||
# What is considered a library load path is documented in the
|
||||
# documentation for find_library_load_path.
|
||||
#
|
||||
# If the slug is not an absolute path it is considered a library name or
|
||||
# relative path. bats_load_safe attempts to find the library load path using
|
||||
# find_in_bats_lib_path.
|
||||
#
|
||||
# If bats_load_safe can find a library load path it is passed to bats_internal_load.
|
||||
# If bats_internal_load fails bats_load_safe returns 1.
|
||||
#
|
||||
# If no library load path can be found bats_load_safe prints an error message
|
||||
# and returns 1.
|
||||
bats_load_safe() {
|
||||
local slug="${1:?}"
|
||||
if [[ ${slug:0:1} != / ]]; then # relative paths are relative to BATS_TEST_DIRNAME
|
||||
slug="$BATS_TEST_DIRNAME/$slug"
|
||||
fi
|
||||
|
||||
if [[ -f "$slug.bash" ]]; then
|
||||
bats_internal_load "$slug.bash"
|
||||
return $?
|
||||
elif [[ -f "$slug" ]]; then
|
||||
bats_internal_load "$slug"
|
||||
return $?
|
||||
fi
|
||||
|
||||
# loading from PATH (retained for backwards compatibility)
|
||||
if [[ ! -f "$1" ]] && type -P "$1" >/dev/null; then
|
||||
# shellcheck disable=SC1090
|
||||
source "$1"
|
||||
return $?
|
||||
fi
|
||||
|
||||
# No library load path can be found
|
||||
printf "bats_load_safe: Could not find '%s'[.bash]\n" "$slug" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
bats_require_lib_path() {
|
||||
if [[ -z "${BATS_LIB_PATH:-}" ]]; then
|
||||
printf "%s: requires BATS_LIB_PATH to be set!\n" "${FUNCNAME[1]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
bats_load_library_safe() { # <slug>
|
||||
local slug="${1:?}" library_path
|
||||
|
||||
bats_require_lib_path
|
||||
|
||||
# Check for library load paths in BATS_TEST_DIRNAME and BATS_LIB_PATH
|
||||
if [[ ${slug:0:1} != / ]]; then
|
||||
find_in_bats_lib_path library_path "$slug"
|
||||
if [[ -z "$library_path" ]]; then
|
||||
printf "Could not find library '%s' relative to test file or in BATS_LIB_PATH\n" "$slug" >&2
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
# absolute paths are taken as is
|
||||
library_path="$slug"
|
||||
if [[ ! -f "$library_path" ]]; then
|
||||
printf "Could not find library on absolute path '%s'\n" "$library_path" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
bats_internal_load "$library_path"
|
||||
return $?
|
||||
}
|
||||
|
||||
# immediately exit on error, use bats_load_library_safe to catch and handle errors
|
||||
bats_load_library() { # <slug>
|
||||
bats_require_lib_path
|
||||
if ! bats_load_library_safe "$@"; then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# load acts like bats_load_safe but exits the shell instead of returning 1.
|
||||
load() {
|
||||
if ! bats_load_safe "$@"; then
|
||||
echo "${FUNCNAME[0]} $LINENO" >&3
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
bats_redirect_stderr_into_file() {
|
||||
"$@" 2>>"$bats_run_separate_stderr_file" # use >> to see collisions' content
|
||||
}
|
||||
|
||||
bats_merge_stdout_and_stderr() {
|
||||
"$@" 2>&1
|
||||
}
|
||||
|
||||
# write separate lines from <input-var> into <output-array>
|
||||
bats_separate_lines() { # <output-array> <input-var>
|
||||
local output_array_name="$1"
|
||||
local input_var_name="$2"
|
||||
if [[ $keep_empty_lines ]]; then
|
||||
local bats_separate_lines_lines=()
|
||||
if [[ -n "${!input_var_name}" ]]; then # avoid getting an empty line for empty input
|
||||
while IFS= read -r line; do
|
||||
bats_separate_lines_lines+=("$line")
|
||||
done <<<"${!input_var_name}"
|
||||
fi
|
||||
eval "${output_array_name}=(\"\${bats_separate_lines_lines[@]}\")"
|
||||
else
|
||||
# shellcheck disable=SC2034,SC2206
|
||||
IFS=$'\n' read -d '' -r -a "$output_array_name" <<<"${!input_var_name}" || true # don't fail due to EOF
|
||||
fi
|
||||
}
|
||||
|
||||
run() { # [!|-N] [--keep-empty-lines] [--separate-stderr] [--] <command to run...>
|
||||
# This has to be restored on exit from this function to avoid leaking our trap INT into surrounding code.
|
||||
# Non zero exits won't restore under the assumption that they will fail the test before it can be aborted,
|
||||
# which allows us to avoid duplicating the restore code on every exit path
|
||||
trap bats_interrupt_trap_in_run INT
|
||||
local expected_rc=
|
||||
local keep_empty_lines=
|
||||
local output_case=merged
|
||||
local has_flags=
|
||||
# parse options starting with -
|
||||
while [[ $# -gt 0 ]] && [[ $1 == -* || $1 == '!' ]]; do
|
||||
has_flags=1
|
||||
case "$1" in
|
||||
'!')
|
||||
expected_rc=-1
|
||||
;;
|
||||
-[0-9]*)
|
||||
expected_rc=${1#-}
|
||||
if [[ $expected_rc =~ [^0-9] ]]; then
|
||||
printf "Usage error: run: '-NNN' requires numeric NNN (got: %s)\n" "$expected_rc" >&2
|
||||
return 1
|
||||
elif [[ $expected_rc -gt 255 ]]; then
|
||||
printf "Usage error: run: '-NNN': NNN must be <= 255 (got: %d)\n" "$expected_rc" >&2
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
--keep-empty-lines)
|
||||
keep_empty_lines=1
|
||||
;;
|
||||
--separate-stderr)
|
||||
output_case="separate"
|
||||
;;
|
||||
--)
|
||||
shift # eat the -- before breaking away
|
||||
break
|
||||
;;
|
||||
*)
|
||||
printf "Usage error: unknown flag '%s'" "$1" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -n $has_flags ]]; then
|
||||
bats_warn_minimum_guaranteed_version "Using flags on \`run\`" 1.5.0
|
||||
fi
|
||||
|
||||
local pre_command=
|
||||
|
||||
case "$output_case" in
|
||||
merged) # redirects stderr into stdout and fills only $output/$lines
|
||||
pre_command=bats_merge_stdout_and_stderr
|
||||
;;
|
||||
separate) # splits stderr into own file and fills $stderr/$stderr_lines too
|
||||
local bats_run_separate_stderr_file
|
||||
bats_run_separate_stderr_file="$(mktemp "${BATS_TEST_TMPDIR}/separate-stderr-XXXXXX")"
|
||||
pre_command=bats_redirect_stderr_into_file
|
||||
;;
|
||||
esac
|
||||
|
||||
local origFlags="$-"
|
||||
set +eET
|
||||
local origIFS="$IFS"
|
||||
if [[ $keep_empty_lines ]]; then
|
||||
# 'output', 'status', 'lines' are global variables available to tests.
|
||||
# preserve trailing newlines by appending . and removing it later
|
||||
# shellcheck disable=SC2034
|
||||
output="$($pre_command "$@"; status=$?; printf .; exit $status)" && status=0 || status=$?
|
||||
output="${output%.}"
|
||||
else
|
||||
# 'output', 'status', 'lines' are global variables available to tests.
|
||||
# shellcheck disable=SC2034
|
||||
output="$($pre_command "$@")" && status=0 || status=$?
|
||||
fi
|
||||
|
||||
bats_separate_lines lines output
|
||||
|
||||
if [[ "$output_case" == separate ]]; then
|
||||
# shellcheck disable=SC2034
|
||||
read -d '' -r stderr < "$bats_run_separate_stderr_file"
|
||||
bats_separate_lines stderr_lines stderr
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
BATS_RUN_COMMAND="${*}"
|
||||
IFS="$origIFS"
|
||||
set "-$origFlags"
|
||||
|
||||
if [[ ${BATS_VERBOSE_RUN:-} ]]; then
|
||||
printf "%s\n" "$output"
|
||||
fi
|
||||
|
||||
|
||||
if [[ -n "$expected_rc" ]]; then
|
||||
if [[ "$expected_rc" = "-1" ]]; then
|
||||
if [[ "$status" -eq 0 ]]; then
|
||||
BATS_ERROR_SUFFIX=", expected nonzero exit code!"
|
||||
return 1
|
||||
fi
|
||||
elif [ "$status" -ne "$expected_rc" ]; then
|
||||
# shellcheck disable=SC2034
|
||||
BATS_ERROR_SUFFIX=", expected exit code $expected_rc, got $status"
|
||||
return 1
|
||||
fi
|
||||
elif [[ "$status" -eq 127 ]]; then # "command not found"
|
||||
bats_generate_warning 1 "$BATS_RUN_COMMAND"
|
||||
fi
|
||||
# don't leak our trap into surrounding code
|
||||
trap bats_interrupt_trap INT
|
||||
}
|
||||
|
||||
setup() {
|
||||
return 0
|
||||
}
|
||||
|
||||
teardown() {
|
||||
return 0
|
||||
}
|
||||
|
||||
skip() {
|
||||
# if this is a skip in teardown ...
|
||||
if [[ -n "${BATS_TEARDOWN_STARTED-}" ]]; then
|
||||
# ... we want to skip the rest of teardown.
|
||||
# communicate to bats_exit_trap that the teardown was completed without error
|
||||
# shellcheck disable=SC2034
|
||||
BATS_TEARDOWN_COMPLETED=1
|
||||
# if we are already in the exit trap (e.g. due to previous skip) ...
|
||||
if [[ "$BATS_TEARDOWN_STARTED" == as-exit-trap ]]; then
|
||||
# ... we need to do the rest of the tear_down_trap that would otherwise be skipped after the next call to exit
|
||||
bats_exit_trap
|
||||
# and then do the exit (at the end of this function)
|
||||
fi
|
||||
# if we aren't in exit trap, the normal exit handling should suffice
|
||||
else
|
||||
# ... this is either skip in test or skip in setup.
|
||||
# Following variables are used in bats-exec-test which sources this file
|
||||
# shellcheck disable=SC2034
|
||||
BATS_TEST_SKIPPED="${1:-1}"
|
||||
# shellcheck disable=SC2034
|
||||
BATS_TEST_COMPLETED=1
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
bats_test_begin() {
|
||||
BATS_TEST_DESCRIPTION="$1"
|
||||
if [[ -n "$BATS_EXTENDED_SYNTAX" ]]; then
|
||||
printf 'begin %d %s\n' "$BATS_SUITE_TEST_NUMBER" "${BATS_TEST_NAME_PREFIX:-}$BATS_TEST_DESCRIPTION" >&3
|
||||
fi
|
||||
setup
|
||||
}
|
||||
|
||||
bats_test_function() {
|
||||
local test_name="$1"
|
||||
BATS_TEST_NAMES+=("$test_name")
|
||||
}
|
||||
|
||||
# decides whether a failed test should be run again
|
||||
bats_should_retry_test() {
|
||||
# test try number starts at 1
|
||||
# 0 retries means run only first try
|
||||
(( BATS_TEST_TRY_NUMBER <= BATS_TEST_RETRIES ))
|
||||
}
|
386
extras/portable/test/bats/lib/bats-core/tracing.bash
Normal file
386
extras/portable/test/bats/lib/bats-core/tracing.bash
Normal file
@ -0,0 +1,386 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=lib/bats-core/common.bash
|
||||
source "$BATS_ROOT/lib/bats-core/common.bash"
|
||||
|
||||
bats_capture_stack_trace() {
|
||||
local test_file
|
||||
local funcname
|
||||
local i
|
||||
|
||||
BATS_DEBUG_LAST_STACK_TRACE=()
|
||||
|
||||
for ((i = 2; i != ${#FUNCNAME[@]}; ++i)); do
|
||||
# Use BATS_TEST_SOURCE if necessary to work around Bash < 4.4 bug whereby
|
||||
# calling an exported function erases the test file's BASH_SOURCE entry.
|
||||
test_file="${BASH_SOURCE[$i]:-$BATS_TEST_SOURCE}"
|
||||
funcname="${FUNCNAME[$i]}"
|
||||
BATS_DEBUG_LAST_STACK_TRACE+=("${BASH_LINENO[$((i-1))]} $funcname $test_file")
|
||||
case "$funcname" in
|
||||
"$BATS_TEST_NAME" | setup | teardown | setup_file | teardown_file | setup_suite | teardown_suite)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
if [[ "${BASH_SOURCE[$i + 1]:-}" == *"bats-exec-file" ]] && [[ "$funcname" == 'source' ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
bats_get_failure_stack_trace() {
|
||||
local stack_trace_var
|
||||
# See bats_debug_trap for details.
|
||||
if [[ -n "${BATS_DEBUG_LAST_STACK_TRACE_IS_VALID:-}" ]]; then
|
||||
stack_trace_var=BATS_DEBUG_LAST_STACK_TRACE
|
||||
else
|
||||
stack_trace_var=BATS_DEBUG_LASTLAST_STACK_TRACE
|
||||
fi
|
||||
# shellcheck disable=SC2016
|
||||
eval "$(printf \
|
||||
'%s=(${%s[@]+"${%s[@]}"})' \
|
||||
"${1}" \
|
||||
"${stack_trace_var}" \
|
||||
"${stack_trace_var}")"
|
||||
}
|
||||
|
||||
bats_print_stack_trace() {
|
||||
local frame
|
||||
local index=1
|
||||
local count="${#@}"
|
||||
local filename
|
||||
local lineno
|
||||
|
||||
for frame in "$@"; do
|
||||
bats_frame_filename "$frame" 'filename'
|
||||
bats_trim_filename "$filename" 'filename'
|
||||
bats_frame_lineno "$frame" 'lineno'
|
||||
|
||||
printf '%s' "${BATS_STACK_TRACE_PREFIX-# }"
|
||||
if [[ $index -eq 1 ]]; then
|
||||
printf '('
|
||||
else
|
||||
printf ' '
|
||||
fi
|
||||
|
||||
local fn
|
||||
bats_frame_function "$frame" 'fn'
|
||||
if [[ "$fn" != "$BATS_TEST_NAME" ]] &&
|
||||
# don't print "from function `source'"",
|
||||
# when failing in free code during `source $test_file` from bats-exec-file
|
||||
! [[ "$fn" == 'source' && $index -eq $count ]]; then
|
||||
local quoted_fn
|
||||
bats_quote_code quoted_fn "$fn"
|
||||
printf "from function %s " "$quoted_fn"
|
||||
fi
|
||||
|
||||
if [[ $index -eq $count ]]; then
|
||||
printf 'in test file %s, line %d)\n' "$filename" "$lineno"
|
||||
else
|
||||
printf 'in file %s, line %d,\n' "$filename" "$lineno"
|
||||
fi
|
||||
|
||||
((++index))
|
||||
done
|
||||
}
|
||||
|
||||
bats_print_failed_command() {
|
||||
local stack_trace=("${@}")
|
||||
if [[ ${#stack_trace[@]} -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
local frame="${stack_trace[${#stack_trace[@]} - 1]}"
|
||||
local filename
|
||||
local lineno
|
||||
local failed_line
|
||||
local failed_command
|
||||
|
||||
bats_frame_filename "$frame" 'filename'
|
||||
bats_frame_lineno "$frame" 'lineno'
|
||||
bats_extract_line "$filename" "$lineno" 'failed_line'
|
||||
bats_strip_string "$failed_line" 'failed_command'
|
||||
local quoted_failed_command
|
||||
bats_quote_code quoted_failed_command "$failed_command"
|
||||
printf '# %s ' "${quoted_failed_command}"
|
||||
|
||||
if [[ "$BATS_ERROR_STATUS" -eq 1 ]]; then
|
||||
printf 'failed%s\n' "$BATS_ERROR_SUFFIX"
|
||||
else
|
||||
printf 'failed with status %d%s\n' "$BATS_ERROR_STATUS" "$BATS_ERROR_SUFFIX"
|
||||
fi
|
||||
}
|
||||
|
||||
bats_frame_lineno() {
|
||||
printf -v "$2" '%s' "${1%% *}"
|
||||
}
|
||||
|
||||
bats_frame_function() {
|
||||
local __bff_function="${1#* }"
|
||||
printf -v "$2" '%s' "${__bff_function%% *}"
|
||||
}
|
||||
|
||||
bats_frame_filename() {
|
||||
local __bff_filename="${1#* }"
|
||||
__bff_filename="${__bff_filename#* }"
|
||||
|
||||
if [[ "$__bff_filename" == "$BATS_TEST_SOURCE" ]]; then
|
||||
__bff_filename="$BATS_TEST_FILENAME"
|
||||
fi
|
||||
printf -v "$2" '%s' "$__bff_filename"
|
||||
}
|
||||
|
||||
bats_extract_line() {
|
||||
local __bats_extract_line_line
|
||||
local __bats_extract_line_index=0
|
||||
|
||||
while IFS= read -r __bats_extract_line_line; do
|
||||
if [[ "$((++__bats_extract_line_index))" -eq "$2" ]]; then
|
||||
printf -v "$3" '%s' "${__bats_extract_line_line%$'\r'}"
|
||||
break
|
||||
fi
|
||||
done <"$1"
|
||||
}
|
||||
|
||||
bats_strip_string() {
|
||||
[[ "$1" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]]
|
||||
printf -v "$2" '%s' "${BASH_REMATCH[1]}"
|
||||
}
|
||||
|
||||
bats_trim_filename() {
|
||||
printf -v "$2" '%s' "${1#"$BATS_CWD"/}"
|
||||
}
|
||||
|
||||
# normalize a windows path from e.g. C:/directory to /c/directory
|
||||
# The path must point to an existing/accessable directory, not a file!
|
||||
bats_normalize_windows_dir_path() { # <output-var> <path>
|
||||
local output_var="$1" path="$2"
|
||||
if [[ "$output_var" != NORMALIZED_INPUT ]]; then
|
||||
local NORMALIZED_INPUT
|
||||
fi
|
||||
if [[ $path == ?:* ]]; then
|
||||
NORMALIZED_INPUT="$(cd "$path" || exit 1; pwd)"
|
||||
else
|
||||
NORMALIZED_INPUT="$path"
|
||||
fi
|
||||
printf -v "$output_var" "%s" "$NORMALIZED_INPUT"
|
||||
}
|
||||
|
||||
bats_emit_trace() {
|
||||
if [[ $BATS_TRACE_LEVEL -gt 0 ]]; then
|
||||
local line=${BASH_LINENO[1]}
|
||||
# shellcheck disable=SC2016
|
||||
if [[ $BASH_COMMAND != '"$BATS_TEST_NAME" >> "$BATS_OUT" 2>&1 4>&1' && $BASH_COMMAND != "bats_test_begin "* ]] && # don't emit these internal calls
|
||||
[[ $BASH_COMMAND != "$BATS_LAST_BASH_COMMAND" || $line != "$BATS_LAST_BASH_LINENO" ]] &&
|
||||
# avoid printing a function twice (at call site and at definition site)
|
||||
[[ $BASH_COMMAND != "$BATS_LAST_BASH_COMMAND" || ${BASH_LINENO[2]} != "$BATS_LAST_BASH_LINENO" || ${BASH_SOURCE[3]} != "$BATS_LAST_BASH_SOURCE" ]]; then
|
||||
local file="${BASH_SOURCE[2]}" # index 2: skip over bats_emit_trace and bats_debug_trap
|
||||
if [[ $file == "${BATS_TEST_SOURCE}" ]]; then
|
||||
file="$BATS_TEST_FILENAME"
|
||||
fi
|
||||
local padding='$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
|
||||
if (( BATS_LAST_STACK_DEPTH != ${#BASH_LINENO[@]} )); then
|
||||
printf '%s [%s:%d]\n' "${padding::${#BASH_LINENO[@]}-4}" "${file##*/}" "$line" >&4
|
||||
fi
|
||||
printf '%s %s\n' "${padding::${#BASH_LINENO[@]}-4}" "$BASH_COMMAND" >&4
|
||||
BATS_LAST_BASH_COMMAND="$BASH_COMMAND"
|
||||
BATS_LAST_BASH_LINENO="$line"
|
||||
BATS_LAST_BASH_SOURCE="${BASH_SOURCE[2]}"
|
||||
BATS_LAST_STACK_DEPTH="${#BASH_LINENO[@]}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# bats_debug_trap tracks the last line of code executed within a test. This is
|
||||
# necessary because $BASH_LINENO is often incorrect inside of ERR and EXIT
|
||||
# trap handlers.
|
||||
#
|
||||
# Below are tables describing different command failure scenarios and the
|
||||
# reliability of $BASH_LINENO within different the executed DEBUG, ERR, and EXIT
|
||||
# trap handlers. Naturally, the behaviors change between versions of Bash.
|
||||
#
|
||||
# Table rows should be read left to right. For example, on bash version
|
||||
# 4.0.44(2)-release, if a test executes `false` (or any other failing external
|
||||
# command), bash will do the following in order:
|
||||
# 1. Call the DEBUG trap handler (bats_debug_trap) with $BASH_LINENO referring
|
||||
# to the source line containing the `false` command, then
|
||||
# 2. Call the DEBUG trap handler again, but with an incorrect $BASH_LINENO, then
|
||||
# 3. Call the ERR trap handler, but with a (possibly-different) incorrect
|
||||
# $BASH_LINENO, then
|
||||
# 4. Call the DEBUG trap handler again, but with $BASH_LINENO set to 1, then
|
||||
# 5. Call the EXIT trap handler, with $BASH_LINENO set to 1.
|
||||
#
|
||||
# bash version 4.4.20(1)-release
|
||||
# command | first DEBUG | second DEBUG | ERR | third DEBUG | EXIT
|
||||
# -------------+-------------+--------------+---------+-------------+--------
|
||||
# false | OK | OK | OK | BAD[1] | BAD[1]
|
||||
# [[ 1 = 2 ]] | OK | BAD[2] | BAD[2] | BAD[1] | BAD[1]
|
||||
# (( 1 = 2 )) | OK | BAD[2] | BAD[2] | BAD[1] | BAD[1]
|
||||
# ! true | OK | --- | BAD[4] | --- | BAD[1]
|
||||
# $var_dne | OK | --- | --- | BAD[1] | BAD[1]
|
||||
# source /dne | OK | --- | --- | BAD[1] | BAD[1]
|
||||
#
|
||||
# bash version 4.0.44(2)-release
|
||||
# command | first DEBUG | second DEBUG | ERR | third DEBUG | EXIT
|
||||
# -------------+-------------+--------------+---------+-------------+--------
|
||||
# false | OK | BAD[3] | BAD[3] | BAD[1] | BAD[1]
|
||||
# [[ 1 = 2 ]] | OK | --- | BAD[3] | --- | BAD[1]
|
||||
# (( 1 = 2 )) | OK | --- | BAD[3] | --- | BAD[1]
|
||||
# ! true | OK | --- | BAD[3] | --- | BAD[1]
|
||||
# $var_dne | OK | --- | --- | BAD[1] | BAD[1]
|
||||
# source /dne | OK | --- | --- | BAD[1] | BAD[1]
|
||||
#
|
||||
# [1] The reported line number is always 1.
|
||||
# [2] The reported source location is that of the beginning of the function
|
||||
# calling the command.
|
||||
# [3] The reported line is that of the last command executed in the DEBUG trap
|
||||
# handler.
|
||||
# [4] The reported source location is that of the call to the function calling
|
||||
# the command.
|
||||
bats_debug_trap() {
|
||||
# on windows we sometimes get a mix of paths (when install via nmp install -g)
|
||||
# which have C:/... or /c/... comparing them is going to be problematic.
|
||||
# We need to normalize them to a common format!
|
||||
local NORMALIZED_INPUT
|
||||
bats_normalize_windows_dir_path NORMALIZED_INPUT "${1%/*}"
|
||||
local file_excluded='' path
|
||||
for path in "${BATS_DEBUG_EXCLUDE_PATHS[@]}"; do
|
||||
if [[ "$NORMALIZED_INPUT" == "$path"* ]]; then
|
||||
file_excluded=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# don't update the trace within library functions or we get backtraces from inside traps
|
||||
# also don't record new stack traces while handling interruptions, to avoid overriding the interrupted command
|
||||
if [[ -z "$file_excluded" && "${BATS_INTERRUPTED-NOTSET}" == NOTSET ]]; then
|
||||
BATS_DEBUG_LASTLAST_STACK_TRACE=(
|
||||
${BATS_DEBUG_LAST_STACK_TRACE[@]+"${BATS_DEBUG_LAST_STACK_TRACE[@]}"}
|
||||
)
|
||||
|
||||
BATS_DEBUG_LAST_LINENO=(${BASH_LINENO[@]+"${BASH_LINENO[@]}"})
|
||||
BATS_DEBUG_LAST_SOURCE=(${BASH_SOURCE[@]+"${BASH_SOURCE[@]}"})
|
||||
bats_capture_stack_trace
|
||||
bats_emit_trace
|
||||
fi
|
||||
}
|
||||
|
||||
# For some versions of Bash, the `ERR` trap may not always fire for every
|
||||
# command failure, but the `EXIT` trap will. Also, some command failures may not
|
||||
# set `$?` properly. See #72 and #81 for details.
|
||||
#
|
||||
# For this reason, we call `bats_check_status_from_trap` at the very beginning
|
||||
# of `bats_teardown_trap` and check the value of `$BATS_TEST_COMPLETED` before
|
||||
# taking other actions. We also adjust the exit status value if needed.
|
||||
#
|
||||
# See `bats_exit_trap` for an additional EXIT error handling case when `$?`
|
||||
# isn't set properly during `teardown()` errors.
|
||||
bats_check_status_from_trap() {
|
||||
local status="$?"
|
||||
if [[ -z "${BATS_TEST_COMPLETED:-}" ]]; then
|
||||
BATS_ERROR_STATUS="${BATS_ERROR_STATUS:-$status}"
|
||||
if [[ "$BATS_ERROR_STATUS" -eq 0 ]]; then
|
||||
BATS_ERROR_STATUS=1
|
||||
fi
|
||||
trap - DEBUG
|
||||
fi
|
||||
}
|
||||
|
||||
bats_add_debug_exclude_path() { # <path>
|
||||
if [[ -z "$1" ]]; then # don't exclude everything
|
||||
printf "bats_add_debug_exclude_path: Exclude path must not be empty!\n" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$OSTYPE" == cygwin || "$OSTYPE" == msys ]]; then
|
||||
local normalized_dir
|
||||
bats_normalize_windows_dir_path normalized_dir "$1"
|
||||
BATS_DEBUG_EXCLUDE_PATHS+=("$normalized_dir")
|
||||
else
|
||||
BATS_DEBUG_EXCLUDE_PATHS+=("$1")
|
||||
fi
|
||||
}
|
||||
|
||||
bats_setup_tracing() {
|
||||
# Variables for capturing accurate stack traces. See bats_debug_trap for
|
||||
# details.
|
||||
#
|
||||
# BATS_DEBUG_LAST_LINENO, BATS_DEBUG_LAST_SOURCE, and
|
||||
# BATS_DEBUG_LAST_STACK_TRACE hold data from the most recent call to
|
||||
# bats_debug_trap.
|
||||
#
|
||||
# BATS_DEBUG_LASTLAST_STACK_TRACE holds data from two bats_debug_trap calls
|
||||
# ago.
|
||||
#
|
||||
# BATS_DEBUG_LAST_STACK_TRACE_IS_VALID indicates that
|
||||
# BATS_DEBUG_LAST_STACK_TRACE contains the stack trace of the test's error. If
|
||||
# unset, BATS_DEBUG_LAST_STACK_TRACE is unreliable and
|
||||
# BATS_DEBUG_LASTLAST_STACK_TRACE should be used instead.
|
||||
BATS_DEBUG_LASTLAST_STACK_TRACE=()
|
||||
BATS_DEBUG_LAST_LINENO=()
|
||||
BATS_DEBUG_LAST_SOURCE=()
|
||||
BATS_DEBUG_LAST_STACK_TRACE=()
|
||||
BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=
|
||||
BATS_ERROR_SUFFIX=
|
||||
BATS_DEBUG_EXCLUDE_PATHS=()
|
||||
# exclude some paths by default
|
||||
bats_add_debug_exclude_path "$BATS_ROOT/lib/"
|
||||
bats_add_debug_exclude_path "$BATS_ROOT/libexec/"
|
||||
|
||||
|
||||
exec 4<&1 # used for tracing
|
||||
if [[ "${BATS_TRACE_LEVEL:-0}" -gt 0 ]]; then
|
||||
# avoid undefined variable errors
|
||||
BATS_LAST_BASH_COMMAND=
|
||||
BATS_LAST_BASH_LINENO=
|
||||
BATS_LAST_BASH_SOURCE=
|
||||
BATS_LAST_STACK_DEPTH=
|
||||
# try to exclude helper libraries if found, this is only relevant for tracing
|
||||
while read -r path; do
|
||||
bats_add_debug_exclude_path "$path"
|
||||
done < <(find "$PWD" -type d -name bats-assert -o -name bats-support)
|
||||
fi
|
||||
|
||||
local exclude_paths path
|
||||
# exclude user defined libraries
|
||||
IFS=':' read -r exclude_paths <<< "${BATS_DEBUG_EXCLUDE_PATHS:-}"
|
||||
for path in "${exclude_paths[@]}"; do
|
||||
if [[ -n "$path" ]]; then
|
||||
bats_add_debug_exclude_path "$path"
|
||||
fi
|
||||
done
|
||||
|
||||
# turn on traps after setting excludes to avoid tracing the exclude setup
|
||||
trap 'bats_debug_trap "$BASH_SOURCE"' DEBUG
|
||||
trap 'bats_error_trap' ERR
|
||||
}
|
||||
|
||||
bats_error_trap() {
|
||||
bats_check_status_from_trap
|
||||
|
||||
# If necessary, undo the most recent stack trace captured by bats_debug_trap.
|
||||
# See bats_debug_trap for details.
|
||||
if [[ "${BASH_LINENO[*]}" = "${BATS_DEBUG_LAST_LINENO[*]:-}"
|
||||
&& "${BASH_SOURCE[*]}" = "${BATS_DEBUG_LAST_SOURCE[*]:-}"
|
||||
&& -z "$BATS_DEBUG_LAST_STACK_TRACE_IS_VALID" ]]; then
|
||||
BATS_DEBUG_LAST_STACK_TRACE=(
|
||||
${BATS_DEBUG_LASTLAST_STACK_TRACE[@]+"${BATS_DEBUG_LASTLAST_STACK_TRACE[@]}"}
|
||||
)
|
||||
fi
|
||||
BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=1
|
||||
}
|
||||
|
||||
bats_interrupt_trap() {
|
||||
# mark the interruption, to handle during exit
|
||||
BATS_INTERRUPTED=true
|
||||
BATS_ERROR_STATUS=130
|
||||
# debug trap fires before interrupt trap but gets wrong linenumber (line 1)
|
||||
# -> use last stack trace
|
||||
exit $BATS_ERROR_STATUS
|
||||
}
|
||||
|
||||
# this is used inside run()
|
||||
bats_interrupt_trap_in_run() {
|
||||
# mark the interruption, to handle during exit
|
||||
BATS_INTERRUPTED=true
|
||||
BATS_ERROR_STATUS=130
|
||||
BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=true
|
||||
exit $BATS_ERROR_STATUS
|
||||
}
|
37
extras/portable/test/bats/lib/bats-core/validator.bash
Normal file
37
extras/portable/test/bats/lib/bats-core/validator.bash
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
bats_test_count_validator() {
|
||||
trap '' INT # continue forwarding
|
||||
header_pattern='[0-9]+\.\.[0-9]+'
|
||||
IFS= read -r header
|
||||
# repeat the header
|
||||
printf "%s\n" "$header"
|
||||
|
||||
# if we detect a TAP plan
|
||||
if [[ "$header" =~ $header_pattern ]]; then
|
||||
# extract the number of tests ...
|
||||
local expected_number_of_tests="${header:3}"
|
||||
# ... count the actual number of [not ] oks...
|
||||
local actual_number_of_tests=0
|
||||
while IFS= read -r line; do
|
||||
# forward line
|
||||
printf "%s\n" "$line"
|
||||
case "$line" in
|
||||
'ok '*)
|
||||
(( ++actual_number_of_tests ))
|
||||
;;
|
||||
'not ok'*)
|
||||
(( ++actual_number_of_tests ))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# ... and error if they are not the same
|
||||
if [[ "${actual_number_of_tests}" != "${expected_number_of_tests}" ]]; then
|
||||
printf '# bats warning: Executed %s instead of expected %s tests\n' "$actual_number_of_tests" "$expected_number_of_tests"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
# forward output unchanged
|
||||
cat
|
||||
fi
|
||||
}
|
35
extras/portable/test/bats/lib/bats-core/warnings.bash
Normal file
35
extras/portable/test/bats/lib/bats-core/warnings.bash
Normal file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=lib/bats-core/tracing.bash
|
||||
source "$BATS_ROOT/lib/bats-core/tracing.bash"
|
||||
|
||||
BATS_WARNING_SHORT_DESCS=(
|
||||
# to start with 1
|
||||
'PADDING'
|
||||
# see issue #578 for context
|
||||
"\`run\`'s command \`%s\` exited with code 127, indicating 'Command not found'. Use run's return code checks, e.g. \`run -127\`, to fix this message."
|
||||
"%s requires at least BATS_VERSION=%s. Use \`bats_require_minimum_version %s\` to fix this message."
|
||||
)
|
||||
|
||||
# generate a warning report for the parent call's call site
|
||||
bats_generate_warning() { # <warning number> [<printf args for warning string>...]
|
||||
local warning_number="$1" padding="00"
|
||||
shift
|
||||
if [[ $warning_number =~ [0-9]+ ]] && ((warning_number < ${#BATS_WARNING_SHORT_DESCS[@]} )); then
|
||||
{
|
||||
printf "BW%s: ${BATS_WARNING_SHORT_DESCS[$warning_number]}\n" "${padding:${#warning_number}}${warning_number}" "$@"
|
||||
bats_capture_stack_trace
|
||||
BATS_STACK_TRACE_PREFIX=' ' bats_print_stack_trace "${BATS_DEBUG_LAST_STACK_TRACE[@]}"
|
||||
} >> "$BATS_WARNING_FILE" 2>&3
|
||||
else
|
||||
printf "Invalid Bats warning number '%s'. It must be an integer between 1 and %d." "$warning_number" "$((${#BATS_WARNING_SHORT_DESCS[@]} - 1))" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# generate a warning if the BATS_GUARANTEED_MINIMUM_VERSION is not high enough
|
||||
bats_warn_minimum_guaranteed_version() { # <feature> <minimum required version>
|
||||
if bats_version_lt "$BATS_GUARANTEED_MINIMUM_VERSION" "$2"; then
|
||||
bats_generate_warning 2 "$1" "$2" "$2"
|
||||
fi
|
||||
}
|
467
extras/portable/test/bats/libexec/bats-core/bats
Executable file
467
extras/portable/test/bats/libexec/bats-core/bats
Executable file
@ -0,0 +1,467 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
export BATS_VERSION='1.7.0'
|
||||
VALID_FORMATTERS="pretty, junit, tap, tap13"
|
||||
|
||||
version() {
|
||||
printf 'Bats %s\n' "$BATS_VERSION"
|
||||
}
|
||||
|
||||
abort() {
|
||||
local print_usage=1
|
||||
if [[ ${1:-} == --no-print-usage ]]; then
|
||||
print_usage=
|
||||
shift
|
||||
fi
|
||||
printf 'Error: %s\n' "$1" >&2
|
||||
if [[ -n $print_usage ]]; then
|
||||
usage >&2
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
local cmd="${0##*/}"
|
||||
local line
|
||||
|
||||
cat <<HELP_TEXT_HEADER
|
||||
Usage: ${cmd} [OPTIONS] <tests>
|
||||
${cmd} [-h | -v]
|
||||
|
||||
HELP_TEXT_HEADER
|
||||
|
||||
cat <<'HELP_TEXT_BODY'
|
||||
<tests> is the path to a Bats test file, or the path to a directory
|
||||
containing Bats test files (ending with ".bats")
|
||||
|
||||
-c, --count Count test cases without running any tests
|
||||
--code-quote-style <style>
|
||||
A two character string of code quote delimiters
|
||||
or 'custom' which requires setting $BATS_BEGIN_CODE_QUOTE and
|
||||
$BATS_END_CODE_QUOTE. Can also be set via $BATS_CODE_QUOTE_STYLE
|
||||
-f, --filter <regex> Only run tests that match the regular expression
|
||||
--filter-status <status> Only run tests with the given status in the last completed (no CTRL+C/SIGINT) run.
|
||||
Valid <status> values are:
|
||||
failed - runs tests that failed or were not present in the last run
|
||||
missed - runs tests that were not present in the last run
|
||||
-F, --formatter <type> Switch between formatters: pretty (default),
|
||||
tap (default w/o term), tap13, junit, /<absolute path to formatter>
|
||||
--gather-test-outputs-in <directory>
|
||||
Gather the output of failing *and* passing tests
|
||||
as files in directory (if existing, must be empty)
|
||||
-h, --help Display this help message
|
||||
-j, --jobs <jobs> Number of parallel jobs (requires GNU parallel)
|
||||
--no-tempdir-cleanup Preserve test output temporary directory
|
||||
--no-parallelize-across-files
|
||||
Serialize test file execution instead of running
|
||||
them in parallel (requires --jobs >1)
|
||||
--no-parallelize-within-files
|
||||
Serialize test execution within files instead of
|
||||
running them in parallel (requires --jobs >1)
|
||||
--report-formatter <type> Switch between reporters (same options as --formatter)
|
||||
-o, --output <dir> Directory to write report files (must exist)
|
||||
-p, --pretty Shorthand for "--formatter pretty"
|
||||
--print-output-on-failure Automatically print the value of `$output` on failed tests
|
||||
-r, --recursive Include tests in subdirectories
|
||||
--show-output-of-passing-tests
|
||||
Print output of passing tests
|
||||
-t, --tap Shorthand for "--formatter tap"
|
||||
-T, --timing Add timing information to tests
|
||||
-x, --trace Print test commands as they are executed (like `set -x`)
|
||||
--verbose-run Make `run` print `$output` by default
|
||||
-v, --version Display the version number
|
||||
|
||||
For more information, see https://github.com/bats-core/bats-core
|
||||
HELP_TEXT_BODY
|
||||
}
|
||||
|
||||
expand_path() {
|
||||
local path="${1%/}"
|
||||
local dirname="${path%/*}"
|
||||
local result="$2"
|
||||
|
||||
if [[ "$dirname" == "$path" ]]; then
|
||||
dirname="$PWD"
|
||||
else
|
||||
cd "$dirname"
|
||||
dirname="$PWD"
|
||||
cd "$OLDPWD"
|
||||
fi
|
||||
printf -v "$result" '%s/%s' "$dirname" "${path##*/}"
|
||||
}
|
||||
|
||||
BATS_LIBEXEC="$(cd "$(dirname "$(bats_readlinkf "${BASH_SOURCE[0]}")")"; pwd)"
|
||||
export BATS_LIBEXEC
|
||||
export BATS_CWD="$PWD"
|
||||
export BATS_TEST_FILTER=
|
||||
export PATH="$BATS_LIBEXEC:$PATH"
|
||||
export BATS_ROOT_PID=$$
|
||||
export BATS_TMPDIR="${TMPDIR:-/tmp}"
|
||||
BATS_TMPDIR=${BATS_TMPDIR%/} # chop off trailing / to avoid duplication
|
||||
export BATS_RUN_TMPDIR=
|
||||
export BATS_GUARANTEED_MINIMUM_VERSION=0.0.0
|
||||
|
||||
if [[ ! -d "${BATS_TMPDIR}" ]];then
|
||||
printf "Error: BATS_TMPDIR (%s) does not exist or is not a directory" "${BATS_TMPDIR}" >&2
|
||||
exit 1
|
||||
elif [[ ! -w "${BATS_TMPDIR}" ]];then
|
||||
printf "Error: BATS_TMPDIR (%s) is not writable" "${BATS_TMPDIR}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
arguments=()
|
||||
|
||||
# Unpack single-character options bundled together, e.g. -cr, -pr.
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" =~ ^-[^-]. ]]; then
|
||||
index=1
|
||||
while option="${arg:$((index++)):1}"; do
|
||||
if [[ -z "$option" ]]; then
|
||||
break
|
||||
fi
|
||||
arguments+=("-$option")
|
||||
done
|
||||
else
|
||||
arguments+=("$arg")
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
set -- "${arguments[@]}"
|
||||
arguments=()
|
||||
|
||||
unset flags recursive formatter_flags
|
||||
flags=('--dummy-flag') # add a dummy flag to prevent unset variable errors on empty array expansion in old bash versions
|
||||
formatter_flags=('--dummy-flag') # add a dummy flag to prevent unset variable errors on empty array expansion in old bash versions
|
||||
formatter='tap'
|
||||
report_formatter=''
|
||||
recursive=
|
||||
setup_suite_file=''
|
||||
export BATS_TEMPDIR_CLEANUP=1
|
||||
output=
|
||||
if [[ -z "${CI:-}" && -t 0 && -t 1 ]] && command -v tput >/dev/null; then
|
||||
formatter='pretty'
|
||||
fi
|
||||
|
||||
while [[ "$#" -ne 0 ]]; do
|
||||
case "$1" in
|
||||
-h | --help)
|
||||
version
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-v | --version)
|
||||
version
|
||||
exit 0
|
||||
;;
|
||||
-c | --count)
|
||||
flags+=('-c')
|
||||
;;
|
||||
-f | --filter)
|
||||
shift
|
||||
flags+=('-f' "$1")
|
||||
;;
|
||||
-F | --formatter)
|
||||
shift
|
||||
# allow cat formatter to see extended output but don't advertise to users
|
||||
if [[ $1 =~ ^(pretty|junit|tap|tap13|cat|/.*)$ ]]; then
|
||||
formatter="$1"
|
||||
else
|
||||
printf "Unknown formatter '%s', valid options are %s\n" "$1" "${VALID_FORMATTERS}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
--report-formatter)
|
||||
shift
|
||||
if [[ $1 =~ ^(pretty|junit|tap|tap13)$ ]]; then
|
||||
report_formatter="$1"
|
||||
else
|
||||
printf "Unknown report formatter '%s', valid options are %s\n" "$1" "${VALID_FORMATTERS}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-o | --output)
|
||||
shift
|
||||
output="$1"
|
||||
;;
|
||||
-p | --pretty)
|
||||
formatter='pretty'
|
||||
;;
|
||||
-j | --jobs)
|
||||
shift
|
||||
flags+=('-j' "$1")
|
||||
;;
|
||||
-r | --recursive)
|
||||
recursive=1
|
||||
;;
|
||||
-t | --tap)
|
||||
formatter='tap'
|
||||
;;
|
||||
-T | --timing)
|
||||
flags+=('-T')
|
||||
formatter_flags+=('-T')
|
||||
;;
|
||||
# this flag is now a no-op, as it is the parallel default
|
||||
--parallel-preserve-environment)
|
||||
;;
|
||||
--no-parallelize-across-files)
|
||||
flags+=("--no-parallelize-across-files")
|
||||
;;
|
||||
--no-parallelize-within-files)
|
||||
flags+=("--no-parallelize-within-files")
|
||||
;;
|
||||
--no-tempdir-cleanup)
|
||||
BATS_TEMPDIR_CLEANUP=''
|
||||
;;
|
||||
--tempdir) # for internal test consumption only!
|
||||
BATS_RUN_TMPDIR="$2"
|
||||
shift
|
||||
;;
|
||||
-x | --trace)
|
||||
flags+=(--trace)
|
||||
;;
|
||||
--print-output-on-failure)
|
||||
flags+=(--print-output-on-failure)
|
||||
;;
|
||||
--show-output-of-passing-tests)
|
||||
flags+=(--show-output-of-passing-tests)
|
||||
;;
|
||||
--verbose-run)
|
||||
flags+=(--verbose-run)
|
||||
;;
|
||||
--gather-test-outputs-in)
|
||||
shift
|
||||
output_dir="$1"
|
||||
if [ -d "$output_dir" ]; then
|
||||
if ! find "$output_dir" -mindepth 1 -exec false {} + 2>/dev/null; then
|
||||
abort --no-print-usage "Directory '$output_dir' must be empty for --gather-test-outputs-in"
|
||||
fi
|
||||
elif ! mkdir "$output_dir" 2>/dev/null; then
|
||||
abort --no-print-usage "Could not create '$output_dir' for --gather-test-outputs-in"
|
||||
fi
|
||||
flags+=(--gather-test-outputs-in "$output_dir")
|
||||
;;
|
||||
--setup-suite-file)
|
||||
shift
|
||||
setup_suite_file="$1"
|
||||
;;
|
||||
--code-quote-style)
|
||||
shift
|
||||
BATS_CODE_QUOTE_STYLE="$1"
|
||||
;;
|
||||
--filter-status)
|
||||
shift
|
||||
flags+=('--filter-status' "$1")
|
||||
;;
|
||||
-*)
|
||||
abort "Bad command line option '$1'"
|
||||
;;
|
||||
*)
|
||||
arguments+=("$1")
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ -n "${BATS_RUN_TMPDIR:-}" ]];then
|
||||
if [[ -d "$BATS_RUN_TMPDIR" ]]; then
|
||||
printf "Error: BATS_RUN_TMPDIR (%s) already exists\n" "$BATS_RUN_TMPDIR" >&2
|
||||
printf "Reusing old run directories can lead to unexpected results ... aborting!\n" >&2
|
||||
exit 1
|
||||
elif ! mkdir -p "$BATS_RUN_TMPDIR" ;then
|
||||
printf "Error: Failed to create BATS_RUN_TMPDIR (%s)\n" "$BATS_RUN_TMPDIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
elif ! BATS_RUN_TMPDIR=$(mktemp -d "${BATS_TMPDIR}/bats-run-XXXXXX");then
|
||||
printf "Error: Failed to create BATS_RUN_TMPDIR (%s) with mktemp\n" "${BATS_TMPDIR}/bats-run-XXXXXX" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export BATS_WARNING_FILE="${BATS_RUN_TMPDIR}/warnings.log"
|
||||
|
||||
bats_exit_trap() {
|
||||
if [[ -s "$BATS_WARNING_FILE" ]]; then
|
||||
local pre_cat='' post_cat=''
|
||||
if [[ $formatter == pretty ]]; then
|
||||
pre_cat=$'\x1B[31m'
|
||||
post_cat=$'\x1B[0m'
|
||||
fi
|
||||
printf "\nThe following warnings were encountered during tests:\n%s" "$pre_cat"
|
||||
cat "$BATS_WARNING_FILE"
|
||||
printf "%s" "$post_cat"
|
||||
fi >&2
|
||||
|
||||
if [[ -n "$BATS_TEMPDIR_CLEANUP" ]]; then
|
||||
rm -rf "$BATS_RUN_TMPDIR"
|
||||
else
|
||||
printf "BATS_RUN_TMPDIR: %s\n" "$BATS_RUN_TMPDIR" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
trap bats_exit_trap EXIT
|
||||
|
||||
if [[ "$formatter" != "tap" ]]; then
|
||||
flags+=('-x')
|
||||
fi
|
||||
|
||||
if [[ -n "$report_formatter" && "$report_formatter" != "tap" ]]; then
|
||||
flags+=('-x')
|
||||
fi
|
||||
|
||||
if [[ "$formatter" == "junit" ]]; then
|
||||
flags+=('-T')
|
||||
formatter_flags+=('--base-path' "${arguments[0]}")
|
||||
fi
|
||||
if [[ "$report_formatter" == "junit" ]]; then
|
||||
flags+=('-T')
|
||||
report_formatter_flags+=('--base-path' "${arguments[0]}")
|
||||
fi
|
||||
|
||||
if [[ "$formatter" == "pretty" ]]; then
|
||||
formatter_flags+=('--base-path' "${arguments[0]}")
|
||||
fi
|
||||
|
||||
# if we don't need to filter extended syntax, use the faster formatter
|
||||
if [[ "$formatter" == tap && -z "$report_formatter" ]]; then
|
||||
formatter="cat"
|
||||
fi
|
||||
|
||||
bats_check_formatter() { # <formatter-path>
|
||||
local -r formatter="$1"
|
||||
if [[ ! -f "$formatter" ]]; then
|
||||
printf "ERROR: Formatter '%s' is not readable!\n" "$formatter"
|
||||
exit 1
|
||||
elif [[ ! -x "$formatter" ]]; then
|
||||
printf "ERROR: Formatter '%s' is not executable!\n" "$formatter"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ $formatter == /* ]]; then # absolute paths are direct references to formatters
|
||||
bats_check_formatter "$formatter"
|
||||
interpolated_formatter="$formatter"
|
||||
else
|
||||
interpolated_formatter="bats-format-${formatter}"
|
||||
fi
|
||||
|
||||
if [[ "${#arguments[@]}" -eq 0 ]]; then
|
||||
abort 'Must specify at least one <test>'
|
||||
fi
|
||||
|
||||
if [[ -n "$report_formatter" ]]; then
|
||||
# default to the current directory for output
|
||||
if [[ -z "$output" ]]; then
|
||||
output=.
|
||||
fi
|
||||
# only set BATS_REPORT_FILENAME if none was given
|
||||
if [[ -z "${BATS_REPORT_FILENAME:-}" ]]; then
|
||||
case "$report_formatter" in
|
||||
tap|tap13)
|
||||
BATS_REPORT_FILE_NAME="report.tap"
|
||||
;;
|
||||
junit)
|
||||
BATS_REPORT_FILE_NAME="report.xml"
|
||||
;;
|
||||
*)
|
||||
BATS_REPORT_FILE_NAME="report.log"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $report_formatter == /* ]]; then # absolute paths are direct references to formatters
|
||||
bats_check_formatter "$report_formatter"
|
||||
interpolated_report_formatter="${report_formatter}"
|
||||
else
|
||||
interpolated_report_formatter="bats-format-${report_formatter}"
|
||||
fi
|
||||
|
||||
if [[ "${BATS_CODE_QUOTE_STYLE-BATS_CODE_QUOTE_STYLE_UNSET}" == BATS_CODE_QUOTE_STYLE_UNSET ]]; then
|
||||
BATS_CODE_QUOTE_STYLE="\`'"
|
||||
fi
|
||||
|
||||
case "${BATS_CODE_QUOTE_STYLE}" in
|
||||
??)
|
||||
BATS_BEGIN_CODE_QUOTE="${BATS_CODE_QUOTE_STYLE::1}"
|
||||
BATS_END_CODE_QUOTE="${BATS_CODE_QUOTE_STYLE:1:1}"
|
||||
export BATS_BEGIN_CODE_QUOTE BATS_END_CODE_QUOTE
|
||||
;;
|
||||
custom)
|
||||
if [[ ${BATS_BEGIN_CODE_QUOTE-BATS_BEGIN_CODE_QUOTE_UNSET} == BATS_BEGIN_CODE_QUOTE_UNSET
|
||||
|| ${BATS_END_CODE_QUOTE-BATS_BEGIN_CODE_QUOTE_UNSET} == BATS_BEGIN_CODE_QUOTE_UNSET ]]; then
|
||||
printf "ERROR: BATS_CODE_QUOTE_STYLE=custom requires BATS_BEGIN_CODE_QUOTE and BATS_END_CODE_QUOTE to be set\n" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
printf "ERROR: Unknown BATS_CODE_QUOTE_STYLE: %s\n" "$BATS_CODE_QUOTE_STYLE" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -n "$output" ]]; then
|
||||
if [[ ! -w "${output}" ]]; then
|
||||
abort "Output path ${output} is not writeable"
|
||||
fi
|
||||
export BATS_REPORT_OUTPUT_PATH="$output"
|
||||
fi
|
||||
|
||||
if [[ -n "$setup_suite_file" && ! -f "$setup_suite_file" ]]; then
|
||||
abort "--setup-suite-file $setup_suite_file does not exist!"
|
||||
fi
|
||||
|
||||
filenames=()
|
||||
for filename in "${arguments[@]}"; do
|
||||
expand_path "$filename" 'filename'
|
||||
|
||||
if [[ -z "$setup_suite_file" ]]; then
|
||||
if [[ -d "$filename" ]]; then
|
||||
dirname="$filename"
|
||||
else
|
||||
dirname="${filename%/*}"
|
||||
fi
|
||||
potential_setup_suite_file="$dirname/setup_suite.bash"
|
||||
if [[ -e "$potential_setup_suite_file" ]]; then
|
||||
setup_suite_file="$potential_setup_suite_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -d "$filename" ]]; then
|
||||
shopt -s nullglob
|
||||
if [[ "$recursive" -eq 1 ]]; then
|
||||
while IFS= read -r -d $'\0' file; do
|
||||
filenames+=("$file")
|
||||
done < <(find -L "$filename" -type f -name "*.${BATS_FILE_EXTENSION:-bats}" -print0 | sort -z)
|
||||
else
|
||||
for suite_filename in "$filename"/*."${BATS_FILE_EXTENSION:-bats}"; do
|
||||
filenames+=("$suite_filename")
|
||||
done
|
||||
fi
|
||||
shopt -u nullglob
|
||||
else
|
||||
filenames+=("$filename")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -n "$setup_suite_file" ]]; then
|
||||
flags+=("--setup-suite-file" "$setup_suite_file")
|
||||
fi
|
||||
|
||||
# shellcheck source=lib/bats-core/validator.bash
|
||||
source "$BATS_ROOT/lib/bats-core/validator.bash"
|
||||
|
||||
trap 'BATS_INTERRUPTED=true' INT # let the lower levels handle the interruption
|
||||
|
||||
set -o pipefail execfail
|
||||
|
||||
if [[ -n "$report_formatter" ]]; then
|
||||
exec bats-exec-suite "${flags[@]}" "${filenames[@]}" | \
|
||||
tee >("$interpolated_report_formatter" "${report_formatter_flags[@]}" >"${BATS_REPORT_OUTPUT_PATH}/${BATS_REPORT_FILE_NAME}") | \
|
||||
bats_test_count_validator | \
|
||||
"$interpolated_formatter" "${formatter_flags[@]}"
|
||||
else
|
||||
exec bats-exec-suite "${flags[@]}" "${filenames[@]}" | \
|
||||
bats_test_count_validator | \
|
||||
"$interpolated_formatter" "${formatter_flags[@]}"
|
||||
fi
|
338
extras/portable/test/bats/libexec/bats-core/bats-exec-file
Executable file
338
extras/portable/test/bats/libexec/bats-core/bats-exec-file
Executable file
@ -0,0 +1,338 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eET
|
||||
|
||||
flags=('--dummy-flag')
|
||||
num_jobs=${BATS_NUMBER_OF_PARALLEL_JOBS:-1}
|
||||
extended_syntax=''
|
||||
BATS_TRACE_LEVEL="${BATS_TRACE_LEVEL:-0}"
|
||||
declare -r BATS_RETRY_RETURN_CODE=126
|
||||
export BATS_TEST_RETRIES=0 # no retries by default
|
||||
|
||||
while [[ "$#" -ne 0 ]]; do
|
||||
case "$1" in
|
||||
-j)
|
||||
shift
|
||||
num_jobs="$1"
|
||||
;;
|
||||
-T)
|
||||
flags+=('-T')
|
||||
;;
|
||||
-x)
|
||||
flags+=('-x')
|
||||
extended_syntax=1
|
||||
;;
|
||||
--no-parallelize-within-files)
|
||||
# use singular to allow for users to override in file
|
||||
BATS_NO_PARALLELIZE_WITHIN_FILE=1
|
||||
;;
|
||||
--dummy-flag)
|
||||
;;
|
||||
--trace)
|
||||
flags+=('--trace')
|
||||
;;
|
||||
--print-output-on-failure)
|
||||
flags+=(--print-output-on-failure)
|
||||
;;
|
||||
--show-output-of-passing-tests)
|
||||
flags+=(--show-output-of-passing-tests)
|
||||
;;
|
||||
--verbose-run)
|
||||
flags+=(--verbose-run)
|
||||
;;
|
||||
--gather-test-outputs-in)
|
||||
shift
|
||||
flags+=(--gather-test-outputs-in "$1")
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
filename="$1"
|
||||
TESTS_FILE="$2"
|
||||
|
||||
if [[ ! -f "$filename" ]]; then
|
||||
printf 'Testfile "%s" not found\n' "$filename" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export BATS_TEST_FILENAME="$filename"
|
||||
|
||||
# shellcheck source=lib/bats-core/preprocessing.bash
|
||||
# shellcheck disable=SC2153
|
||||
source "$BATS_ROOT/lib/bats-core/preprocessing.bash"
|
||||
|
||||
bats_run_setup_file() {
|
||||
# shellcheck source=lib/bats-core/tracing.bash
|
||||
# shellcheck disable=SC2153
|
||||
source "$BATS_ROOT/lib/bats-core/tracing.bash"
|
||||
# shellcheck source=lib/bats-core/test_functions.bash
|
||||
# shellcheck disable=SC2153
|
||||
source "$BATS_ROOT/lib/bats-core/test_functions.bash"
|
||||
|
||||
exec 3<&1
|
||||
|
||||
# these are defined only to avoid errors when referencing undefined variables down the line
|
||||
# shellcheck disable=2034
|
||||
BATS_TEST_NAME= # used in tracing.bash
|
||||
# shellcheck disable=2034
|
||||
BATS_TEST_COMPLETED= # used in tracing.bash
|
||||
|
||||
BATS_SOURCE_FILE_COMPLETED=
|
||||
BATS_SETUP_FILE_COMPLETED=
|
||||
BATS_TEARDOWN_FILE_COMPLETED=
|
||||
# shellcheck disable=2034
|
||||
BATS_ERROR_STATUS= # used in tracing.bash
|
||||
touch "$BATS_OUT"
|
||||
bats_setup_tracing
|
||||
trap 'bats_file_teardown_trap' EXIT
|
||||
|
||||
local status=0
|
||||
# get the setup_file/teardown_file functions for this file (if it has them)
|
||||
# shellcheck disable=SC1090
|
||||
source "$BATS_TEST_SOURCE" >>"$BATS_OUT" 2>&1
|
||||
|
||||
BATS_SOURCE_FILE_COMPLETED=1
|
||||
|
||||
setup_file >>"$BATS_OUT" 2>&1
|
||||
|
||||
BATS_SETUP_FILE_COMPLETED=1
|
||||
}
|
||||
|
||||
bats_run_teardown_file() {
|
||||
# avoid running the therdown trap due to errors in teardown_file
|
||||
trap 'bats_file_exit_trap' EXIT
|
||||
# rely on bats_error_trap to catch failures
|
||||
teardown_file >>"$BATS_OUT" 2>&1
|
||||
|
||||
BATS_TEARDOWN_FILE_COMPLETED=1
|
||||
}
|
||||
|
||||
bats_file_teardown_trap() {
|
||||
bats_run_teardown_file
|
||||
bats_file_exit_trap
|
||||
}
|
||||
|
||||
# shellcheck source=lib/bats-core/common.bash
|
||||
source "$BATS_ROOT/lib/bats-core/common.bash"
|
||||
|
||||
bats_file_exit_trap() {
|
||||
trap - ERR EXIT
|
||||
local failure_reason
|
||||
local -i failure_test_index=$(( BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE + 1 ))
|
||||
if [[ -z "$BATS_SETUP_FILE_COMPLETED" || -z "$BATS_TEARDOWN_FILE_COMPLETED" ]]; then
|
||||
if [[ -z "$BATS_SETUP_FILE_COMPLETED" ]]; then
|
||||
failure_reason='setup_file'
|
||||
elif [[ -z "$BATS_TEARDOWN_FILE_COMPLETED" ]]; then
|
||||
failure_reason='teardown_file'
|
||||
failure_test_index=$(( BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE + ${#tests_to_run[@]} + 1 ))
|
||||
elif [[ -z "$BATS_SOURCE_FILE_COMPLETED" ]]; then
|
||||
failure_reason='source'
|
||||
else
|
||||
failure_reason='unknown internal'
|
||||
fi
|
||||
printf "not ok %d %s\n" "$failure_test_index" "$failure_reason failed" >&3
|
||||
local stack_trace
|
||||
bats_get_failure_stack_trace stack_trace
|
||||
bats_print_stack_trace "${stack_trace[@]}" >&3
|
||||
bats_print_failed_command "${stack_trace[@]}" >&3
|
||||
bats_prefix_lines_for_tap_output < "$BATS_OUT" | bats_replace_filename >&3
|
||||
rm -rf "$BATS_OUT"
|
||||
bats_exec_file_status=1
|
||||
fi
|
||||
exit $bats_exec_file_status
|
||||
}
|
||||
|
||||
function setup_file() {
|
||||
return 0
|
||||
}
|
||||
|
||||
function teardown_file() {
|
||||
return 0
|
||||
}
|
||||
|
||||
bats_forward_output_of_parallel_test() {
|
||||
local test_number_in_suite=$1
|
||||
local status=0
|
||||
wait "$(cat "$output_folder/$test_number_in_suite/pid")" || status=1
|
||||
cat "$output_folder/$test_number_in_suite/stdout"
|
||||
cat "$output_folder/$test_number_in_suite/stderr" >&2
|
||||
return $status
|
||||
}
|
||||
|
||||
bats_is_next_parallel_test_finished() {
|
||||
local PID
|
||||
# get the pid of the next potentially finished test
|
||||
PID=$(cat "$output_folder/$(( test_number_in_suite_of_last_finished_test + 1 ))/pid")
|
||||
# try to send a signal to this process
|
||||
# if it fails, the process exited,
|
||||
# if it succeeds, the process is still running
|
||||
if kill -0 "$PID" 2>/dev/null; then
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# prints output from all tests in the order they were started
|
||||
# $1 == "blocking": wait for a test to finish before printing
|
||||
# != "blocking": abort printing, when a test has not finished
|
||||
bats_forward_output_for_parallel_tests() {
|
||||
local status=0
|
||||
# was the next test already started?
|
||||
while (( test_number_in_suite_of_last_finished_test + 1 <= test_number_in_suite )); do
|
||||
# if we are okay with waiting or if the test has already been finished
|
||||
if [[ "$1" == "blocking" ]] || bats_is_next_parallel_test_finished ; then
|
||||
(( ++test_number_in_suite_of_last_finished_test ))
|
||||
bats_forward_output_of_parallel_test "$test_number_in_suite_of_last_finished_test" || status=$?
|
||||
else
|
||||
# non-blocking and the process has not finished -> abort the printing
|
||||
break
|
||||
fi
|
||||
done
|
||||
return $status
|
||||
}
|
||||
|
||||
bats_run_test_with_retries() { # <args>
|
||||
local status=0
|
||||
local should_try_again=1 try_number
|
||||
for ((try_number=1; should_try_again; ++try_number)); do
|
||||
if "$BATS_LIBEXEC/bats-exec-test" "$@" "$try_number"; then
|
||||
should_try_again=0
|
||||
else
|
||||
status=$?
|
||||
if ((status == BATS_RETRY_RETURN_CODE)); then
|
||||
should_try_again=1
|
||||
else
|
||||
should_try_again=0
|
||||
bats_exec_file_status=$status
|
||||
fi
|
||||
fi
|
||||
done
|
||||
return $status
|
||||
}
|
||||
|
||||
bats_run_tests_in_parallel() {
|
||||
local output_folder="$BATS_RUN_TMPDIR/parallel_output"
|
||||
local status=0
|
||||
mkdir -p "$output_folder"
|
||||
# shellcheck source=lib/bats-core/semaphore.bash
|
||||
source "$BATS_ROOT/lib/bats-core/semaphore.bash"
|
||||
bats_semaphore_setup
|
||||
# the test_number_in_file is not yet incremented -> one before the next test to run
|
||||
local test_number_in_suite_of_last_finished_test="$BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE" # stores which test was printed last
|
||||
local test_number_in_file=0 test_number_in_suite=$BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE
|
||||
for test_name in "${tests_to_run[@]}"; do
|
||||
# Only handle non-empty lines
|
||||
if [[ $test_name ]]; then
|
||||
((++test_number_in_suite))
|
||||
((++test_number_in_file))
|
||||
mkdir -p "$output_folder/$test_number_in_suite"
|
||||
bats_semaphore_run "$output_folder/$test_number_in_suite" \
|
||||
bats_run_test_with_retries "${flags[@]}" "$filename" "$test_name" "$test_number_in_suite" "$test_number_in_file" \
|
||||
> "$output_folder/$test_number_in_suite/pid"
|
||||
fi
|
||||
# print results early to get interactive feedback
|
||||
bats_forward_output_for_parallel_tests non-blocking || status=1 # ignore if we did not finish yet
|
||||
done
|
||||
bats_forward_output_for_parallel_tests blocking || status=1
|
||||
return $status
|
||||
}
|
||||
|
||||
bats_read_tests_list_file() {
|
||||
local line_number=0
|
||||
tests_to_run=()
|
||||
# the global test number must be visible to traps -> not local
|
||||
local test_number_in_suite=''
|
||||
while read -r test_line; do
|
||||
# check if the line begins with filename
|
||||
# filename might contain some hard to parse characters,
|
||||
# use simple string operations to work around that issue
|
||||
if [[ "$filename" == "${test_line::${#filename}}" ]]; then
|
||||
# get the rest of the line without the separator \t
|
||||
test_name=${test_line:$((1 + ${#filename} ))}
|
||||
tests_to_run+=("$test_name")
|
||||
# save the first test's number for later iteration
|
||||
# this assumes that tests for a file are stored consecutive in the file!
|
||||
if [[ -z "$test_number_in_suite" ]]; then
|
||||
test_number_in_suite=$line_number
|
||||
fi
|
||||
fi
|
||||
((++line_number))
|
||||
done <"$TESTS_FILE"
|
||||
BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE="$test_number_in_suite"
|
||||
declare -ri BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE # mark readonly (cannot merge assignment, because value would be lost)
|
||||
}
|
||||
|
||||
bats_run_tests() {
|
||||
bats_exec_file_status=0
|
||||
|
||||
if [[ "$num_jobs" != 1 && "${BATS_NO_PARALLELIZE_WITHIN_FILE-False}" == False ]]; then
|
||||
export BATS_SEMAPHORE_NUMBER_OF_SLOTS="$num_jobs"
|
||||
bats_run_tests_in_parallel "$BATS_RUN_TMPDIR/parallel_output" || bats_exec_file_status=1
|
||||
else
|
||||
local test_number_in_suite=$BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE \
|
||||
test_number_in_file=0
|
||||
for test_name in "${tests_to_run[@]}"; do
|
||||
if [[ "${BATS_INTERRUPTED-NOTSET}" != NOTSET ]]; then
|
||||
bats_exec_file_status=130 # bash's code for SIGINT exits
|
||||
break
|
||||
fi
|
||||
# Only handle non-empty lines
|
||||
if [[ $test_name ]]; then
|
||||
((++test_number_in_suite))
|
||||
((++test_number_in_file))
|
||||
bats_run_test_with_retries "${flags[@]}" "$filename" "$test_name" \
|
||||
"$test_number_in_suite" "$test_number_in_file" || bats_exec_file_status=$?
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
bats_create_file_tempdirs() {
|
||||
local bats_files_tmpdir="${BATS_RUN_TMPDIR}/file"
|
||||
if ! mkdir -p "$bats_files_tmpdir"; then
|
||||
printf 'Failed to create %s\n' "$bats_files_tmpdir" >&2
|
||||
exit 1
|
||||
fi
|
||||
BATS_FILE_TMPDIR="$bats_files_tmpdir/${BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE?}"
|
||||
if ! mkdir "$BATS_FILE_TMPDIR"; then
|
||||
printf 'Failed to create BATS_FILE_TMPDIR=%s\n' "$BATS_FILE_TMPDIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
ln -s "$BATS_TEST_FILENAME" "$BATS_FILE_TMPDIR-$(basename "$BATS_TEST_FILENAME").source_file"
|
||||
export BATS_FILE_TMPDIR
|
||||
}
|
||||
|
||||
trap 'BATS_INTERRUPTED=true' INT
|
||||
|
||||
if [[ -n "$extended_syntax" ]]; then
|
||||
printf "suite %s\n" "$filename"
|
||||
fi
|
||||
|
||||
BATS_FILE_FIRST_TEST_NUMBER_IN_SUITE=0 # predeclare as Bash 3.2 does not support declare -g
|
||||
bats_read_tests_list_file
|
||||
|
||||
# don't run potentially expensive setup/teardown_file
|
||||
# when there are no tests to run
|
||||
if [[ ${#tests_to_run[@]} -eq 0 ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# requires the test list to be read but not empty
|
||||
bats_create_file_tempdirs
|
||||
|
||||
bats_preprocess_source "$filename"
|
||||
|
||||
trap bats_interrupt_trap INT
|
||||
bats_run_setup_file
|
||||
|
||||
# during tests, we don't want to get backtraces from this level
|
||||
# just wait for the test to be interrupted and display their trace
|
||||
trap 'BATS_INTERRUPTED=true' INT
|
||||
bats_run_tests
|
||||
|
||||
trap bats_interrupt_trap INT
|
||||
bats_run_teardown_file
|
||||
|
||||
exit $bats_exec_file_status
|
359
extras/portable/test/bats/libexec/bats-core/bats-exec-suite
Executable file
359
extras/portable/test/bats/libexec/bats-core/bats-exec-suite
Executable file
@ -0,0 +1,359 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
count_only_flag=''
|
||||
filter=''
|
||||
num_jobs=${BATS_NUMBER_OF_PARALLEL_JOBS:-1}
|
||||
bats_no_parallelize_across_files=${BATS_NO_PARALLELIZE_ACROSS_FILES-}
|
||||
bats_no_parallelize_within_files=
|
||||
filter_status=''
|
||||
flags=('--dummy-flag') # add a dummy flag to prevent unset variable errors on empty array expansion in old bash versions
|
||||
setup_suite_file=''
|
||||
BATS_TRACE_LEVEL="${BATS_TRACE_LEVEL:-0}"
|
||||
|
||||
abort() {
|
||||
printf 'Error: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ "$#" -ne 0 ]]; do
|
||||
case "$1" in
|
||||
-c)
|
||||
count_only_flag=1
|
||||
;;
|
||||
-f)
|
||||
shift
|
||||
filter="$1"
|
||||
;;
|
||||
-j)
|
||||
shift
|
||||
num_jobs="$1"
|
||||
flags+=('-j' "$num_jobs")
|
||||
;;
|
||||
-T)
|
||||
flags+=('-T')
|
||||
;;
|
||||
-x)
|
||||
flags+=('-x')
|
||||
;;
|
||||
--no-parallelize-across-files)
|
||||
bats_no_parallelize_across_files=1
|
||||
;;
|
||||
--no-parallelize-within-files)
|
||||
bats_no_parallelize_within_files=1
|
||||
flags+=("--no-parallelize-within-files")
|
||||
;;
|
||||
--filter-status)
|
||||
shift
|
||||
filter_status="$1"
|
||||
;;
|
||||
--dummy-flag)
|
||||
;;
|
||||
--trace)
|
||||
flags+=('--trace')
|
||||
(( ++BATS_TRACE_LEVEL )) # avoid returning 0
|
||||
;;
|
||||
--print-output-on-failure)
|
||||
flags+=(--print-output-on-failure)
|
||||
;;
|
||||
--show-output-of-passing-tests)
|
||||
flags+=(--show-output-of-passing-tests)
|
||||
;;
|
||||
--verbose-run)
|
||||
flags+=(--verbose-run)
|
||||
;;
|
||||
--gather-test-outputs-in)
|
||||
shift
|
||||
flags+=(--gather-test-outputs-in "$1")
|
||||
;;
|
||||
--setup-suite-file)
|
||||
shift
|
||||
setup_suite_file="$1"
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ "$num_jobs" != 1 ]]; then
|
||||
if ! type -p parallel >/dev/null && [[ -z "$bats_no_parallelize_across_files" ]]; then
|
||||
abort "Cannot execute \"${num_jobs}\" jobs without GNU parallel"
|
||||
exit 1
|
||||
fi
|
||||
# shellcheck source=lib/bats-core/semaphore.bash
|
||||
source "${BATS_ROOT}/lib/bats-core/semaphore.bash"
|
||||
bats_semaphore_setup
|
||||
fi
|
||||
|
||||
# create a file that contains all (filtered) tests to run from all files
|
||||
TESTS_LIST_FILE="${BATS_RUN_TMPDIR}/test_list_file.txt"
|
||||
|
||||
bats_gather_tests() {
|
||||
all_tests=()
|
||||
for filename in "$@"; do
|
||||
if [[ ! -f "$filename" ]]; then
|
||||
abort "Test file \"${filename}\" does not exist"
|
||||
fi
|
||||
|
||||
test_names=()
|
||||
test_dupes=()
|
||||
while read -r line; do
|
||||
if [[ ! "$line" =~ ^bats_test_function\ ]]; then
|
||||
continue
|
||||
fi
|
||||
line="${line%$'\r'}"
|
||||
line="${line#* }"
|
||||
test_line=$(printf "%s\t%s" "$filename" "$line")
|
||||
all_tests+=("$test_line")
|
||||
printf "%s\n" "$test_line" >>"$TESTS_LIST_FILE"
|
||||
# avoid unbound variable errors on empty array expansion with old bash versions
|
||||
if [[ ${#test_names[@]} -gt 0 && " ${test_names[*]} " == *" $line "* ]]; then
|
||||
test_dupes+=("$line")
|
||||
continue
|
||||
fi
|
||||
test_names+=("$line")
|
||||
done < <(BATS_TEST_FILTER="$filter" bats-preprocess "$filename")
|
||||
|
||||
if [[ "${#test_dupes[@]}" -ne 0 ]]; then
|
||||
abort "Duplicate test name(s) in file \"${filename}\": ${test_dupes[*]}"
|
||||
fi
|
||||
done
|
||||
|
||||
test_count="${#all_tests[@]}"
|
||||
}
|
||||
|
||||
TEST_ROOT=${1-}
|
||||
TEST_ROOT=${TEST_ROOT%/*}
|
||||
BATS_RUN_LOGS_DIRECTORY="$TEST_ROOT/.bats/run-logs"
|
||||
if [[ ! -d "$BATS_RUN_LOGS_DIRECTORY" ]]; then
|
||||
if [[ -n "$filter_status" ]]; then
|
||||
printf "Error: --filter-status needs '%s/' to save failed tests. Please create this folder, add it to .gitignore and try again.\n" "$BATS_RUN_LOGS_DIRECTORY"
|
||||
exit 1
|
||||
else
|
||||
BATS_RUN_LOGS_DIRECTORY=
|
||||
fi
|
||||
# discard via sink instead of having a conditional later
|
||||
export BATS_RUNLOG_FILE='/dev/null'
|
||||
else
|
||||
# use UTC (-u) to avoid problems with TZ changes
|
||||
BATS_RUNLOG_DATE=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||
export BATS_RUNLOG_FILE="$BATS_RUN_LOGS_DIRECTORY/${BATS_RUNLOG_DATE}.log"
|
||||
fi
|
||||
|
||||
bats_gather_tests "$@"
|
||||
|
||||
if [[ -n "$filter_status" ]]; then
|
||||
# shellcheck source=lib/bats-core/common.bash
|
||||
source "$BATS_ROOT/lib/bats-core/common.bash"
|
||||
case "$filter_status" in
|
||||
failed)
|
||||
bats_filter_test_by_status() { # <line>
|
||||
! bats_binary_search "$1" "passed_tests"
|
||||
}
|
||||
;;
|
||||
passed)
|
||||
bats_filter_test_by_status() {
|
||||
! bats_binary_search "$1" "failed_tests"
|
||||
}
|
||||
;;
|
||||
missed)
|
||||
bats_filter_test_by_status() {
|
||||
! bats_binary_search "$1" "failed_tests" && ! bats_binary_search "$1" "passed_tests"
|
||||
}
|
||||
;;
|
||||
*)
|
||||
printf "Error: Unknown value '%s' for --filter-status. Valid values are 'failed' and 'missed'.\n" "$filter_status">&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if IFS='' read -d $'\n' -r BATS_PREVIOUS_RUNLOG_FILE < <(ls -1r "$BATS_RUN_LOGS_DIRECTORY"); then
|
||||
BATS_PREVIOUS_RUNLOG_FILE="$BATS_RUN_LOGS_DIRECTORY/$BATS_PREVIOUS_RUNLOG_FILE"
|
||||
if [[ $BATS_PREVIOUS_RUNLOG_FILE == "$BATS_RUNLOG_FILE" ]]; then
|
||||
count=$(find "$BATS_RUN_LOGS_DIRECTORY" -name "$BATS_RUNLOG_DATE*" | wc -l)
|
||||
BATS_RUNLOG_FILE="$BATS_RUN_LOGS_DIRECTORY/${BATS_RUNLOG_DATE}-$count.log"
|
||||
fi
|
||||
failed_tests=()
|
||||
passed_tests=()
|
||||
# store tests that were already filtered out in the last run for the same filter reason
|
||||
last_filtered_tests=()
|
||||
i=0
|
||||
while read -rd $'\n' line; do
|
||||
((++i))
|
||||
case "$line" in
|
||||
"passed "*)
|
||||
passed_tests+=("${line#passed }")
|
||||
;;
|
||||
"failed "*)
|
||||
failed_tests+=("${line#failed }")
|
||||
;;
|
||||
"status-filtered $filter_status"*) # pick up tests that were filtered in the last round for the same status
|
||||
last_filtered_tests+=("${line#status-filtered "$filter_status" }")
|
||||
;;
|
||||
"status-filtered "*) # ignore other status-filtered lines
|
||||
;;
|
||||
"#"*) # allow for comments
|
||||
;;
|
||||
*)
|
||||
printf "Error: %s:%d: Invalid format: %s\n" "$BATS_PREVIOUS_RUNLOG_FILE" "$i" "$line" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done < <(sort "$BATS_PREVIOUS_RUNLOG_FILE")
|
||||
|
||||
filtered_tests=()
|
||||
for line in "${all_tests[@]}"; do
|
||||
if bats_filter_test_by_status "$line" && ! bats_binary_search "$line" last_filtered_tests; then
|
||||
printf "%s\n" "$line"
|
||||
filtered_tests+=("$line")
|
||||
else
|
||||
printf "status-filtered %s %s\n" "$filter_status" "$line" >> "$BATS_RUNLOG_FILE"
|
||||
fi
|
||||
done > "$TESTS_LIST_FILE"
|
||||
|
||||
# save filtered tests to exclude them again in next round
|
||||
for test_line in "${last_filtered_tests[@]}"; do
|
||||
printf "status-filtered %s %s\n" "$filter_status" "$test_line"
|
||||
done >> "$BATS_RUNLOG_FILE"
|
||||
|
||||
test_count="${#filtered_tests[@]}"
|
||||
if [[ ${#failed_tests[@]} -eq 0 && ${#filtered_tests[@]} -eq 0 ]]; then
|
||||
printf "There where no failed tests in the last recorded run.\n" >&2
|
||||
fi
|
||||
else
|
||||
printf "No recording of previous runs found. Running all tests!\n" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$count_only_flag" ]]; then
|
||||
printf '%d\n' "${test_count}"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [[ -n "$bats_no_parallelize_across_files" ]] && [[ ! "$num_jobs" -gt 1 ]]; then
|
||||
abort "The flag --no-parallelize-across-files requires at least --jobs 2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$bats_no_parallelize_within_files" ]] && [[ ! "$num_jobs" -gt 1 ]]; then
|
||||
abort "The flag --no-parallelize-across-files requires at least --jobs 2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# only abort on the lowest levels
|
||||
trap 'BATS_INTERRUPTED=true' INT
|
||||
|
||||
bats_exec_suite_status=0
|
||||
printf '1..%d\n' "${test_count}"
|
||||
|
||||
# No point on continuing if there's no tests.
|
||||
if [[ "${test_count}" == 0 ]]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
export BATS_SUITE_TMPDIR="${BATS_RUN_TMPDIR}/suite"
|
||||
if ! mkdir "$BATS_SUITE_TMPDIR"; then
|
||||
printf '%s\n' "Failed to create BATS_SUITE_TMPDIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Deduplicate filenames (without reordering) to avoid running duplicate tests n by n times.
|
||||
# (see https://github.com/bats-core/bats-core/issues/329)
|
||||
# If a file was specified multiple times, we already got it repeatedly in our TESTS_LIST_FILE.
|
||||
# Thus, it suffices to bats-exec-file it once to run all repeated tests on it.
|
||||
IFS=$'\n' read -d '' -r -a BATS_UNIQUE_TEST_FILENAMES < <(printf "%s\n" "$@"| nl | sort -k 2 | uniq -f 1 | sort -n | cut -f 2-) || true
|
||||
|
||||
# shellcheck source=lib/bats-core/tracing.bash
|
||||
source "$BATS_ROOT/lib/bats-core/tracing.bash"
|
||||
bats_setup_tracing
|
||||
|
||||
trap bats_suite_exit_trap EXIT
|
||||
|
||||
bats_suite_exit_trap() {
|
||||
if [[ -z "${BATS_SETUP_SUITE_COMPLETED}" || -z "${BATS_TEARDOWN_SUITE_COMPLETED}" ]]; then
|
||||
if [[ -z "${BATS_SETUP_SUITE_COMPLETED}" ]]; then
|
||||
printf "not ok 1 setup_suite\n"
|
||||
elif [[ -z "${BATS_TEARDOWN_SUITE_COMPLETED}" ]]; then
|
||||
printf "not ok %d teardown_suite\n" $((test_count+1))
|
||||
fi
|
||||
local stack_trace
|
||||
bats_get_failure_stack_trace stack_trace
|
||||
bats_print_stack_trace "${stack_trace[@]}"
|
||||
bats_print_failed_command "${stack_trace[@]}"
|
||||
bats_exec_suite_status=1
|
||||
fi
|
||||
if [[ ${BATS_INTERRUPTED-NOTSET} != NOTSET ]]; then
|
||||
printf "\n# Received SIGINT, aborting ...\n\n"
|
||||
fi
|
||||
|
||||
if [[ -d "$BATS_RUN_LOGS_DIRECTORY" && -n "${BATS_INTERRUPTED:-}" ]]; then
|
||||
# aborting a test run with CTRL+C does not save the runlog file
|
||||
rm "$BATS_RUNLOG_FILE"
|
||||
fi
|
||||
exit "$bats_exec_suite_status"
|
||||
}
|
||||
|
||||
bats_run_teardown_suite() {
|
||||
# avoid being called twice, in case this is not called through bats_teardown_suite_trap
|
||||
# but from the end of file
|
||||
trap bats_suite_exit_trap EXIT
|
||||
set -eET
|
||||
BATS_TEARDOWN_SUITE_COMPLETED=
|
||||
teardown_suite 2>&1
|
||||
BATS_TEARDOWN_SUITE_COMPLETED=1
|
||||
set +ET
|
||||
}
|
||||
|
||||
bats_teardown_suite_trap() {
|
||||
bats_run_teardown_suite
|
||||
bats_suite_exit_trap
|
||||
}
|
||||
|
||||
setup_suite() {
|
||||
:
|
||||
}
|
||||
|
||||
teardown_suite() {
|
||||
:
|
||||
}
|
||||
|
||||
trap bats_teardown_suite_trap EXIT
|
||||
|
||||
if [[ -n "$setup_suite_file" ]]; then
|
||||
setup_suite() {
|
||||
printf "%s does not define \`setup_suite()\`\n" "$setup_suite_file" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# shellcheck disable=SC1090
|
||||
source "$setup_suite_file"
|
||||
fi
|
||||
|
||||
set -eET
|
||||
BATS_SETUP_SUITE_COMPLETED=
|
||||
setup_suite 2>&1
|
||||
BATS_SETUP_SUITE_COMPLETED=1
|
||||
set +ET
|
||||
|
||||
if [[ "$num_jobs" -gt 1 ]] && [[ -z "$bats_no_parallelize_across_files" ]]; then
|
||||
# run files in parallel to get the maximum pool of parallel tasks
|
||||
# shellcheck disable=SC2086,SC2068
|
||||
# we need to handle the quoting of ${flags[@]} ourselves,
|
||||
# because parallel can only quote it as one
|
||||
parallel --keep-order --jobs "$num_jobs" bats-exec-file "$(printf "%q " "${flags[@]}")" "{}" "$TESTS_LIST_FILE" ::: "${BATS_UNIQUE_TEST_FILENAMES[@]}" 2>&1 || bats_exec_suite_status=1
|
||||
else
|
||||
for filename in "${BATS_UNIQUE_TEST_FILENAMES[@]}"; do
|
||||
if [[ "${BATS_INTERRUPTED-NOTSET}" != NOTSET ]]; then
|
||||
bats_exec_suite_status=130 # bash's code for SIGINT exits
|
||||
break
|
||||
fi
|
||||
bats-exec-file "${flags[@]}" "$filename" "${TESTS_LIST_FILE}" || bats_exec_suite_status=1
|
||||
done
|
||||
fi
|
||||
|
||||
set -eET
|
||||
bats_run_teardown_suite
|
||||
|
||||
exit "$bats_exec_suite_status"
|
231
extras/portable/test/bats/libexec/bats-core/bats-exec-test
Executable file
231
extras/portable/test/bats/libexec/bats-core/bats-exec-test
Executable file
@ -0,0 +1,231 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eET
|
||||
|
||||
# Variables used in other scripts.
|
||||
BATS_ENABLE_TIMING=''
|
||||
BATS_EXTENDED_SYNTAX=''
|
||||
BATS_TRACE_LEVEL="${BATS_TRACE_LEVEL:-0}"
|
||||
BATS_PRINT_OUTPUT_ON_FAILURE="${BATS_PRINT_OUTPUT_ON_FAILURE:-}"
|
||||
BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS="${BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS:-}"
|
||||
BATS_VERBOSE_RUN="${BATS_VERBOSE_RUN:-}"
|
||||
BATS_GATHER_TEST_OUTPUTS_IN="${BATS_GATHER_TEST_OUTPUTS_IN:-}"
|
||||
BATS_TEST_NAME_PREFIX="${BATS_TEST_NAME_PREFIX:-}"
|
||||
|
||||
while [[ "$#" -ne 0 ]]; do
|
||||
case "$1" in
|
||||
-T)
|
||||
BATS_ENABLE_TIMING='-T'
|
||||
;;
|
||||
-x)
|
||||
# shellcheck disable=SC2034
|
||||
BATS_EXTENDED_SYNTAX='-x'
|
||||
;;
|
||||
--dummy-flag)
|
||||
;;
|
||||
--trace)
|
||||
(( ++BATS_TRACE_LEVEL )) # avoid returning 0
|
||||
;;
|
||||
--print-output-on-failure)
|
||||
BATS_PRINT_OUTPUT_ON_FAILURE=1
|
||||
;;
|
||||
--show-output-of-passing-tests)
|
||||
BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS=1
|
||||
;;
|
||||
--verbose-run)
|
||||
BATS_VERBOSE_RUN=1
|
||||
;;
|
||||
--gather-test-outputs-in)
|
||||
shift
|
||||
BATS_GATHER_TEST_OUTPUTS_IN="$1"
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
export BATS_TEST_FILENAME="$1"
|
||||
export BATS_TEST_NAME="$2"
|
||||
export BATS_SUITE_TEST_NUMBER="$3"
|
||||
export BATS_TEST_NUMBER="$4"
|
||||
BATS_TEST_TRY_NUMBER="$5"
|
||||
|
||||
if [[ -z "$BATS_TEST_FILENAME" ]]; then
|
||||
printf 'usage: bats-exec-test <filename>\n' >&2
|
||||
exit 1
|
||||
elif [[ ! -f "$BATS_TEST_FILENAME" ]]; then
|
||||
printf 'bats: %s does not exist\n' "$BATS_TEST_FILENAME" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bats_create_test_tmpdirs() {
|
||||
local tests_tmpdir="${BATS_RUN_TMPDIR}/test"
|
||||
if ! mkdir -p "$tests_tmpdir"; then
|
||||
printf 'Failed to create: %s\n' "$tests_tmpdir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BATS_TEST_TMPDIR="$tests_tmpdir/$BATS_SUITE_TEST_NUMBER"
|
||||
if ! mkdir "$BATS_TEST_TMPDIR"; then
|
||||
printf 'Failed to create BATS_TEST_TMPDIR%d: %s\n' "$BATS_TEST_TRY_NUMBER" "$BATS_TEST_TMPDIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf "%s\n" "$BATS_TEST_NAME" > "$BATS_TEST_TMPDIR.name"
|
||||
|
||||
export BATS_TEST_TMPDIR
|
||||
}
|
||||
|
||||
# load the test helper functions like `load` or `run` that are needed to run a (preprocessed) .bats file without bash errors
|
||||
# shellcheck source=lib/bats-core/test_functions.bash disable=SC2153
|
||||
source "$BATS_ROOT/lib/bats-core/test_functions.bash"
|
||||
# shellcheck source=lib/bats-core/tracing.bash disable=SC2153
|
||||
source "$BATS_ROOT/lib/bats-core/tracing.bash"
|
||||
|
||||
bats_teardown_trap() {
|
||||
bats_check_status_from_trap
|
||||
local bats_teardown_trap_status=0
|
||||
# mark the start of this function to distinguish where skip is called
|
||||
# parameter 1 will signify the reason why this function was called
|
||||
# this is used to identify when this is called as exit trap function
|
||||
BATS_TEARDOWN_STARTED=${1:-1}
|
||||
teardown >>"$BATS_OUT" 2>&1 || bats_teardown_trap_status="$?"
|
||||
|
||||
if [[ $bats_teardown_trap_status -eq 0 ]]; then
|
||||
BATS_TEARDOWN_COMPLETED=1
|
||||
elif [[ -n "$BATS_TEST_COMPLETED" ]]; then
|
||||
BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=1
|
||||
BATS_ERROR_STATUS="$bats_teardown_trap_status"
|
||||
fi
|
||||
|
||||
bats_exit_trap
|
||||
}
|
||||
|
||||
# shellcheck source=lib/bats-core/common.bash
|
||||
source "$BATS_ROOT/lib/bats-core/common.bash"
|
||||
|
||||
bats_exit_trap() {
|
||||
local status
|
||||
local skipped=''
|
||||
trap - ERR EXIT
|
||||
|
||||
if [[ -n "$BATS_TEST_SKIPPED" ]]; then
|
||||
skipped=' # skip'
|
||||
if [[ "$BATS_TEST_SKIPPED" != '1' ]]; then
|
||||
skipped+=" $BATS_TEST_SKIPPED"
|
||||
fi
|
||||
fi
|
||||
|
||||
BATS_TEST_TIME=''
|
||||
if [[ -z "${skipped}" && -n "$BATS_ENABLE_TIMING" ]]; then
|
||||
BATS_TEST_TIME=" in "$(( $(get_mills_since_epoch) - BATS_TEST_START_TIME ))"ms"
|
||||
fi
|
||||
|
||||
local print_bats_out="${BATS_SHOW_OUTPUT_OF_SUCCEEDING_TESTS}"
|
||||
|
||||
local should_retry=''
|
||||
if [[ -z "$BATS_TEST_COMPLETED" || -z "$BATS_TEARDOWN_COMPLETED" || "${BATS_INTERRUPTED-NOTSET}" != NOTSET ]]; then
|
||||
if [[ "$BATS_ERROR_STATUS" -eq 0 ]]; then
|
||||
# For some versions of bash, `$?` may not be set properly for some error
|
||||
# conditions before triggering the EXIT trap directly (see #72 and #81).
|
||||
# Thanks to the `BATS_TEARDOWN_COMPLETED` signal, this will pinpoint such
|
||||
# errors if they happen during `teardown()` when `bats_perform_test` calls
|
||||
# `bats_teardown_trap` directly after the test itself passes.
|
||||
#
|
||||
# If instead the test fails, and the `teardown()` error happens while
|
||||
# `bats_teardown_trap` runs as the EXIT trap, the test will fail with no
|
||||
# output, since there's no way to reach the `bats_exit_trap` call.
|
||||
BATS_ERROR_STATUS=1
|
||||
fi
|
||||
if bats_should_retry_test; then
|
||||
should_retry=1
|
||||
status=126 # signify retry
|
||||
rm -r "$BATS_TEST_TMPDIR" # clean up for retry
|
||||
else
|
||||
printf 'not ok %d %s\n' "$BATS_SUITE_TEST_NUMBER" "${BATS_TEST_NAME_PREFIX:-}${BATS_TEST_DESCRIPTION}${BATS_TEST_TIME}" >&3
|
||||
local stack_trace
|
||||
bats_get_failure_stack_trace stack_trace
|
||||
bats_print_stack_trace "${stack_trace[@]}" >&3
|
||||
bats_print_failed_command "${stack_trace[@]}" >&3
|
||||
|
||||
if [[ $BATS_PRINT_OUTPUT_ON_FAILURE && -n "${output:-}" ]]; then
|
||||
printf "Last output:\n%s\n" "$output" >> "$BATS_OUT"
|
||||
fi
|
||||
|
||||
print_bats_out=1
|
||||
status=1
|
||||
local state=failed
|
||||
fi
|
||||
else
|
||||
printf 'ok %d %s%s\n' "$BATS_SUITE_TEST_NUMBER" "${BATS_TEST_NAME_PREFIX:-}${BATS_TEST_DESCRIPTION}${BATS_TEST_TIME}" \
|
||||
"$skipped" >&3
|
||||
status=0
|
||||
local state=passed
|
||||
fi
|
||||
|
||||
if [[ -z "$should_retry" ]]; then
|
||||
printf "%s %s\t%s\n" "$state" "$BATS_TEST_FILENAME" "$BATS_TEST_NAME" >> "$BATS_RUNLOG_FILE"
|
||||
|
||||
if [[ $print_bats_out ]]; then
|
||||
bats_prefix_lines_for_tap_output < "$BATS_OUT" | bats_replace_filename >&3
|
||||
fi
|
||||
fi
|
||||
if [[ $BATS_GATHER_TEST_OUTPUTS_IN ]]; then
|
||||
local try_suffix=
|
||||
if [[ -n "$should_retry" ]]; then
|
||||
try_suffix="-try$BATS_TEST_TRY_NUMBER"
|
||||
fi
|
||||
cp "$BATS_OUT" "$BATS_GATHER_TEST_OUTPUTS_IN/$BATS_SUITE_TEST_NUMBER$try_suffix-$BATS_TEST_DESCRIPTION.log"
|
||||
fi
|
||||
rm -f "$BATS_OUT"
|
||||
exit "$status"
|
||||
}
|
||||
|
||||
get_mills_since_epoch() {
|
||||
local ms_since_epoch
|
||||
ms_since_epoch=$(date +%s%N)
|
||||
if [[ "$ms_since_epoch" == *N || "${#ms_since_epoch}" -lt 19 ]]; then
|
||||
ms_since_epoch=$(( $(date +%s) * 1000 ))
|
||||
else
|
||||
ms_since_epoch=$(( ms_since_epoch / 1000000 ))
|
||||
fi
|
||||
|
||||
printf "%d\n" "$ms_since_epoch"
|
||||
}
|
||||
|
||||
bats_perform_test() {
|
||||
if ! declare -F "$BATS_TEST_NAME" &>/dev/null; then
|
||||
local quoted_test_name
|
||||
bats_quote_code quoted_test_name "$BATS_TEST_NAME"
|
||||
printf "bats: unknown test name %s\n" "$quoted_test_name" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BATS_TEST_COMPLETED=
|
||||
BATS_TEST_SKIPPED=
|
||||
BATS_TEARDOWN_COMPLETED=
|
||||
BATS_ERROR_STATUS=
|
||||
bats_setup_tracing
|
||||
# mark this call as trap call
|
||||
trap 'bats_teardown_trap as-exit-trap' EXIT
|
||||
|
||||
BATS_TEST_START_TIME=$(get_mills_since_epoch)
|
||||
"$BATS_TEST_NAME" >>"$BATS_OUT" 2>&1 4>&1
|
||||
|
||||
BATS_TEST_COMPLETED=1
|
||||
trap 'bats_exit_trap' EXIT
|
||||
bats_teardown_trap "" # pass empty parameter to signify call outside trap
|
||||
}
|
||||
|
||||
trap bats_interrupt_trap INT
|
||||
|
||||
# shellcheck source=lib/bats-core/preprocessing.bash
|
||||
source "$BATS_ROOT/lib/bats-core/preprocessing.bash"
|
||||
|
||||
exec 3<&1
|
||||
|
||||
bats_create_test_tmpdirs
|
||||
# Run the given test.
|
||||
bats_evaluate_preprocessed_source
|
||||
bats_perform_test
|
6
extras/portable/test/bats/libexec/bats-core/bats-format-cat
Executable file
6
extras/portable/test/bats/libexec/bats-core/bats-format-cat
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
trap '' INT
|
||||
|
||||
cat
|
251
extras/portable/test/bats/libexec/bats-core/bats-format-junit
Executable file
251
extras/portable/test/bats/libexec/bats-core/bats-format-junit
Executable file
@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# shellcheck source=lib/bats-core/formatter.bash
|
||||
source "$BATS_ROOT/lib/bats-core/formatter.bash"
|
||||
|
||||
BASE_PATH=.
|
||||
|
||||
|
||||
while [[ "$#" -ne 0 ]]; do
|
||||
case "$1" in
|
||||
--base-path)
|
||||
shift
|
||||
normalize_base_path BASE_PATH "$1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
init_suite() {
|
||||
suite_test_exec_time=0
|
||||
# since we have to print the suite header before its contents but we don't know the contents before the header,
|
||||
# we have to buffer the contents
|
||||
_suite_buffer=""
|
||||
test_result_state="" # declare for the first flush, when no test has been encountered
|
||||
}
|
||||
|
||||
_buffer_log=
|
||||
init_file() {
|
||||
file_count=0
|
||||
file_failures=0
|
||||
file_skipped=0
|
||||
file_exec_time=0
|
||||
test_exec_time=0
|
||||
_buffer=""
|
||||
_buffer_log=""
|
||||
_system_out_log=""
|
||||
test_result_state="" # mark that no test has run in this file so far
|
||||
}
|
||||
|
||||
host() {
|
||||
local hostname="${HOST:-}"
|
||||
[[ -z "$hostname" ]] && hostname="${HOSTNAME:-}"
|
||||
[[ -z "$hostname" ]] && hostname="$(uname -n)"
|
||||
[[ -z "$hostname" ]] && hostname="$(hostname -f)"
|
||||
|
||||
echo "$hostname"
|
||||
}
|
||||
|
||||
# convert $1 (time in milliseconds) to seconds
|
||||
milliseconds_to_seconds() {
|
||||
# we cannot rely on having bc for this calculation
|
||||
full_seconds=$(($1 / 1000))
|
||||
remaining_milliseconds=$(($1 % 1000))
|
||||
if [[ $remaining_milliseconds -eq 0 ]]; then
|
||||
printf "%d" "$full_seconds"
|
||||
else
|
||||
printf "%d.%03d" "$full_seconds" "$remaining_milliseconds"
|
||||
fi
|
||||
}
|
||||
|
||||
suite_header() {
|
||||
printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||
<testsuites time=\"%s\">\n" "$(milliseconds_to_seconds "${suite_test_exec_time}")"
|
||||
}
|
||||
|
||||
file_header() {
|
||||
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S")
|
||||
printf "<testsuite name=\"%s\" tests=\"%s\" failures=\"%s\" errors=\"0\" skipped=\"%s\" time=\"%s\" timestamp=\"%s\" hostname=\"%s\">\n" \
|
||||
"$(xml_escape "${class}")" "${file_count}" "${file_failures}" "${file_skipped}" "$(milliseconds_to_seconds "${file_exec_time}")" "${timestamp}" "$(host)"
|
||||
}
|
||||
|
||||
file_footer() {
|
||||
printf "</testsuite>\n"
|
||||
}
|
||||
|
||||
suite_footer() {
|
||||
printf "</testsuites>\n"
|
||||
}
|
||||
|
||||
print_test_case() {
|
||||
if [[ "$test_result_state" == ok && -z "$_system_out_log" && -z "$_buffer_log" ]]; then
|
||||
# pass and no output can be shortened
|
||||
printf " <testcase classname=\"%s\" name=\"%s\" time=\"%s\" />\n" "$(xml_escape "${class}")" "$(xml_escape "${name}")" "$(milliseconds_to_seconds "${test_exec_time}")"
|
||||
else
|
||||
printf " <testcase classname=\"%s\" name=\"%s\" time=\"%s\">\n" "$(xml_escape "${class}")" "$(xml_escape "${name}")" "$(milliseconds_to_seconds "${test_exec_time}")"
|
||||
if [[ -n "$_system_out_log" ]]; then
|
||||
printf " <system-out>%s</system-out>\n" "$(xml_escape "${_system_out_log}")"
|
||||
fi
|
||||
if [[ -n "$_buffer_log" || "$test_result_state" == not_ok ]]; then
|
||||
printf " <failure type=\"failure\">%s</failure>\n" "$(xml_escape "${_buffer_log}")"
|
||||
fi
|
||||
if [[ "$test_result_state" == skipped ]]; then
|
||||
printf " <skipped>%s</skipped>\n" "$(xml_escape "$test_skip_message")"
|
||||
fi
|
||||
printf " </testcase>\n"
|
||||
fi
|
||||
}
|
||||
|
||||
xml_escape() {
|
||||
output=${1//&/&}
|
||||
output=${output//</<}
|
||||
output=${output//>/>}
|
||||
output=${output//'"'/"}
|
||||
output=${output//\'/'}
|
||||
local CONTROL_CHAR=$'\033'
|
||||
output="${output//$CONTROL_CHAR/}"
|
||||
printf "%s" "$output"
|
||||
}
|
||||
|
||||
suite_buffer() {
|
||||
local output
|
||||
output="$("$@"; printf "x")" # use x marker to avoid losing trailing newlines
|
||||
_suite_buffer="${_suite_buffer}${output%x}"
|
||||
}
|
||||
|
||||
suite_flush() {
|
||||
echo -n "${_suite_buffer}"
|
||||
_suite_buffer=""
|
||||
}
|
||||
|
||||
buffer() {
|
||||
local output
|
||||
output="$("$@"; printf "x")" # use x marker to avoid losing trailing newlines
|
||||
_buffer="${_buffer}${output%x}"
|
||||
}
|
||||
|
||||
flush() {
|
||||
echo -n "${_buffer}"
|
||||
_buffer=""
|
||||
}
|
||||
|
||||
log() {
|
||||
if [[ -n "$_buffer_log" ]]; then
|
||||
_buffer_log="${_buffer_log}
|
||||
$1"
|
||||
else
|
||||
_buffer_log="$1"
|
||||
fi
|
||||
}
|
||||
|
||||
flush_log() {
|
||||
if [[ -n "$test_result_state" ]]; then
|
||||
buffer print_test_case
|
||||
fi
|
||||
_buffer_log=""
|
||||
_system_out_log=""
|
||||
}
|
||||
|
||||
log_system_out() {
|
||||
if [[ -n "$_system_out_log" ]]; then
|
||||
_system_out_log="${_system_out_log}
|
||||
$1"
|
||||
else
|
||||
_system_out_log="$1"
|
||||
fi
|
||||
}
|
||||
|
||||
finish_file() {
|
||||
if [[ "${class-JUNIT_FORMATTER_NO_FILE_ENCOUNTERED}" != JUNIT_FORMATTER_NO_FILE_ENCOUNTERED ]]; then
|
||||
file_header
|
||||
printf "%s\n" "${_buffer}"
|
||||
file_footer
|
||||
fi
|
||||
}
|
||||
|
||||
finish_suite() {
|
||||
flush_log
|
||||
suite_header
|
||||
suite_flush
|
||||
finish_file # must come after suite flush to not print the last file before the others
|
||||
suite_footer
|
||||
}
|
||||
|
||||
bats_tap_stream_plan() { # <number of tests>
|
||||
:
|
||||
}
|
||||
|
||||
init_suite
|
||||
trap finish_suite EXIT
|
||||
trap '' INT
|
||||
|
||||
bats_tap_stream_begin() { # <test index> <test name>
|
||||
flush_log
|
||||
# set after flushing to avoid overriding name of test
|
||||
name="$2"
|
||||
}
|
||||
|
||||
bats_tap_stream_ok() { # [--duration <milliseconds] <test index> <test name>
|
||||
if [[ "$1" == "--duration" ]]; then
|
||||
test_exec_time="${BASH_REMATCH[1]}"
|
||||
else
|
||||
test_exec_time=0
|
||||
fi
|
||||
((file_count += 1))
|
||||
test_result_state='ok'
|
||||
file_exec_time="$((file_exec_time + test_exec_time))"
|
||||
suite_test_exec_time=$((suite_test_exec_time + test_exec_time))
|
||||
}
|
||||
|
||||
bats_tap_stream_skipped() { # <test index> <test name> <skip reason>
|
||||
((file_count += 1))
|
||||
((file_skipped += 1))
|
||||
test_result_state='skipped'
|
||||
test_exec_time=0
|
||||
test_skip_message="$3"
|
||||
}
|
||||
|
||||
bats_tap_stream_not_ok() { # [--duration <milliseconds>] <test index> <test name>
|
||||
((file_count += 1))
|
||||
((file_failures += 1))
|
||||
if [[ "$1" == "--duration" ]]; then
|
||||
test_exec_time="${BASH_REMATCH[1]}"
|
||||
else
|
||||
test_exec_time=0
|
||||
fi
|
||||
test_result_state=not_ok
|
||||
file_exec_time="$((file_exec_time + test_exec_time))"
|
||||
suite_test_exec_time=$((suite_test_exec_time + test_exec_time))
|
||||
}
|
||||
|
||||
bats_tap_stream_comment() { # <comment text without leading '# '> <scope>
|
||||
local comment="$1" scope="$2"
|
||||
case "$scope" in
|
||||
begin)
|
||||
# everything that happens between begin and [not] ok is FD3 output from the test
|
||||
log_system_out "$comment"
|
||||
;;
|
||||
ok)
|
||||
# non failed tests can produce FD3 output
|
||||
log_system_out "$comment"
|
||||
;;
|
||||
*)
|
||||
# everything else is considered error output
|
||||
log "$1"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
bats_tap_stream_suite() { # <file name>
|
||||
flush_log
|
||||
suite_buffer finish_file
|
||||
init_file
|
||||
class="${1/$BASE_PATH}"
|
||||
}
|
||||
|
||||
bats_tap_stream_unknown() { # <full line>
|
||||
:
|
||||
}
|
||||
|
||||
bats_parse_internal_extended_tap
|
328
extras/portable/test/bats/libexec/bats-core/bats-format-pretty
Executable file
328
extras/portable/test/bats/libexec/bats-core/bats-format-pretty
Executable file
@ -0,0 +1,328 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# shellcheck source=lib/bats-core/formatter.bash
|
||||
source "$BATS_ROOT/lib/bats-core/formatter.bash"
|
||||
|
||||
BASE_PATH=.
|
||||
BATS_ENABLE_TIMING=
|
||||
|
||||
while [[ "$#" -ne 0 ]]; do
|
||||
case "$1" in
|
||||
-T)
|
||||
BATS_ENABLE_TIMING="-T"
|
||||
;;
|
||||
--base-path)
|
||||
shift
|
||||
normalize_base_path BASE_PATH "$1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
update_count_column_width() {
|
||||
count_column_width=$((${#count} * 2 + 2))
|
||||
if [[ -n "$BATS_ENABLE_TIMING" ]]; then
|
||||
# additional space for ' in %s sec'
|
||||
count_column_width=$((count_column_width + ${#SECONDS} + 8))
|
||||
fi
|
||||
# also update dependent value
|
||||
update_count_column_left
|
||||
}
|
||||
|
||||
update_screen_width() {
|
||||
screen_width="$(tput cols)"
|
||||
# also update dependent value
|
||||
update_count_column_left
|
||||
}
|
||||
|
||||
update_count_column_left() {
|
||||
count_column_left=$((screen_width - count_column_width))
|
||||
}
|
||||
|
||||
# avoid unset variables
|
||||
count=0
|
||||
screen_width=80
|
||||
update_count_column_width
|
||||
update_screen_width
|
||||
test_result=
|
||||
|
||||
trap update_screen_width WINCH
|
||||
|
||||
begin() {
|
||||
test_result= # reset to avoid carrying over result state from previous test
|
||||
line_backoff_count=0
|
||||
go_to_column 0
|
||||
update_count_column_width
|
||||
buffer_with_truncation $((count_column_left - 1)) ' %s' "$name"
|
||||
clear_to_end_of_line
|
||||
go_to_column $count_column_left
|
||||
if [[ -n "$BATS_ENABLE_TIMING" ]]; then
|
||||
buffer "%${#count}s/${count} in %s sec" "$index" "$SECONDS"
|
||||
else
|
||||
buffer "%${#count}s/${count}" "$index"
|
||||
fi
|
||||
go_to_column 1
|
||||
}
|
||||
|
||||
finish_test() {
|
||||
move_up $line_backoff_count
|
||||
go_to_column 0
|
||||
buffer "$@"
|
||||
if [[ -n "$BATS_ENABLE_TIMING" ]]; then
|
||||
set_color 2
|
||||
buffer ' [%s]' "$TIMING"
|
||||
fi
|
||||
advance
|
||||
move_down $(( line_backoff_count - 1 ))
|
||||
}
|
||||
|
||||
pass() {
|
||||
TIMING="${1:-}"
|
||||
finish_test ' ✓ %s' "$name"
|
||||
test_result=pass
|
||||
}
|
||||
|
||||
skip() {
|
||||
local reason="$1"
|
||||
if [[ -n "$reason" ]]; then
|
||||
reason=": $reason"
|
||||
fi
|
||||
BATS_ENABLE_TIMING='' finish_test ' - %s (skipped%s)' "$name" "$reason"
|
||||
test_result=skip
|
||||
}
|
||||
|
||||
fail() {
|
||||
set_color 1 bold
|
||||
TIMING="${1:-}"
|
||||
finish_test ' ✗ %s' "$name"
|
||||
test_result=fail
|
||||
}
|
||||
|
||||
log() {
|
||||
case ${test_result} in
|
||||
pass)
|
||||
clear_color
|
||||
;;
|
||||
fail)
|
||||
set_color 1
|
||||
;;
|
||||
esac
|
||||
buffer ' %s\n' "$1"
|
||||
clear_color
|
||||
}
|
||||
|
||||
summary() {
|
||||
if [ "$failures" -eq 0 ] ; then
|
||||
set_color 2 bold
|
||||
else
|
||||
set_color 1 bold
|
||||
fi
|
||||
|
||||
buffer '\n%d test' "$count"
|
||||
if [[ "$count" -ne 1 ]]; then
|
||||
buffer 's'
|
||||
fi
|
||||
|
||||
buffer ', %d failure' "$failures"
|
||||
if [[ "$failures" -ne 1 ]]; then
|
||||
buffer 's'
|
||||
fi
|
||||
|
||||
if [[ "$skipped" -gt 0 ]]; then
|
||||
buffer ', %d skipped' "$skipped"
|
||||
fi
|
||||
|
||||
not_run=$((count - passed - failures - skipped))
|
||||
if [[ "$not_run" -gt 0 ]]; then
|
||||
buffer ', %d not run' "$not_run"
|
||||
fi
|
||||
|
||||
if [[ -n "$BATS_ENABLE_TIMING" ]]; then
|
||||
buffer " in $SECONDS seconds"
|
||||
fi
|
||||
|
||||
buffer '\n'
|
||||
clear_color
|
||||
}
|
||||
|
||||
buffer_with_truncation() {
|
||||
local width="$1"
|
||||
shift
|
||||
local string
|
||||
|
||||
# shellcheck disable=SC2059
|
||||
printf -v 'string' -- "$@"
|
||||
|
||||
if [[ "${#string}" -gt "$width" ]]; then
|
||||
buffer '%s...' "${string:0:$((width - 4))}"
|
||||
else
|
||||
buffer '%s' "$string"
|
||||
fi
|
||||
}
|
||||
|
||||
move_up() {
|
||||
if [[ $1 -gt 0 ]]; then # avoid moving if we got 0
|
||||
buffer '\x1B[%dA' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
move_down() {
|
||||
if [[ $1 -gt 0 ]]; then # avoid moving if we got 0
|
||||
buffer '\x1B[%dB' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
go_to_column() {
|
||||
local column="$1"
|
||||
buffer '\x1B[%dG' $((column + 1))
|
||||
}
|
||||
|
||||
clear_to_end_of_line() {
|
||||
buffer '\x1B[K'
|
||||
}
|
||||
|
||||
advance() {
|
||||
clear_to_end_of_line
|
||||
buffer '\n'
|
||||
clear_color
|
||||
}
|
||||
|
||||
set_color() {
|
||||
local color="$1"
|
||||
local weight=22
|
||||
|
||||
if [[ "${2:-}" == 'bold' ]]; then
|
||||
weight=1
|
||||
fi
|
||||
buffer '\x1B[%d;%dm' "$((30 + color))" "$weight"
|
||||
}
|
||||
|
||||
clear_color() {
|
||||
buffer '\x1B[0m'
|
||||
}
|
||||
|
||||
_buffer=
|
||||
|
||||
buffer() {
|
||||
local content
|
||||
# shellcheck disable=SC2059
|
||||
printf -v content -- "$@"
|
||||
_buffer+="$content"
|
||||
}
|
||||
|
||||
prefix_buffer_with() {
|
||||
local old_buffer="$_buffer"
|
||||
_buffer=''
|
||||
"$@"
|
||||
_buffer="$_buffer$old_buffer"
|
||||
}
|
||||
|
||||
flush() {
|
||||
printf '%s' "$_buffer"
|
||||
_buffer=
|
||||
}
|
||||
|
||||
finish() {
|
||||
flush
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
trap finish EXIT
|
||||
trap '' INT
|
||||
|
||||
bats_tap_stream_plan() {
|
||||
count="$1"
|
||||
index=0
|
||||
passed=0
|
||||
failures=0
|
||||
skipped=0
|
||||
name=
|
||||
update_count_column_width
|
||||
}
|
||||
|
||||
bats_tap_stream_begin() {
|
||||
index="$1"
|
||||
name="$2"
|
||||
begin
|
||||
flush
|
||||
}
|
||||
|
||||
bats_tap_stream_ok() {
|
||||
local duration=
|
||||
if [[ "$1" == "--duration" ]]; then
|
||||
duration="$2"
|
||||
shift 2
|
||||
fi
|
||||
index="$1"
|
||||
name="$2"
|
||||
((++passed))
|
||||
|
||||
pass "$duration"
|
||||
}
|
||||
|
||||
bats_tap_stream_skipped() {
|
||||
index="$1"
|
||||
name="$2"
|
||||
((++skipped))
|
||||
skip "$3"
|
||||
}
|
||||
|
||||
bats_tap_stream_not_ok() {
|
||||
local duration=
|
||||
if [[ "$1" == "--duration" ]]; then
|
||||
duration="$2"
|
||||
shift 2
|
||||
fi
|
||||
index="$1"
|
||||
name="$2"
|
||||
((++failures))
|
||||
|
||||
fail "$duration"
|
||||
}
|
||||
|
||||
bats_tap_stream_comment() { # <comment> <scope>
|
||||
local scope=$2
|
||||
# count the lines we printed after the begin text,
|
||||
if [[ $line_backoff_count -eq 0 && $scope == begin ]]; then
|
||||
# if this is the first line after begin, go down one line
|
||||
buffer "\n"
|
||||
(( ++line_backoff_count )) # prefix-increment to avoid "error" due to returning 0
|
||||
fi
|
||||
|
||||
(( ++line_backoff_count ))
|
||||
(( line_backoff_count += ${#1} / screen_width)) # account for linebreaks due to length
|
||||
log "$1"
|
||||
}
|
||||
|
||||
bats_tap_stream_suite() {
|
||||
#test_file="$1"
|
||||
line_backoff_count=0
|
||||
index=
|
||||
# indicate filename for failures
|
||||
local file_name="${1/$BASE_PATH}"
|
||||
name="File $file_name"
|
||||
set_color 4 bold
|
||||
buffer "%s\n" "$file_name"
|
||||
clear_color
|
||||
}
|
||||
|
||||
line_backoff_count=0
|
||||
bats_tap_stream_unknown() { # <full line> <scope>
|
||||
local scope=$2
|
||||
# count the lines we printed after the begin text, (or after suite, in case of syntax errors)
|
||||
if [[ $line_backoff_count -eq 0 && ( $scope == begin || $scope == suite )]]; then
|
||||
# if this is the first line after begin, go down one line
|
||||
buffer "\n"
|
||||
(( ++line_backoff_count )) # prefix-increment to avoid "error" due to returning 0
|
||||
fi
|
||||
|
||||
(( ++line_backoff_count ))
|
||||
(( line_backoff_count += ${#1} / screen_width)) # account for linebreaks due to length
|
||||
buffer "%s\n" "$1"
|
||||
flush
|
||||
}
|
||||
|
||||
bats_parse_internal_extended_tap
|
||||
|
||||
summary
|
52
extras/portable/test/bats/libexec/bats-core/bats-format-tap
Executable file
52
extras/portable/test/bats/libexec/bats-core/bats-format-tap
Executable file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
trap '' INT
|
||||
|
||||
# shellcheck source=lib/bats-core/formatter.bash
|
||||
source "$BATS_ROOT/lib/bats-core/formatter.bash"
|
||||
|
||||
bats_tap_stream_plan() {
|
||||
printf "1..%d\n" "$1"
|
||||
}
|
||||
|
||||
bats_tap_stream_begin() { #<test index> <test name>
|
||||
:
|
||||
}
|
||||
|
||||
bats_tap_stream_ok() { # [--duration <milliseconds] <test index> <test name>
|
||||
if [[ "$1" == "--duration" ]]; then
|
||||
printf "ok %d %s # in %d ms\n" "$3" "$4" "$2"
|
||||
else
|
||||
printf "ok %d %s\n" "$1" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
bats_tap_stream_not_ok() { # [--duration <milliseconds>] <test index> <test name>
|
||||
if [[ "$1" == "--duration" ]]; then
|
||||
printf "not ok %d %s # in %d ms\n" "$3" "$4" "$2"
|
||||
else
|
||||
printf "not ok %d %s\n" "$1" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
bats_tap_stream_skipped() { # <test index> <test name> <reason>
|
||||
if [[ -n "$3" ]]; then
|
||||
printf "ok %d %s # skip %s\n" "$1" "$2" "$3"
|
||||
else
|
||||
printf "ok %d %s # skip\n" "$1" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
bats_tap_stream_comment() { # <comment text without leading '# '>
|
||||
printf "# %s\n" "$1"
|
||||
}
|
||||
|
||||
bats_tap_stream_suite() { # <file name>
|
||||
:
|
||||
}
|
||||
|
||||
bats_tap_stream_unknown() { # <full line>
|
||||
printf "%s\n" "$1"
|
||||
}
|
||||
|
||||
bats_parse_internal_extended_tap
|
91
extras/portable/test/bats/libexec/bats-core/bats-format-tap13
Executable file
91
extras/portable/test/bats/libexec/bats-core/bats-format-tap13
Executable file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
while [[ "$#" -ne 0 ]]; do
|
||||
case "$1" in
|
||||
-T)
|
||||
BATS_ENABLE_TIMING="-T"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
header_pattern='[0-9]+\.\.[0-9]+'
|
||||
IFS= read -r header
|
||||
|
||||
if [[ "$header" =~ $header_pattern ]]; then
|
||||
printf "TAP version 13\n"
|
||||
printf "%s\n" "$header"
|
||||
else
|
||||
# If the first line isn't a TAP plan, print it and pass the rest through
|
||||
printf '%s\n' "$header"
|
||||
exec cat
|
||||
fi
|
||||
|
||||
yaml_block_open=''
|
||||
add_yaml_entry() {
|
||||
if [[ -z "$yaml_block_open" ]]; then
|
||||
printf " ---\n"
|
||||
fi
|
||||
printf " %s: %s\n" "$1" "$2"
|
||||
yaml_block_open=1
|
||||
}
|
||||
|
||||
close_previous_yaml_block() {
|
||||
if [[ -n "$yaml_block_open" ]]; then
|
||||
printf " ...\n"
|
||||
yaml_block_open=''
|
||||
fi
|
||||
}
|
||||
|
||||
trap '' INT
|
||||
|
||||
number_of_printed_log_lines_for_this_test_so_far=0
|
||||
|
||||
while IFS= read -r line; do
|
||||
case "$line" in
|
||||
'begin '*) ;;
|
||||
'ok '*)
|
||||
close_previous_yaml_block
|
||||
number_of_printed_log_lines_for_this_test_so_far=0
|
||||
if [[ -n "${BATS_ENABLE_TIMING-}" ]]; then
|
||||
timing_expr="(ok [0-9]+ .+) in ([0-9]+)ms$"
|
||||
if [[ "$line" =~ $timing_expr ]]; then
|
||||
printf "%s\n" "${BASH_REMATCH[1]}"
|
||||
add_yaml_entry "duration_ms" "${BASH_REMATCH[2]}"
|
||||
else
|
||||
echo "Could not match output line to timing regex: $line" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
printf "%s\n" "${line}"
|
||||
fi
|
||||
;;
|
||||
'not ok '*)
|
||||
close_previous_yaml_block
|
||||
number_of_printed_log_lines_for_this_test_so_far=0
|
||||
timing_expr="(not ok [0-9]+ .+) in ([0-9])+ms$"
|
||||
if [[ -n "${BATS_ENABLE_TIMING-}" ]]; then
|
||||
if [[ "$line" =~ $timing_expr ]]; then
|
||||
printf "%s\n" "${BASH_REMATCH[1]}"
|
||||
add_yaml_entry "duration_ms" "${BASH_REMATCH[2]}"
|
||||
else
|
||||
echo "Could not match failure line to timing regex: $line" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
printf "%s\n" "${line}"
|
||||
fi
|
||||
;;
|
||||
'# '*)
|
||||
if [[ $number_of_printed_log_lines_for_this_test_so_far -eq 0 ]]; then
|
||||
add_yaml_entry "message" "|" # use a multiline string for this entry
|
||||
fi
|
||||
((++number_of_printed_log_lines_for_this_test_so_far))
|
||||
printf " %s\n" "${line:2}"
|
||||
;;
|
||||
'suite '*) ;;
|
||||
esac
|
||||
done
|
||||
# close the final block if there was one
|
||||
close_previous_yaml_block
|
60
extras/portable/test/bats/libexec/bats-core/bats-preprocess
Executable file
60
extras/portable/test/bats/libexec/bats-core/bats-preprocess
Executable file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
bats_encode_test_name() {
|
||||
local name="$1"
|
||||
local result='test_'
|
||||
local hex_code
|
||||
|
||||
if [[ ! "$name" =~ [^[:alnum:]\ _-] ]]; then
|
||||
name="${name//_/-5f}"
|
||||
name="${name//-/-2d}"
|
||||
name="${name// /_}"
|
||||
result+="$name"
|
||||
else
|
||||
local length="${#name}"
|
||||
local char i
|
||||
|
||||
for ((i = 0; i < length; i++)); do
|
||||
char="${name:$i:1}"
|
||||
if [[ "$char" == ' ' ]]; then
|
||||
result+='_'
|
||||
elif [[ "$char" =~ [[:alnum:]] ]]; then
|
||||
result+="$char"
|
||||
else
|
||||
printf -v 'hex_code' -- '-%02x' \'"$char"
|
||||
result+="$hex_code"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
printf -v "$2" '%s' "$result"
|
||||
}
|
||||
|
||||
BATS_TEST_PATTERN="^[[:blank:]]*@test[[:blank:]]+(.*[^[:blank:]])[[:blank:]]+\{(.*)\$"
|
||||
BATS_TEST_PATTERN_COMMENT="[[:blank:]]*([^[:blank:]()]+)[[:blank:]]*\(?\)?[[:blank:]]+\{[[:blank:]]+#[[:blank:]]*@test[[:blank:]]*\$"
|
||||
|
||||
test_file="$1"
|
||||
tests=()
|
||||
{
|
||||
while IFS= read -r line; do
|
||||
line="${line//$'\r'/}"
|
||||
if [[ "$line" =~ $BATS_TEST_PATTERN ]] || [[ "$line" =~ $BATS_TEST_PATTERN_COMMENT ]]; then
|
||||
name="${BASH_REMATCH[1]#[\'\"]}"
|
||||
name="${name%[\'\"]}"
|
||||
body="${BASH_REMATCH[2]:-}"
|
||||
bats_encode_test_name "$name" 'encoded_name'
|
||||
printf '%s() { bats_test_begin "%s"; %s\n' "${encoded_name:?}" "$name" "$body" || :
|
||||
|
||||
if [[ -z "$BATS_TEST_FILTER" || "$name" =~ $BATS_TEST_FILTER ]]; then
|
||||
tests+=("$encoded_name")
|
||||
fi
|
||||
else
|
||||
printf '%s\n' "$line"
|
||||
fi
|
||||
done
|
||||
} <<<"$(<"$test_file")"$'\n'
|
||||
|
||||
for test_name in "${tests[@]}"; do
|
||||
printf 'bats_test_function %s\n' "$test_name"
|
||||
done
|
197
extras/portable/test/bats_setup
Normal file
197
extras/portable/test/bats_setup
Normal file
@ -0,0 +1,197 @@
|
||||
# setup paths for BATS test units
|
||||
setup() {
|
||||
[ ! -f ${BATS_PARENT_TMPNAME}.skip ] || skip "skip remaining tests"
|
||||
bats_require_minimum_version 1.5.0
|
||||
R="$BATS_TEST_DIRNAME"
|
||||
# R=`cd "$T"/.. && pwd`
|
||||
TMP="$BATS_FILE_TMPDIR"
|
||||
load test_helper/bats-support/load
|
||||
load test_helper/bats-assert/load
|
||||
load test_helper/bats-file/load
|
||||
ZTMP="$BATS_FILE_TMPDIR"
|
||||
if [ "$ZENROOM_EXECUTABLE" == "" ]; then
|
||||
ZENROOM_EXECUTABLE="/usr/local/bin/zenroom"
|
||||
fi
|
||||
|
||||
PATH="$PATH:/usr/local/bin:/usr/local/sbin"
|
||||
MNT="/media/`basename $BATS_TEST_FILENAME`"
|
||||
PIM=42
|
||||
# max password stdin size to veracrypt is 128 bytes
|
||||
PW="91cd69b2caab05cb64f8e1c8ae22a7c5a25564e7fc5116d0303dce1ffd26861ea0483c25bdb85adb216718c19815eb59ac14ec9783bfbbb57786ca7d9038c845"
|
||||
# `openssl rand -hex 64`"
|
||||
FS='ext4'
|
||||
SIZE='20M'
|
||||
[ "$TOMB" = "" ] && TOMB=test.tomb
|
||||
|
||||
# default on freebsd is 1001
|
||||
user_uid=1000
|
||||
user_gid=1000
|
||||
|
||||
system="`uname -s`"
|
||||
f_create=""
|
||||
f_format=""
|
||||
f_map=""
|
||||
f_mount=""
|
||||
f_close=""
|
||||
|
||||
case "$system" in
|
||||
FreeBSD)
|
||||
f_create=portable_create
|
||||
f_format=freebsd_format
|
||||
f_map=portable_map
|
||||
f_mount=freebsd_mount
|
||||
f_close=freebsd_close
|
||||
user_uid=1001
|
||||
user_gid=1001
|
||||
;;
|
||||
Linux)
|
||||
f_create=portable_create
|
||||
f_format=linux_format
|
||||
f_map=portable_map
|
||||
f_mount=linux_mount
|
||||
f_close=portable_close
|
||||
user_uid=1000
|
||||
user_gid=1000
|
||||
;;
|
||||
*)
|
||||
>&2 echo "Unsupported system: $system"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
# cd $ZTMP
|
||||
}
|
||||
|
||||
teardown() {
|
||||
[ -n "$BATS_TEST_COMPLETED" ] || touch ${BATS_PARENT_TMPNAME}.skip
|
||||
>&3 echo
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# usage: echo PASSWORD | portable_create file size pim
|
||||
portable_create() {
|
||||
local file="$1" # must not exist
|
||||
local size="$2" # veracrypt format (accepts M or G)
|
||||
local pim="$3" # any number
|
||||
# >&2 echo "portable_create $file $size $pim"
|
||||
veracrypt --non-interactive --text --stdin \
|
||||
-m nokernelcrypto \
|
||||
-c ${file} --volume-type normal \
|
||||
--hash sha512 --encryption serpent-aes \
|
||||
--filesystem none --size ${size} --pim ${pim} \
|
||||
--random-source /dev/urandom -k ''
|
||||
return $?
|
||||
}
|
||||
|
||||
# usage: echo PASSWORD | portable_map file pim
|
||||
portable_map() {
|
||||
local file="$1"
|
||||
local pim="$2"
|
||||
# >&2 echo "portable_map $file $pim"
|
||||
veracrypt --non-interactive --text --stdin \
|
||||
--protect-hidden no -m nokernelcrypto \
|
||||
-k '' --pim ${pim} --filesystem none \
|
||||
${file}
|
||||
local loop=`veracrypt -l "$file" | awk '{print $3}'`
|
||||
return $?
|
||||
}
|
||||
|
||||
portable_close() {
|
||||
local file="$1"
|
||||
veracrypt -d ${file}
|
||||
return $?
|
||||
}
|
||||
|
||||
linux_format() {
|
||||
local file="$1"
|
||||
# loop="`losetup -j ${vera}/volume | cut -d: -f1`"
|
||||
local loop=`veracrypt -l "$FILE" | awk '{print $3}'`
|
||||
# losetup -l
|
||||
>&2 echo "veramap format: ${loop}"
|
||||
sync
|
||||
sudo mkfs.ext4 -E root_owner="${user_uid}:${user_gid}" "$loop"
|
||||
return $?
|
||||
}
|
||||
|
||||
# usage: _mount /tmp/.veracrypt_ mountpoint
|
||||
linux_mount() {
|
||||
local file="$1"
|
||||
local mnt="$2"
|
||||
# local loop="`losetup -j ${vera}/volume | cut -d: -f1`"
|
||||
local loop=`veracrypt -l "$file" | awk '{print $3}'`
|
||||
>&3 echo "fsck $loop"
|
||||
fsck.ext4 -p -C0 "$loop"
|
||||
sudo mount ${loop} "$mnt"
|
||||
return $?
|
||||
}
|
||||
|
||||
freebsd_format() {
|
||||
file="$1"
|
||||
local loop=`veracrypt -l "$FILE" | awk '{print $3}'`
|
||||
mkfs.ext4 -E root_owner="${user_uid}:${user_gid}" "${loop}"
|
||||
return $?
|
||||
}
|
||||
|
||||
freebsd_mount() {
|
||||
local file="$1"
|
||||
local mnt="$2"
|
||||
>&2 echo `veracrypt -l "$file"`
|
||||
local loop=`veracrypt -l "$file" | awk '{print $3}'`
|
||||
>&3 echo "fsck $loop"
|
||||
fsck.ext4 -p -C0 "$loop"
|
||||
lklfuse -o type=ext4 "${loop}" "$mnt"
|
||||
return $?
|
||||
}
|
||||
|
||||
freebsd_close() {
|
||||
local file="$1"
|
||||
local md=`veracrypt -l "$file" | awk '{print $3}'`
|
||||
# umount "$mnt"
|
||||
>&2 echo "md: $md"
|
||||
local mnt=`pgrep -lf "lklfuse.*$md" | awk '{print $6}'`
|
||||
>&2 echo "mnt: $mnt"
|
||||
lkl=`pgrep -f "lklfuse.*$md" | awk '{print $1}'`
|
||||
>&3 echo "kill $lkl (lklfuse on $md)"
|
||||
# trying to deail with lklfuse bug
|
||||
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=239831
|
||||
renice -20 $lkl
|
||||
kill $lkl
|
||||
sync
|
||||
sleep 1
|
||||
kill -9 $lkl
|
||||
# lkl should have really exited now
|
||||
>&3 echo "veracrypt -d $file"
|
||||
veracrypt -d "$file"
|
||||
return $?
|
||||
}
|
||||
|
||||
Z() {
|
||||
tmptmp=0
|
||||
if ! [ "$TMP" ]; then
|
||||
TMP=`mktemp -d`; tmptmp=1
|
||||
fi
|
||||
script=$1
|
||||
if [ "$script" == "-" ]; then
|
||||
cat > $TMP/script_stdin
|
||||
script=$TMP/script_stdin
|
||||
else
|
||||
if ! [ -r "$script" ]; then
|
||||
script=$T/$script
|
||||
fi
|
||||
fi
|
||||
if ! [ -r $script ]; then
|
||||
>&2 echo "Error - script not found: $script"
|
||||
return 1
|
||||
fi
|
||||
shift 1
|
||||
if [ "${1##*.}" == "zen" ]; then
|
||||
$ZENROOM_EXECUTABLE $@ -z $script
|
||||
else
|
||||
$ZENROOM_EXECUTABLE $@ $script
|
||||
fi
|
||||
if [ $tmptmp = 1 ]; then
|
||||
rm -f $TMP/*
|
||||
rmdir $TMP
|
||||
fi
|
||||
}
|
26
extras/portable/test/check-random-data.bats
Normal file
26
extras/portable/test/check-random-data.bats
Normal file
@ -0,0 +1,26 @@
|
||||
load bats_setup
|
||||
|
||||
@test "Find the tomb" {
|
||||
assert_file_exists "$TOMB"
|
||||
>&3 echo "Found: $TOMB"
|
||||
}
|
||||
|
||||
@test "Open tomb with key" {
|
||||
mkdir -p "$TOMB".mnt
|
||||
./tomb open -k "$TOMB".key "$TOMB" "$TOMB".mnt
|
||||
}
|
||||
|
||||
@test "Check integrity of random data" {
|
||||
sha512sum "$TOMB".mnt/random.data | awk '{print $1}'
|
||||
cat "$TOMB".hash
|
||||
>&2 echo $newhash
|
||||
>&2 echo $oldhash
|
||||
assert_equal "$newhash" "$oldhash"
|
||||
if [ -r "$TOMB".uname ]; then
|
||||
>&3 cat "$TOMB".uname
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Close tomb" {
|
||||
./tomb close "$TOMB"
|
||||
}
|
79
extras/portable/test/create-fillrandom.bats
Normal file
79
extras/portable/test/create-fillrandom.bats
Normal file
@ -0,0 +1,79 @@
|
||||
load bats_setup
|
||||
|
||||
# f_create=""
|
||||
# f_format=""
|
||||
# f_map=""
|
||||
# f_mount=""
|
||||
# f_close=""
|
||||
|
||||
@test "Create a new tomb" {
|
||||
# >&3 echo $PW
|
||||
>&3 echo $TOMB
|
||||
echo -n "$PW" | $f_create "$TOMB" 20M ${PIM}
|
||||
}
|
||||
|
||||
@test "Map the tomb" {
|
||||
echo -n "$PW" | $f_map "$TOMB" ${PIM}
|
||||
}
|
||||
|
||||
@test "Format the tomb" {
|
||||
$f_format "/tmp/.veracrypt_aux_mnt1" || {
|
||||
$f_close "$TOMB"
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@test "Mount the tomb" {
|
||||
mkdir -p "$MNT"
|
||||
$f_mount "$TOMB" "$MNT" || {
|
||||
$f_close "$TOMB"
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@test "Create random.data inside the tomb" {
|
||||
dd if=/dev/urandom of="$MNT"/random.data bs=1024 count=10000 || {
|
||||
# sudo umount testmnt
|
||||
$f_close "$TOMB"
|
||||
return false
|
||||
}
|
||||
>&3 ls -l "$MNT"/random.data
|
||||
sha512sum "$MNT"/random.data | awk '{print $1}' | >&3 tee "$TOMB".hash
|
||||
uname -a > "$TOMB".uname
|
||||
}
|
||||
|
||||
@test "Close the test.tomb" {
|
||||
>&3 veracrypt -l
|
||||
# sudo umount "$TMP"/testmnt
|
||||
$f_close "$TOMB"
|
||||
}
|
||||
|
||||
|
||||
@test "Re-Map the test.tomb" {
|
||||
echo -n "$PW" | $f_map "$TOMB" ${PIM}
|
||||
}
|
||||
|
||||
@test "Re-Mount the test.tomb" {
|
||||
mkdir -p "$MNT"
|
||||
$f_mount "$TOMB" "$MNT" || {
|
||||
$f_close "$TOMB"
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@test "Re-Check integrity of random data" {
|
||||
newhash=`sha512sum "$MNT"/random.data | awk '{print $1}'`
|
||||
oldhash=`cat "$TOMB".hash`
|
||||
>&2 echo $newhash
|
||||
>&2 echo $oldhash
|
||||
assert_equal "$newhash" "$oldhash"
|
||||
if [ -r "$TOMB".uname ]; then
|
||||
>&3 cat "$TOMB".uname
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@test "Re-Close the test.tomb" {
|
||||
>&3 veracrypt -l
|
||||
$f_close "$TOMB"
|
||||
}
|
51
extras/portable/test/create_open_close.bats
Normal file
51
extras/portable/test/create_open_close.bats
Normal file
@ -0,0 +1,51 @@
|
||||
load bats_setup
|
||||
|
||||
@test "Dig tomb" {
|
||||
rm -f "$TOMB"
|
||||
>&3 echo "$TOMB"
|
||||
./tomb dig -s 20 "$TOMB"
|
||||
}
|
||||
|
||||
@test "Forge key" {
|
||||
rm -f "$TOMB".key
|
||||
./tomb forge "$TOMB".key
|
||||
}
|
||||
|
||||
@test "Lock tomb with key" {
|
||||
./tomb lock -k "$TOMB".key "$TOMB"
|
||||
}
|
||||
|
||||
@test "Open tomb with key" {
|
||||
mkdir -p "$TOMB".mnt
|
||||
./tomb open -k "$TOMB".key "$TOMB" "$TOMB".mnt
|
||||
}
|
||||
|
||||
@test "Create random.data inside the tomb" {
|
||||
dd if=/dev/urandom of="$TOMB".mnt/random.data bs=1024 count=10000
|
||||
>&3 ls -l "$TOMB".mnt/random.data
|
||||
sha512sum "$TOMB".mnt/random.data | awk '{print $1}' | >&3 tee "$TOMB".hash
|
||||
uname -a > "$TOMB".uname
|
||||
}
|
||||
|
||||
@test "Close tomb" {
|
||||
./tomb close "$TOMB"
|
||||
}
|
||||
|
||||
@test "Re-open tomb with key" {
|
||||
./tomb open -k "$TOMB".key "$TOMB" "$TOMB".mnt
|
||||
}
|
||||
|
||||
@test "Check integrity of random data" {
|
||||
newhash=`sha512sum "$TOMB".mnt/random.data | awk '{print $1}'`
|
||||
oldhash=`cat "$TOMB".hash`
|
||||
>&2 echo $newhash
|
||||
>&2 echo $oldhash
|
||||
assert_equal "$newhash" "$oldhash"
|
||||
if [ -r "$TOMB".uname ]; then
|
||||
>&3 cat "$TOMB".uname
|
||||
fi
|
||||
}
|
||||
|
||||
@test "Close the tomb again" {
|
||||
./tomb close "$TOMB"
|
||||
}
|
33
extras/portable/test/test_helper/bats-assert/load.bash
Normal file
33
extras/portable/test/test_helper/bats-assert/load.bash
Normal file
@ -0,0 +1,33 @@
|
||||
# bats-assert - Common assertions for Bats
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
# Assertions are functions that perform a test and output relevant
|
||||
# information on failure to help debugging. They return 1 on failure
|
||||
# and 0 otherwise.
|
||||
#
|
||||
# All output is formatted for readability using the functions of
|
||||
# `output.bash' and sent to the standard error.
|
||||
|
||||
# shellcheck disable=1090
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/refute.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_equal.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_not_equal.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_success.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_failure.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_output.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/refute_output.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_line.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/refute_line.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/assert_regex.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/refute_regex.bash"
|
42
extras/portable/test/test_helper/bats-assert/src/assert.bash
Normal file
42
extras/portable/test/test_helper/bats-assert/src/assert.bash
Normal file
@ -0,0 +1,42 @@
|
||||
# assert
|
||||
# ======
|
||||
#
|
||||
# Summary: Fail if the given expression evaluates to false.
|
||||
#
|
||||
# Usage: assert <expression>
|
||||
|
||||
# Options:
|
||||
# <expression> The expression to evaluate for truthiness.
|
||||
# *__Note:__ The expression must be a simple command.
|
||||
# [Compound commands](https://www.gnu.org/software/bash/manual/bash.html#Compound-Commands),
|
||||
# such as `[[`, can be used only when executed with `bash -c`.*
|
||||
#
|
||||
# IO:
|
||||
# STDERR - the failed expression, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if expression evaluates to true
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert()' {
|
||||
# touch '/var/log/test.log'
|
||||
# assert [ -e '/var/log/test.log' ]
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the failed expression is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- assertion failed --
|
||||
# expression : [ -e /var/log/test.log ]
|
||||
# --
|
||||
# ```
|
||||
assert() {
|
||||
if ! "$@"; then
|
||||
batslib_print_kv_single 10 'expression' "$*" \
|
||||
| batslib_decorate 'assertion failed' \
|
||||
| fail
|
||||
fi
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
# assert_equal
|
||||
# ============
|
||||
#
|
||||
# Summary: Fail if the actual and expected values are not equal.
|
||||
#
|
||||
# Usage: assert_equal <actual> <expected>
|
||||
#
|
||||
# Options:
|
||||
# <actual> The value being compared.
|
||||
# <expected> The value to compare against.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_equal()' {
|
||||
# assert_equal 'have' 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# IO:
|
||||
# STDERR - expected and actual values, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if values equal
|
||||
# 1 - otherwise
|
||||
#
|
||||
# On failure, the expected and actual values are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- values do not equal --
|
||||
# expected : want
|
||||
# actual : have
|
||||
# --
|
||||
# ```
|
||||
assert_equal() {
|
||||
if [[ $1 != "$2" ]]; then
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'expected' "$2" \
|
||||
'actual' "$1" \
|
||||
| batslib_decorate 'values do not equal' \
|
||||
| fail
|
||||
fi
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
# assert_failure
|
||||
# ==============
|
||||
#
|
||||
# Summary: Fail if `$status` is 0; or is not equal to the optionally provided status.
|
||||
#
|
||||
# Usage: assert_failure [<expected_status>]
|
||||
#
|
||||
# Options:
|
||||
# <expected_status> The specific status code to check against.
|
||||
# If not provided, simply asserts status is != 0.
|
||||
#
|
||||
# IO:
|
||||
# STDERR - `$output`, on failure;
|
||||
# - also, `$status` and `expected_status`, if provided
|
||||
# Globals:
|
||||
# status
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if `$status' is 0,
|
||||
# or if expected_status is provided but does not equal `$status'
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_failure() status only' {
|
||||
# run echo 'Success!'
|
||||
# assert_failure
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, `$output` is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command succeeded, but it was expected to fail --
|
||||
# output : Success!
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Expected status
|
||||
#
|
||||
# When `expected_status` is provided, fail if `$status` does not equal the `expected_status`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_failure() with expected status' {
|
||||
# run bash -c "echo 'Error!'; exit 1"
|
||||
# assert_failure 2
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, both the expected and actual statuses, and `$output` are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command failed as expected, but status differs --
|
||||
# expected : 2
|
||||
# actual : 1
|
||||
# output : Error!
|
||||
# --
|
||||
# ```
|
||||
assert_failure() {
|
||||
: "${output?}"
|
||||
: "${status?}"
|
||||
|
||||
(( $# > 0 )) && local -r expected="$1"
|
||||
if (( status == 0 )); then
|
||||
batslib_print_kv_single_or_multi 6 'output' "$output" \
|
||||
| batslib_decorate 'command succeeded, but it was expected to fail' \
|
||||
| fail
|
||||
elif (( $# > 0 )) && (( status != expected )); then
|
||||
{ local -ir width=8
|
||||
batslib_print_kv_single "$width" \
|
||||
'expected' "$expected" \
|
||||
'actual' "$status"
|
||||
batslib_print_kv_single_or_multi "$width" \
|
||||
'output' "$output"
|
||||
} \
|
||||
| batslib_decorate 'command failed as expected, but status differs' \
|
||||
| fail
|
||||
fi
|
||||
}
|
@ -0,0 +1,248 @@
|
||||
# assert_line
|
||||
# ===========
|
||||
#
|
||||
# Summary: Fail if the expected line is not found in the output (default) or at a specific line number.
|
||||
#
|
||||
# Usage: assert_line [-n index] [-p | -e] [--] <expected>
|
||||
#
|
||||
# Options:
|
||||
# -n, --index <idx> Match the <idx>th line
|
||||
# -p, --partial Match if `expected` is a substring of `$output` or line <idx>
|
||||
# -e, --regexp Treat `expected` as an extended regular expression
|
||||
# <expected> The expected line string, substring, or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# lines
|
||||
# Returns:
|
||||
# 0 - if matching line found
|
||||
# 1 - otherwise
|
||||
#
|
||||
# Similarly to `assert_output`, this function verifies that a command or function produces the expected output.
|
||||
# (It is the logical complement of `refute_line`.)
|
||||
# It checks that the expected line appears in the output (default) or at a specific line number.
|
||||
# Matching can be literal (default), partial or regular expression.
|
||||
#
|
||||
# *__Warning:__
|
||||
# Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`,
|
||||
# causing line indices to change and preventing testing for empty lines.*
|
||||
#
|
||||
# [bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
#
|
||||
# ## Looking for a line in the output
|
||||
#
|
||||
# By default, the entire output is searched for the expected line.
|
||||
# The assertion fails if the expected line is not found in `${lines[@]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() looking for line' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the expected line and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output does not contain line --
|
||||
# line : want
|
||||
# output (3 lines):
|
||||
# have-0
|
||||
# have-1
|
||||
# have-2
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Matching a specific line
|
||||
#
|
||||
# When the `--index <idx>` option is used (`-n <idx>` for short), the expected line is matched only against the line identified by the given index.
|
||||
# The assertion fails if the expected line does not equal `${lines[<idx>]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() specific line' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line --index 1 'want-1'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the index and the compared lines are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line differs --
|
||||
# index : 1
|
||||
# expected : want-1
|
||||
# actual : have-1
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, a match fails if the expected *substring* is not found in the matched line.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() partial matching' {
|
||||
# run echo $'have 1\nhave 2\nhave 3'
|
||||
# assert_line --partial 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the same details are displayed as for literal matching, except that the substring replaces the expected line.
|
||||
#
|
||||
# ```
|
||||
# -- no output line contains substring --
|
||||
# substring : want
|
||||
# output (3 lines):
|
||||
# have 1
|
||||
# have 2
|
||||
# have 3
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, a match fails if the *extended regular expression* does not match the line being tested.
|
||||
#
|
||||
# *__Note__:
|
||||
# As expected, the anchors `^` and `$` bind to the beginning and the end (respectively) of the matched line.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_line() regular expression matching' {
|
||||
# run echo $'have-0\nhave-1\nhave-2'
|
||||
# assert_line --index 1 --regexp '^want-[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the same details are displayed as for literal matching, except that the regular expression replaces the expected line.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression does not match line --
|
||||
# index : 1
|
||||
# regexp : ^want-[0-9]$
|
||||
# line : have-1
|
||||
# --
|
||||
# ```
|
||||
# FIXME(ztombol): Display `${lines[@]}' instead of `$output'!
|
||||
assert_line() {
|
||||
local -i is_match_line=0
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
: "${lines?}"
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-n|--index)
|
||||
if (( $# < 2 )) || ! [[ $2 =~ ^-?([0-9]|[1-9][0-9]+)$ ]]; then
|
||||
echo "\`--index' requires an integer argument: \`$2'" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
is_match_line=1
|
||||
local -ri idx="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local -r expected="$1"
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $expected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$expected'" \
|
||||
| batslib_decorate 'ERROR: assert_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_match_line )); then
|
||||
# Specific line.
|
||||
if (( is_mode_regexp )); then
|
||||
if ! [[ ${lines[$idx]} =~ $expected ]]; then
|
||||
batslib_print_kv_single 6 \
|
||||
'index' "$idx" \
|
||||
'regexp' "$expected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'regular expression does not match line' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ ${lines[$idx]} != *"$expected"* ]]; then
|
||||
batslib_print_kv_single 9 \
|
||||
'index' "$idx" \
|
||||
'substring' "$expected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line does not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ ${lines[$idx]} != "$expected" ]]; then
|
||||
batslib_print_kv_single 8 \
|
||||
'index' "$idx" \
|
||||
'expected' "$expected" \
|
||||
'actual' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line differs' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Contained in output.
|
||||
if (( is_mode_regexp )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} =~ $expected ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'regexp' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'no output line matches regular expression' \
|
||||
| fail
|
||||
elif (( is_mode_partial )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} == *"$expected"* ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'substring' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'no output line contains substring' \
|
||||
| fail
|
||||
else
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
[[ ${lines[$idx]} == "$expected" ]] && return 0
|
||||
done
|
||||
{ local -ar single=( 'line' "$expected" )
|
||||
local -ar may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}"
|
||||
} \
|
||||
| batslib_decorate 'output does not contain line' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
# assert_not_equal
|
||||
# ============
|
||||
#
|
||||
# Summary: Fail if the actual and unexpected values are equal.
|
||||
#
|
||||
# Usage: assert_not_equal <actual> <unexpected>
|
||||
#
|
||||
# Options:
|
||||
# <actual> The value being compared.
|
||||
# <unexpected> The value to compare against.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_not_equal()' {
|
||||
# assert_not_equal 'foo' 'foo'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# IO:
|
||||
# STDERR - expected and actual values, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if actual does not equal unexpected
|
||||
# 1 - otherwise
|
||||
#
|
||||
# On failure, the unexpected and actual values are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- values should not be equal --
|
||||
# unexpected : foo
|
||||
# actual : foo
|
||||
# --
|
||||
# ```
|
||||
assert_not_equal() {
|
||||
if [[ "$1" == "$2" ]]; then
|
||||
batslib_print_kv_single_or_multi 10 \
|
||||
'unexpected' "$2" \
|
||||
'actual' "$1" \
|
||||
| batslib_decorate 'values should not be equal' \
|
||||
| fail
|
||||
fi
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
# assert_output
|
||||
# =============
|
||||
#
|
||||
# Summary: Fail if `$output' does not match the expected output.
|
||||
#
|
||||
# Usage: assert_output [-p | -e] [- | [--] <expected>]
|
||||
#
|
||||
# Options:
|
||||
# -p, --partial Match if `expected` is a substring of `$output`
|
||||
# -e, --regexp Treat `expected` as an extended regular expression
|
||||
# -, --stdin Read `expected` value from STDIN
|
||||
# <expected> The expected value, substring or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDIN - [=$1] expected output
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if output matches the expected value/partial/regexp
|
||||
# 1 - otherwise
|
||||
#
|
||||
# This function verifies that a command or function produces the expected output.
|
||||
# (It is the logical complement of `refute_output`.)
|
||||
# Output matching can be literal (the default), partial or by regular expression.
|
||||
# The expected output can be specified either by positional argument or read from STDIN by passing the `-`/`--stdin` flag.
|
||||
#
|
||||
# ## Literal matching
|
||||
#
|
||||
# By default, literal matching is performed.
|
||||
# The assertion fails if `$output` does not equal the expected output.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output()' {
|
||||
# run echo 'have'
|
||||
# assert_output 'want'
|
||||
# }
|
||||
#
|
||||
# @test 'assert_output() with pipe' {
|
||||
# run echo 'hello'
|
||||
# echo 'hello' | assert_output -
|
||||
# }
|
||||
#
|
||||
# @test 'assert_output() with herestring' {
|
||||
# run echo 'hello'
|
||||
# assert_output - <<< hello
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the expected and actual output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output differs --
|
||||
# expected : want
|
||||
# actual : have
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Existence
|
||||
#
|
||||
# To assert that any output exists at all, omit the `expected` argument.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output()' {
|
||||
# run echo 'have'
|
||||
# assert_output
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, an error message is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- no output --
|
||||
# expected non-empty output, but output was empty
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, the assertion fails if the expected _substring_ is not found in `$output`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output() partial matching' {
|
||||
# run echo 'ERROR: no such file or directory'
|
||||
# assert_output --partial 'SUCCESS'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the substring and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output does not contain substring --
|
||||
# substring : SUCCESS
|
||||
# output : ERROR: no such file or directory
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, the assertion fails if the *extended regular expression* does not match `$output`.
|
||||
#
|
||||
# *__Note__:
|
||||
# The anchors `^` and `$` bind to the beginning and the end (respectively) of the entire output;
|
||||
# not individual lines.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_output() regular expression matching' {
|
||||
# run echo 'Foobar 0.1.0'
|
||||
# assert_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the regular expression and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression does not match output --
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# output : Foobar 0.1.0
|
||||
# --
|
||||
# ```
|
||||
assert_output() {
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
local -i is_mode_nonempty=0
|
||||
local -i use_stdin=0
|
||||
: "${output?}"
|
||||
|
||||
# Handle options.
|
||||
if (( $# == 0 )); then
|
||||
is_mode_nonempty=1
|
||||
fi
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
-|--stdin) use_stdin=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: assert_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local expected
|
||||
if (( use_stdin )); then
|
||||
expected="$(cat -)"
|
||||
else
|
||||
expected="${1-}"
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_mode_nonempty )); then
|
||||
if [ -z "$output" ]; then
|
||||
echo 'expected non-empty output, but output was empty' \
|
||||
| batslib_decorate 'no output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_regexp )); then
|
||||
if [[ '' =~ $expected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$expected'" \
|
||||
| batslib_decorate 'ERROR: assert_output' \
|
||||
| fail
|
||||
elif ! [[ $output =~ $expected ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'regexp' "$expected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'regular expression does not match output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ $output != *"$expected"* ]]; then
|
||||
batslib_print_kv_single_or_multi 9 \
|
||||
'substring' "$expected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output does not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ $output != "$expected" ]]; then
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'expected' "$expected" \
|
||||
'actual' "$output" \
|
||||
| batslib_decorate 'output differs' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
# `assert_regex`
|
||||
#
|
||||
# This function is similar to `assert_equal` but uses pattern matching instead
|
||||
# of equality, by wrapping `[[ value =~ pattern ]]`.
|
||||
#
|
||||
# Fail if the value (first parameter) does not match the pattern (second
|
||||
# parameter).
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_regex()' {
|
||||
# assert_regex 'what' 'x$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the value and the pattern are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- values does not match regular expression --
|
||||
# value : what
|
||||
# pattern : x$
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# If the value is longer than one line then it is displayed in *multi-line*
|
||||
# format.
|
||||
#
|
||||
# An error is displayed if the specified extended regular expression is invalid.
|
||||
#
|
||||
# For description of the matching behavior, refer to the documentation of the
|
||||
# `=~` operator in the
|
||||
# [Bash manual]: https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html.
|
||||
# Note that the `BASH_REMATCH` array is available immediately after the
|
||||
# assertion succeeds but is fragile, i.e. prone to being overwritten as a side
|
||||
# effect of other actions.
|
||||
assert_regex() {
|
||||
local -r value="${1}"
|
||||
local -r pattern="${2}"
|
||||
|
||||
if [[ '' =~ ${pattern} ]] || (( ${?} == 2 )); then
|
||||
echo "Invalid extended regular expression: \`${pattern}'" \
|
||||
| batslib_decorate 'ERROR: assert_regex' \
|
||||
| fail
|
||||
elif ! [[ "${value}" =~ ${pattern} ]]; then
|
||||
if shopt -p nocasematch &>/dev/null; then
|
||||
local case_sensitive=insensitive
|
||||
else
|
||||
local case_sensitive=sensitive
|
||||
fi
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'value' "${value}" \
|
||||
'pattern' "${pattern}" \
|
||||
'case' "${case_sensitive}" \
|
||||
| batslib_decorate 'value does not match regular expression' \
|
||||
| fail
|
||||
fi
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
# assert_success
|
||||
# ==============
|
||||
#
|
||||
# Summary: Fail if `$status` is not 0.
|
||||
#
|
||||
# Usage: assert_success
|
||||
#
|
||||
# IO:
|
||||
# STDERR - `$status` and `$output`, on failure
|
||||
# Globals:
|
||||
# status
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if `$status' is 0
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'assert_success() status only' {
|
||||
# run bash -c "echo 'Error!'; exit 1"
|
||||
# assert_success
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, `$status` and `$output` are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- command failed --
|
||||
# status : 1
|
||||
# output : Error!
|
||||
# --
|
||||
# ```
|
||||
assert_success() {
|
||||
: "${output?}"
|
||||
: "${status?}"
|
||||
|
||||
if (( status != 0 )); then
|
||||
{ local -ir width=6
|
||||
batslib_print_kv_single "$width" 'status' "$status"
|
||||
batslib_print_kv_single_or_multi "$width" 'output' "$output"
|
||||
} \
|
||||
| batslib_decorate 'command failed' \
|
||||
| fail
|
||||
fi
|
||||
}
|
42
extras/portable/test/test_helper/bats-assert/src/refute.bash
Normal file
42
extras/portable/test/test_helper/bats-assert/src/refute.bash
Normal file
@ -0,0 +1,42 @@
|
||||
# refute
|
||||
# ======
|
||||
#
|
||||
# Summary: Fail if the given expression evaluates to true.
|
||||
#
|
||||
# Usage: refute <expression>
|
||||
#
|
||||
# Options:
|
||||
# <expression> The expression to evaluate for falsiness.
|
||||
# *__Note:__ The expression must be a simple command.
|
||||
# [Compound commands](https://www.gnu.org/software/bash/manual/bash.html#Compound-Commands),
|
||||
# such as `[[`, can be used only when executed with `bash -c`.*
|
||||
#
|
||||
# IO:
|
||||
# STDERR - the successful expression, on failure
|
||||
# Globals:
|
||||
# none
|
||||
# Returns:
|
||||
# 0 - if expression evaluates to false
|
||||
# 1 - otherwise
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute()' {
|
||||
# rm -f '/var/log/test.log'
|
||||
# refute [ -e '/var/log/test.log' ]
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the successful expression is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- assertion succeeded, but it was expected to fail --
|
||||
# expression : [ -e /var/log/test.log ]
|
||||
# --
|
||||
# ```
|
||||
refute() {
|
||||
if "$@"; then
|
||||
batslib_print_kv_single 10 'expression' "$*" \
|
||||
| batslib_decorate 'assertion succeeded, but it was expected to fail' \
|
||||
| fail
|
||||
fi
|
||||
}
|
@ -0,0 +1,271 @@
|
||||
# refute_line
|
||||
# ===========
|
||||
#
|
||||
# Summary: Fail if the unexpected line is found in the output (default) or at a specific line number.
|
||||
#
|
||||
# Usage: refute_line [-n index] [-p | -e] [--] <unexpected>
|
||||
#
|
||||
# Options:
|
||||
# -n, --index <idx> Match the <idx>th line
|
||||
# -p, --partial Match if `unexpected` is a substring of `$output` or line <idx>
|
||||
# -e, --regexp Treat `unexpected` as an extended regular expression
|
||||
# <unexpected> The unexpected line string, substring, or regular expression.
|
||||
#
|
||||
# IO:
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# lines
|
||||
# Returns:
|
||||
# 0 - if match not found
|
||||
# 1 - otherwise
|
||||
#
|
||||
# Similarly to `refute_output`, this function verifies that a command or function does not produce the unexpected output.
|
||||
# (It is the logical complement of `assert_line`.)
|
||||
# It checks that the unexpected line does not appear in the output (default) or at a specific line number.
|
||||
# Matching can be literal (default), partial or regular expression.
|
||||
#
|
||||
# *__Warning:__
|
||||
# Due to a [bug in Bats][bats-93], empty lines are discarded from `${lines[@]}`,
|
||||
# causing line indices to change and preventing testing for empty lines.*
|
||||
#
|
||||
# [bats-93]: https://github.com/sstephenson/bats/pull/93
|
||||
#
|
||||
# ## Looking for a line in the output
|
||||
#
|
||||
# By default, the entire output is searched for the unexpected line.
|
||||
# The assertion fails if the unexpected line is found in `${lines[@]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() looking for line' {
|
||||
# run echo $'have-0\nwant\nhave-2'
|
||||
# refute_line 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the unexpected line, the index of its first match and the output with the matching line highlighted are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line should not be in output --
|
||||
# line : want
|
||||
# index : 1
|
||||
# output (3 lines):
|
||||
# have-0
|
||||
# > want
|
||||
# have-2
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Matching a specific line
|
||||
#
|
||||
# When the `--index <idx>` option is used (`-n <idx>` for short), the unexpected line is matched only against the line identified by the given index.
|
||||
# The assertion fails if the unexpected line equals `${lines[<idx>]}`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() specific line' {
|
||||
# run echo $'have-0\nwant-1\nhave-2'
|
||||
# refute_line --index 1 'want-1'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the index and the unexpected line are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- line should differ --
|
||||
# index : 1
|
||||
# line : want-1
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, a match fails if the unexpected *substring* is found in the matched line.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() partial matching' {
|
||||
# run echo $'have 1\nwant 2\nhave 3'
|
||||
# refute_line --partial 'want'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, in addition to the details of literal matching, the substring is also displayed.
|
||||
# When used with `--index <idx>` the substring replaces the unexpected line.
|
||||
#
|
||||
# ```
|
||||
# -- no line should contain substring --
|
||||
# substring : want
|
||||
# index : 1
|
||||
# output (3 lines):
|
||||
# have 1
|
||||
# > want 2
|
||||
# have 3
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, a match fails if the *extended regular expression* matches the line being tested.
|
||||
#
|
||||
# *__Note__:
|
||||
# As expected, the anchors `^` and `$` bind to the beginning and the end (respectively) of the matched line.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_line() regular expression matching' {
|
||||
# run echo $'Foobar v0.1.0\nRelease date: 2015-11-29'
|
||||
# refute_line --index 0 --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, in addition to the details of literal matching, the regular expression is also displayed.
|
||||
# When used with `--index <idx>` the regular expression replaces the unexpected line.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression should not match line --
|
||||
# index : 0
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# line : Foobar v0.1.0
|
||||
# --
|
||||
# ```
|
||||
# FIXME(ztombol): Display `${lines[@]}' instead of `$output'!
|
||||
refute_line() {
|
||||
local -i is_match_line=0
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
: "${lines?}"
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-n|--index)
|
||||
if (( $# < 2 )) || ! [[ $2 =~ ^-?([0-9]|[1-9][0-9]+)$ ]]; then
|
||||
echo "\`--index' requires an integer argument: \`$2'" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
is_match_line=1
|
||||
local -ri idx="$2"
|
||||
shift 2
|
||||
;;
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local -r unexpected="$1"
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$unexpected'" \
|
||||
| batslib_decorate 'ERROR: refute_line' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_match_line )); then
|
||||
# Specific line.
|
||||
if (( is_mode_regexp )); then
|
||||
if [[ ${lines[$idx]} =~ $unexpected ]]; then
|
||||
batslib_print_kv_single 6 \
|
||||
'index' "$idx" \
|
||||
'regexp' "$unexpected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'regular expression should not match line' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ ${lines[$idx]} == *"$unexpected"* ]]; then
|
||||
batslib_print_kv_single 9 \
|
||||
'index' "$idx" \
|
||||
'substring' "$unexpected" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line should not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ ${lines[$idx]} == "$unexpected" ]]; then
|
||||
batslib_print_kv_single 5 \
|
||||
'index' "$idx" \
|
||||
'line' "${lines[$idx]}" \
|
||||
| batslib_decorate 'line should differ' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Line contained in output.
|
||||
if (( is_mode_regexp )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} =~ $unexpected ]]; then
|
||||
{ local -ar single=( 'regexp' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'no line should match the regular expression' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
elif (( is_mode_partial )); then
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} == *"$unexpected"* ]]; then
|
||||
{ local -ar single=( 'substring' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'no line should contain substring' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
else
|
||||
local -i idx
|
||||
for (( idx = 0; idx < ${#lines[@]}; ++idx )); do
|
||||
if [[ ${lines[$idx]} == "$unexpected" ]]; then
|
||||
{ local -ar single=( 'line' "$unexpected" 'index' "$idx" )
|
||||
local -a may_be_multi=( 'output' "$output" )
|
||||
local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )"
|
||||
batslib_print_kv_single "$width" "${single[@]}"
|
||||
if batslib_is_single_line "${may_be_multi[1]}"; then
|
||||
batslib_print_kv_single "$width" "${may_be_multi[@]}"
|
||||
else
|
||||
may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )"
|
||||
batslib_print_kv_multi "${may_be_multi[@]}"
|
||||
fi
|
||||
} \
|
||||
| batslib_decorate 'line should not be in output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
# refute_output
|
||||
# =============
|
||||
#
|
||||
# Summary: Fail if `$output' matches the unexpected output.
|
||||
#
|
||||
# Usage: refute_output [-p | -e] [- | [--] <unexpected>]
|
||||
#
|
||||
# Options:
|
||||
# -p, --partial Match if `unexpected` is a substring of `$output`
|
||||
# -e, --regexp Treat `unexpected` as an extended regular expression
|
||||
# -, --stdin Read `unexpected` value from STDIN
|
||||
# <unexpected> The unexpected value, substring, or regular expression
|
||||
#
|
||||
# IO:
|
||||
# STDIN - [=$1] unexpected output
|
||||
# STDERR - details, on failure
|
||||
# error message, on error
|
||||
# Globals:
|
||||
# output
|
||||
# Returns:
|
||||
# 0 - if output matches the unexpected value/partial/regexp
|
||||
# 1 - otherwise
|
||||
#
|
||||
# This function verifies that a command or function does not produce the unexpected output.
|
||||
# (It is the logical complement of `assert_output`.)
|
||||
# Output matching can be literal (the default), partial or by regular expression.
|
||||
# The unexpected output can be specified either by positional argument or read from STDIN by passing the `-`/`--stdin` flag.
|
||||
#
|
||||
# ## Literal matching
|
||||
#
|
||||
# By default, literal matching is performed.
|
||||
# The assertion fails if `$output` equals the unexpected output.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output()' {
|
||||
# run echo 'want'
|
||||
# refute_output 'want'
|
||||
# }
|
||||
#
|
||||
# @test 'refute_output() with pipe' {
|
||||
# run echo 'hello'
|
||||
# echo 'world' | refute_output -
|
||||
# }
|
||||
#
|
||||
# @test 'refute_output() with herestring' {
|
||||
# run echo 'hello'
|
||||
# refute_output - <<< world
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the output is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output equals, but it was expected to differ --
|
||||
# output : want
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Existence
|
||||
#
|
||||
# To assert that there is no output at all, omit the matching argument.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output()' {
|
||||
# run foo --silent
|
||||
# refute_output
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, an error message is displayed.
|
||||
#
|
||||
# ```
|
||||
# -- unexpected output --
|
||||
# expected no output, but output was non-empty
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Partial matching
|
||||
#
|
||||
# Partial matching can be enabled with the `--partial` option (`-p` for short).
|
||||
# When used, the assertion fails if the unexpected _substring_ is found in `$output`.
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output() partial matching' {
|
||||
# run echo 'ERROR: no such file or directory'
|
||||
# refute_output --partial 'ERROR'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the substring and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- output should not contain substring --
|
||||
# substring : ERROR
|
||||
# output : ERROR: no such file or directory
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# ## Regular expression matching
|
||||
#
|
||||
# Regular expression matching can be enabled with the `--regexp` option (`-e` for short).
|
||||
# When used, the assertion fails if the *extended regular expression* matches `$output`.
|
||||
#
|
||||
# *__Note__:
|
||||
# The anchors `^` and `$` bind to the beginning and the end (respectively) of the entire output;
|
||||
# not individual lines.*
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_output() regular expression matching' {
|
||||
# run echo 'Foobar v0.1.0'
|
||||
# refute_output --regexp '^Foobar v[0-9]+\.[0-9]+\.[0-9]$'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the regular expression and the output are displayed.
|
||||
#
|
||||
# ```
|
||||
# -- regular expression should not match output --
|
||||
# regexp : ^Foobar v[0-9]+\.[0-9]+\.[0-9]$
|
||||
# output : Foobar v0.1.0
|
||||
# --
|
||||
# ```
|
||||
refute_output() {
|
||||
local -i is_mode_partial=0
|
||||
local -i is_mode_regexp=0
|
||||
local -i is_mode_empty=0
|
||||
local -i use_stdin=0
|
||||
: "${output?}"
|
||||
|
||||
# Handle options.
|
||||
if (( $# == 0 )); then
|
||||
is_mode_empty=1
|
||||
fi
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-p|--partial) is_mode_partial=1; shift ;;
|
||||
-e|--regexp) is_mode_regexp=1; shift ;;
|
||||
-|--stdin) use_stdin=1; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if (( is_mode_partial )) && (( is_mode_regexp )); then
|
||||
echo "\`--partial' and \`--regexp' are mutually exclusive" \
|
||||
| batslib_decorate 'ERROR: refute_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Arguments.
|
||||
local unexpected
|
||||
if (( use_stdin )); then
|
||||
unexpected="$(cat -)"
|
||||
else
|
||||
unexpected="${1-}"
|
||||
fi
|
||||
|
||||
if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then
|
||||
echo "Invalid extended regular expression: \`$unexpected'" \
|
||||
| batslib_decorate 'ERROR: refute_output' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Matching.
|
||||
if (( is_mode_empty )); then
|
||||
if [ -n "$output" ]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output non-empty, but expected no output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_regexp )); then
|
||||
if [[ $output =~ $unexpected ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'regexp' "$unexpected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'regular expression should not match output' \
|
||||
| fail
|
||||
fi
|
||||
elif (( is_mode_partial )); then
|
||||
if [[ $output == *"$unexpected"* ]]; then
|
||||
batslib_print_kv_single_or_multi 9 \
|
||||
'substring' "$unexpected" \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output should not contain substring' \
|
||||
| fail
|
||||
fi
|
||||
else
|
||||
if [[ $output == "$unexpected" ]]; then
|
||||
batslib_print_kv_single_or_multi 6 \
|
||||
'output' "$output" \
|
||||
| batslib_decorate 'output equals, but it was expected to differ' \
|
||||
| fail
|
||||
fi
|
||||
fi
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
# `refute_regex`
|
||||
#
|
||||
# This function is similar to `refute_equal` but uses pattern matching instead
|
||||
# of equality, by wrapping `! [[ value =~ pattern ]]`.
|
||||
#
|
||||
# Fail if the value (first parameter) matches the pattern (second parameter).
|
||||
#
|
||||
# ```bash
|
||||
# @test 'refute_regex()' {
|
||||
# refute_regex 'WhatsApp' 'Threema'
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# On failure, the value, the pattern and the match are displayed.
|
||||
#
|
||||
# ```
|
||||
# @test 'refute_regex()' {
|
||||
# refute_regex 'WhatsApp' 'What.'
|
||||
# }
|
||||
#
|
||||
# -- value matches regular expression --
|
||||
# value : WhatsApp
|
||||
# pattern : What.
|
||||
# match : Whats
|
||||
# case : sensitive
|
||||
# --
|
||||
# ```
|
||||
#
|
||||
# If the value or pattern is longer than one line then it is displayed in
|
||||
# *multi-line* format.
|
||||
#
|
||||
# An error is displayed if the specified extended regular expression is invalid.
|
||||
#
|
||||
# For description of the matching behavior, refer to the documentation of the
|
||||
# `=~` operator in the
|
||||
# [Bash manual]: https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html.
|
||||
#
|
||||
# Note that the `BASH_REMATCH` array is available immediately after the
|
||||
# assertion fails but is fragile, i.e. prone to being overwritten as a side
|
||||
# effect of other actions like calling `run`. Thus, it's good practice to avoid
|
||||
# using `BASH_REMATCH` in conjunction with `refute_regex()`. The valuable
|
||||
# information the array contains is the matching part of the value which is
|
||||
# printed in the failing test log, as mentioned above.
|
||||
refute_regex() {
|
||||
local -r value="${1}"
|
||||
local -r pattern="${2}"
|
||||
|
||||
if [[ '' =~ ${pattern} ]] || (( ${?} == 2 )); then
|
||||
echo "Invalid extended regular expression: \`${pattern}'" \
|
||||
| batslib_decorate 'ERROR: refute_regex' \
|
||||
| fail
|
||||
elif [[ "${value}" =~ ${pattern} ]]; then
|
||||
if shopt -p nocasematch &>/dev/null; then
|
||||
local case_sensitive=insensitive
|
||||
else
|
||||
local case_sensitive=sensitive
|
||||
fi
|
||||
batslib_print_kv_single_or_multi 8 \
|
||||
'value' "${value}" \
|
||||
'pattern' "${pattern}" \
|
||||
'match' "${BASH_REMATCH[0]}" \
|
||||
'case' "${case_sensitive}" \
|
||||
| batslib_decorate 'value matches regular expression' \
|
||||
| fail
|
||||
fi
|
||||
}
|
2
extras/portable/test/test_helper/bats-file/load.bash
Normal file
2
extras/portable/test/test_helper/bats-file/load.bash
Normal file
@ -0,0 +1,2 @@
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/file.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/temp.bash"
|
1111
extras/portable/test/test_helper/bats-file/src/file.bash
Normal file
1111
extras/portable/test/test_helper/bats-file/src/file.bash
Normal file
File diff suppressed because it is too large
Load Diff
182
extras/portable/test/test_helper/bats-file/src/temp.bash
Executable file
182
extras/portable/test/test_helper/bats-file/src/temp.bash
Executable file
@ -0,0 +1,182 @@
|
||||
#
|
||||
# bats-file - Common filesystem assertions and helpers for Bats
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
|
||||
#
|
||||
# temp.bash
|
||||
# ---------
|
||||
#
|
||||
# Functions for handling temporary directories.
|
||||
#
|
||||
|
||||
# Create a temporary directory for the current test in `BATS_TMPDIR`,
|
||||
# and display its path on the standard output.
|
||||
#
|
||||
# The directory name is derived from the test's filename and number, and
|
||||
# a random string for uniqueness.
|
||||
#
|
||||
# <test-filename>-<test-number>-<random-string>
|
||||
#
|
||||
# When `--prefix <prefix>' is specified, `<prefix>' is prepended to the
|
||||
# directory name.
|
||||
#
|
||||
# <prefix><test-filename>-<test-number>-<random-string>
|
||||
#
|
||||
# Must be called from `setup', `@test' or `teardown'.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# setup() {
|
||||
# TEST_TEMP_DIR="$(temp_make --prefix 'myapp-')"
|
||||
# }
|
||||
#
|
||||
# teardown() {
|
||||
# temp_del "$TEST_TEMP_DIR"
|
||||
# }
|
||||
#
|
||||
# Globals:
|
||||
# BATS_TEST_NAME
|
||||
# BATS_TEST_FILENAME
|
||||
# BATS_TEST_NUMBER
|
||||
# BATS_TMPDIR
|
||||
# Arguments:
|
||||
# none
|
||||
# Options:
|
||||
# -p, --prefix <prefix> - prefix the directory name with `<prefix>'
|
||||
# Returns:
|
||||
# 0 - on success
|
||||
# 1 - otherwise
|
||||
# Outputs:
|
||||
# STDOUT - path of temporary directory
|
||||
# STDERR - error messages
|
||||
temp_make() {
|
||||
# Check caller.
|
||||
if ! ( batslib_is_caller --indirect 'setup' \
|
||||
|| batslib_is_caller --indirect 'setup_file' \
|
||||
|| batslib_is_caller --indirect "$BATS_TEST_NAME" \
|
||||
|| batslib_is_caller --indirect 'teardown' \
|
||||
|| batslib_is_caller --indirect 'teardown_file' )
|
||||
then
|
||||
echo "Must be called from \`setup', \`@test' or \`teardown'" \
|
||||
| batslib_decorate 'ERROR: temp_make' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Handle options.
|
||||
local prefix=''
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-p|--prefix)
|
||||
if (( $# < 2 )); then
|
||||
echo "\`--prefix' requires an argument" \
|
||||
| batslib_decorate 'ERROR: temp_make' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
prefix="$2"
|
||||
shift 2
|
||||
;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Create directory.
|
||||
local template="$prefix"
|
||||
template+="${BATS_TEST_FILENAME##*/}"
|
||||
template+="-${BATS_TEST_NUMBER}"
|
||||
template+='-XXXXXXXXXX'
|
||||
|
||||
local path
|
||||
path="$(mktemp -d -- "${BATS_TMPDIR}/${template}" 2>&1)"
|
||||
if (( $? )); then
|
||||
echo "$path" \
|
||||
| batslib_decorate 'ERROR: temp_make' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
echo "$path"
|
||||
}
|
||||
|
||||
# Delete a temporary directory, typically created with `temp_make', and
|
||||
# its contents.
|
||||
#
|
||||
# Note: Actually, this function can be used to delete any file or
|
||||
# directory. However, it is most useful in deleting temporary
|
||||
# directories created with `temp_make', hence the naming.
|
||||
#
|
||||
# For development and debugging, deletion can be prevented using
|
||||
# environment variables.
|
||||
#
|
||||
# When `BATSLIB_TEMP_PRESERVE' is set to 1, the function succeeds but
|
||||
# the directory is not deleted.
|
||||
#
|
||||
# When `BATSLIB_TEMP_PRESERVE_ON_FAILURE' is set to 1 and `temp_del' is
|
||||
# called, directly or indirectly, from `teardown', the function succeeds
|
||||
# but the directory is not deleted if the test has failed.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# setup() {
|
||||
# TEST_TEMP_DIR="$(temp_make --prefix 'myapp-')"
|
||||
# }
|
||||
#
|
||||
# teardown() {
|
||||
# temp_del "$TEST_TEMP_DIR"
|
||||
# }
|
||||
#
|
||||
# Globals:
|
||||
# BATSLIB_TEMP_PRESERVE
|
||||
# BATSLIB_TEMP_PRESERVE_ON_FAILURE
|
||||
# BATS_TEST_COMPLETED
|
||||
# Arguments:
|
||||
# $1 - path of directory
|
||||
# Returns:
|
||||
# 0 - on success
|
||||
# 1 - otherwise
|
||||
# Outputs:
|
||||
# STDERR - error messages
|
||||
temp_del() {
|
||||
local -r path="$1"
|
||||
|
||||
# Environment variables.
|
||||
if [[ ${BATSLIB_TEMP_PRESERVE-} == '1' ]]; then
|
||||
return 0
|
||||
elif [[ ${BATSLIB_TEMP_PRESERVE_ON_FAILURE-} == '1' ]]; then
|
||||
# Check caller.
|
||||
if ! ( batslib_is_caller --indirect 'teardown' \
|
||||
|| batslib_is_caller --indirect 'teardown_file' )
|
||||
then
|
||||
echo "Must be called from \`teardown' or \`teardown_file' when using \`BATSLIB_TEMP_PRESERVE_ON_FAILURE'" \
|
||||
| batslib_decorate 'ERROR: temp_del' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
|
||||
(( ${BATS_TEST_COMPLETED:-0} != 1 )) && return 0
|
||||
fi
|
||||
|
||||
# Delete directory.
|
||||
local result
|
||||
result="$(rm -r -- "$path" 2>&1 </dev/null)"
|
||||
if (( $? )); then
|
||||
echo "$result" \
|
||||
| batslib_decorate 'ERROR: temp_del' \
|
||||
| fail
|
||||
return $?
|
||||
fi
|
||||
}
|
3
extras/portable/test/test_helper/bats-support/load.bash
Normal file
3
extras/portable/test/test_helper/bats-support/load.bash
Normal file
@ -0,0 +1,3 @@
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/output.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/error.bash"
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/src/lang.bash"
|
41
extras/portable/test/test_helper/bats-support/src/error.bash
Normal file
41
extras/portable/test/test_helper/bats-support/src/error.bash
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# bats-support - Supporting library for Bats test helpers
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
|
||||
#
|
||||
# error.bash
|
||||
# ----------
|
||||
#
|
||||
# Functions implementing error reporting. Used by public helper
|
||||
# functions or test suits directly.
|
||||
#
|
||||
|
||||
# Fail and display a message. When no parameters are specified, the
|
||||
# message is read from the standard input. Other functions use this to
|
||||
# report failure.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $@ - [=STDIN] message
|
||||
# Returns:
|
||||
# 1 - always
|
||||
# Inputs:
|
||||
# STDIN - [=$@] message
|
||||
# Outputs:
|
||||
# STDERR - message
|
||||
fail() {
|
||||
(( $# == 0 )) && batslib_err || batslib_err "$@"
|
||||
return 1
|
||||
}
|
73
extras/portable/test/test_helper/bats-support/src/lang.bash
Normal file
73
extras/portable/test/test_helper/bats-support/src/lang.bash
Normal file
@ -0,0 +1,73 @@
|
||||
#
|
||||
# bats-util - Various auxiliary functions for Bats
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
|
||||
#
|
||||
# lang.bash
|
||||
# ---------
|
||||
#
|
||||
# Bash language and execution related functions. Used by public helper
|
||||
# functions.
|
||||
#
|
||||
|
||||
# Check whether the calling function was called from a given function.
|
||||
#
|
||||
# By default, direct invocation is checked. The function succeeds if the
|
||||
# calling function was called directly from the given function. In other
|
||||
# words, if the given function is the next element on the call stack.
|
||||
#
|
||||
# When `--indirect' is specified, indirect invocation is checked. The
|
||||
# function succeeds if the calling function was called from the given
|
||||
# function with any number of intermediate calls. In other words, if the
|
||||
# given function can be found somewhere on the call stack.
|
||||
#
|
||||
# Direct invocation is a form of indirect invocation with zero
|
||||
# intermediate calls.
|
||||
#
|
||||
# Globals:
|
||||
# FUNCNAME
|
||||
# Options:
|
||||
# -i, --indirect - check indirect invocation
|
||||
# Arguments:
|
||||
# $1 - calling function's name
|
||||
# Returns:
|
||||
# 0 - current function was called from the given function
|
||||
# 1 - otherwise
|
||||
batslib_is_caller() {
|
||||
local -i is_mode_direct=1
|
||||
|
||||
# Handle options.
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
-i|--indirect) is_mode_direct=0; shift ;;
|
||||
--) shift; break ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Arguments.
|
||||
local -r func="$1"
|
||||
|
||||
# Check call stack.
|
||||
if (( is_mode_direct )); then
|
||||
[[ $func == "${FUNCNAME[2]}" ]] && return 0
|
||||
else
|
||||
local -i depth
|
||||
for (( depth=2; depth<${#FUNCNAME[@]}; ++depth )); do
|
||||
[[ $func == "${FUNCNAME[$depth]}" ]] && return 0
|
||||
done
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
279
extras/portable/test/test_helper/bats-support/src/output.bash
Normal file
279
extras/portable/test/test_helper/bats-support/src/output.bash
Normal file
@ -0,0 +1,279 @@
|
||||
#
|
||||
# bats-support - Supporting library for Bats test helpers
|
||||
#
|
||||
# Written in 2016 by Zoltan Tombol <zoltan dot tombol at gmail dot com>
|
||||
#
|
||||
# To the extent possible under law, the author(s) have dedicated all
|
||||
# copyright and related and neighboring rights to this software to the
|
||||
# public domain worldwide. This software is distributed without any
|
||||
# warranty.
|
||||
#
|
||||
# You should have received a copy of the CC0 Public Domain Dedication
|
||||
# along with this software. If not, see
|
||||
# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
#
|
||||
|
||||
#
|
||||
# output.bash
|
||||
# -----------
|
||||
#
|
||||
# Private functions implementing output formatting. Used by public
|
||||
# helper functions.
|
||||
#
|
||||
|
||||
# Print a message to the standard error. When no parameters are
|
||||
# specified, the message is read from the standard input.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $@ - [=STDIN] message
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - [=$@] message
|
||||
# Outputs:
|
||||
# STDERR - message
|
||||
batslib_err() {
|
||||
{ if (( $# > 0 )); then
|
||||
echo "$@"
|
||||
else
|
||||
cat -
|
||||
fi
|
||||
} >&2
|
||||
}
|
||||
|
||||
# Count the number of lines in the given string.
|
||||
#
|
||||
# TODO(ztombol): Fix tests and remove this note after #93 is resolved!
|
||||
# NOTE: Due to a bug in Bats, `batslib_count_lines "$output"' does not
|
||||
# give the same result as `${#lines[@]}' when the output contains
|
||||
# empty lines.
|
||||
# See PR #93 (https://github.com/sstephenson/bats/pull/93).
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - string
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - number of lines
|
||||
batslib_count_lines() {
|
||||
local -i n_lines=0
|
||||
local line
|
||||
while IFS='' read -r line || [[ -n $line ]]; do
|
||||
(( ++n_lines ))
|
||||
done < <(printf '%s' "$1")
|
||||
echo "$n_lines"
|
||||
}
|
||||
|
||||
# Determine whether all strings are single-line.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $@ - strings
|
||||
# Returns:
|
||||
# 0 - all strings are single-line
|
||||
# 1 - otherwise
|
||||
batslib_is_single_line() {
|
||||
for string in "$@"; do
|
||||
(( $(batslib_count_lines "$string") > 1 )) && return 1
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# Determine the length of the longest key that has a single-line value.
|
||||
#
|
||||
# This function is useful in determining the correct width of the key
|
||||
# column in two-column format when some keys may have multi-line values
|
||||
# and thus should be excluded.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $odd - key
|
||||
# $even - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - length of longest key
|
||||
batslib_get_max_single_line_key_width() {
|
||||
local -i max_len=-1
|
||||
while (( $# != 0 )); do
|
||||
local -i key_len="${#1}"
|
||||
batslib_is_single_line "$2" && (( key_len > max_len )) && max_len="$key_len"
|
||||
shift 2
|
||||
done
|
||||
echo "$max_len"
|
||||
}
|
||||
|
||||
# Print key-value pairs in two-column format.
|
||||
#
|
||||
# Keys are displayed in the first column, and their corresponding values
|
||||
# in the second. To evenly line up values, the key column is fixed-width
|
||||
# and its width is specified with the first parameter (possibly computed
|
||||
# using `batslib_get_max_single_line_key_width').
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - width of key column
|
||||
# $even - key
|
||||
# $odd - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - formatted key-value pairs
|
||||
batslib_print_kv_single() {
|
||||
local -ir col_width="$1"; shift
|
||||
while (( $# != 0 )); do
|
||||
printf '%-*s : %s\n' "$col_width" "$1" "$2"
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
# Print key-value pairs in multi-line format.
|
||||
#
|
||||
# The key is displayed first with the number of lines of its
|
||||
# corresponding value in parenthesis. Next, starting on the next line,
|
||||
# the value is displayed. For better readability, it is recommended to
|
||||
# indent values using `batslib_prefix'.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $odd - key
|
||||
# $even - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - formatted key-value pairs
|
||||
batslib_print_kv_multi() {
|
||||
while (( $# != 0 )); do
|
||||
printf '%s (%d lines):\n' "$1" "$( batslib_count_lines "$2" )"
|
||||
printf '%s\n' "$2"
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
# Print all key-value pairs in either two-column or multi-line format
|
||||
# depending on whether all values are single-line.
|
||||
#
|
||||
# If all values are single-line, print all pairs in two-column format
|
||||
# with the specified key column width (identical to using
|
||||
# `batslib_print_kv_single').
|
||||
#
|
||||
# Otherwise, print all pairs in multi-line format after indenting values
|
||||
# with two spaces for readability (identical to using `batslib_prefix'
|
||||
# and `batslib_print_kv_multi')
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - width of key column (for two-column format)
|
||||
# $even - key
|
||||
# $odd - value of the previous key
|
||||
# Returns:
|
||||
# none
|
||||
# Outputs:
|
||||
# STDOUT - formatted key-value pairs
|
||||
batslib_print_kv_single_or_multi() {
|
||||
local -ir width="$1"; shift
|
||||
local -a pairs=( "$@" )
|
||||
|
||||
local -a values=()
|
||||
local -i i
|
||||
for (( i=1; i < ${#pairs[@]}; i+=2 )); do
|
||||
values+=( "${pairs[$i]}" )
|
||||
done
|
||||
|
||||
if batslib_is_single_line "${values[@]}"; then
|
||||
batslib_print_kv_single "$width" "${pairs[@]}"
|
||||
else
|
||||
local -i i
|
||||
for (( i=1; i < ${#pairs[@]}; i+=2 )); do
|
||||
pairs[$i]="$( batslib_prefix < <(printf '%s' "${pairs[$i]}") )"
|
||||
done
|
||||
batslib_print_kv_multi "${pairs[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Prefix each line read from the standard input with the given string.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - [= ] prefix string
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - lines
|
||||
# Outputs:
|
||||
# STDOUT - prefixed lines
|
||||
batslib_prefix() {
|
||||
local -r prefix="${1:- }"
|
||||
local line
|
||||
while IFS='' read -r line || [[ -n $line ]]; do
|
||||
printf '%s%s\n' "$prefix" "$line"
|
||||
done
|
||||
}
|
||||
|
||||
# Mark select lines of the text read from the standard input by
|
||||
# overwriting their beginning with the given string.
|
||||
#
|
||||
# Usually the input is indented by a few spaces using `batslib_prefix'
|
||||
# first.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - marking string
|
||||
# $@ - indices (zero-based) of lines to mark
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - lines
|
||||
# Outputs:
|
||||
# STDOUT - lines after marking
|
||||
batslib_mark() {
|
||||
local -r symbol="$1"; shift
|
||||
# Sort line numbers.
|
||||
set -- $( sort -nu <<< "$( printf '%d\n' "$@" )" )
|
||||
|
||||
local line
|
||||
local -i idx=0
|
||||
while IFS='' read -r line || [[ -n $line ]]; do
|
||||
if (( ${1:--1} == idx )); then
|
||||
printf '%s\n' "${symbol}${line:${#symbol}}"
|
||||
shift
|
||||
else
|
||||
printf '%s\n' "$line"
|
||||
fi
|
||||
(( ++idx ))
|
||||
done
|
||||
}
|
||||
|
||||
# Enclose the input text in header and footer lines.
|
||||
#
|
||||
# The header contains the given string as title. The output is preceded
|
||||
# and followed by an additional newline to make it stand out more.
|
||||
#
|
||||
# Globals:
|
||||
# none
|
||||
# Arguments:
|
||||
# $1 - title
|
||||
# Returns:
|
||||
# none
|
||||
# Inputs:
|
||||
# STDIN - text
|
||||
# Outputs:
|
||||
# STDOUT - decorated text
|
||||
batslib_decorate() {
|
||||
echo
|
||||
echo "-- $1 --"
|
||||
cat -
|
||||
echo '--'
|
||||
echo
|
||||
}
|
403
extras/portable/tomb
Executable file
403
extras/portable/tomb
Executable file
@ -0,0 +1,403 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Tomb v3, the Crypto Undertaker portable version 3
|
||||
#
|
||||
# A commandline tool to easily operate encryption of secret data
|
||||
#
|
||||
# {{{ License
|
||||
|
||||
# Copyright (C) 2007-2022 Dyne.org Foundation
|
||||
#
|
||||
# Tomb is designed, written and maintained by Denis Roio <jaromil@dyne.org>
|
||||
#
|
||||
# Please refer to the AUTHORS file for more information.
|
||||
#
|
||||
# This source code is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This source code is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please refer
|
||||
# to the GNU Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Public License along with
|
||||
# this source code; if not, , see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# }}} - License
|
||||
|
||||
# {{{ Global variables
|
||||
|
||||
VERSION="3.1.0"
|
||||
DATE="Nov/2022"
|
||||
TOMBEXEC="$0"
|
||||
TMPDIR="${TMP:-/tmp}"
|
||||
TOMBTMPFILES=""
|
||||
PATH="${PATH}:.:/usr/local/bin"
|
||||
exitcode=0
|
||||
# }}}
|
||||
|
||||
# {{{ Logging functions
|
||||
|
||||
_success() {
|
||||
echo "[*] " "$1" "$2" "$3" "$4" 1>&2
|
||||
}
|
||||
_message() {
|
||||
echo " . " "$1" "$2" "$3" "$4" 1>&2
|
||||
}
|
||||
_warning() {
|
||||
echo "[W] " "$1" "$2" "$3" "$4" 1>&2
|
||||
}
|
||||
_verbose() {
|
||||
echo "[D] " "$1" "$2" "$3" "$4" 1>&2
|
||||
}
|
||||
_error() {
|
||||
echo "[!] " "$1" "$2" "$3" "$4" 1>&2
|
||||
exitcode=1
|
||||
}
|
||||
_failure() {
|
||||
echo "[!!] " "$1" "$2" "$3" "$4" 1>&2
|
||||
exitcode=1
|
||||
exit 1
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
_success "Starting Tomb v$VERSION"
|
||||
|
||||
# {{{ Internal functions
|
||||
|
||||
_random_string() {
|
||||
len=${1:-32}
|
||||
[ "$1" != "" ] && {
|
||||
echo "print(O.random($len):base58())" | zenroom 2>/dev/null
|
||||
}
|
||||
return $?
|
||||
}
|
||||
|
||||
_tmp_create() {
|
||||
[ -d "$TMPDIR" ] || {
|
||||
# we create the tempdir with the sticky bit on
|
||||
mkdir -m 1777 "$TMPDIR"
|
||||
[ $? = 0 ] || {
|
||||
_failure "Fatal error creating the temporary directory: %s" "$TMPDIR"
|
||||
}
|
||||
}
|
||||
tfile="${TMPDIR}/`_random_string 64`" # Temporary file
|
||||
umask 066
|
||||
[ $? = 0 ] || {
|
||||
_failure "Fatal error setting the permission umask for temporary files"
|
||||
}
|
||||
[ -r "$tfile" ] && {
|
||||
_failure "Someone is messing up with us trying to hijack temporary files."
|
||||
}
|
||||
touch "$tfile"
|
||||
[ $? = 0 ] || {
|
||||
_failure "Fatal error creating a temporary file: %s" "$tfile"
|
||||
}
|
||||
_verbose "Created tempfile: ::1 temp file::" "$tfile"
|
||||
TOMBTMP="$tfile"
|
||||
TOMBTMPFILES="$TOMBTMPFILES:$tfile"
|
||||
return 0
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
# {{{ FreeBSD
|
||||
freebsd_mount() {
|
||||
file="$1"
|
||||
mnt="$2"
|
||||
_verbose `veracrypt -l "$file"`
|
||||
loop=`veracrypt -l "$file" | awk '{print $3}'`
|
||||
_verbose "fsck $loop"
|
||||
fsck.ext4 -p -C0 "$loop"
|
||||
lklfuse -o type=ext4 "${loop}" "$mnt"
|
||||
return $?
|
||||
}
|
||||
|
||||
freebsd_close() {
|
||||
file="$1"
|
||||
md=`veracrypt -l "$file" | awk '{print $3}'`
|
||||
# umount "$mnt"
|
||||
_verbose "md: $md"
|
||||
mnt=`pgrep -lf "lklfuse.*$md" | awk '{print $6}'`
|
||||
_verbose "mnt: $mnt"
|
||||
lkl=`pgrep -f "lklfuse.*$md" | awk '{print $1}'`
|
||||
_verbose "kill $lkl (lklfuse on $md)"
|
||||
# trying to deail with lklfuse bug
|
||||
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=239831
|
||||
renice -20 $lkl
|
||||
kill $lkl
|
||||
sync
|
||||
sleep 1
|
||||
kill -9 $lkl
|
||||
# lkl should have really exited now
|
||||
_verbose "veracrypt -d $file"
|
||||
veracrypt --text --non-interactive -d "$file"
|
||||
return $?
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ Linux
|
||||
# usage: _mount /tmp/.veracrypt_ mountpoint
|
||||
linux_mount() {
|
||||
file="$1"
|
||||
mnt="$2"
|
||||
veralist=`veracrypt -l "$file" | awk '{print($2,":",$3,":",$4)}'`
|
||||
[ "$veralist" = "" ] && {
|
||||
_error "Cannot mount tomb not yet mapped " "$file"
|
||||
return 1
|
||||
}
|
||||
loop=`echo $veralist | cut -d: -f2 | xargs`
|
||||
[ "`echo $veralist | cut -d: -f3 | xargs`" != "-" ] && {
|
||||
_error "Tomb already mounted " "$file on $loop"
|
||||
return 1
|
||||
}
|
||||
_verbose "fsck $loop"
|
||||
fsck.ext4 -p -C0 "$loop" 1>&2
|
||||
_verbose "linux_mount $mnt"
|
||||
mount "$loop" "$mnt"
|
||||
return $?
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ POSIX portable
|
||||
|
||||
# usage: echo PASSWORD | posix_create file size pim
|
||||
posix_create() {
|
||||
file="$1" # must not exist
|
||||
size="$2" # size in bytes
|
||||
pim="$3" # any number
|
||||
_verbose "posix_create $file $size $pim"
|
||||
veracrypt --text --non-interactive --stdin \
|
||||
-m nokernelcrypto \
|
||||
-c "$file" --volume-type normal \
|
||||
--hash sha512 --encryption serpent-aes \
|
||||
--filesystem none --size "${size}" --pim "$pim" \
|
||||
--random-source /dev/urandom -k ''
|
||||
return $?
|
||||
}
|
||||
|
||||
posix_format() {
|
||||
file="$1"
|
||||
loop=`veracrypt -l "$file" | awk '{print $3}'`
|
||||
_verbose "posix_format: ${loop}"
|
||||
mkfs.ext4 -L "`basename $file`" "$loop" # -E root_owner="${user_uid}:${user_gid}" "$loop"
|
||||
return $?
|
||||
}
|
||||
|
||||
# usage: echo PASSWORD | posix_map file pim
|
||||
posix_map() {
|
||||
file="$1"
|
||||
pim="$2"
|
||||
_verbose "posix_map $file $pim"
|
||||
veracrypt --text --non-interactive --stdin \
|
||||
--protect-hidden no -m nokernelcrypto \
|
||||
-k '' --pim "$pim" --filesystem none \
|
||||
"$file"
|
||||
return $?
|
||||
}
|
||||
|
||||
posix_close() {
|
||||
file="$1"
|
||||
_verbose "posix_close $file"
|
||||
veracrypt --text --non-interactive -d "$file"
|
||||
return $?
|
||||
}
|
||||
# }}}
|
||||
|
||||
# {{{ Initialization
|
||||
|
||||
system="unknown"
|
||||
create=""
|
||||
format=""
|
||||
map=""
|
||||
mount=""
|
||||
close=""
|
||||
|
||||
tomb_init() {
|
||||
system="`uname -s`"
|
||||
case "$system" in
|
||||
FreeBSD)
|
||||
cat <<EOF
|
||||
create=posix_create
|
||||
format=posix_format
|
||||
map=posix_map
|
||||
mount=freebsd_mount
|
||||
close=freebsd_close
|
||||
EOF
|
||||
;;
|
||||
Linux)
|
||||
cat <<EOF
|
||||
create=posix_create
|
||||
format=posix_format
|
||||
map=posix_map
|
||||
mount=linux_mount
|
||||
close=posix_close
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
_failure "Unsupported system: %s" "$system"
|
||||
esac
|
||||
echo "system=$system"
|
||||
# _verbose "system detected: %s" $system
|
||||
}
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
# {{{ Main
|
||||
[ "$1" = "source" ] && return 0
|
||||
eval "`tomb_init`"
|
||||
tombfile=""
|
||||
tombsize=""
|
||||
PIM=69
|
||||
|
||||
cmd="$1"
|
||||
shift 1
|
||||
|
||||
case "$cmd" in
|
||||
dig)
|
||||
args=2
|
||||
while [ $args -gt 0 ]; do
|
||||
[ "$1" = '-s' ] && { tombsize="$2"; shift 2; }
|
||||
[ "$1" != "" ] && { tombfile="$1"; shift 1; }
|
||||
args=$(( $args - 1 ))
|
||||
done
|
||||
|
||||
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
||||
[ "$tombsize" = "" ] && _failure "Size argument missing, use -s"
|
||||
# TODO: check if size is integer
|
||||
# [ "$tombsize" -ge 10 ] || _failure "Tombs can't be smaller than 10 mebibytes"
|
||||
[ -e "$tombfile" ] && {
|
||||
_error "A tomb exists already. I'm not digging here:"
|
||||
ls -l "$tombfile"; exit 1
|
||||
}
|
||||
_message "Commanded to dig tomb " "$tombfile" " sized $tombsize MiB"
|
||||
touch "$tombfile" || _failure "Error creating the tomb " "$tombfile"
|
||||
# dd if=/dev/urandom bs=1048576 count=$tombsize of="$tombfile" || {
|
||||
# _failure "Error creating the tomb " "$tombfile"
|
||||
# exit 1
|
||||
# }
|
||||
bytesize="$(( $tombsize * 1048576 ))"
|
||||
[ "$bytesize" = "" ] &&
|
||||
_failure "Error reading tomb size " "$tombsize"
|
||||
if [ "$system" = "Linux" ]; then
|
||||
fallocate -x -l "$bytesize" "$tombfile" ||
|
||||
_failure "Error creating the tomb " "$tombfile"
|
||||
else
|
||||
dd if=/dev/zero of="$tombfile" count="$tombsize" bs=1048576 ||
|
||||
_failure "Error creating the tomb " "$tombfile of $tombsize MiB"
|
||||
fi
|
||||
;;
|
||||
|
||||
forge)
|
||||
args=1
|
||||
[ "$1" = "" ] && _failure "Missing argument in command " "forge"
|
||||
while [ $args -gt 0 ]; do
|
||||
case "$1" in
|
||||
'-k') tombkey="$2"; shift 2 ;;
|
||||
*) tombkey="$1"; shift 1 ;;
|
||||
esac
|
||||
args=$(( $args - 1 ))
|
||||
done
|
||||
[ "$tombkey" = "" ] && _failure "Missing path to tomb key"
|
||||
[ -e "$tombkey" ] && {
|
||||
_error "A tomb key exists already. I'm not forging here:"
|
||||
ls -l "$tombkey"; exit 1
|
||||
}
|
||||
_message "Commanded to forge tomb key " "$tombkey"
|
||||
touch "$tombkey" || _failure "Error creating the tomb key " "$tombkey"
|
||||
cat <<EOF | zenroom -z | cut -d\" -f4 > "$tombkey"
|
||||
rule check version 2.0.0
|
||||
Given nothing
|
||||
When I create the random object of '64' bytes
|
||||
Then print the 'random object' as 'hex'
|
||||
EOF
|
||||
;;
|
||||
|
||||
lock)
|
||||
args=2
|
||||
while [ $args -gt 0 ]; do
|
||||
case "$1" in
|
||||
'-k') tombkey="$2"; shift 2 ;;
|
||||
*) tombfile="$1"; shift 1 ;;
|
||||
esac
|
||||
args=$(( $args - 1 ))
|
||||
done
|
||||
case "$system" in
|
||||
Linux)
|
||||
bytesize=`stat "$tombfile" | awk '/Size:/ {print $2; exit}'`
|
||||
;;
|
||||
*)
|
||||
bytesize=`stat -f '%z' "$tombfile"`
|
||||
;;
|
||||
esac
|
||||
_message "Commanded to lock tomb " "$tombfile with key $tombkey"
|
||||
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
||||
[ -r "$tombfile" ] || _failure "Tomb file not readable"
|
||||
[ "$tombkey" = "" ] && _failure "Missing path to key"
|
||||
[ -r "$tombkey" ] || _failure "Key file not readable"
|
||||
"$create" "$tombfile" "$bytesize" "$PIM" < "$tombkey" || {
|
||||
_failure "Error creating the tomb " "$tombfile"
|
||||
exit 1
|
||||
}
|
||||
"$map" "$tombfile" "$PIM" < "$tombkey" ||
|
||||
_failure "Error mapping the tomb " "$tombfile with key $tombkey"
|
||||
"$format" "$tombfile" ||
|
||||
_error "Error formatting tomb " "$tombfile"
|
||||
"$close" "$tombfile"
|
||||
[ $exitcode = 0 ] &&
|
||||
_success "Success locking tomb " "$tombfile with key $tombkey"
|
||||
;;
|
||||
|
||||
open)
|
||||
args=3
|
||||
while [ $args -gt 0 ]; do
|
||||
case "$1" in
|
||||
'-k') tombkey="$2"; shift 2 ;;
|
||||
*) if [ "$tombfile" = "" ]; then
|
||||
tombfile="$1"
|
||||
else
|
||||
tombmount="$1"
|
||||
fi
|
||||
shift 1 ;;
|
||||
esac
|
||||
args=$(( $args - 1 ))
|
||||
done
|
||||
_message "Commanded to open tomb " "$tombfile with key $tombkey on $tombmount"
|
||||
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
||||
[ -r "$tombfile" ] || _failure "Tomb file not readable"
|
||||
[ "$tombkey" = "" ] && _failure "Missing path to key"
|
||||
[ -r "$tombkey" ] || _failure "Key file not readable"
|
||||
[ "$tombmount" = "" ] && tombmount="`basename $tombfile`"
|
||||
"$map" "$tombfile" "$PIM" < "$tombkey"
|
||||
[ $? != 0 ] &&
|
||||
_failure "Error mapping the tomb " "$tombfile with key $tombkey"
|
||||
"$mount" "$tombfile" "$tombmount" || {
|
||||
"$close" "$tombfile"
|
||||
_failure "Error mounting the tomb " "$tombfile on $tombmount"
|
||||
}
|
||||
;;
|
||||
|
||||
close)
|
||||
# args=1
|
||||
if [ "$1" = "all" ]; then
|
||||
"$close"
|
||||
elif [ -e "$1" ]; then
|
||||
"$close" "`realpath $1`" ||
|
||||
_failure "Error closing " "$1"
|
||||
elif [ "$1" = "" ]; then
|
||||
_failure "Missing argument: tomb file or mountpoint"
|
||||
else
|
||||
_failure "Wrong argument: $1"
|
||||
fi
|
||||
;;
|
||||
list)
|
||||
veracrypt -l
|
||||
;;
|
||||
esac
|
||||
# }}}
|
||||
|
||||
exit 0
|
@ -3,3 +3,9 @@ Build with 'qmake' and then 'make'
|
||||
|
||||
Requires QT version 5.4 or above
|
||||
|
||||
To install copy the binary in your PATH
|
||||
then all contents of pixmaps to /usr/share/pixmaps
|
||||
and all contents of i18n to /usr/share/i18n
|
||||
|
||||
The prefix /usr/local may be preferred if ever packaged.
|
||||
|
||||
|
@ -11,19 +11,41 @@ test_expect_success 'Testing tomb creation: dig, forge and lock' '
|
||||
tt_forge --tomb-pwd $DUMMYPASS &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| hexdump -C &&
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
if test_have_prereq SPHINX ORACLE; then
|
||||
test_export "sphinx_test"
|
||||
test_expect_success 'Testing tomb creation: dig, forge and lock (sphinx password handling)' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
print $(echo $DUMMYPASS | sphinx get $DUMMYUSER $DUMMYHOST) \
|
||||
if test_have_prereq DOAS; then
|
||||
test_export "doas_test"
|
||||
test_expect_success 'Testing tomb creation: dig, forge and lock (using doas instead of sudo)' '
|
||||
tt_dig --sudo doas -s 20 &&
|
||||
tt_forge --sudo doas --tomb-pwd $DUMMYPASS &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| xxd &&
|
||||
tt_lock --sudo doas --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
fi
|
||||
|
||||
if test_have_prereq BTRFS; then
|
||||
test_export "btrfs"
|
||||
test_expect_success 'Testing tomb creation using BTRFS filesystem' '
|
||||
tt_dig -s 120 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| hexdump -C &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS --filesystem btrfs
|
||||
'
|
||||
|
||||
test_export "btrfsmixed"
|
||||
test_expect_success 'Testing tomb creation using BTRFS mixedmode filesystem' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS --filesystem btrfsmixedmode
|
||||
'
|
||||
fi
|
||||
|
||||
|
@ -44,13 +44,12 @@ if test_have_prereq LSOF; then
|
||||
'
|
||||
fi
|
||||
|
||||
if test_have_prereq SPHINX ORACLE; then
|
||||
test_export "sphinx_test" # Using already generated tomb
|
||||
test_expect_success 'Testing open with good password (sphinx)' '
|
||||
tt_open --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
tt_close
|
||||
if test_have_prereq DOAS; then
|
||||
test_export "doas_test" # Using already generated tomb
|
||||
test_expect_success 'Testing open with good password (using doas instead of sudo)' '
|
||||
tt_open --sudo doas --tomb-pwd $DUMMYPASS &&
|
||||
tt_close --sudo doas
|
||||
'
|
||||
fi
|
||||
|
||||
|
||||
test_done
|
||||
|
@ -4,6 +4,8 @@ export test_description="Testing tomb with GnuPG keys"
|
||||
|
||||
source ./setup
|
||||
|
||||
if test_have_prereq GPGRCPT; then
|
||||
|
||||
test_export "recipient"
|
||||
test_expect_success 'Testing tomb with GnuPG keys: creation' '
|
||||
tt_dig -s 20 &&
|
||||
@ -54,4 +56,6 @@ test_expect_success 'Testing tomb creation with untrusted GnuPG keys' '
|
||||
test_must_fail tt_forge -g -r $KEY_UNTRUSTED
|
||||
'
|
||||
|
||||
fi
|
||||
|
||||
test_done
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
export test_description="Testing tomb with KDF key"
|
||||
export test_description="Testing tomb with KDF keys"
|
||||
|
||||
source ./setup
|
||||
|
||||
@ -11,19 +11,46 @@ if test_have_prereq KDF; then
|
||||
tt_forge --tomb-pwd $DUMMYPASS --kdf 1 &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| hexdump -C &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS --kdf 1
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF: tomb passwd' '
|
||||
tt passwd -k $tomb_key --kdf 1 \
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW &&
|
||||
tt passwd -k $tomb_key --kdf 1 \
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF: tomb open & close' '
|
||||
tt_open --tomb-pwd $DUMMYPASS --kdf 1 &&
|
||||
tt_open --tomb-pwd $DUMMYPASS &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
||||
# clean to avoid overwrite errors
|
||||
# rm -f "$tomb_key" "$tomb"
|
||||
|
||||
if test_have_prereq ARGON2; then
|
||||
test_export "argon2"
|
||||
test_expect_success 'Testing KDF ARGON2: tomb creation' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS --kdftype argon2 --kdfmem 18 --kdf 1 &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF ARGON2: tomb passwd' '
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW &&
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF ARGON2: tomb open & close' '
|
||||
tt_open --tomb-pwd $DUMMYPASS &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
@ -5,22 +5,29 @@ export test_description="Testing tomb resize feature"
|
||||
source ./setup
|
||||
|
||||
if test_have_prereq RESIZER; then
|
||||
test_export "test" # Using already generated tomb
|
||||
test_expect_success 'Testing resize to 30 MB tomb' '
|
||||
tt resize -s 30 $tomb -k $tomb_key --unsafe --tomb-pwd $DUMMYPASS
|
||||
test_export "test" # Using already generated tomb
|
||||
test_expect_success 'Testing resize to 30 MB tomb' '
|
||||
tt resize -s 190 $tomb -k $tomb_key --unsafe --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
if test_have_prereq GPGRCPT; then
|
||||
test_export "recipient" # Using already generated tomb
|
||||
test_expect_success 'Testing resize to 30 MB tomb with GnuPG keys' '
|
||||
tt resize -s 30 $tomb -k $tomb_key -g -r $KEY2
|
||||
tt resize -s 190 $tomb -k $tomb_key -g -r $KEY2
|
||||
'
|
||||
fi
|
||||
fi
|
||||
|
||||
if test_have_prereq RESIZER SPHINX ORACLE; then
|
||||
test_export "sphinx_test" # Using already generated tomb
|
||||
test_expect_success 'Testing resize to 30 MB tomb (sphinx)' '
|
||||
tt resize -s 30 $tomb -k $tomb_key --unsafe --tomb-pwd $DUMMYPASS --sphx-user $DUMMYUSER --sphx-host $DUMMYHOST
|
||||
fi # RESIZER
|
||||
|
||||
if test_have_prereq BTRFS; then
|
||||
test_export "btrfs"
|
||||
test_expect_success 'Testing resize using BTRFS filesystem' '
|
||||
tt resize -s 280 $tomb -k $tomb_key --unsafe --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
# test_export "btrfsmixed"
|
||||
# test_expect_success 'Testing resize using BTRFS filesystem' '
|
||||
# tt resize -s 190 $tomb -k $tomb_key --unsafe --tomb-pwd $DUMMYPASS
|
||||
# '
|
||||
fi
|
||||
|
||||
test_done
|
||||
|
@ -6,27 +6,19 @@ source ./setup
|
||||
|
||||
test_export "test" # Using already generated tomb
|
||||
test_expect_success 'Testing tomb with GnuPG keys: passwd' '
|
||||
tt passwd -k $tomb_key --unsafe \
|
||||
tt passwd -f -k $tomb_key --unsafe \
|
||||
--tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW &&
|
||||
tt passwd -k $tomb_key --unsafe \
|
||||
tt passwd -f -k $tomb_key --unsafe \
|
||||
--tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
if test_have_prereq GPGRCPT; then
|
||||
|
||||
test_export "recipient" # Using already generated tomb
|
||||
test_expect_success 'Testing tomb with GnuPG keys: passwd' '
|
||||
tt passwd -k $tomb_key -g -r $KEY2
|
||||
tt passwd -f -k $tomb_key -g -r $KEY2
|
||||
'
|
||||
|
||||
if test_have_prereq SPHINX ORACLE; then
|
||||
test_export "sphinx_test" # Using already generated tomb
|
||||
test_expect_success 'Testing changing tomb password with sphinx' '
|
||||
tt passwd -k $tomb_key --unsafe \
|
||||
--tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW \
|
||||
--sphx-user $DUMMYUSER --sphx-host $DUMMYHOST &&
|
||||
tt passwd -k $tomb_key --unsafe \
|
||||
--tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS \
|
||||
--sphx-user $DUMMYUSER --sphx-host $DUMMYHOST
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user