python-delta-tar
6 years agoallow selecting individual tests with runtests.py
Philipp Gesang [Tue, 18 Apr 2017 09:59:02 +0000]
allow selecting individual tests with runtests.py

If arguments are passed on the command line, interpret them as
test names and attempt to compose a suite comprising only the
tests specified.

The behavior remains the same if invoked without argument.

6 years agoimprove error handling in crypto handler
Philipp Gesang [Mon, 10 Apr 2017 15:37:33 +0000]
improve error handling in crypto handler

Since invalid tags are some the most important bits of
information to be passed down, make the corresponding error
message human-readable.

6 years agoremove obsolete block size check
Philipp Gesang [Mon, 10 Apr 2017 14:32:50 +0000]
remove obsolete block size check

6 years agofix fallout from EOF changes in CLI decryptor
Philipp Gesang [Mon, 10 Apr 2017 13:08:31 +0000]
fix fallout from EOF changes in CLI decryptor

6 years agothrow error on partial header reading stream
Philipp Gesang [Mon, 10 Apr 2017 13:01:56 +0000]
throw error on partial header reading stream

Throw the EOF exception only if the stream ends exactly at an
object boundary. Otherwise, when less then sizeof(hdr) bytes
are returned from read(), throw InvalidHeader to indicate a
malformed file. This keeps EOF a “benign” exception.

6 years agocommunicate remainder to caller when hitting EOF from crypto
Philipp Gesang [Mon, 10 Apr 2017 11:43:53 +0000]
communicate remainder to caller when hitting EOF from crypto

6 years agostrip extraneous parameters from decryption handler ctor
Philipp Gesang [Mon, 10 Apr 2017 09:43:06 +0000]
strip extraneous parameters from decryption handler ctor

Format and parameter version as well as the salt are supplied
from the headers. Decrypting should thus only require the
password and, depending on context, an explicit counter as well
as the list of valid IV fixed parts.

6 years agoadd input checks at API boundaries
Philipp Gesang [Mon, 10 Apr 2017 09:15:09 +0000]
add input checks at API boundaries

Verify conformance of user-supplied inputs on a very basic level,
communicating violations via InvalidParameter exception.

Of course due to the limitations of the type systems these can’t
be made exhaustive. E. g. no effort is being made to inspect a
(passing) list or dict test for well-formed contents.

6 years agodocument exceptions used in encryption handler
Philipp Gesang [Mon, 10 Apr 2017 08:36:12 +0000]
document exceptions used in encryption handler

Prepare clear and rigorous communication of errors and other
unexpected conditions to the user. Eventually these will make
the foundation for messages propagating up the stack until they
reach the UI.

6 years agouse exception to communicate tag mismatch
Philipp Gesang [Mon, 10 Apr 2017 08:27:47 +0000]
use exception to communicate tag mismatch

6 years agounify error and parameter handling in crypto.py
Philipp Gesang [Mon, 10 Apr 2017 08:13:02 +0000]
unify error and parameter handling in crypto.py

Three classes of errors:

    - bad encryption (tag mismatch, bad IVs);
    - bad user input (request info counter twice);
    - internal error (state was reached that indicates a problem
      with crypto.py).

6 years agoremove obsolete tag handling functionality from crypto.py
Philipp Gesang [Mon, 10 Apr 2017 07:34:32 +0000]
remove obsolete tag handling functionality from crypto.py

The GCM tag does no longer occur independent of a PDT header so
these are no longer relevant.

6 years agofix search string in tar volume generation
Philipp Gesang [Fri, 7 Apr 2017 15:49:35 +0000]
fix search string in tar volume generation

6 years agouse OSError instead of IOError
Philipp Gesang [Fri, 7 Apr 2017 14:59:19 +0000]
use OSError instead of IOError

IOError is a synonym for OSError, so the latter should be used
everywhere to avoid confusion, especially when throwing the one
but catching the other.

Cf. PEP 3151.

