mirror of
https://github.com/zlib-ng/minizip-ng
synced 2026-08-25 14:26:08 -04:00
mz_os: split file and link attribute getters (#797)
mz_os_get_file_attribs used lstat on POSIX and GetFileAttributesW on Win32, both of which return the link's own attributes rather than the target's. Callers that wanted to follow a symlink had no way to ask for that, so mz_zip_writer_add_file produced followed entries tagged ISLNK and readers that tried to recreate them as symlinks. Flip mz_os_get_file_attribs to stat on POSIX and to a CreateFile + GetFileInformationByHandle path on Win32 when the entry is a reparse point. Add mz_os_get_link_attribs preserving the original lstat / GetFileAttributesW semantics. Update mz_zip_writer_add_file to pick the right getter for each branch and to skip symlinks cleanly when neither store_links nor follow_links is set. Refs #797.
This commit is contained in:
parent
3f23ed7a11
commit
6b9defc73c
5 changed files with 102 additions and 5 deletions
26
doc/mz_os.md
26
doc/mz_os.md
|
|
@ -39,6 +39,7 @@ These functions provide support for handling common file system operations.
|
|||
- [mz\_os\_close\_dir](#mz_os_close_dir)
|
||||
- [mz\_os\_is\_dir](#mz_os_is_dir)
|
||||
- [mz\_os\_is\_symlink](#mz_os_is_symlink)
|
||||
- [mz\_os\_get\_link\_attribs](#mz_os_get_link_attribs)
|
||||
- [mz\_os\_make\_symlink](#mz_os_make_symlink)
|
||||
- [mz\_os\_read\_symlink](#mz_os_read_symlink)
|
||||
- [mz\_os\_ms\_time](#mz_os_ms_time)
|
||||
|
|
@ -621,7 +622,7 @@ if (mz_os_get_file_date(src_path, &modified_date, &accessed_date, &creation_date
|
|||
|
||||
### mz_os_get_file_attribs
|
||||
|
||||
Gets a file's attributes.
|
||||
Gets a file's attributes, following symbolic links.
|
||||
|
||||
**Arguments**
|
||||
|Type|Name|Description|
|
||||
|
|
@ -839,6 +840,29 @@ else
|
|||
printf("Path %s is not a symbolic link\n", path);
|
||||
```
|
||||
|
||||
### mz_os_get_link_attribs
|
||||
|
||||
Gets a symbolic link's attributes.
|
||||
|
||||
**Arguments**
|
||||
|Type|Name|Description|
|
||||
|-|-|-|
|
||||
|const char *|path|File path|
|
||||
|uint32_t *|attributes|Pointer to store file attributes value|
|
||||
|
||||
**Return**
|
||||
|Type|Description|
|
||||
|-|-|
|
||||
|int32_t|[MZ_ERROR](mz_error.md) code, MZ_OK if successful|
|
||||
|
||||
**Example**
|
||||
```
|
||||
const char *path = "c:\\test7.txt";
|
||||
uint32_t attributes = 0;
|
||||
if (mz_os_get_link_attribs(path, &attributes) == MZ_OK)
|
||||
printf("Link %s attributes %08x\n", path, attributes);
|
||||
```
|
||||
|
||||
### mz_os_make_symlink
|
||||
|
||||
Creates a symbolic link pointing to a target.
|
||||
|
|
|
|||
5
mz_os.h
5
mz_os.h
|
|
@ -146,7 +146,7 @@ int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t acces
|
|||
/* Sets a file's modified, access, and creation dates if supported */
|
||||
|
||||
int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes);
|
||||
/* Gets a file's attributes */
|
||||
/* Gets a file's attributes, following symbolic links */
|
||||
|
||||
int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes);
|
||||
/* Sets a file's attributes */
|
||||
|
|
@ -177,6 +177,9 @@ int32_t mz_os_is_dir(const char *path);
|
|||
int32_t mz_os_is_symlink(const char *path);
|
||||
/* Checks to see if path is a symbolic link */
|
||||
|
||||
int32_t mz_os_get_link_attribs(const char *path, uint32_t *attributes);
|
||||
/* Gets a symbolic link's attributes */
|
||||
|
||||
int32_t mz_os_make_symlink(const char *path, const char *target_path);
|
||||
/* Creates a symbolic link pointing to a target */
|
||||
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) {
|
|||
int32_t err = MZ_OK;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
if (lstat(path, &path_stat) == -1)
|
||||
if (stat(path, &path_stat) == -1)
|
||||
err = MZ_INTERNAL_ERROR;
|
||||
*attributes = path_stat.st_mode;
|
||||
return err;
|
||||
|
|
@ -333,6 +333,17 @@ int32_t mz_os_is_symlink(const char *path) {
|
|||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_os_get_link_attribs(const char *path, uint32_t *attributes) {
|
||||
struct stat path_stat;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
memset(&path_stat, 0, sizeof(path_stat));
|
||||
if (lstat(path, &path_stat) == -1)
|
||||
err = MZ_INTERNAL_ERROR;
|
||||
*attributes = path_stat.st_mode;
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_os_make_symlink(const char *path, const char *target_path) {
|
||||
#if !HAVE_SYMLINK
|
||||
return MZ_SUPPORT_ERROR;
|
||||
|
|
|
|||
|
|
@ -336,11 +336,39 @@ int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) {
|
|||
|
||||
if (!path || !attributes)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
|
||||
if (!path_wide)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
*attributes = GetFileAttributesW(path_wide);
|
||||
|
||||
/* If target is a reparse point, open with default flags to get attributes */
|
||||
if (*attributes != INVALID_FILE_ATTRIBUTES && (*attributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
BY_HANDLE_FILE_INFORMATION info;
|
||||
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
|
||||
CREATEFILE2_EXTENDED_PARAMETERS extended_params;
|
||||
|
||||
memset(&extended_params, 0, sizeof(extended_params));
|
||||
extended_params.dwSize = sizeof(extended_params);
|
||||
extended_params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||
|
||||
handle = CreateFile2(path_wide, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, OPEN_EXISTING,
|
||||
&extended_params);
|
||||
#else
|
||||
handle = CreateFileW(path_wide, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
#endif
|
||||
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
if (GetFileInformationByHandle(handle, &info))
|
||||
*attributes = info.dwFileAttributes;
|
||||
CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
mz_os_unicode_string_delete(&path_wide);
|
||||
|
||||
if (*attributes == INVALID_FILE_ATTRIBUTES)
|
||||
|
|
@ -512,6 +540,26 @@ int32_t mz_os_is_symlink(const char *path) {
|
|||
return MZ_EXIST_ERROR;
|
||||
}
|
||||
|
||||
int32_t mz_os_get_link_attribs(const char *path, uint32_t *attributes) {
|
||||
wchar_t *path_wide = NULL;
|
||||
int32_t err = MZ_OK;
|
||||
|
||||
if (!path || !attributes)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
|
||||
if (!path_wide)
|
||||
return MZ_PARAM_ERROR;
|
||||
|
||||
*attributes = GetFileAttributesW(path_wide);
|
||||
mz_os_unicode_string_delete(&path_wide);
|
||||
|
||||
if (*attributes == INVALID_FILE_ATTRIBUTES)
|
||||
err = MZ_INTERNAL_ERROR;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t mz_os_make_symlink(const char *path, const char *target_path) {
|
||||
typedef BOOLEAN(WINAPI * LPCREATESYMBOLICLINKW)(LPCWSTR, LPCWSTR, DWORD);
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
|
|
|||
15
mz_zip_rw.c
15
mz_zip_rw.c
|
|
@ -1628,6 +1628,7 @@ int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filen
|
|||
uint32_t src_attrib = 0;
|
||||
int32_t err = MZ_OK;
|
||||
uint8_t src_sys = 0;
|
||||
uint8_t is_symlink = 0;
|
||||
void *stream = NULL;
|
||||
char link_path[1024];
|
||||
const char *filename = filename_in_zip;
|
||||
|
|
@ -1643,6 +1644,12 @@ int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filen
|
|||
return err;
|
||||
}
|
||||
|
||||
if (mz_os_is_symlink(path) == MZ_OK)
|
||||
is_symlink = 1;
|
||||
|
||||
if (is_symlink && !writer->store_links && !writer->follow_links)
|
||||
return MZ_OK;
|
||||
|
||||
memset(&file_info, 0, sizeof(file_info));
|
||||
|
||||
/* The path name saved, should not include a leading slash. */
|
||||
|
|
@ -1665,7 +1672,11 @@ int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filen
|
|||
file_info.aes_version = MZ_AES_VERSION;
|
||||
|
||||
mz_os_get_file_date(path, &file_info.modified_date, &file_info.accessed_date, &file_info.creation_date);
|
||||
mz_os_get_file_attribs(path, &src_attrib);
|
||||
|
||||
if (is_symlink && writer->store_links)
|
||||
mz_os_get_link_attribs(path, &src_attrib);
|
||||
else
|
||||
mz_os_get_file_attribs(path, &src_attrib);
|
||||
|
||||
src_sys = MZ_HOST_SYSTEM(file_info.version_madeby);
|
||||
|
||||
|
|
@ -1678,7 +1689,7 @@ int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filen
|
|||
file_info.external_fa = src_attrib;
|
||||
}
|
||||
|
||||
if (writer->store_links && mz_os_is_symlink(path) == MZ_OK) {
|
||||
if (is_symlink && writer->store_links) {
|
||||
err = mz_os_read_symlink(path, link_path, sizeof(link_path));
|
||||
if (err == MZ_OK)
|
||||
file_info.linkname = link_path;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue