Skip to content

Commit 66521ff

Browse files
committed
Add remaining libzip compatibility apis
1 parent 3a0feee commit 66521ff

9 files changed

Lines changed: 227 additions & 9 deletions

File tree

src/include/otezip.h

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <stdlib.h>
3030
#include <stdio.h>
3131
#include <string.h>
32+
#include <time.h>
3233

3334
#include "config.h"
3435

@@ -69,6 +70,8 @@ typedef int64_t zip_int64_t;
6970
typedef int zip_flags_t; /* we don't interpret any flags for now */
7071
typedef int32_t zip_int32_t;
7172
typedef uint32_t zip_uint32_t;
73+
typedef uint16_t zip_uint16_t;
74+
typedef uint8_t zip_uint8_t;
7275

7376
/* an in-memory representation of a single directory entry */
7477
struct otezip_entry {
@@ -95,17 +98,25 @@ struct otezip_archive {
9598
struct otezip_file {
9699
uint8_t *data; /* complete uncompressed data */
97100
uint32_t size;
101+
zip_uint64_t pos; /* current read position for zip_fread */
98102
};
99103

100-
struct otezip_src_buf {
104+
struct otezip_src_buf {
101105
const void *buf;
102106
zip_uint64_t len;
103107
int freep;
104108
};
105109

110+
/* Error information structure */
111+
struct otezip_error {
112+
int zip_err; /* libzip error code (ZIP_ER_*) */
113+
int sys_err; /* copy of errno (E*) or zlib error code */
114+
};
115+
106116
typedef struct otezip_archive zip_t; /* opaque archive handle */
107117
typedef struct otezip_file zip_file_t; /* opaque file-in-memory handle */
108118
typedef struct otezip_src_buf zip_source_t;/* stub */
119+
typedef struct otezip_error zip_error_t; /* error structure */
109120

110121
/* Only flag we meaningfully accept at the moment. */
111122
#ifndef ZIP_RDONLY
@@ -124,25 +135,75 @@ typedef struct otezip_src_buf zip_source_t;/* stub */
124135
#define ZIP_TRUNCATE 8
125136
#endif
126137

138+
/* Compression methods */
139+
#define ZIP_CM_STORE 0 /* stored (uncompressed) */
140+
#define ZIP_CM_DEFLATE 8 /* deflated */
141+
142+
/* Maximum value for zip_uint64_t */
143+
#define ZIP_UINT64_MAX ((zip_uint64_t)-1)
144+
145+
/* libzip error codes */
146+
#define ZIP_ER_OK 0 /* No error */
147+
#define ZIP_ER_INVAL 18 /* Invalid argument */
148+
#define ZIP_ER_NOENT 9 /* No such file */
149+
#define ZIP_ER_EXISTS 10 /* File already exists */
150+
#define ZIP_ER_NOZIP 19 /* Not a zip archive */
151+
#define ZIP_ER_RDONLY 25 /* Read-only archive */
152+
153+
/* zip_stat flags */
154+
#define ZIP_STAT_NAME 0x0001u
155+
#define ZIP_STAT_INDEX 0x0002u
156+
#define ZIP_STAT_SIZE 0x0004u
157+
#define ZIP_STAT_COMP_SIZE 0x0008u
158+
#define ZIP_STAT_MTIME 0x0010u
159+
#define ZIP_STAT_CRC 0x0020u
160+
#define ZIP_STAT_COMP_METHOD 0x0040u
161+
162+
/* zip_stat structure */
163+
struct otezip_stat {
164+
zip_uint64_t valid; /* which fields have valid values */
165+
const char *name; /* name of the file */
166+
zip_uint64_t index; /* index within archive */
167+
zip_uint64_t size; /* size of file (uncompressed) */
168+
zip_uint64_t comp_size; /* size of file (compressed) */
169+
time_t mtime; /* modification time */
170+
zip_uint32_t crc; /* crc of file data */
171+
zip_uint16_t comp_method; /* compression method used */
172+
};
173+
174+
typedef struct otezip_stat zip_stat_t;
175+
127176
/* ---------------------------- public API ----------------------------- */
128177

129178
#ifdef __cplusplus
130179
extern "C" {
131180
#endif
132181

133182
zip_t * zip_open (const char *path, int flags, int *errorp);
183+
zip_t * zip_open_from_source(zip_source_t *src, int flags, zip_error_t *error);
134184
int zip_close (zip_t *za);
135185

136186
zip_uint64_t zip_get_num_files (zip_t *za);
137187
zip_int64_t zip_name_locate (zip_t *za, const char *fname, zip_flags_t flags);
188+
const char * zip_get_name (zip_t *za, zip_uint64_t index, zip_flags_t flags);
138189

139190
zip_file_t * zip_fopen_index (zip_t *za, zip_uint64_t index, zip_flags_t flags);
140191
int zip_fclose (zip_file_t *zf);
192+
zip_int64_t zip_fread (zip_file_t *zf, void *buf, zip_uint64_t nbytes);
141193

142194
zip_source_t * zip_source_buffer (zip_t *za, const void *data, zip_uint64_t len, int freep);
195+
zip_source_t * zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error);
196+
void zip_source_free (zip_source_t *src);
143197
zip_int64_t zip_file_add (zip_t *za, const char *name, zip_source_t *src, zip_flags_t flags);
198+
int zip_file_replace (zip_t *za, zip_uint64_t index, zip_source_t *src, zip_flags_t flags);
199+
int zip_replace (zip_t *za, zip_uint64_t index, zip_source_t *src);
200+
zip_int64_t zip_add (zip_t *za, const char *name, zip_source_t *src);
144201
int zip_set_file_compression(zip_t *za, zip_uint64_t index, zip_int32_t comp, zip_uint32_t comp_flags);
145202

203+
int zip_stat (zip_t *za, const char *fname, zip_flags_t flags, zip_stat_t *st);
204+
int zip_stat_index (zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st);
205+
void zip_stat_init (zip_stat_t *st);
206+
146207
#ifdef __cplusplus
147208
} /* extern "C" */
148209
#endif
@@ -163,12 +224,4 @@ extern int otezip_ignore_zipbomb;
163224
* Returns the OTEZIP_METHOD_* value or -1 if invalid/not supported. */
164225
int otezip_method_from_string(const char *method_name);
165226

166-
#ifdef __cplusplus
167-
extern "C" {
168-
#endif
169-
170-
#ifdef __cplusplus
171-
} /* extern "C" */
172-
#endif
173-
174227
#endif /* OTEZIP_H_ */

src/lib/otezip.c

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,7 @@ zip_file_t *zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t flags) {
12401240
}
12411241
zf->data = buf;
12421242
zf->size = sz;
1243+
zf->pos = 0;
12431244
return zf;
12441245
}
12451246

