Skip to content

Commit

Permalink
Get/Set file permissions (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
kuba-- authored Aug 6, 2018
1 parent c072b27 commit 593b795
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 12 deletions.
30 changes: 25 additions & 5 deletions src/miniz.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,18 @@
#define fseeko64 fseeko
#define fopen64 fopen
#define freopen64 freopen

// Darwin OSX
#define MZ_PLATFORM 19
#endif

#ifndef MZ_PLATFORM
#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__)
#define MZ_PLATFORM 0
#else
// UNIX
#define MZ_PLATFORM 3
#endif
#endif

#ifdef __cplusplus
Expand Down Expand Up @@ -862,7 +874,8 @@ mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
// with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION.
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
const char *pSrc_filename, const void *pComment,
mz_uint16 comment_size, mz_uint level_and_flags);
mz_uint16 comment_size, mz_uint level_and_flags,
mz_uint32 ext_attributes);
#endif

// Adds a file to an archive by fully cloning the data from another archive.
Expand Down Expand Up @@ -5333,6 +5346,7 @@ mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
MZ_FILE *pFile;
if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
return MZ_FALSE;

pFile = MZ_FOPEN(pDst_filename, "wb");
if (!pFile)
return MZ_FALSE;
Expand All @@ -5344,6 +5358,7 @@ mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
if (status)
mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
#endif

return status;
}
#endif // #ifndef MINIZ_NO_STDIO
Expand Down Expand Up @@ -5634,8 +5649,12 @@ static mz_bool mz_zip_writer_create_central_dir_header(
mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
(void)pZip;
mz_uint16 version_made_by = 10 * MZ_VER_MAJOR + MZ_VER_MINOR;
version_made_by |= (MZ_PLATFORM << 8);

memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_MADE_BY_OFS, version_made_by);
MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
Expand Down Expand Up @@ -5740,8 +5759,9 @@ mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
mz_uint16 comment_size,
mz_uint level_and_flags, mz_uint64 uncomp_size,
mz_uint32 uncomp_crc32) {
mz_uint32 ext_attributes = 0;
mz_uint16 method = 0, dos_time = 0, dos_date = 0;
mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
mz_uint level, num_alignment_padding_bytes;
mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, comp_size = 0;
size_t archive_name_size;
mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
Expand Down Expand Up @@ -5915,10 +5935,10 @@ mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
#ifndef MINIZ_NO_STDIO
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
const char *pSrc_filename, const void *pComment,
mz_uint16 comment_size,
mz_uint level_and_flags) {
mz_uint16 comment_size, mz_uint level_and_flags,
mz_uint32 ext_attributes) {
mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
mz_uint16 method = 0, dos_time = 0, dos_date = 0;
mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
comp_size = 0;
size_t archive_name_size;
Expand Down
76 changes: 70 additions & 6 deletions src/zip.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
#include <sys/stat.h>
#include <time.h>

#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || defined(__MINGW64__)
#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
defined(__MINGW64__)
/* Win32, DOS, MSVC, MSVS */
#include <direct.h>

Expand Down Expand Up @@ -117,6 +118,7 @@ struct zip_entry_t {
mz_uint16 method;
mz_zip_writer_add_state state;
tdefl_compressor comp;
mz_uint32 external_attr;
};

struct zip_t {
Expand Down Expand Up @@ -244,6 +246,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
zip->entry.offset = stats.m_central_dir_ofs;
zip->entry.header_offset = stats.m_local_header_ofs;
zip->entry.method = stats.m_method;
zip->entry.external_attr = stats.m_external_attr;

return 0;
}
Expand All @@ -256,6 +259,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
zip->entry.header_offset = zip->archive.m_archive_size;
memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8));
zip->entry.method = 0;
zip->entry.external_attr = 0;

