Commit Graph
100 Commits
Author SHA1 Message Date
Igor Anić 9cfac4718d fetch: combine unpack error validation in a single function
Follow up of: #19500
[discussion](https://github.com/ziglang/zig/pull/19500#discussion_r1558238138)
2024-04-11 15:44:40 -07:00
Igor Anić 4151e6c31b fetch: use arena allocator for diagnostic/UnpackResult
Reference:
https://github.com/ziglang/zig/pull/19500#discussion_r1556476973

Arena is now used for Diagnostic (tar and git). `deinit` is not called on Diagnostic
allowing us to reference strings from Diagnostic in UnpackResult without
dupe.

That seamed reasonable to me. Instead of using gpa for Diagnostic, and
then dupe to arena. Or using arena for both and making dupe so we can deinit
Diagnostic.
2024-04-09 15:00:22 +02:00
Igor Anić f8dd2a1064 fetch: add executable bit test 2024-04-09 15:00:22 +02:00
Igor Anić 8c58b8fe01 fetch: refactor package root in errors
Use stripRoot in less places. Strip it while copying error from
diagnostic to unpack result so other palaces can be free of this logic.
2024-04-09 15:00:22 +02:00
Igor Anić b422e4a202 fetch: save test cases
Prepare test cases, store them in Fetch/testdata.
They cover changes in this PR as well from previous one #19111.
2024-04-09 15:00:22 +02:00
Igor Anić 3d5a9237f7 fetch: use empty string instead of null for root_dir
Make it consistent with Cache.Path sub_path.
Remove null check in many locations.
2024-04-09 15:00:22 +02:00
Igor Anić 5f0b434f90 fetch: remove root_dir from error messages
To be consistent with paths in manifest.
2024-04-09 15:00:22 +02:00
Igor Anić 22e9c50376 fetch: fix test tarball
Should include folder structure, at least root folder so it can be found
in pipeToFileSystem.
2024-04-09 15:00:21 +02:00
Igor Anić fc745fb05c fetch: remove test with mount and net dependencies 2024-04-09 15:00:21 +02:00
Igor Anić 84fac2242c fix zig fmt 2024-04-09 15:00:21 +02:00
Igor Anić dc61c2e904 add comments 2024-04-09 15:00:21 +02:00
Igor Anić 373d48212f fetch: add pathological packages test
Using test cases from:
https://github.com/ianprime0509/pathological-packages repository.
Depends on existence of the FAT32 file system. Folder is in FAT32 file
system because it is case insensitive and and does not support symlinks.

It is complicated test case requires internet connection, depends on
existence of FAT32 in the specific location. But it is so valuable for
development. Running `zig test Package.zig` is so much faster than
building zig binary and running `zig fetch URL`. Committing it here
although it should probably be removed.
2024-04-09 15:00:21 +02:00
Igor Anić 5a38924a7d fetch.git: collect file create diagnostic errors
On case insensitive file systems, don't overwrite files with same name
in different casing. Add diagnostic error so caller could decide what to do.
2024-04-09 15:00:21 +02:00
Igor Anić ad60b6c1ed fetch: update comments 2024-04-09 15:00:21 +02:00
Igor Anić dfec4918a3 fetch: remove absolute path from tests 2024-04-09 15:00:21 +02:00
Igor Anić 4d6a7e074b fetch: filter unpack errors
Report only errors which are not filtered by paths in build.zig.zon.
2024-04-09 15:00:21 +02:00
Igor Anić a0790914b4 fetch: return UnpackResult from unpackResource
Test that we are still outputing same errors.
2024-04-09 15:00:21 +02:00
Igor Anić b3339f3cd5 tar: store diagnostic errors into UnpackResult
Test that UnpackResult prints same error output as diagnostic.
2024-04-09 15:00:21 +02:00
Igor Anić 9e47857ae9 fetch: make failing test 2024-04-09 15:00:21 +02:00
Igor Anić 34bb670bb6 package manager: set executable bit
Based on file content. Detects elf magic header or shebang line.

Executable bit is ignored in hash calculation, as it was before this. So
packages hashes are not changed.

Reference:
https://github.com/ziglang/zig/issues/17463#issuecomment-1984798880

Fixes: 17463

Test is here:
https://github.com/ianic/zig-fetch-test/blob/7c4600d7bb263f9b72fe3d0b70071f42be89e25c/src/main.zig#L307
(if #19500 got accepted I'll move this test to the Fetch.zig)
2024-04-06 13:00:57 -07:00
Igor Anić a60b7af2c1 fetch: fix manifest included paths filtering
Filter should be applied on path where package root folder (if
there is any) is stripped. Manifest is inside package root and has paths
relative to package root not temporary directory root.
2024-04-04 01:59:15 +02:00
Igor Anić 8545cb0147 fetch: use package root detection pipeToFileSystem
Based on:
https://github.com/ziglang/zig/pull/19111#discussion_r1548620985

In pipeToFileSystem we are already iterating over all files in tarball.
Inspecting them there for existence of single root folder saves two
syscalls later.
2024-04-03 21:20:39 +02:00
Igor Anić 363acf4991 fetch: update comments 2024-04-03 21:17:57 +02:00
Igor Anić 1431e34cb9 fetch: remove one openDir in runResource
Based on comment:
https://github.com/ziglang/zig/pull/19111#discussion_r1548640939

computeHash finds all files in temporary directory. There is no
difference on what path are they. When calculating hash normalized_path
must be set relative to package root. That's the place where we strip
root if needed.
2024-04-03 21:01:29 +02:00
Igor Anić b1e70edd90 tar: find package root dir in pipeToFileSystem
While iterating over all files in tarball set root_dir in diagnostic if
there is single root in tarball. Will be used in package manager with
strip_components = 0 to find the root of the fetched package.
2024-04-03 19:44:51 +02:00
Igor Anić 24304a4385 fetch: save syscall, and add comment
From review comments: https://github.com/ziglang/zig/pull/19111
2024-04-03 17:08:41 +02:00
Igor Anić c4261bf562 fetch: find package root only for archives 2024-04-03 17:06:20 +02:00
Igor Anić 15ca0c9471 fix typo 2024-04-03 17:06:20 +02:00
Igor Anić a5a928b966 package manager: don't strip components in tar
Unpack tar without removing leading root folder. Then find package root
in unpacked tmp folder.
2024-04-03 17:06:20 +02:00
Igor Anić bc5076715b fetch: fix failing test
Prior to
[this](https://github.com/ziglang/zig/commit/ef9966c9855dd855afda767f212abec6e5a36307#diff-08c935ef8c633bb630641d44230597f1cff5afb0e736d451e2ba5569fa53d915R805)
commit tar was not a valid extension. After that this one is valid case.
2024-04-03 17:06:20 +02:00
Igor Anić b88ae8dbd8 std.tar: implement executable bit only 2024-04-02 14:02:43 -07:00
Igor Anić 254c05a9e1 io_uring: simplify copy_cqe logic
First copy as much as we can in this cycle. If there is more needed
wrap and start from the buffer 0 position.
2024-03-31 23:57:16 +02:00
Igor Anić 704660c81a io_uring: fix copy_cqes logic 2024-03-31 23:52:46 +02:00
Igor Anić 631c28c9e3 io_uring: add failing test
For issue: #19451
2024-03-31 23:51:40 +02:00
Igor Anić e831313b10 std.io: remove BufferedTee
Introduced in  #19032 as a fix for #18967.
Not needed any more after #19253.
2024-03-20 21:05:35 -07:00
Igor Anić 3ea1276eeb io_uring: ring mapped buffers (#17806)
* io_uring: ring mapped buffers

Ring mapped buffers are newer implementation of ring provided buffers, supported
since kernel 5.19. Best described in Jens Axboe [post](https://github.com/axboe/liburing/wiki/io_uring-and-networking-in-2023#provided-buffers)

This commit implements low level io_uring_*_buf_ring_* functions as mostly
direct translation from liburing. It also adds BufferGroup abstraction over those
low level functions.

* io_uring: add multishot recv to BufferGroup

Once we have ring mapped provided buffers functionality it is possible to use
multishot recv operation. Multishot receive is submitted once, and completions
are posted whenever data arrives on the socket. Received data are placed in a
new buffer from buffer group.

Reference: [io_uring and networking in 2023](https://github.com/axboe/liburing/wiki/io_uring-and-networking-in-2023#multi-shot)

Getting NOENT for cancel completion result, meaning:
  -ENOENT
    The request identified by user_data could not be located.
    This could be because it completed before the cancelation
    request was issued, or if an invalid identifier is used.

https://man7.org/linux/man-pages/man3/io_uring_prep_cancel.3.html
https://github.com/ziglang/zig/actions/runs/6801394000/job/18492139893?pr=17806

Result in cancel/recv cqes are different depending on the kernel.
on older kernel (tested with v6.0.16, v6.1.57, v6.2.12, v6.4.16)
  cqe_cancel.err() == .NOENT
  cqe_crecv.err() == .NOBUFS
on kernel (tested with v6.5.0, v6.5.7)
  cqe_cancel.err() == .SUCCESS
  cqe_crecv.err() == .CANCELED
2024-03-15 22:34:31 -04:00
Igor Anić 791c4491a7 compress.xz: remove unnecessary variable
`to_read.items.len is always zero when entering readBlock.
2024-03-13 18:43:36 +01:00
Igor Anić 54f882c4aa compress.xz: make reader loop little more readable
No need to do same error check on two places. First return all
uncompressed data then on last read check error.
2024-03-13 18:41:20 +01:00
Igor Anić a21f9b6d8b compress.xz: remove copyForwards from tight loop
In the example from the issue #19052 to_read holds 213_315_584
uncompressed bytes. Calling read with small output results in many
shifts of that big buffer.
This removes need to shift to_read after each read.
2024-03-13 18:22:08 +01:00
Igor Anić f8f43ca3e1 package: remove git fetch zlib lookahead fix
My first zlib implementation broke git fetch because it introduce
[lookahead](https://github.com/ziglang/zig/issues/18967). That resulted
in workarounds [1](https://github.com/ziglang/zig/commit/80f3ef6e14a1213d1c3b31d515870afb43cc9379)
[2](https://github.com/ziglang/zig/commit/d00faa2407cdeaa058da62f2d95f64f9e7ed6a09)

After [fixing](https://github.com/ziglang/zig/pull/19163) lookahead in
zlib decompressor this fixes are no longer necessary.
2024-03-11 16:49:21 -07:00
Igor Anić c974e19816 docs: make docs work with recent tar changes
It is no longer need to call skip if file content is not consumed. It is
handled internally now. File types are now same as in os.File.
2024-03-11 13:30:26 +01:00
Igor Anić 0cca7e732e std.tar: fix broken public interface 2024-03-11 12:25:51 +01:00
Igor Anić c4868b2bbc std.tar: use doctest
Make std.tar look better in docs. Remove from public interface what is
not necessary. Add comment to the public methods. Add doctest as usage
examples for iterator and pipeToFileSystem.
2024-03-11 12:25:03 +01:00
Igor Anić a9e7abda20 std.tar: fix test hanging on windows
Problem was manifested only on windows with target `-target
aarch64-windows-gnu`.

I was creating new files but not closing any of them. Tmp dir cleanup
hangs looping in deleteTree forever.
2024-03-11 12:24:11 +01:00
Igor Anić 8ec990d6d7 disable test which is hanging on windows in ci
When this test is enabled something like:
`zig build test docs --zig-lib-dir .\lib\ -Dstatic-llvm -Dskip-non-native -Denable-symlinks-windows`
never finishes.

Those are failed runs from ci:
https://github.com/ziglang/zig/actions/runs/8137710393
https://github.com/ziglang/zig/actions/runs/8129619923
https://github.com/ziglang/zig/actions/runs/8125845128

Isolating that test and running it is not a problem. Running something
like `zig test .\lib\std\std.zig  --zig-lib-dir .\lib\` is fine.
2024-03-11 12:24:11 +01:00
Igor Anić 8cc35a0255 std.tar: fix path testing on windows
Fixing ci error: error:

'tar.test.test.pipeToFileSystem' failed: slices differ. first difference occurs at index 2 (0x2)

============ expected this output: =============  len: 9 (0x9)

2E 2E 2F 61 2F 66 69 6C  65                       ../a/file

============= instead found this: ==============  len: 9 (0x9)

2E 2E 5C 61 5C 66 69 6C  65                       ..\a\file

After #19136 dir.symlink changes path separtors to \ on windows.
2024-03-11 12:24:11 +01:00
Igor Anić 67336ca8c6 std.tar: fix build on 32 bit platform
Fixing error from ci:

std/tar.zig:423:54: error: expected type 'usize', found 'u64'
std/tar.zig:423:54: note: unsigned 32-bit int cannot represent all possible unsigned 64-bit values
2024-03-11 12:24:11 +01:00
Igor Anić f5fd4691e5 std.tar: document iterator interface with example 2024-03-11 12:24:06 +01:00
Igor Anić 614161a7cf std.tar make iterator interface more ergonomic
for the then end users:

1. Don't require user to call file.skip() on file returned from
iterator.next if file is not read. Iterator will now handle this.
Previously that returned header parsing error, without knowing some tar
internals it is hard to understand what is required from user.

2. Use iterator.File.kind enum which is similar to fs.File.Kind,
something familiar. Internal Header.Kind has many types which are not
exposed but the user needs to have else in kind switch to cover those
cases.

3. Add reader interface to the iterator.File.
2024-03-11 12:22:12 +01:00
Igor Anić 5ccbb196ad std.tar: don't return in iterator init
Don't assert min buffer size on iterator init. That was changing public
interface. This way we don't break that interface.
2024-03-11 12:22:12 +01:00
Igor Anić 10add7c677 std.tar: remove redundant test name prefixes 2024-03-11 12:22:12 +01:00
Igor Anić 04e8bbd932 std.tar: test buffers provided to the iterator
Tar header stores name in max 256 bytes and link name in max 100 bytes.
Those are minimums for provided buffers. Error is raised during iterator
init if buffers are not long enough.

Pax and gnu extensions can store longer names. If such extension is
reached during unpack and don't fit into provided buffer error is
returned.
2024-03-11 12:22:12 +01:00
Igor Anić af0502f6c4 std.tar: add tests for file and symlink create
Should do that before I broke package manager!
2024-03-11 12:22:00 +01:00
Igor Anić a06a305f97 zlib: fix missing comptime attribute 2024-03-04 09:53:01 +01:00
Igor Anić c680b5d138 compress.zlib: add overshoot test cast
Using example from [zigimg](https://github.com/zigimg/zigimg/pull/164) project.
2024-03-04 09:53:01 +01:00
Igor Anić f2508abfa6 flate: use 4 bytes lookahead for zlib
That ensures no bytes are left in the BitReader buffer after we reach
end of the stream.
2024-03-04 09:53:01 +01:00
Igor Anić 711281602a flate: option to fill BitReader
fill(0) will fill all bytes in bit reader. If bit reader is aligned to
the byte, as it is at the end of the stream this ensures no overshoot
when reading footer. Footer is 4 bytes (zlib) or 8 bytes (gzip). For
zlib we will use 4 bytes BitReader and 8 for gzip. After align and fill
we will read those bytes and leave BitReader empty after that.
2024-03-04 09:53:01 +01:00
Igor Anić 8a963fd66e flate: 32 bit BitReader
Extend BitReader to accept size of internal buffer. It can be u64 (only
option until now) or u32.
2024-03-04 09:53:01 +01:00
Igor Anić e57800610b std.tar: disable test failing on windows
Just to pass ci of regression fix #19126.
I'll return to this later.
Currently can't reproduce on my Windows wm, here I'm failing on symlink creation
in ci fails later in the process.
2024-02-29 07:57:49 +01:00
Igor Anić 7d536e8970 std.tar: fix unconditional error return 2024-02-29 01:22:49 +01:00
Igor Anić 62ce753814 compress: activate tests in wasm32
They were disabled because insufficient stack size.
That is
[changed](https://github.com/ziglang/zig/commit/d51aa9748f9e4e3616328a207a8047ff37d81f8b) now.
2024-02-27 19:19:59 -08:00
Igor Anić 65e5c46d61 std.tar fix refactored function
It was not returning error in all cases. Bug in refactoring.
2024-02-26 00:24:23 +01:00
Igor Anić f086ea856c std.tar skip test on windows
Or other platform which don't support symlinks.
2024-02-25 15:57:20 +01:00
Igor Anić 30a319be6d std.tar improve error reporting
Report file name which failed to create in all cases.
2024-02-25 12:03:23 +01:00
Igor Anić 96e4d56819 std.tar add case sensitive file name test
Like in issue #18089, this tar contains, same file name in two case
sensitive name version. Unpack should fail on case insensitive file
systems and succeed on case sensitive.

$ tar tvf 18089.tar
    18089/
    18089/alacritty/
    18089/alacritty/darkermatrix.yml
    18089/alacritty/Darkermatrix.yml
2024-02-25 10:35:18 +01:00
Igor Anić b84301c8e5 std.tar don't overwrite existing file
Fail with error if file already exists. File is not silently overwritten
but an error is raised.

Fixes: #18089
2024-02-24 23:37:55 +01:00
Igor Anić 8d651f512b std.tar fix assert exploited by fuzzing 2024-02-24 13:17:04 -08:00
Igor Anić 0a86b117bf std.tar fix integer overflow in header size parse
Found by fuzzing. Fixing code and adding test.
2024-02-23 21:57:40 +01:00
Igor Anić f67aa8b9b3 std.tar fix parsing mode field in tar header
Found by fuzzing. Previous numeric function assumed that is is getting
buffer of size 12, mode is size 8. Fuzzing found overflow.
Fixing and adding test cases.
2024-02-23 21:57:15 +01:00
Igor Anić 30f15e3afe fix crash in tar found by fuzzing
Running fuzzing tar test with [zig std lib
fuzzing](https://github.com/squeek502/zig-std-lib-fuzzing) reached and
assert in tar implementation. Assert (in std lib) should not be
reachable by external input, so I'm fixing this to return error.
2024-02-22 18:20:05 -08:00
Igor Anić a5326c5ef8 return few previous fixes
Review: https://github.com/ziglang/zig/pull/19032#pullrequestreview-1896251841
2024-02-22 17:20:41 +01:00
Igor Anić d00faa2407 use BufferedTee in Fetch/git.zig 2024-02-22 15:18:03 +01:00
Igor Anić eb67fab2d9 refactor according to Ian's review
https://github.com/ziglang/zig/pull/19032#pullrequestreview-1894702793
2024-02-22 12:29:21 +01:00
Igor Anić ce1a590fc9 cleanup tests 2024-02-21 20:26:29 +01:00
Igor Anić d995029844 add BufferedTee
BufferedTee provides reader interface to the consumer. Data read by consumer
is also written to the output. Output is hold lookahead_size bytes behind
consumer. Allowing consumer to put back some bytes to be read again. On flush
all consumed bytes are flushed to the output.

      input   ->   tee   ->   consumer
                    |
                 output

input - underlying unbuffered reader
output - writer, receives data read by consumer
consumer - uses provided reader interface

If lookahead_size is zero output always has same bytes as consumer.
2024-02-21 20:01:45 +01:00
Igor Anić 3e8cb153ea fix flate regression
Until now literal and distance code lengths where treated as two
different arrays. But according to rfc they can overlap:

  The code length repeat codes can cross from HLIT + 257 to the
  HDIST + 1 code lengths.  In other words, all code lengths form
  a single sequence of HLIT + HDIST + 258 values.

Now code lengths are decoded in single array which is then split
to literal and distance part.
2024-02-17 15:31:13 -08:00
Igor Anić 99cb201438 skip failing wasm tests 2024-02-15 00:35:08 +01:00
Igor Anić fd9db4962c reorganize compress package root folder 2024-02-14 23:34:13 +01:00
Igor Anić 2457b68b2f remove v1 deflate implementation 2024-02-14 22:34:13 +01:00
Igor Anić e20080be13 preserve valuable tests from v1 implementation
Before removal of v1.
2024-02-14 22:12:54 +01:00
Igor Anić 0afe808928 remove testing struct sizes
It was usefull during development.

From andrewrk code review comment:
In fact, Zig does not guarantee the @sizeOf structs, and so these tests are not valid.
2024-02-14 21:06:45 +01:00
Igor Anić d49cdf5b2d skip calculating struct sizes on 32 bit platforms 2024-02-14 19:58:45 +01:00
Igor Anić c2361bf548 fix top level docs comments
I didn't understand the difference.

ref: https://ziglang.org/documentation/0.11.0/#Comments
2024-02-14 18:28:20 +01:00
Igor Anić 5fbc371b41 fix wording in comment 2024-02-14 18:28:20 +01:00
Igor Anić f81b3a2095 fix reading input stream during decompression
By using read instead of readAll decompression reader could get bytes
then available in the stream and then later wrongly failed with end of
stream.
2024-02-14 18:28:20 +01:00
Igor Anić 0cba50d73e set testdata as binary
Testing on windows is failing because line ending are changed on some
binary files during git checkout.
2024-02-14 18:28:20 +01:00
Igor Anić d645114f7e add deflate implemented from first principles
Zig deflate compression/decompression implementation. It supports compression and decompression of gzip, zlib and raw deflate format.

Fixes #18062.

This PR replaces current compress/gzip and compress/zlib packages. Deflate package is renamed to flate. Flate is common name for deflate/inflate where deflate is compression and inflate decompression.

There are breaking change. Methods signatures are changed because of removal of the allocator, and I also unified API for all three namespaces (flate, gzip, zlib).

Currently I put old packages under v1 namespace they are still available as compress/v1/gzip, compress/v1/zlib, compress/v1/deflate. Idea is to give users of the current API little time to postpone analyzing what they had to change. Although that rises question when it is safe to remove that v1 namespace.

Here is current API in the compress package:

```Zig
// deflate
    fn compressor(allocator, writer, options) !Compressor(@TypeOf(writer))
    fn Compressor(comptime WriterType) type

    fn decompressor(allocator, reader, null) !Decompressor(@TypeOf(reader))
    fn Decompressor(comptime ReaderType: type) type

// gzip
    fn compress(allocator, writer, options) !Compress(@TypeOf(writer))
    fn Compress(comptime WriterType: type) type

    fn decompress(allocator, reader) !Decompress(@TypeOf(reader))
    fn Decompress(comptime ReaderType: type) type

// zlib
    fn compressStream(allocator, writer, options) !CompressStream(@TypeOf(writer))
    fn CompressStream(comptime WriterType: type) type

    fn decompressStream(allocator, reader) !DecompressStream(@TypeOf(reader))
    fn DecompressStream(comptime ReaderType: type) type

// xz
   fn decompress(allocator: Allocator, reader: anytype) !Decompress(@TypeOf(reader))
   fn Decompress(comptime ReaderType: type) type

// lzma
    fn decompress(allocator, reader) !Decompress(@TypeOf(reader))
    fn Decompress(comptime ReaderType: type) type

// lzma2
    fn decompress(allocator, reader, writer !void

// zstandard:
    fn DecompressStream(ReaderType, options) type
    fn decompressStream(allocator, reader) DecompressStream(@TypeOf(reader), .{})
    struct decompress
```

The proposed naming convention:
 - Compressor/Decompressor for functions which return type, like Reader/Writer/GeneralPurposeAllocator
 - compressor/compressor for functions which are initializers for that type, like reader/writer/allocator
 - compress/decompress for one shot operations, accepts reader/writer pair, like read/write/alloc

```Zig
/// Compress from reader and write compressed data to the writer.
fn compress(reader: anytype, writer: anytype, options: Options) !void

/// Create Compressor which outputs the writer.
fn compressor(writer: anytype, options: Options) !Compressor(@TypeOf(writer))

/// Compressor type
fn Compressor(comptime WriterType: type) type

/// Decompress from reader and write plain data to the writer.
fn decompress(reader: anytype, writer: anytype) !void

/// Create Decompressor which reads from reader.
fn decompressor(reader: anytype) Decompressor(@TypeOf(reader)

/// Decompressor type
fn Decompressor(comptime ReaderType: type) type

```

Comparing this implementation with the one we currently have in Zig's standard library (std).
Std is roughly 1.2-1.4 times slower in decompression, and 1.1-1.2 times slower in compression. Compressed sizes are pretty much same in both cases.
More resutls in [this](https://github.com/ianic/flate) repo.

This library uses static allocations for all structures, doesn't require allocator. That makes sense especially for deflate where all structures, internal buffers are allocated to the full size. Little less for inflate where we std version uses less memory by not preallocating to theoretical max size array which are usually not fully used.

For deflate this library allocates 395K while std 779K.
For inflate this library allocates 74.5K while std around 36K.

Inflate difference is because we here use 64K history instead of 32K in std.

If merged existing usage of compress gzip/zlib/deflate need some changes. Here is example with necessary changes in comments:

```Zig

const std = @import("std");

// To get this file:
// wget -nc -O war_and_peace.txt https://www.gutenberg.org/ebooks/2600.txt.utf-8
const data = @embedFile("war_and_peace.txt");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer std.debug.assert(gpa.deinit() == .ok);
    const allocator = gpa.allocator();

    try oldDeflate(allocator);
    try new(std.compress.flate, allocator);

    try oldZlib(allocator);
    try new(std.compress.zlib, allocator);

    try oldGzip(allocator);
    try new(std.compress.gzip, allocator);
}

pub fn new(comptime pkg: type, allocator: std.mem.Allocator) !void {
    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    var cmp = try pkg.compressor(buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.finish();

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    var dcp = pkg.decompressor(fbs.reader());

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldDeflate(allocator: std.mem.Allocator) !void {
    const deflate = std.compress.v1.deflate;

    // Compressor
    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();
    // Remove allocator
    // Rename deflate -> flate
    var cmp = try deflate.compressor(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.close(); // Rename to finish
    cmp.deinit(); // Remove

    // Decompressor
    var fbs = std.io.fixedBufferStream(buf.items);
    // Remove allocator and last param
    // Rename deflate -> flate
    // Remove try
    var dcp = try deflate.decompressor(allocator, fbs.reader(), null);
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldZlib(allocator: std.mem.Allocator) !void {
    const zlib = std.compress.v1.zlib;

    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    // Rename compressStream => compressor
    // Remove allocator
    var cmp = try zlib.compressStream(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.finish();
    cmp.deinit(); // Remove

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    // decompressStream => decompressor
    // Remove allocator
    // Remove try
    var dcp = try zlib.decompressStream(allocator, fbs.reader());
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

pub fn oldGzip(allocator: std.mem.Allocator) !void {
    const gzip = std.compress.v1.gzip;

    var buf = std.ArrayList(u8).init(allocator);
    defer buf.deinit();

    // Compressor
    // Rename compress => compressor
    // Remove allocator
    var cmp = try gzip.compress(allocator, buf.writer(), .{});
    _ = try cmp.write(data);
    try cmp.close(); // Rename to finisho
    cmp.deinit(); // Remove

    var fbs = std.io.fixedBufferStream(buf.items);
    // Decompressor
    // Rename decompress => decompressor
    // Remove allocator
    // Remove try
    var dcp = try gzip.decompress(allocator, fbs.reader());
    defer dcp.deinit(); // Remove

    const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize));
    defer allocator.free(plain);
    try std.testing.expectEqualSlices(u8, data, plain);
}

```
2024-02-14 18:28:20 +01:00
Igor Anić 7d3a31872e tar: improve diagnostic reporting
Using Python testtar file (mentioned in #14310) to test diagnostic
reporting.
Added computing checksum by using both unsigned and signed header bytes
values.
Added skipping gnu exteneded sparse headers while reporting unsupported
header in diagnostic.

Note on testing:

wget https://github.com/python/cpython/raw/3.11/Lib/test/testtar.tar -O
/tmp/testtar.tar

```
test "Python testtar.tar file" {
    const file_name = "testtar.tar";

    var file = try std.fs.cwd().openFile("/tmp/" ++ file_name, .{});
    defer file.close();

    var diag = Options.Diagnostics{ .allocator = std.testing.allocator };
    defer diag.deinit();

    var iter = iterator(file.reader(), &diag);
    while (try iter.next()) |f| {
        std.debug.print("supported: {} {s} {d}\n", .{ f.kind, f.name, f.size });
        try f.skip();
    }
    for (diag.errors.items) |e| {
        switch (e) {
            .unsupported_file_type => |u| {
                std.debug.print("unsupported: {} {s}\n", .{ u.file_type, u.file_name });
            },
            else => unreachable,
        }
    }
}
```
2024-01-13 19:37:33 -07:00
Igor Anić 7923a53996 tar: rename reader to iterator
Itarator has `next` function, iterates over tar files. When using from
outside of module with `tar.` prefix makes more sense.

var iter = tar.iterator(reader, null);
while (try iter.next()) |file| {
...
}
2024-01-13 19:37:33 -07:00
Igor Anić e21a12e56b tar: use @embedFile in tests
Like in other tests which uses testdata files (compress). That enables
wasi testing also, was failing because file system operations in tests.
2024-01-13 19:37:33 -07:00
Igor Anić 76fe1f53d5 tar: fix tests on 32-bit platforms 2024-01-13 19:37:33 -07:00
Igor Anić a75fd4ff15 tar: move test cases to std/tar/testdata
Create std/tar/test.zig for test which uses cases from testdata.
2024-01-13 19:37:33 -07:00
Igor Anić f8e42d6b30 tar: add Go test case files to the project 2024-01-13 19:37:33 -07:00
Igor Anić c07527abac tar: reorganize file, functions before tests 2024-01-13 19:37:33 -07:00
Igor Anić c76abe0e18 tar: use file word in less places 2024-01-13 19:37:33 -07:00
Igor Anić 4a6d67ab1a tar: remove stratch from tar reader
Use explicit buffers for name, link_name instead.
It is cleaner that way.
2024-01-13 19:37:33 -07:00
Igor Anić 9f7dd32308 tar: refactor pax attribute
Make it little readable.
2024-01-13 19:37:33 -07:00
Igor Anić dbab45cfc6 tar: replace custom buffered reader with std.io 2024-01-13 19:37:33 -07:00
Igor Anić 58e0e509c6 tar: add module comment and references 2024-01-13 19:37:33 -07:00
Igor Anić a3cf8ec71e tar: add pax file reader tests 2024-01-13 19:37:33 -07:00