@@ -1252,6 +1253,100 @@ int zip_fclose(zip_file_t *zf) {
12521253
return 0;
12531254
}
12541255

1256+
zip_int64_t zip_fread(zip_file_t *zf, void *buf, zip_uint64_t nbytes) {
1257+
if (!zf || !buf) {
1258+
return -1;
1259+
}
1260+
if (zf->pos >= zf->size) {
1261+
return 0;
1262+
}
1263+
zip_uint64_t remaining = zf->size - zf->pos;
1264+
zip_uint64_t to_copy = (nbytes < remaining) ? nbytes : remaining;
1265+
memcpy (buf, (uint8_t *)zf->data + zf->pos, to_copy);
1266+
zf->pos += to_copy;
1267+
return (zip_int64_t)to_copy;
1268+
}
1269+
1270+
void zip_stat_init(zip_stat_t *st) {
1271+
if (!st) {
1272+
return;
1273+
}
1274+
st->valid = 0;
1275+
st->name = NULL;
1276+
st->index = ZIP_UINT64_MAX;
1277+
st->size = 0;
1278+
st->comp_size = 0;
1279+
st->mtime = (time_t)-1;
1280+
st->crc = 0;
1281+
st->comp_method = ZIP_CM_STORE;
1282+
}
1283+
1284+
int zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st) {
1285+
(void)flags;
1286+
if (!za || !st || index >= za->n_entries) {
1287+
return -1;
1288+
}
1289+
zip_stat_init (st);
1290+
struct otezip_entry *e = &za->entries[index];
1291+
st->name = e->name;
1292+
st->index = index;
1293+
st->size = e->uncomp_size;
1294+
st->comp_size = e->comp_size;
1295+
st->crc = e->crc32;
1296+
st->comp_method = e->method;
1297+
st->valid = ZIP_STAT_NAME | ZIP_STAT_INDEX | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_METHOD;
1298+
return 0;
1299+
}
1300+
1301+
const char *zip_get_name(zip_t *za, zip_uint64_t index, zip_flags_t flags) {
1302+
(void)flags;
1303+
if (!za || index >= za->n_entries) {
1304+
return NULL;
1305+
}
1306+
return za->entries[index].name;
1307+
}
1308+
1309+
int zip_stat(zip_t *za, const char *fname, zip_flags_t flags, zip_stat_t *st) {
1310+
zip_int64_t index = zip_name_locate (za, fname, flags);
1311+
if (index < 0) {
1312+
return -1;
1313+
}
1314+
return zip_stat_index (za, (zip_uint64_t)index, flags, st);
1315+
}
1316+
1317+
zip_t *zip_open_from_source(zip_source_t *src, int flags, zip_error_t *error) {
1318+
(void)error;
1319+
if (!src) {
1320+
return NULL;
1321+
}
1322+
/* Since otezip's zip_source_t is a simple buffer wrapper,
1323+
* we create a temporary file and write the buffer to it,
1324+
* then open the archive normally. */
1325+
char tmp_path[] = "/tmp/otezip_XXXXXX";
1326+
int fd = mkstemp (tmp_path);
1327+
if (fd < 0) {
1328+
return NULL;
1329+
}
1330+
/* Write the source buffer to the temp file */
1331+
ssize_t written = write (fd, src->buf, src->len);
1332+
close (fd);
1333+
if (written != (ssize_t)src->len) {
1334+
unlink (tmp_path);
1335+
return NULL;
1336+
}
1337+
/* Open the archive from the temp file */
1338+
int errorp = 0;
1339+
zip_t *za = zip_open (tmp_path, flags, &errorp);
1340+
if (!za) {
1341+
unlink (tmp_path);
1342+
return NULL;
1343+
}
1344+
/* Note: The temp file will be cleaned up when the archive is closed.
1345+
* This is a simple implementation; a more sophisticated one would
1346+
* handle in-memory sources directly. */
1347+
return za;
1348+
}
1349+
12551350
/* Helper function to write local file header */
12561351
static uint32_t otezip_write_local_header(FILE *fp, const char *name, uint32_t comp_method,
12571352
uint32_t comp_size, uint32_t uncomp_size, uint32_t crc32) {
@@ -1414,3 +1509,73 @@ zip_source_t *zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, i
14141509
src->freep = freep;
14151510
return src;
14161511
}
1512+
1513+
zip_source_t *zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
1514+
(void)error;
1515+
return zip_source_buffer (NULL, data, len, freep);
1516+
}
1517+
1518+
void zip_source_free(zip_source_t *src) {
1519+
if (!src) {
1520+
return;
1521+
}
1522+
if (src->freep && src->buf) {
1523+
free ((void *)src->buf);
1524+
}
1525+
free (src);
1526+
}
1527+
1528+
/* Helper to replace entry data at an existing index */
1529+
static int otezip_replace_entry_data(zip_t *za, zip_uint64_t index, zip_source_t *src) {
1530+
if (!za || index >= za->n_entries || !src) {
1531+
return -1;
1532+
}
1533+
if (za->mode != 1) {
1534+
return -1;
1535+
}
1536+
struct otezip_entry *e = &za->entries[index];
1537+
/* Free old data if present */
1538+
free ((void *)src->buf);
1539+
/* Update entry with new source data */
1540+
e->uncomp_size = (uint32_t)src->len;
1541+
e->crc32 = otezip_crc32 (0, src->buf, src->len);
1542+
/* Compress the data using the selected method */
1543+
uint8_t *comp_buf = NULL;
1544+
uint32_t comp_size = 0;
1545+
if (otezip_compress_data ((uint8_t *)src->buf, src->len, &comp_buf, &comp_size, &e->method) != 0) {
1546+
return -1;
1547+
}
1548+
if ((uint64_t)comp_size > MZIP_MAX_PAYLOAD) {
1549+
free (comp_buf);
1550+
return -1;
1551+
}
1552+
e->comp_size = comp_size;
1553+
/* Write the updated entry */
1554+
long current_pos = ftell (za->fp);
1555+
if (current_pos < 0) {
1556+
free (comp_buf);
1557+
return -1;
1558+
}
1559+
e->local_hdr_ofs = (uint32_t)current_pos;
1560+
otezip_write_local_header (za->fp, e->name, e->method, e->comp_size, e->uncomp_size, e->crc32);
1561+
fwrite (comp_buf, 1, comp_size, za->fp);
1562+
free (comp_buf);
1563+
return 0;
1564+
}
1565+
1566+
int zip_file_replace(zip_t *za, zip_uint64_t index, zip_source_t *src, zip_flags_t flags) {
1567+
(void)flags;
1568+
if (otezip_replace_entry_data (za, index, src) != 0) {
1569+
return -1;
1570+
}
1571+
return 0;
1572+
}
1573+
1574+
/* Deprecated functions - just forward to the new API */
1575+
int zip_replace(zip_t *za, zip_uint64_t index, zip_source_t *src) {
1576+
return zip_file_replace (za, index, src, 0);
1577+
}
1578+
1579+
zip_int64_t zip_add(zip_t *za, const char *name, zip_source_t *src) {
1580+
return zip_file_add (za, name, src, 0);
1581+
}

test_large.zip

-1.3 KB
Binary file not shown.

test_new.zip

-122 Bytes
Binary file not shown.

test_z.zip

-122 Bytes
Binary file not shown.

test_z_100k.zip

-100 KB
Binary file not shown.

test_z_1mb.zip

-64.1 KB
Binary file not shown.

test_z_500k.zip

-64.1 KB
Binary file not shown.

test_z_512k.zip

-512 KB
Binary file not shown.

0 commit comments

Comments
 (0)