num_alignment_padding_bytes =
mz_zip_writer_compute_padding_needed_for_file_alignment(pzip);
Expand Down Expand Up @@ -381,6 +385,7 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) {
zip->entry.offset = stats.m_central_dir_ofs;
zip->entry.header_offset = stats.m_local_header_ofs;
zip->entry.method = stats.m_method;
zip->entry.external_attr = stats.m_external_attr;

return 0;
}
Expand All @@ -394,7 +399,8 @@ int zip_entry_close(struct zip_t *zip) {
mz_uint16 dos_time, dos_date;
int status = -1;

#if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || defined(__MINGW64__)
#if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || \
defined(__MINGW64__)
struct tm tmb, *tm = (struct tm *)&tmb;
#else
struct tm *tm;
Expand Down Expand Up @@ -468,7 +474,7 @@ int zip_entry_close(struct zip_t *zip) {
pzip, zip->entry.name, entrylen, NULL, 0, "", 0,
zip->entry.uncomp_size, zip->entry.comp_size, zip->entry.uncomp_crc32,
zip->entry.method, 0, dos_time, dos_date, zip->entry.header_offset,
0)) {
zip->entry.external_attr)) {
// Cannot write to zip central dir
goto cleanup;
}
Expand Down Expand Up @@ -566,12 +572,24 @@ int zip_entry_fwrite(struct zip_t *zip, const char *filename) {
size_t n = 0;
FILE *stream = NULL;
mz_uint8 buf[MZ_ZIP_MAX_IO_BUF_SIZE] = {0};
struct MZ_FILE_STAT_STRUCT file_stat = {0};

if (!zip) {
// zip_t handler is not initialized
return -1;
}

if (MZ_FILE_STAT(filename, &file_stat) != 0) {
// problem getting information - check errno
return -1;
}

if ((file_stat.st_mode & 0200) == 0) {
// MS-DOS read-only attribute
zip->entry.external_attr |= 0x01;
}
zip->entry.external_attr |= ((file_stat.st_mode & 0xFFFF) << 16);

#if defined(_MSC_VER) || defined(__MINGW64__)
if (!fopen_s(&stream, filename, "rb"))
#else
Expand Down Expand Up @@ -646,6 +664,8 @@ int zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) {
int zip_entry_fread(struct zip_t *zip, const char *filename) {
mz_zip_archive *pzip = NULL;
mz_uint idx;
mz_uint32 xattr = 0;
mz_zip_archive_file_stat info = {0};

if (!zip) {
// zip_t handler is not initialized
Expand All @@ -664,7 +684,26 @@ int zip_entry_fread(struct zip_t *zip, const char *filename) {
return -1;
}

return (mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) ? 0 : -1;
if (!mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) {
return -1;
}

#if defined(_MSC_VER)
#else
if (!mz_zip_reader_file_stat(pzip, idx, &info)) {
// Cannot get information about zip archive;
return -1;
}

xattr = (info.m_external_attr >> 16) & 0xFFFF;
if (xattr > 0) {
if (chmod(filename, xattr) < 0) {
return -1;
}
}
#endif

return 0;
}

int zip_entry_extract(struct zip_t *zip,
Expand Down Expand Up @@ -704,6 +743,8 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) {
int status = 0;
size_t i;
mz_zip_archive zip_archive;
struct MZ_FILE_STAT_STRUCT file_stat = {0};
mz_uint32 ext_attributes = 0;

if (!zipname || strlen(zipname) < 1) {
// zip_t archive name is empty or NULL
Expand All @@ -728,8 +769,20 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) {
break;
}

if (MZ_FILE_STAT(name, &file_stat) != 0) {
// problem getting information - check errno
return -1;
}

if ((file_stat.st_mode & 0200) == 0) {
// MS-DOS read-only attribute
ext_attributes |= 0x01;
}
ext_attributes |= ((file_stat.st_mode & 0xFFFF) << 16);

if (!mz_zip_writer_add_file(&zip_archive, basename(name), name, "", 0,
ZIP_DEFAULT_COMPRESSION_LEVEL)) {
ZIP_DEFAULT_COMPRESSION_LEVEL,
ext_attributes)) {
// Cannot add file to zip_archive
status = -1;
break;
Expand All @@ -747,8 +800,9 @@ int zip_extract(const char *zipname, const char *dir,
mz_uint i, n;
char path[MAX_PATH + 1] = {0};
mz_zip_archive zip_archive;
mz_zip_archive_file_stat info;
mz_zip_archive_file_stat info = {0};
size_t dirlen = 0;
mz_uint32 xattr = 0;

if (!memset(&(zip_archive), 0, sizeof(zip_archive))) {
// Cannot memset zip archive
Expand Down Expand Up @@ -811,6 +865,16 @@ int zip_extract(const char *zipname, const char *dir,
}
}

#if defined(_MSC_VER)
#else
xattr = (info.m_external_attr >> 16) & 0xFFFF;
if (xattr > 0) {
if (chmod(path, xattr) < 0) {
goto out;
}
}
#endif

if (on_extract) {
if (on_extract(path, arg) < 0) {
goto out;
Expand Down
57 changes: 56 additions & 1 deletion test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,23 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#define ZIPNAME "test.zip"
#define TESTDATA1 "Some test data 1...\0"
#define CRC32DATA1 2220805626
#define TESTDATA2 "Some test data 2...\0"
#define CRC32DATA2 2532008468

#define RFILE "4.txt"
#define RMODE 0100444

#define WFILE "6.txt"
#define WMODE 0100666

#define XFILE "7.txt"
#define XMODE 0100777

static int total_entries = 0;

static void test_write(void) {
Expand Down Expand Up @@ -255,7 +265,50 @@ static void test_list_entries(void) {
zip_close(zip);
}

static void test_file_permissions(void) {
#if defined(_MSC_VER)
#else

struct stat file_stats;
const char *filenames[] = {RFILE, WFILE, XFILE};
FILE *f4 = fopen(RFILE, "w"), *f6 = fopen(WFILE, "w"),
*f7 = fopen(XFILE, "w");
fclose(f4);
fclose(f6);
fclose(f7);
chmod(RFILE, RMODE);
chmod(WFILE, WMODE);
chmod(XFILE, XMODE);

remove(ZIPNAME);

assert(0 == zip_create(ZIPNAME, filenames, 3));

remove(RFILE);
remove(WFILE);
remove(XFILE);

assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));

assert(0 == stat(RFILE, &file_stats));
assert(RMODE == file_stats.st_mode);

assert(0 == stat(WFILE, &file_stats));
assert(WMODE == file_stats.st_mode);

assert(0 == stat(XFILE, &file_stats));
assert(XMODE == file_stats.st_mode);

remove(RFILE);
remove(WFILE);
remove(XFILE);
remove(ZIPNAME);
#endif
}

int main(int argc, char *argv[]) {
remove(ZIPNAME);

test_write();
test_append();
test_read();
Expand All @@ -265,6 +318,8 @@ int main(int argc, char *argv[]) {
test_entry_index();
test_entry_openbyindex();
test_list_entries();
test_file_permissions();

return remove(ZIPNAME);
remove(ZIPNAME);
return 0;
}

0 comments on commit 593b795

Please sign in to comment.