projects
/
git.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
submodule update: add submodule.<name>.remote config option
[git.git]
/
archive-zip.c
diff --git
a/archive-zip.c
b/archive-zip.c
index f5af81f904df081002dad46a71be2eca8e3bebab..55f66b4060c64789bdb443f6c71f82a75ef22d0b 100644
(file)
--- a/
archive-zip.c
+++ b/
archive-zip.c
@@
-4,6
+4,7
@@
#include "cache.h"
#include "archive.h"
#include "streaming.h"
#include "cache.h"
#include "archive.h"
#include "streaming.h"
+#include "utf8.h"
static int zip_date;
static int zip_time;
static int zip_date;
static int zip_time;
@@
-16,7
+17,8
@@
static unsigned int zip_dir_offset;
static unsigned int zip_dir_entries;
#define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
static unsigned int zip_dir_entries;
#define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
-#define ZIP_STREAM (8)
+#define ZIP_STREAM (1 << 3)
+#define ZIP_UTF8 (1 << 11)
struct zip_local_header {
unsigned char magic[4];
struct zip_local_header {
unsigned char magic[4];
@@
-74,6
+76,14
@@
struct zip_dir_trailer {
unsigned char _end[1];
};
unsigned char _end[1];
};
+struct zip_extra_mtime {
+ unsigned char magic[2];
+ unsigned char extra_size[2];
+ unsigned char flags[1];
+ unsigned char mtime[4];
+ unsigned char _end[1];
+};
+
/*
* On ARM, padding is added at the end of the struct, so a simple
* sizeof(struct ...) reports two bytes more than the payload size
/*
* On ARM, padding is added at the end of the struct, so a simple
* sizeof(struct ...) reports two bytes more than the payload size
@@
-83,6
+93,9
@@
struct zip_dir_trailer {
#define ZIP_DATA_DESC_SIZE offsetof(struct zip_data_desc, _end)
#define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
#define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
#define ZIP_DATA_DESC_SIZE offsetof(struct zip_data_desc, _end)
#define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
#define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
+#define ZIP_EXTRA_MTIME_SIZE offsetof(struct zip_extra_mtime, _end)
+#define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
+ (ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
static void copy_le16(unsigned char *dest, unsigned int n)
{
static void copy_le16(unsigned char *dest, unsigned int n)
{
@@
-164,6
+177,17
@@
static void set_zip_header_data_desc(struct zip_local_header *header,
copy_le32(header->size, size);
}
copy_le32(header->size, size);
}
+static int has_only_ascii(const char *s)
+{
+ for (;;) {
+ int c = *s++;
+ if (c == '\0')
+ return 1;
+ if (!isascii(c))
+ return 0;
+ }
+}
+
#define STREAM_BUFFER_SIZE (1024 * 16)
static int write_zip_entry(struct archiver_args *args,
#define STREAM_BUFFER_SIZE (1024 * 16)
static int write_zip_entry(struct archiver_args *args,
@@
-173,6
+197,7
@@
static int write_zip_entry(struct archiver_args *args,
{
struct zip_local_header header;
struct zip_dir_header dirent;
{
struct zip_local_header header;
struct zip_dir_header dirent;
+ struct zip_extra_mtime extra;
unsigned long attr2;
unsigned long compressed_size;
unsigned long crc;
unsigned long attr2;
unsigned long compressed_size;
unsigned long crc;
@@
-187,6
+212,13
@@
static int write_zip_entry(struct archiver_args *args,
crc = crc32(0, NULL, 0);
crc = crc32(0, NULL, 0);
+ if (!has_only_ascii(path)) {
+ if (is_utf8(path))
+ flags |= ZIP_UTF8;
+ else
+ warning("Path is not valid UTF-8: %s", path);
+ }
+
if (pathlen > 0xffff) {
return error("path too long (%d chars, SHA1: %s): %s",
(int)pathlen, sha1_to_hex(sha1), path);
if (pathlen > 0xffff) {
return error("path too long (%d chars, SHA1: %s): %s",
(int)pathlen, sha1_to_hex(sha1), path);
@@
-246,8
+278,13
@@
static int write_zip_entry(struct archiver_args *args,
}
}
}
}
+ copy_le16(extra.magic, 0x5455);
+ copy_le16(extra.extra_size, ZIP_EXTRA_MTIME_PAYLOAD_SIZE);
+ extra.flags[0] = 1; /* just mtime */
+ copy_le32(extra.mtime, args->time);
+
/* make sure we have enough free space in the dictionary */
/* make sure we have enough free space in the dictionary */
- direntsize = ZIP_DIR_HEADER_SIZE + pathlen;
+ direntsize = ZIP_DIR_HEADER_SIZE + pathlen
+ ZIP_EXTRA_MTIME_SIZE
;
while (zip_dir_size < zip_dir_offset + direntsize) {
zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
zip_dir = xrealloc(zip_dir, zip_dir_size);
while (zip_dir_size < zip_dir_offset + direntsize) {
zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
zip_dir = xrealloc(zip_dir, zip_dir_size);
@@
-263,7
+300,7
@@
static int write_zip_entry(struct archiver_args *args,
copy_le16(dirent.mdate, zip_date);
set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
copy_le16(dirent.filename_length, pathlen);
copy_le16(dirent.mdate, zip_date);
set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
copy_le16(dirent.filename_length, pathlen);
- copy_le16(dirent.extra_length,
0
);
+ copy_le16(dirent.extra_length,
ZIP_EXTRA_MTIME_SIZE
);
copy_le16(dirent.comment_length, 0);
copy_le16(dirent.disk, 0);
copy_le16(dirent.attr1, 0);
copy_le16(dirent.comment_length, 0);
copy_le16(dirent.disk, 0);
copy_le16(dirent.attr1, 0);
@@
-281,11
+318,13
@@
static int write_zip_entry(struct archiver_args *args,
else
set_zip_header_data_desc(&header, size, compressed_size, crc);
copy_le16(header.filename_length, pathlen);
else
set_zip_header_data_desc(&header, size, compressed_size, crc);
copy_le16(header.filename_length, pathlen);
- copy_le16(header.extra_length,
0
);
+ copy_le16(header.extra_length,
ZIP_EXTRA_MTIME_SIZE
);
write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
zip_offset += ZIP_LOCAL_HEADER_SIZE;
write_or_die(1, path, pathlen);
zip_offset += pathlen;
write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
zip_offset += ZIP_LOCAL_HEADER_SIZE;
write_or_die(1, path, pathlen);
zip_offset += pathlen;
+ write_or_die(1, &extra, ZIP_EXTRA_MTIME_SIZE);
+ zip_offset += ZIP_EXTRA_MTIME_SIZE;
if (stream && method == 0) {
unsigned char buf[STREAM_BUFFER_SIZE];
ssize_t readlen;
if (stream && method == 0) {
unsigned char buf[STREAM_BUFFER_SIZE];
ssize_t readlen;
@@
-382,6
+421,8
@@
static int write_zip_entry(struct archiver_args *args,
zip_dir_offset += ZIP_DIR_HEADER_SIZE;
memcpy(zip_dir + zip_dir_offset, path, pathlen);
zip_dir_offset += pathlen;
zip_dir_offset += ZIP_DIR_HEADER_SIZE;
memcpy(zip_dir + zip_dir_offset, path, pathlen);
zip_dir_offset += pathlen;
+ memcpy(zip_dir + zip_dir_offset, &extra, ZIP_EXTRA_MTIME_SIZE);
+ zip_dir_offset += ZIP_EXTRA_MTIME_SIZE;
zip_dir_entries++;
return 0;
zip_dir_entries++;
return 0;