-
-
Notifications
You must be signed in to change notification settings - Fork 21.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create script API for reading and writing zip files #34444
Conversation
2740f84
to
ad31e03
Compare
ad31e03
to
e688cd3
Compare
It seems the rebase failed, as lots of unrelated commits are included. Also, I think ZipWriter should be called ZIPPacker to be consistent with the PCKPacker class we currently have. Likewise, ZipReader should be called ZIPReader. |
e688cd3
to
5b1cc71
Compare
Ah, oops, I rebased on 3.2 instead of master. I've renamed the classes and fixed a couple build errors. |
875e56f
to
f773877
Compare
@akien-mga Is this still a feature you'd want to include in some version of 3.2? |
fde5ae1
to
bd624be
Compare
What is the status on this? |
@Frontrider The |
i tested this zip-module-3.2.1 , works nice, and its very useful, |
@avril-gh New features are added to |
@asheraryam Thank's for clarifying. Didnt know about this workflow. 👍
been wondering, because i already tried it and this PR does not work with 3.2 due to differences in 4.0 . |
@avril-gh This pull request could be remade for the |
I've backported this to 3.2 in my branch here: https://github.com/flyingpimonster/godot/tree/zip-module-3.2 Should I open a separate pull request? |
Previously, the file mode would be write-only if the write flag was present, and read-only if it wasn't. However, ADDINZIP mode requires read-write mode, and CREATE requires the file to be truncated. Fixed by checking all of the relevant flags individually and constructing a correct file access mode.
Rebased. |
Very much looking forward to this, as well as the backport to 3.x. It would untie my hands for a lot of optimizations and improvements in my project. I know it is not likely, but if there is anything I could do to expedite this PR, please let me know. |
How would I access these two classes in a script? I am trying to use the filedialog to save a file as a .zip and also be able to open/edit images within the .zip for resaving using the signals if I can. |
Sorry for the delay reviewing this - we finally discussed and approved the linked proposal, and this seems to be a fairly straightforward implementation for it. Would be good if @bruvzg could review. Some changes will be needed to adapt to the new RefCounted Finally, I think that this would make sense to have in The commit history could likely also be rebased as we usually don't use so much granularity in the implementation of features (we prefer a small number of commits - often 1 - that directly implements the finalized feature, not the intermediate WIP history). |
Can this be cherry-picked for Godot 3.5 or at least 3.x ? |
3.5 is nearing release, so I'm afraid not. There's another pull request remaking this feature for |
Thank you Hugo |
} | ||
|
||
do { | ||
char filename[256]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure about this limit ?
filename contains not only the name of the file, but also it path within the archive (e.g. foo/bar/spam.txt
)
So the limit is fine on Windows where path are limited to 250 characters (but I think to recall there is special case in Windows where this might be longer), but on Linux/Mac 255 is the max size of file name (and entire path is at least 1024 bytes).
So I think it would be better to set a bigger buffer here
Typically doing something like
char filename[256]; | |
char filename[256]; // Note filename is a path ! | |
int err = unzGetCurrentFileInfo64(uzf, NULL, filename, sizeof(filename), NULL, 0, NULL, 0); | |
if (err == UNZ_OK) { | |
s.push_back(filename); | |
} else { | |
// Assume filename buffer was too small | |
unz_file_info64 file_info; | |
int err = unzGetCurrentFileInfo64(uzf, &file_info, NULL, 0, NULL, 0, NULL, 0); | |
char long_filename_buff = memalloc(file_info.size_filename); | |
int err = unzGetCurrentFileInfo64(uzf, NULL, long_filename_buff, sizeof(filename), NULL, 0, NULL, 0); | |
s.push_back(long_filename_buff); | |
memfree(long_filename_buff); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the limit is fine on Windows where path are limited to 250 characters
By default, Windows MAX_PATH
is 260 (but it's possible to disable the limit on Windows 10+). Unicode UNC (\\?\
prefixed) paths are limited to 32K UTF-16 characters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what limits Zip itself imposes, but:
- If you use
\\?\
-format paths (every NT-based Windows that's still in any way relevant) or enable Win32 long paths via group policy or the registry (Windows 10), then you're subject to much longer filesystem-based length limits on Windows. - Various POSIX-specified libc functions are limited to
PATH_MAX
(limits.h
) by a buffer allocation, which is typically 4096, but you can work around that.
Here are the limits I'm aware of:
- FAT32: 32,760 "Unicode characters" for paths, 255 "Unicode characters" for filenames
- exFAT: 32,760 "Unicode characters" for paths, 255 "Unicode characters" for filenames
- NTFS: 32,768 "Unicode characters" for paths, 255 "Unicode characters" for filenames
- ReFS: 32,768 "Unicode characters" for paths, 255 "Unicode characters" for filenames
- UDF: 1023 bytes for paths, 255 bytes for filenames
- ext2/3/4: No limit for paths (As I demonstrate with some Python here), 255 bytes for filenames
- HFS+: No limit for paths as far as I was able to google up, 255 bytes for filenames
As far as I'm aware, "Unicode characters" means 16-bit code units.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ZIP format uses a 16-bit value to store filename length, so it's probably limited to 64K (UTF-8). Not sure if there are extra limitations, but it's probably better to always use unz_file_info64
and allocate space for filename on demand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also...
So the limit is fine on Windows where path are limited to 250 characters
Actually, if I remember correctly, the limit is 260 characters and they chose that limit based on A:\<some buffer that allocates for 256 chars><NUL>
.
ZIP format uses a 16-bit value to store filename length, so it's probably limited to 64K (UTF-8).
Yeah. No clue about the upper limit, but there are plenty of google results with people complaining about this or that unzipping tool erroring out because the Zip file contains paths longer than 260 and the tool isn't using \\?\
.
(Apparently long titles are common in science and lawyers like to pack as much of the beginning of the document's contents into the filename as possible as a hack for searchability.)
@akien-mga do you think this PR will be able to make it into Godot 4.0 ? The asset store currently doesn't play well with Godot-Python (the assets must be stored as a git repo and there is no possibility to provide different asset per platform, so for Godot 3 I have to put ~200mo of data on a git repo for each release... ) Long story short, I wrote a Godot-Python installer addon in GDScript that download just the right data. This works great except I need a way bundle data...
So in the end having this PR merged for Godot 4.0 would help me a lot 😃 (of course Godot 4.0 feature freeze might already be there, so I would totally understand if this train as already left ^^) |
@RevoluPowered You mentioned you wanted to read and write zips. |
I created a squashed version of this PR's branch and rebased it on the lastest master: https://github.com/MisterMX/godot/tree/zip-module Not sure, if I should create a second PR or if @jameswestman wants to copy the changes. |
@MisterMX You might want to integrate the file path size changes suggested by touilleMan above if you haven't already, and then open a new PR from your repo branch and reference this PR in the description. For the actual commit, you can still give credit to the original author by using Thanks for salvaging this! |
We can close this since #65281 is merged, right? |
Yes! |
Closing as salvaged in #65281. |
Bugsquad edit: this was salvaged and merged in #65281.
Bugsquad edit:
master
version of #58900.This builds on #22554, which only supported writing zip files.
Creates two new classes, ZipReader and ZipWriter, for reading and writing zip files in GDScript using the already bundled minizip library.
Example:
Note: Append modes don't work yet due to a bug in
core/io/zip_io.cpp
. Thezipio_open
function doesn't properly handle theZLIB_FILEFUNC_MODE_EXISTING
flag. I'll fix that in another PR.Bugsquad edit: This closes godotengine/godot-proposals#1069.