6 years agoallow test_compression_level.py as module
Philipp Gesang [Fri, 7 Apr 2017 09:15:00 +0000]
allow test_compression_level.py as module

6 years agorework crypto.py unittests for revised encryption
Philipp Gesang [Thu, 6 Apr 2017 15:56:09 +0000]
rework crypto.py unittests for revised encryption

Main changes:

    - Adjust usage to revised encryption handler.

    - Adapt to header format.

    - Adjust to changes in error passing (above all ``hdr_read()``).

    - Remove Scrypt or tag tests, these interfaces are no longer
      available.

6 years agospecify salt and version in ctor when encrypting
Philipp Gesang [Fri, 7 Apr 2017 07:29:27 +0000]
specify salt and version in ctor when encrypting

Simplify the signature of Encrypt.next() by removing the salt and
version arguments: This will make the encryptor reuse the values
it already has which was either passed to or randomly generated
by the ctor. Currently there is no case where we’d need to change
the salt or version during encryption. When decrypting, the
values from the headers are used anyways so nothing changes over
there.

6 years agoincrement file counter after handling current object
Philipp Gesang [Thu, 6 Apr 2017 15:54:35 +0000]
increment file counter after handling current object

6 years agofix IV fixed part validation on decryption
Philipp Gesang [Thu, 6 Apr 2017 15:06:05 +0000]
fix IV fixed part validation on decryption

6 years agoparse buffer as header if passed as arg to next()
Philipp Gesang [Thu, 6 Apr 2017 14:54:33 +0000]
parse buffer as header if passed as arg to next()

6 years agoadapt concat_compress unit tests to gzip block sequence
Philipp Gesang [Thu, 6 Apr 2017 13:42:15 +0000]
adapt concat_compress unit tests to gzip block sequence

The unit tests assume that compression of three files requires
three distinct Gzip blocks. The first one of these is empty and
serves no purpose, differing from the others by containing the
more or less redundant archive name. This is no longer the case
after the revision of the header code: the first block will still
have the archive name in the metadata but also contain the first
file.

Thus, adapt the unit tests to no longer check for and then ignore
the empty initial gzip block.

6 years agoprefer symbolic constants over literals referring to gzip header
Philipp Gesang [Thu, 6 Apr 2017 13:09:10 +0000]
prefer symbolic constants over literals referring to gzip header

The mixed use of hex and octal is pretty confusing to say the
least, use named constants instead that are defined only in
tarfile.

6 years agofix tarfile crypto parameter passing
Philipp Gesang [Thu, 6 Apr 2017 12:36:26 +0000]
fix tarfile crypto parameter passing

Remove obsolete parameters like “password” that are no longer
meaningful after moving the creation of the crypto context
outside of tarfile.py.

