A recent OS change altered how sparse files are represented in backup
streams. This caused backuptar to no longer work with certain files. The
specific behavior that changed is as follows:
- Empty sparse files (size = 0), previously did not have any data or
sparse block streams in the backup stream. Now, they will have a
data stream with size = 0, and no sparse block streams.
- Sparse files with a single allocated range (e.g. a normal file that
has the sparse attribute set) previously would not show as sparse in
the backup stream. Now, they will show as sparse.
The old backuptar behavior assumed that if the sparse flag was set on
the data stream, then there would always be a set of sparse blocks
following. These changes break this assumption, and so require special
handling.
It is unsupported to have a data stream, marked sparse, that contains
file content AND a series of sparse block streams following. As far as
I can tell this is not a valid case for backup streams.
This change also cleans up some code and error messages, and expands on
the test coverage for backuptar.
For more information on backup stream format see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-bkup/f67950c8-d583-469a-83dd-c4ff4cedf533
Signed-off-by: Kevin Parsons <kevpar@microsoft.com>
These packages had incorrect error handling for their generated syscall
bindings. The functions they were calling returned errors directly, but
the binding was written such that the generated code was calling
GetLastError instead.
Thankfully, this did not affect the detection of whether or not an error
had occurred, it only caused the value returned in the case of an error
to be not the right error code.
Signed-off-by: Kevin Parsons <kevpar@microsoft.com>
We don't support actually using ETW on windows/arm, but to make things
easier for downstream dependencies, we want to still allow the package
to compile and just no-op on this architecture. We do this by returning
a nil Provider, and implementing its methods to no-op when the receiver
is nil.
Previously this was implemented by putting NewProviderWithID in
provider_unsupported.go, but when we refactored the code so that the
actual work was done in NewProviderWithOptions instead, we didn't fix up
provider_unsupported. This change fixes this by putting only
NewProviderWithOptions in provider_unsupported.go, since the other
provider creation functions call into this one.
Signed-off-by: Kevin Parsons <kevpar@microsoft.com>
The ETW registration handle is defined to be 64-bits on all platforms. The Go
type previously used a uintptr which created problems on 32-bit systems. This
change adds a new wrapper file which receives a 64-bit handle for the functions
defined in it, and correctly passes it to the native ETW functions either as-is
(on 64-bit) or as two 32-bit values (on 32-bit).
This required a minor change in mksyscall_windows.go, to allow multiple syscalls
that map to the same underlying function without causing a duplicate definition
error in the generated file.
Proper support for ETW on ARM will require additional changes in Go to support
more than 16 bytes of arguments to a syscall callback. Until this work is done,
the ETW package is being changed to no-op on ARM.
There is a cleanup function deferred to remove the provider from the global
provider map. However, this function didn't bind the value of provider ahead of
time, so when the provider creation returned with nil for provider, we tried to
cleanup a nil provider, and panicked.
Previously, the only constructor for the etwlogrus hook accepted a name, and
created a new ETW provider with that name. With this change, there is another
constructor which takes an already created ETW provider. This is to allow the
use of the ETW provider for other things, such as if the application wants to
support ETW capture state.
ETW and Logrus have similar, but different definitiosn of log level.
Originally, the plan was to just convert the integer value of the Logrus level
to an ETW level, and leave it at that. However, it turns out there are tools
that assume you are logging with the standard set of ETW log level. So now we
will map the Logrus level to an ETW level, so that these tools better.