Also, check test the presence of encryption attributes before
accessing them to avoid conflicts with zlib streams. (Kludgy, but
not avoidable without a larger changes due to the possibility of
“fileobj” being anything, including things that don’t satisfy all
the interfaces that “_Stream” provides.

6 years agoaccept external counter in crypto.py
Philipp Gesang [Thu, 6 Apr 2017 12:34:20 +0000]
accept external counter in crypto.py

Required when encrypting an auxiliary file of type info.

6 years agounify constant naming I2N_→PDTCRYPT_
Philipp Gesang [Wed, 5 Apr 2017 06:49:50 +0000]
unify constant naming I2N_→PDTCRYPT_

7 years agounify file extension handling
Philipp Gesang [Tue, 4 Apr 2017 15:35:04 +0000]
unify file extension handling

The required extension no longer depends on the “[index]mode”
parameter since the encryption context is handled independently.
Add a function pick_extension() that reflects this circumstance
and appends the required suffixed depending on three inputs.

7 years agocatch ESPIPE from ftell () on stream
Philipp Gesang [Tue, 4 Apr 2017 08:00:17 +0000]
catch ESPIPE from ftell () on stream

The result is only used for status output so defaulting to -1 for
stdin doesn’t hurt. All functional uses of the current position
rely on the value of total_read.

7 years agoimprove parameter handling of crypto.py
Philipp Gesang [Tue, 4 Apr 2017 07:43:23 +0000]
improve parameter handling of crypto.py

7 years agoallow decryption from std{in,out} via crypto.py
Philipp Gesang [Tue, 4 Apr 2017 06:54:31 +0000]
allow decryption from std{in,out} via crypto.py

Make it possible to invoke the script as

    $ ./crypto.py test1234 - - <bfull-2017-04-04-0856-001.tar.pdtcrypt >out.tar.gz

for extra convenience.

7 years agohandle zlib correctly
Philipp Gesang [Mon, 3 Apr 2017 15:32:44 +0000]
handle zlib correctly

Encryption was split from the “compression mode” and now depends
entirely on the crypto context. Also only finalize a tar stream
being “closed” if the underlying file is being closed.

7 years agodelay index file write until backup is complete
Philipp Gesang [Mon, 3 Apr 2017 14:53:46 +0000]
delay index file write until backup is complete

Due to restrictions of the file counting in the encryption
module, files must be handled in a strictly sequential manner.
Thus, postpone the creation of and all writes to the index file
until after all other files have been processed.

7 years agofix file offset calculation
Philipp Gesang [Mon, 3 Apr 2017 13:56:25 +0000]
fix file offset calculation

Move the seek-back code down into the “low level file” wrapper so
header writes aren’t counted. This way byte counters match again.

7 years agoadd simple decryption routine to crypto.py
Philipp Gesang [Mon, 3 Apr 2017 11:54:54 +0000]
add simple decryption routine to crypto.py

Currently this allows decrypting (and only decrypting) a backup
volume without requiring the deltatar layer in between.

7 years agorename open_index to open_auxiliary_file
Philipp Gesang [Fri, 31 Mar 2017 14:37:43 +0000]
rename open_index to open_auxiliary_file

We need a more neutral name since the functionality is accessed
elsewhere to write the info file too.

7 years agoprevent the empty string as password
Philipp Gesang [Fri, 31 Mar 2017 13:56:11 +0000]
prevent the empty string as password

backup.py would default to using the empty string as password
which would cause a crypto context to be created even without
encryption being required.

Use ``None`` instead to indicate absence of a user-supplied
password.

7 years agoactually output something in toc mode
Philipp Gesang [Fri, 31 Mar 2017 13:35:53 +0000]
actually output something in toc mode

Until now backup.py wouldn’t print anything when passed the -l
flag. Supply a trivial printer to the “list_func” argument to
output the contents similar to what GNU tar does.

7 years agopass encryption context to tarfile
Philipp Gesang [Fri, 31 Mar 2017 13:01:20 +0000]
pass encryption context to tarfile

This supersedes the individual parameters.

7 years agodo not require parameter version with each encrypted object
Philipp Gesang [Fri, 31 Mar 2017 12:31:19 +0000]
do not require parameter version with each encrypted object

When encrypting, stick to the parameter version specified in the
ctor. Despite the format allowing for on-the-fly adjustment of
encryption parameters, there is no real world scenario yet in
which this might be desired. Thus, remove this prerequisite as it
only encumbers the signature of ``.next()`` with cruft.

7 years agofirst draft for making the encryption layer independent
Philipp Gesang [Tue, 28 Mar 2017 15:44:31 +0000]
first draft for making the encryption layer independent

WIP.

In Deltatar, we cannot use the ctor itself to set up the
encryption because it is neutral wrt. reading / writing.
Only once one of the entry points:

- ``.list_backup()``,
- ``.create_full_backup()``, ``.create_diff_backup()``, or
- ``.restore_backup()``.

are invoked do we know what the object’s intended use is.
Thus we hook the encryption handler somewhere in there.

7 years agochange extension for encrypted files
Philipp Gesang [Tue, 28 Mar 2017 13:12:04 +0000]
change extension for encrypted files

7 years agoreturn collected fixed iv parts from .close() when encrypting
Philipp Gesang [Tue, 28 Mar 2017 12:28:06 +0000]
return collected fixed iv parts from .close() when encrypting

Provisional implementation for dumping the IVs in the info file
that will be superseded once the crypto context can be provided
to tarfile by the user.

7 years agoautomate iv fixed-part generation
Philipp Gesang [Mon, 27 Mar 2017 15:43:27 +0000]
automate iv fixed-part generation

The crypto context keeps track of the used IV fixed parts
so they can eventually be included in the info file. A new
fixed part is created in the ctor, then for every time the
counter wraps.

“Wrapping” resets the counter to 2 since 1 is globally reserved
for the info file.

7 years agoproperly enter/leave encryption sections
Philipp Gesang [Mon, 27 Mar 2017 15:22:13 +0000]
properly enter/leave encryption sections

7 years agoexplicitly constuct zlib headers
Philipp Gesang [Mon, 27 Mar 2017 14:06:18 +0000]
explicitly constuct zlib headers

Get rid of the unnecessary literal byte strings. Commit

    5fdff89f4d9fa28e6b210d40d389680072651eb7

introduced headers for additional blocks, omitting the “original
file name” field that gzip set by default.

7 years agounify zlib initialization
Philipp Gesang [Mon, 27 Mar 2017 12:10:51 +0000]
unify zlib initialization

7 years agoapply compression if compressor is present
Philipp Gesang [Mon, 27 Mar 2017 09:11:00 +0000]
apply compression if compressor is present

7 years agooverhaul pre- and post-crypto sync
Philipp Gesang [Fri, 24 Mar 2017 13:46:59 +0000]
overhaul pre- and post-crypto sync

In order to handle ``_Stream.close()`` well later, we need to
write the header of the last object before the tar info is
injected. To allow the padding and zlib finalization in .close(),
this cannot be performed when the actual file contents are
written but has to be suspended until we are certain no data will
be written to the current crypto object.

7 years agoimplement encryption passthrough mode
Philipp Gesang [Fri, 24 Mar 2017 11:20:45 +0000]
implement encryption passthrough mode

7 years agounify common operations between encryption and decryption
Philipp Gesang [Fri, 24 Mar 2017 10:27:45 +0000]
unify common operations between encryption and decryption

7 years agoadjust versioned encryption parameters
Philipp Gesang [Fri, 24 Mar 2017 10:12:29 +0000]
adjust versioned encryption parameters

Prepare for revised versioning: Both the encryption mechanism and
the KDF may be specified in the versioning.

7 years agoextend open_index() API for info file handling
Philipp Gesang [Thu, 23 Mar 2017 10:48:59 +0000]
extend open_index() API for info file handling

In fact, backup_python’s “info file” is just another “index file”
to deltatar. Conceptually they’re quite different though
especially regarding encryption. To allow requesting an info
flavored index file, add a parameter to communicate with the
crypto layer.

7 years agostart payload encryption counter at 2
Philipp Gesang [Thu, 23 Mar 2017 09:43:25 +0000]
start payload encryption counter at 2

As per the spec, a file counter of 1 is reserved for the info
file.

7 years agotrack encryption state
Philipp Gesang [Tue, 21 Mar 2017 14:32:32 +0000]
track encryption state

7 years agoreinit crypto for objects other than files
Philipp Gesang [Tue, 21 Mar 2017 14:20:44 +0000]
reinit crypto for objects other than files

Invoke the new-item handler to force a new crypto object for
directories and anything else as well.

7 years agotrack data handled in crypto
Philipp Gesang [Tue, 21 Mar 2017 14:11:32 +0000]
track data handled in crypto

7 years agofirst draft of revised encryption layer
Philipp Gesang [Tue, 21 Mar 2017 12:33:16 +0000]
first draft of revised encryption layer

WIP. Tested for encryption (no compression) only, and only for
TOC listings (-l).

Decryption is handled entirely by the stream, traversing the
archive entry wise relying only one the header informations.

Encryption requires poking the _Stream thingy to initiate a new
crypto entry.

7 years agosimplify password save and retrieval
Philipp Gesang [Tue, 21 Mar 2017 12:13:00 +0000]
simplify password save and retrieval

The password must be available for the entire time of the
decryption since it might be necessary to recalculate the key on
account of different salt or parameters of some object.

7 years agoimplement null-kdf to speed up testing
Philipp Gesang [Mon, 20 Mar 2017 16:35:45 +0000]
implement null-kdf to speed up testing

With “parameter version” zero, the KDF consists only of a trivial
string derived from the password so as to reduce runtime. (SCRYPT
takes about 48 seconds here with our parameters.)

7 years agoadapt tag handling in decryption
Philipp Gesang [Mon, 20 Mar 2017 15:42:51 +0000]
adapt tag handling in decryption

7 years agofix encrypted read logic for begin/end at entry boundaries
Philipp Gesang [Mon, 20 Mar 2017 14:02:03 +0000]
fix encrypted read logic for begin/end at entry boundaries

7 years agoretrieve and save GCM tag from object header
Philipp Gesang [Mon, 20 Mar 2017 11:07:08 +0000]
retrieve and save GCM tag from object header

7 years agodelay kdf until parameters are available from header
Philipp Gesang [Mon, 20 Mar 2017 10:48:38 +0000]
delay kdf until parameters are available from header

When decrypting, initialize the key immediately if parameters and
salt are being passed to the ctor. Otherwise, just save the
passphrase in the object and run the KDF when ``.next()`` is
passed the required bits as part of a PDTCRYPT header.

7 years agomove ct length bookkeeping into encryptor
Philipp Gesang [Fri, 17 Mar 2017 16:19:10 +0000]
move ct length bookkeeping into encryptor

This saves us unreliable calculations over the _Stream progress
in tarfile.py.

7 years agomove tag back into the header
Philipp Gesang [Fri, 17 Mar 2017 15:02:31 +0000]
move tag back into the header

Since we seek back to write the final header it makes little
sense to append the tag to the ciphertext regardless.

7 years agoinitially write dummy header during encryption
Philipp Gesang [Fri, 17 Mar 2017 10:22:44 +0000]
initially write dummy header during encryption

7 years agocreate crypto header in .next()
Philipp Gesang [Thu, 16 Mar 2017 16:39:57 +0000]
create crypto header in .next()

Saves us from exposing the IV to the stream.

7 years agoredo transition between objects in crypto layer
Philipp Gesang [Thu, 16 Mar 2017 16:06:28 +0000]
redo transition between objects in crypto layer

When encrypting, the ciphertext size isn’t known beforehand.
Likewise, the file name isn’t available when initializing the
decryption of a file.

7 years agopass salt between index and archive
Philipp Gesang [Thu, 16 Mar 2017 15:40:31 +0000]
pass salt between index and archive

Memoization of the scrypt params requires static storage because
both the index file and the archive each have an encryption
context.

7 years agorevise crypto context interface
Philipp Gesang [Thu, 9 Mar 2017 15:41:57 +0000]
revise crypto context interface

Fold key handling and encryption into a common context “class”.
The context takes care of the counter, iv, keys etc. It has one
entry point (ctor) for each direction (read, write → decrypt,
encrypt) and provides hooks for transitioning to the next item.

Header and tag handling remain accessible independent of the
context since tarfile operates on the archive stream and file
objects.

7 years agoredo stream decryption
Philipp Gesang [Mon, 6 Mar 2017 15:51:13 +0000]
redo stream decryption

When decrypting, the size of the encrypted object is known, as is
the length of the appended authentication tag; there is no
ambiguity regarding the end of an object. Thus the old string
matching logic with its linear search behavior can go.

7 years agosupersede encryption type by encryption parameters
Philipp Gesang [Fri, 3 Mar 2017 16:57:37 +0000]
supersede encryption type by encryption parameters

WIP

7 years agopolish up backup.py arguments
Philipp Gesang [Thu, 2 Mar 2017 14:41:42 +0000]
polish up backup.py arguments

These are about the only high-level clues regarding its
functionality so it may as well be presented right.

7 years agoinclude offending mode string in exception
Philipp Gesang [Thu, 2 Mar 2017 13:54:59 +0000]
include offending mode string in exception

Be a little more informative about the cause considering this
exception is passed on to the user as-is.

7 years agoensure octal format is fed an integer
Philipp Gesang [Thu, 2 Mar 2017 13:40:39 +0000]
ensure octal format is fed an integer

Fix a “type” error that seems to be enforced by Python 3:

      File "/src/python/python-delta-tar/deltatar/tarfile.py", line 220, in itn
        s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL
    TypeError: %o format: an integer is required, not float

7 years agodisplay backup.py usage if no action was specified
Philipp Gesang [Thu, 2 Mar 2017 13:36:43 +0000]
display backup.py usage if no action was specified

Getting no feedback if the invocation had no effect is rather
unseemly. Print the help message instead.

7 years agohandle reading and formatting of tags
Philipp Gesang [Tue, 28 Feb 2017 16:45:54 +0000]
handle reading and formatting of tags

7 years agounit test scrypt wrapper
Philipp Gesang [Tue, 28 Feb 2017 16:01:07 +0000]
unit test scrypt wrapper

7 years agounit test bogus header data
Philipp Gesang [Tue, 28 Feb 2017 15:34:34 +0000]
unit test bogus header data

7 years agounit test auth tag handling
Philipp Gesang [Tue, 28 Feb 2017 14:58:20 +0000]
unit test auth tag handling

7 years agounit test crypto handling of data spanning multiple chunks
Philipp Gesang [Tue, 28 Feb 2017 14:45:16 +0000]
unit test crypto handling of data spanning multiple chunks

7 years agounit test header handling
Philipp Gesang [Tue, 28 Feb 2017 14:17:04 +0000]
unit test header handling

7 years agoadd basic wrapper for GCM handling with python-cryptography
Philipp Gesang [Tue, 28 Feb 2017 13:36:19 +0000]
add basic wrapper for GCM handling with python-cryptography

This currently requires our yet unmerged contribution:
https://github.com/pyca/cryptography/pull/3421

7 years agoadd unit test module for encryption layer
Philipp Gesang [Tue, 28 Feb 2017 13:34:59 +0000]
add unit test module for encryption layer

7 years agoremove key length parameter wherever feasible
Philipp Gesang [Fri, 24 Feb 2017 10:18:18 +0000]
remove key length parameter wherever feasible

Since we’re using fixed AES-128 everywhere, the  revised version
no longer offers adjustable key length.

7 years agomake tarfile.py error out on invalid crypto modes and combos
Philipp Gesang [Fri, 24 Feb 2017 09:50:03 +0000]
make tarfile.py error out on invalid crypto modes and combos

The tarfile stream ctor will simply gloss over encryption
requested by the caller unless it happens to exactly match the
string (!) “aes”. Furthermore, with non-gzip compression the
encryption will be ignored altogether.

Instead of deceiving the user about the encryption being applied,
have the ctor fail immediately on invalid combinations.

7 years agoinit crypto support v2
Philipp Gesang [Thu, 23 Feb 2017 15:34:19 +0000]
init crypto support v2

Implements header reading and writing as well as PoC encryption
wrappers.

WIP

7 years agoignore all symlinks
Philipp Gesang [Mon, 7 Nov 2016 09:00:32 +0000]
ignore all symlinks

Don’t delay the creation of symlinks but suppress it entirely.

The rationale is that extraction with deltatar will only ever
operate on inputs whose symlinks are dereferenced upon archive
creation. Thus valid archives will not contain symlinks at all.

Also, it would appear that deltatar assumes paths of objects
inside a tarball are unique. If the tarball contains ultiple
objects with the same path, it will extract only the first one it
encounters and ignore the rest. This means that it would take at
least two successive backups to perform a symlink attack, the
first one planting the link and the second writing over the
location. This is prevented by the current mitigation strategy
(and by the --unlink option of other tar utilities).

7 years agoadd unit test for overwriting symlinks
Philipp Gesang [Fri, 4 Nov 2016 16:00:59 +0000]
add unit test for overwriting symlinks

Currently, we implement the behavior of GNU Tar: Subsequent files
in an archive override previous ones, which is also true of
symlinks.

7 years agorectify delayed symlink restoration
Philipp Gesang [Fri, 4 Nov 2016 14:32:13 +0000]
rectify delayed symlink restoration

Again, GNU tar serves as the model for safe behavior: We now
check whether the placeholder file exists and if it is indeed the
one we created earlier.

Since deltatar does not allow including symlinks in the backup,
the unit tests invoke tarfile functionality directly to add some
symlinks to an existing backup.

7 years agoadd unit test tracking behavior wrt symlinks
Philipp Gesang [Fri, 4 Nov 2016 10:59:34 +0000]
add unit test tracking behavior wrt symlinks

7 years agofix calls to deprecated function in deltatar.py
Philipp Gesang [Thu, 3 Nov 2016 16:02:54 +0000]
fix calls to deprecated function in deltatar.py

Fixes warning mandating “.warning()” over “.warn()”:

    DeprecationWarning: The 'warn' method is deprecated, use 'warning' instead

7 years agodelay only absolute symlinks and those pointing to parent dirs
Philipp Gesang [Thu, 3 Nov 2016 13:31:14 +0000]
delay only absolute symlinks and those pointing to parent dirs

Only apply the symlink hook on those with fishy targets. Internal
symlinks need not be contained so they can be applied as-is.

7 years agoimplement delayed symlink creation
Philipp Gesang [Thu, 3 Nov 2016 11:02:15 +0000]
implement delayed symlink creation

Introduce a hook in ``extract()`` to invoke a callback if a
symlink is encountered in the archive. The implementation is
modeled after GNU Tar.

This is a v2 attempt on the symlink extraction problematic. The
first version simply ``unlink(2)`` all files before extraction
which is a less efficient albeit more robust strategy.

7 years agoavoid crash in test helper due to fp division
Philipp Gesang [Mon, 31 Oct 2016 16:44:42 +0000]
avoid crash in test helper due to fp division

As a matter of fact, ``randomint()`` accepts only int-ishly typed
values, not floats. Consequently, integer division is the way to
go.

7 years agosimplify control flow in RestoreHelper methods
Philipp Gesang [Wed, 2 Nov 2016 16:42:33 +0000]
simplify control flow in RestoreHelper methods

Make the control flow more obvious. The code in question was
introduced with commit ea6d3c3e… but did not make sense back then
either because cur_index which is the constant $1$ was compared
to the literal constant $0$:

+        cur_index = 1
+        while cur_index < len(self._data):
+            data = self._data[cur_index]

+                if cur_index == 0:

This bogus test was since removed but the convoluted ``while``
loop survived. Instead, access index 1 only once using an integer
literal.

7 years agoIncrease version to 1.5
Thomas Jarosch [Mon, 4 Jul 2016 10:13:39 +0000]
Increase version to 1.5

7 years agoCode review done, comment changes only
Thomas Jarosch [Mon, 4 Jul 2016 09:49:06 +0000]
Code review done, comment changes only

7 years agoRemove dead code
Thomas Jarosch [Mon, 4 Jul 2016 09:48:28 +0000]
Remove dead code

cur_index is always >= 1 in this code path

7 years agoRemove code duplication
Thomas Jarosch [Mon, 4 Jul 2016 09:48:16 +0000]
Remove code duplication

7 years agoDon't use exception handling for normal control flow
Thomas Jarosch [Thu, 30 Jun 2016 08:03:40 +0000]
Don't use exception handling for normal control flow

-> Replace buf.index() with buf.find().

Unwinding the stack is expensive and we were
even doing it for the default code path.