libarchive/archive_string.h \
libarchive/archive_string_composition.h \
libarchive/archive_string_sprintf.c \
+ libarchive/archive_time.c \
+ libarchive/archive_time_private.h \
libarchive/archive_util.c \
libarchive/archive_version_details.c \
libarchive/archive_virtual.c \
archive_string.h
archive_string_composition.h
archive_string_sprintf.c
+ archive_time.c
+ archive_time_private.h
archive_util.c
archive_version_details.c
archive_virtual.c
*/
#include "archive_platform.h"
-
+#include "archive_time_private.h"
#include "archive_private.h"
#include "archive_entry.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
-__inline static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
- ULARGE_INTEGER utc;
-
- utc.HighPart = filetime->dwHighDateTime;
- utc.LowPart = filetime->dwLowDateTime;
- if (utc.QuadPart >= EPOC_TIME) {
- utc.QuadPart -= EPOC_TIME;
- *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
- *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
- } else {
- *t = 0;
- *ns = 0;
- }
-}
-
void
archive_entry_copy_bhfi(struct archive_entry *entry,
BY_HANDLE_FILE_INFORMATION *bhfi)
{
- time_t secs;
- long nsecs;
+ int64_t secs;
+ uint32_t nsecs;
- fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
+ ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
archive_entry_set_atime(entry, secs, nsecs);
- fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
+ ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
archive_entry_set_mtime(entry, secs, nsecs);
- fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
+ ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
archive_entry_set_birthtime(entry, secs, nsecs);
archive_entry_set_ctime(entry, secs, nsecs);
archive_entry_set_dev(entry, bhfi->dwVolumeSerialNumber);
+ bhfi->nFileSizeLow);
/* archive_entry_set_mode(entry, st->st_mode); */
}
-#endif
+#endif
\ No newline at end of file
#include "archive_pathmatch.h"
#include "archive_rb.h"
#include "archive_string.h"
+#include "archive_time_private.h"
struct match {
struct match *next;
}
#if defined(_WIN32) && !defined(__CYGWIN__)
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
static int
set_timefilter_find_data(struct archive_match *a, int timetype,
- DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
- DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
+ const FILETIME* ftLastWriteTime, const FILETIME* ftCreationTime)
{
- ULARGE_INTEGER utc;
time_t ctime_sec, mtime_sec;
- long ctime_ns, mtime_ns;
+ uint32_t ctime_ns, mtime_ns;
- utc.HighPart = ftCreationTime_dwHighDateTime;
- utc.LowPart = ftCreationTime_dwLowDateTime;
- if (utc.QuadPart >= EPOC_TIME) {
- utc.QuadPart -= EPOC_TIME;
- ctime_sec = (time_t)(utc.QuadPart / 10000000);
- ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
- } else {
- ctime_sec = 0;
- ctime_ns = 0;
- }
- utc.HighPart = ftLastWriteTime_dwHighDateTime;
- utc.LowPart = ftLastWriteTime_dwLowDateTime;
- if (utc.QuadPart >= EPOC_TIME) {
- utc.QuadPart -= EPOC_TIME;
- mtime_sec = (time_t)(utc.QuadPart / 10000000);
- mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
- } else {
- mtime_sec = 0;
- mtime_ns = 0;
- }
+ ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
+ ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
return set_timefilter(a, timetype,
mtime_sec, mtime_ns, ctime_sec, ctime_ns);
}
return (ARCHIVE_FAILED);
}
FindClose(h);
- return set_timefilter_find_data(a, timetype,
- d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
- d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
+ return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
}
static int
return (ARCHIVE_FAILED);
}
FindClose(h);
- return set_timefilter_find_data(a, timetype,
- d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
- d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
+ return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
}
#else /* _WIN32 && !__CYGWIN__ */
return (r);
}
return (0);
-}
-
+}
\ No newline at end of file
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_read_disk_private.h"
+#include "archive_time_private.h"
#ifndef O_BINARY
#define O_BINARY 0
}
}
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
- ULARGE_INTEGER utc;
-
- utc.HighPart = filetime->dwHighDateTime;
- utc.LowPart = filetime->dwLowDateTime;
- if (utc.QuadPart >= EPOC_TIME) {
- utc.QuadPart -= EPOC_TIME;
- /* milli seconds base */
- *t = (time_t)(utc.QuadPart / 10000000);
- /* nano seconds base */
- *ns = (long)(utc.QuadPart % 10000000) * 100;
- } else {
- *t = 0;
- *ns = 0;
- }
-}
-
static void
entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
const WIN32_FIND_DATAW *findData,
const BY_HANDLE_FILE_INFORMATION *bhfi)
{
- time_t secs;
- long nsecs;
+ int64_t secs;
+ uint32_t nsecs;
mode_t mode;
- fileTimeToUtc(&bhfi->ftLastAccessTime, &secs, &nsecs);
+ ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastAccessTime), &secs, &nsecs);
archive_entry_set_atime(entry, secs, nsecs);
- fileTimeToUtc(&bhfi->ftLastWriteTime, &secs, &nsecs);
+ ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftLastWriteTime), &secs, &nsecs);
archive_entry_set_mtime(entry, secs, nsecs);
- fileTimeToUtc(&bhfi->ftCreationTime, &secs, &nsecs);
+ ntfs_to_unix(FILETIME_to_ntfs(&bhfi->ftCreationTime), &secs, &nsecs);
archive_entry_set_birthtime(entry, secs, nsecs);
archive_entry_set_ctime(entry, secs, nsecs);
archive_entry_set_dev(entry, bhfi_dev(bhfi));
return (exit_sts);
}
-#endif
+#endif
\ No newline at end of file
#include "archive_ppmd7_private.h"
#include "archive_private.h"
#include "archive_read_private.h"
+#include "archive_time_private.h"
#include "archive_endian.h"
#ifndef HAVE_ZLIB_H
#define SFX_MIN_ADDR 0x27000
#define SFX_MAX_ADDR 0x60000
-
/*
* Codec ID
*/
uint32_t *digests;
};
-
struct _7z_folder {
uint64_t numCoders;
struct _7z_coder {
#define CRC32_IS_SET (1<<3)
#define HAS_STREAM (1<<4)
- time_t mtime;
- time_t atime;
- time_t ctime;
- long mtime_ns;
- long atime_ns;
- long ctime_ns;
+ int64_t mtime;
+ int64_t atime;
+ int64_t ctime;
+ uint32_t mtime_ns;
+ uint32_t atime_ns;
+ uint32_t ctime_ns;
uint32_t mode;
uint32_t attr;
};
static int decompress(struct archive_read *, struct _7zip *,
void *, size_t *, const void *, size_t *);
static ssize_t extract_pack_stream(struct archive_read *, size_t);
-static void fileTimeToUtc(uint64_t, time_t *, long *);
static uint64_t folder_uncompressed_size(struct _7z_folder *);
static void free_CodersInfo(struct _7z_coders_info *);
static void free_Digest(struct _7z_digests *);
return (0);
}
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static void
-fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
-{
-
- if (fileTime >= EPOC_TIME) {
- fileTime -= EPOC_TIME;
- /* milli seconds base */
- *timep = (time_t)(fileTime / 10000000);
- /* nano seconds base */
- *ns = (long)(fileTime % 10000000) * 100;
- } else {
- *timep = 0;
- *ns = 0;
- }
-}
-
static int
read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
{
goto failed;
switch (type) {
case kCTime:
- fileTimeToUtc(archive_le64dec(p),
+ ntfs_to_unix(archive_le64dec(p),
&(entries[i].ctime),
&(entries[i].ctime_ns));
entries[i].flg |= CTIME_IS_SET;
break;
case kATime:
- fileTimeToUtc(archive_le64dec(p),
+ ntfs_to_unix(archive_le64dec(p),
&(entries[i].atime),
&(entries[i].atime_ns));
entries[i].flg |= ATIME_IS_SET;
break;
case kMTime:
- fileTimeToUtc(archive_le64dec(p),
+ ntfs_to_unix(archive_le64dec(p),
&(entries[i].mtime),
&(entries[i].mtime_ns));
entries[i].flg |= MTIME_IS_SET;
zip->bcj2_outPos += outPos;
return ((ssize_t)outPos);
-}
-
+}
\ No newline at end of file
#include "archive_entry_locale.h"
#include "archive_private.h"
#include "archive_read_private.h"
+#include "archive_time_private.h"
#include "archive_endian.h"
#define ATIME_IS_SET 2
#define UNIX_MODE_IS_SET 4
#define CRC_IS_SET 8
- time_t birthtime;
- long birthtime_tv_nsec;
- time_t mtime;
- long mtime_tv_nsec;
- time_t atime;
- long atime_tv_nsec;
+ int64_t birthtime;
+ uint32_t birthtime_tv_nsec;
+ int64_t mtime;
+ uint32_t mtime_tv_nsec;
+ int64_t atime;
+ uint32_t atime_tv_nsec;
mode_t mode;
int64_t uid;
int64_t gid;
struct lha *, uint16_t *, int, uint64_t, size_t *);
static size_t lha_check_header_format(const void *);
static int lha_skip_sfx(struct archive_read *);
-static time_t lha_dos_time(const unsigned char *);
-static time_t lha_win_time(uint64_t, long *);
static unsigned char lha_calcsum(unsigned char, const void *,
int, size_t);
static int lha_parse_linkname(struct archive_wstring *,
headersum = p[H0_HEADER_SUM_OFFSET];
lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET);
lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET);
- lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET);
+ lha->mtime = dos_to_unix(archive_le32dec(p + H0_DOS_TIME_OFFSET));
namelen = p[H0_NAME_LEN_OFFSET];
extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen;
if ((namelen > 221 || extdsize < 0) && extdsize != -2) {
/* Note: An extended header size is included in a compsize. */
lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET);
lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET);
- lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET);
+ lha->mtime = dos_to_unix(archive_le32dec(p + H1_DOS_TIME_OFFSET));
namelen = p[H1_NAME_LEN_OFFSET];
/* Calculate a padding size. The result will be normally 0 only(?) */
padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen;
if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4)
goto invalid;
- lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
+ lha->header_size = archive_le32dec(p + H3_HEADER_SIZE_OFFSET);
lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET);
lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET);
lha->mtime = archive_le32dec(p + H3_TIME_OFFSET);
break;
case EXT_TIMESTAMP:
if (datasize == (sizeof(uint64_t) * 3)) {
- lha->birthtime = lha_win_time(
- archive_le64dec(extdheader),
+ ntfs_to_unix(archive_le64dec(extdheader),
+ &lha->birthtime,
&lha->birthtime_tv_nsec);
extdheader += sizeof(uint64_t);
- lha->mtime = lha_win_time(
- archive_le64dec(extdheader),
+ ntfs_to_unix(archive_le64dec(extdheader),
+ &lha->mtime,
&lha->mtime_tv_nsec);
extdheader += sizeof(uint64_t);
- lha->atime = lha_win_time(
- archive_le64dec(extdheader),
+ ntfs_to_unix(archive_le64dec(extdheader),
+ &lha->atime,
&lha->atime_tv_nsec);
lha->setflag |= BIRTHTIME_IS_SET |
ATIME_IS_SET;
return (0);
}
-/* Convert an MSDOS-style date/time into Unix-style time. */
-static time_t
-lha_dos_time(const unsigned char *p)
-{
- int msTime, msDate;
- struct tm ts;
-
- msTime = archive_le16dec(p);
- msDate = archive_le16dec(p+2);
-
- memset(&ts, 0, sizeof(ts));
- ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
- ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
- ts.tm_mday = msDate & 0x1f; /* Day of month. */
- ts.tm_hour = (msTime >> 11) & 0x1f;
- ts.tm_min = (msTime >> 5) & 0x3f;
- ts.tm_sec = (msTime << 1) & 0x3e;
- ts.tm_isdst = -1;
- return (mktime(&ts));
-}
-
-/* Convert an MS-Windows-style date/time into Unix-style time. */
-static time_t
-lha_win_time(uint64_t wintime, long *ns)
-{
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
- if (wintime >= EPOC_TIME) {
- wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */
- if (ns != NULL)
- *ns = (long)(wintime % 10000000) * 100;
- return (wintime / 10000000);
- } else {
- if (ns != NULL)
- *ns = 0;
- return (0);
- }
-}
-
static unsigned char
lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size)
{
return (c);
/* This bit pattern needs to be found out at a huffman tree. */
return (lzh_decode_huffman_tree(hf, rbits, c));
-}
-
+}
\ No newline at end of file
#include "archive_entry_locale.h"
#include "archive_ppmd7_private.h"
#include "archive_entry_private.h"
+#include "archive_time_private.h"
#ifdef HAVE_BLAKE2_H
#include <blake2.h>
uint8_t dir : 1; /* Is this file entry a directory? */
/* Optional time fields. */
- uint64_t e_mtime;
- uint64_t e_ctime;
- uint64_t e_atime;
- uint32_t e_unix_ns;
+ int64_t e_mtime;
+ int64_t e_ctime;
+ int64_t e_atime;
+ uint32_t e_mtime_ns;
+ uint32_t e_ctime_ns;
+ uint32_t e_atime_ns;
/* Optional hash fields. */
uint32_t stored_crc32;
return ARCHIVE_OK;
}
-static int read_u32(struct archive_read* a, uint32_t* pvalue) {
+static char read_u32(struct archive_read* a, uint32_t* pvalue) {
const uint8_t* p;
if(!read_ahead(a, 4, &p))
return 0;
*pvalue = archive_le32dec(p);
- return ARCHIVE_OK == consume(a, 4) ? 1 : 0;
+ return ARCHIVE_OK == consume(a, 4);
}
-static int read_u64(struct archive_read* a, uint64_t* pvalue) {
+static char read_u64(struct archive_read* a, uint64_t* pvalue) {
const uint8_t* p;
if(!read_ahead(a, 8, &p))
return 0;
*pvalue = archive_le64dec(p);
- return ARCHIVE_OK == consume(a, 8) ? 1 : 0;
+ return ARCHIVE_OK == consume(a, 8);
}
static int bid_standard(struct archive_read* a) {
return ARCHIVE_OK;
}
-static uint64_t time_win_to_unix(uint64_t win_time) {
- const size_t ns_in_sec = 10000000;
- const uint64_t sec_to_unix = 11644473600LL;
- return win_time / ns_in_sec - sec_to_unix;
-}
-
static int parse_htime_item(struct archive_read* a, char unix_time,
- uint64_t* where, int64_t* extra_data_size)
+ int64_t* sec, uint32_t* nsec, int64_t* extra_data_size)
{
if(unix_time) {
uint32_t time_val;
return ARCHIVE_EOF;
*extra_data_size -= 4;
- *where = (uint64_t) time_val;
+ *sec = (int64_t) time_val;
} else {
uint64_t windows_time;
if(!read_u64(a, &windows_time))
return ARCHIVE_EOF;
- *where = time_win_to_unix(windows_time);
+ ntfs_to_unix(windows_time, sec, nsec);
*extra_data_size -= 8;
}
static int parse_file_extra_htime(struct archive_read* a,
struct archive_entry* e, struct rar5* rar, int64_t* extra_data_size)
{
- char unix_time = 0;
+ char unix_time, has_unix_ns, has_mtime, has_ctime, has_atime;
size_t flags = 0;
size_t value_len;
}
unix_time = flags & IS_UNIX;
+ has_unix_ns = unix_time && (flags & HAS_UNIX_NS);
+ has_mtime = flags & HAS_MTIME;
+ has_atime = flags & HAS_ATIME;
+ has_ctime = flags & HAS_CTIME;
+ rar->file.e_atime_ns = rar->file.e_ctime_ns = rar->file.e_mtime_ns = 0;
- if(flags & HAS_MTIME) {
+ if(has_mtime) {
parse_htime_item(a, unix_time, &rar->file.e_mtime,
- extra_data_size);
- archive_entry_set_mtime(e, rar->file.e_mtime, 0);
+ &rar->file.e_mtime_ns, extra_data_size);
}
- if(flags & HAS_CTIME) {
+ if(has_ctime) {
parse_htime_item(a, unix_time, &rar->file.e_ctime,
- extra_data_size);
- archive_entry_set_ctime(e, rar->file.e_ctime, 0);
+ &rar->file.e_ctime_ns, extra_data_size);
}
- if(flags & HAS_ATIME) {
+ if(has_atime) {
parse_htime_item(a, unix_time, &rar->file.e_atime,
- extra_data_size);
- archive_entry_set_atime(e, rar->file.e_atime, 0);
+ &rar->file.e_atime_ns, extra_data_size);
+ }
+
+ if(has_mtime && has_unix_ns) {
+ if(!read_u32(a, &rar->file.e_mtime_ns))
+ return ARCHIVE_EOF;
+
+ *extra_data_size -= 4;
+ }
+
+ if(has_ctime && has_unix_ns) {
+ if(!read_u32(a, &rar->file.e_ctime_ns))
+ return ARCHIVE_EOF;
+
+ *extra_data_size -= 4;
}
- if(flags & HAS_UNIX_NS) {
- if(!read_u32(a, &rar->file.e_unix_ns))
+ if(has_atime && has_unix_ns) {
+ if(!read_u32(a, &rar->file.e_atime_ns))
return ARCHIVE_EOF;
*extra_data_size -= 4;
}
+ /* The seconds and nanoseconds are either together, or separated in two
+ * fields so we parse them, then set the archive_entry's times. */
+ if(has_mtime) {
+ archive_entry_set_mtime(e, rar->file.e_mtime, rar->file.e_mtime_ns);
+ }
+
+ if(has_ctime) {
+ archive_entry_set_ctime(e, rar->file.e_ctime, rar->file.e_ctime_ns);
+ }
+
+ if(has_atime) {
+ archive_entry_set_atime(e, rar->file.e_atime, rar->file.e_atime_ns);
+ }
+
return ARCHIVE_OK;
}
}
return ret;
-}
+}
\ No newline at end of file
#include "archive_private.h"
#include "archive_rb.h"
#include "archive_read_private.h"
+#include "archive_time_private.h"
#include "archive_ppmd8_private.h"
#ifndef HAVE_ZLIB_H
return "??";
}
-/* Convert an MSDOS-style date/time into Unix-style time. */
-static time_t
-zip_time(const char *p)
-{
- int msTime, msDate;
- struct tm ts;
-
- msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]);
- msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]);
-
- memset(&ts, 0, sizeof(ts));
- ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
- ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
- ts.tm_mday = msDate & 0x1f; /* Day of month. */
- ts.tm_hour = (msTime >> 11) & 0x1f;
- ts.tm_min = (msTime >> 5) & 0x3f;
- ts.tm_sec = (msTime << 1) & 0x3e;
- ts.tm_isdst = -1;
- return mktime(&ts);
-}
-
/*
* The extra data is stored as a list of
* id1+size1+data1 + id2+size2+data2 ...
}
zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
zip_entry->compression = (char)archive_le16dec(p + 8);
- zip_entry->mtime = zip_time(p + 10);
+ zip_entry->mtime = dos_to_unix(archive_le32dec(p + 10));
zip_entry->crc32 = archive_le32dec(p + 14);
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
zip_entry->decdat = p[11];
zip->has_encrypted_entries = 1;
}
zip_entry->compression = (char)archive_le16dec(p + 10);
- zip_entry->mtime = zip_time(p + 12);
+ zip_entry->mtime = dos_to_unix(archive_le32dec(p + 12));
zip_entry->crc32 = archive_le32dec(p + 16);
if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
zip_entry->decdat = p[13];
return (ARCHIVE_OK);
}
-/*# vim:set noet:*/
+/*# vim:set noet:*/
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright © 2025 ARJANEN Loïc Jean David
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+#include "archive_private.h"
+#include "archive_time_private.h"
+#include <stdlib.h>
+
+#define NTFS_EPOC_TIME ARCHIVE_LITERAL_ULL(11644473600)
+#define NTFS_TICKS ARCHIVE_LITERAL_ULL(10000000)
+#define NTFS_EPOC_TICKS (NTFS_EPOC_TIME * NTFS_TICKS)
+#define DOS_MIN_TIME 0x00210000U
+#define DOS_MAX_TIME 0xff9fbf7dU
+/* The min/max DOS Unix time are locale-dependant, so they're static variables,
+ * initialised on first use. */
+static char dos_initialised = 0;
+static int64_t dos_max_unix;
+static int64_t dos_min_unix;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <winnt.h>
+/* Windows FILETIME to NTFS time. */
+uint64_t
+FILETIME_to_ntfs(const FILETIME* filetime)
+{
+ ULARGE_INTEGER utc;
+ utc.HighPart = filetime->dwHighDateTime;
+ utc.LowPart = filetime->dwLowDateTime;
+ return utc.QuadPart;
+}
+#endif
+
+/* Convert an MSDOS-style date/time into Unix-style time. */
+int64_t
+dos_to_unix(uint32_t dos_time)
+{
+ uint16_t msTime, msDate;
+ struct tm ts;
+
+ msTime = (0xFFFF & dos_time);
+ msDate = (dos_time >> 16);
+ ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
+ ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
+ ts.tm_mday = msDate & 0x1f; /* Day of month. */
+ ts.tm_hour = (msTime >> 11) & 0x1f;
+ ts.tm_min = (msTime >> 5) & 0x3f;
+ ts.tm_sec = (msTime << 1) & 0x3e;
+ ts.tm_isdst = -1;
+ return mktime(&ts);
+}
+
+/* Convert into MSDOS-style date/time. */
+uint32_t
+unix_to_dos(int64_t unix_time)
+{
+ struct tm *t;
+ uint32_t dt;
+ time_t ut = unix_time;
+#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
+ struct tm tmbuf;
+#endif
+
+ if (!dos_initialised) {
+ dos_max_unix = dos_to_unix(DOS_MAX_TIME);
+ dos_min_unix = dos_to_unix(DOS_MIN_TIME);
+ dos_initialised = 1;
+ }
+ if (unix_time >= dos_max_unix) {
+ return DOS_MAX_TIME;
+ }
+ else if(unix_time <= dos_min_unix) {
+ return DOS_MIN_TIME;
+ }
+ else {
+#if defined(HAVE_LOCALTIME_S)
+ t = localtime_s(&tmbuf, &ut) ? NULL : &tmbuf;
+#elif defined(HAVE_LOCALTIME_R)
+ t = localtime_r(&ut, &tmbuf);
+#else
+ t = localtime(&ut);
+#endif
+ dt = 0;
+ dt += ((t->tm_year - 80) & 0x7f) << 9;
+ dt += ((t->tm_mon + 1) & 0x0f) << 5;
+ dt += (t->tm_mday & 0x1f);
+ dt <<= 16;
+ dt += (t->tm_hour & 0x1f) << 11;
+ dt += (t->tm_min & 0x3f) << 5;
+ dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */
+ return dt;
+ }
+}
+
+/* Convert NTFS time to Unix sec/ncse */
+void
+ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs)
+{
+ ntfs -= NTFS_EPOC_TICKS;
+ lldiv_t tdiv = lldiv(ntfs, NTFS_TICKS);
+ *secs = tdiv.quot;
+ *nsecs = tdiv.rem * 100;
+}
+
+/* Convert Unix sec/nsec to NTFS time */
+uint64_t
+unix_to_ntfs(int64_t secs, uint32_t nsecs)
+{
+ uint64_t ntfs = secs + NTFS_EPOC_TIME;
+ ntfs *= NTFS_TICKS;
+ return ntfs + nsecs/100;
+}
\ No newline at end of file
--- /dev/null
+/*-
+ * Copyright © 2025 ARJANEN Loïc Jean David
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef ARCHIVE_TIME_PRIVATE_H_INCLUDED
+#define ARCHIVE_TIME_PRIVATE_H_INCLUDED
+
+#ifndef __LIBARCHIVE_BUILD
+#error This header is only to be used internally to libarchive.
+#endif
+#include <stdint.h>
+
+/* NTFS time to Unix sec/nsec. */
+void ntfs_to_unix(uint64_t ntfs, int64_t* secs, uint32_t* nsecs);
+/* DOS time to Unix sec. */
+int64_t dos_to_unix(uint32_t dos);
+/* Unix sec/nsec to NTFS time. */
+uint64_t unix_to_ntfs(int64_t secs, uint32_t nsecs);
+/* Unix sec to DOS time. */
+uint32_t unix_to_dos(int64_t secs);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windef.h>
+#include <winbase.h>
+/* Windows FILETIME to NTFS time. */
+uint64_t FILETIME_to_ntfs(const FILETIME* filetime);
+#endif
+#endif /* ARCHIVE_TIME_PRIVATE_H_INCLUDED */
\ No newline at end of file
#include "archive_platform.h"
#include "archive_private.h"
#include "archive_entry.h"
+#include "archive_time_private.h"
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
#include <windows.h>
#include <share.h>
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-
#if defined(__LA_LSEEK_NEEDED)
static BOOL SetFilePointerEx_perso(HANDLE hFile,
LARGE_INTEGER liDistanceToMove,
return ((ssize_t)bytes_read);
}
-/* Convert Windows FILETIME to UTC */
-__inline static void
-fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns)
-{
- ULARGE_INTEGER utc;
-
- utc.HighPart = filetime->dwHighDateTime;
- utc.LowPart = filetime->dwLowDateTime;
- if (utc.QuadPart >= EPOC_TIME) {
- utc.QuadPart -= EPOC_TIME;
- *t = (time_t)(utc.QuadPart / 10000000); /* milli seconds base */
- *ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
- } else {
- *t = 0;
- *ns = 0;
- }
-}
-
/* Stat by handle
* Windows' stat() does not accept the path added "\\?\" especially "?"
* character.
ULARGE_INTEGER ino64;
DWORD ftype;
mode_t mode;
- time_t t;
- long ns;
switch (ftype = GetFileType(handle)) {
case FILE_TYPE_UNKNOWN:
mode |= S_IFREG;
st->st_mode = mode;
- fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
- st->st_atime = t;
- st->st_atime_nsec = ns;
- fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
- st->st_mtime = t;
- st->st_mtime_nsec = ns;
- fileTimeToUTC(&info.ftCreationTime, &t, &ns);
- st->st_ctime = t;
- st->st_ctime_nsec = ns;
+ ntfs_to_unix(FILETIME_to_ntfs(&info.ftLastAccessTime), &st->st_atime, &st->st_atime_nsec);
+ ntfs_to_unix(FILETIME_to_ntfs(&info.ftLastWriteTime), &st->st_mtime, &st->st_mtime_nsec);
+ ntfs_to_unix(FILETIME_to_ntfs(&info.ftCreationTime), &st->st_ctime, &st->st_ctime_nsec);
st->st_size =
((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
+ (int64_t)(info.nFileSizeLow);
#include "archive_string.h"
#include "archive_entry.h"
#include "archive_private.h"
+#include "archive_time_private.h"
#ifndef O_BINARY
#define O_BINARY 0
time_t mtime, long mtime_nanos,
time_t ctime_sec, long ctime_nanos)
{
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-#define WINTIME(sec, nsec) (((sec * 10000000LL) + EPOC_TIME)\
- + ((nsec)/100))
-
HANDLE hw = 0;
ULARGE_INTEGER wintm;
FILETIME *pfbtime;
h = hw;
}
- wintm.QuadPart = WINTIME(atime, atime_nanos);
+ wintm.QuadPart = unix_to_ntfs(atime, atime_nanos);
fatime.dwLowDateTime = wintm.LowPart;
fatime.dwHighDateTime = wintm.HighPart;
- wintm.QuadPart = WINTIME(mtime, mtime_nanos);
+ wintm.QuadPart = unix_to_ntfs(mtime, mtime_nanos);
fmtime.dwLowDateTime = wintm.LowPart;
fmtime.dwHighDateTime = wintm.HighPart;
/*
* SetFileTime() supports birthtime.
*/
if (birthtime > 0 || birthtime_nanos > 0) {
- wintm.QuadPart = WINTIME(birthtime, birthtime_nanos);
+ wintm.QuadPart = unix_to_ntfs(birthtime, birthtime_nanos);
fbtime.dwLowDateTime = wintm.LowPart;
fbtime.dwHighDateTime = wintm.HighPart;
pfbtime = &fbtime;
return (ARCHIVE_OK);
}
-static void
-fileTimeToUtc(const FILETIME *filetime, time_t *t, long *ns)
-{
- ULARGE_INTEGER utc;
-
- utc.HighPart = filetime->dwHighDateTime;
- utc.LowPart = filetime->dwLowDateTime;
- if (utc.QuadPart >= EPOC_TIME) {
- utc.QuadPart -= EPOC_TIME;
- /* milli seconds base */
- *t = (time_t)(utc.QuadPart / 10000000);
- /* nano seconds base */
- *ns = (long)(utc.QuadPart % 10000000) * 100;
- } else {
- *t = 0;
- *ns = 0;
- }
-}
/*
* Test if file on disk is older than entry.
*/
static int
older(BY_HANDLE_FILE_INFORMATION *st, struct archive_entry *entry)
{
- time_t sec;
- long nsec;
+ int64_t sec;
+ uint32_t nsec;
- fileTimeToUtc(&st->ftLastWriteTime, &sec, &nsec);
+ ntfs_to_unix(FILETIME_to_ntfs(&st->ftLastWriteTime), &sec, &nsec);
/* First, test the seconds and return if we have a definite answer. */
/* Definitely older. */
if (sec < archive_entry_mtime(entry))
/* Definitely younger. */
if (sec > archive_entry_mtime(entry))
return (0);
- if (nsec < archive_entry_mtime_nsec(entry))
+ if ((long)nsec < archive_entry_mtime_nsec(entry))
return (1);
/* Same age or newer, so not older. */
return (0);
}
-#endif /* _WIN32 && !__CYGWIN__ */
-
+#endif /* _WIN32 && !__CYGWIN__ */
\ No newline at end of file
#include "archive_private.h"
#include "archive_rb.h"
#include "archive_string.h"
+#include "archive_time_private.h"
#include "archive_write_private.h"
#include "archive_write_set_format_private.h"
return (ARCHIVE_OK);
}
-
-#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
-static uint64_t
-utcToFiletime(time_t t, long ns)
-{
- uint64_t fileTime;
-
- fileTime = t;
- fileTime *= 10000000;
- fileTime += ns / 100;
- fileTime += EPOC_TIME;
- return (fileTime);
-}
-
static int
make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
{
if (r < 0)
return (r);
-
/*
* Make Times.
*/
for (;file != NULL; file = file->next) {
if ((file->flg & flg) == 0)
continue;
- archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
+ archive_le64enc(filetime, unix_to_ntfs(file->times[ti].time,
file->times[ti].time_ns));
r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
if (r < 0)
return (lastrm->end(a, lastrm));
}
return (ARCHIVE_OK);
-}
+}
\ No newline at end of file
#include "archive_hmac_private.h"
#include "archive_private.h"
#include "archive_random_private.h"
+#include "archive_time_private.h"
#include "archive_write_private.h"
#include "archive_write_set_format_private.h"
struct archive_entry *);
static int archive_write_zip_options(struct archive_write *,
const char *, const char *);
-static unsigned int dos_time(const time_t);
static size_t path_length(struct archive_entry *);
static int write_path(struct archive_entry *, struct archive_write *);
static void copy_path(struct archive_entry *, unsigned char *);
else
archive_le16enc(local_header + 8, zip->entry_compression);
archive_le32enc(local_header + 10,
- dos_time(archive_entry_mtime(zip->entry)));
+ unix_to_dos(archive_entry_mtime(zip->entry)));
if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) == 0) {
archive_le32enc(local_header + 14, zip->entry_crc32);
archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size);
else
archive_le16enc(zip->file_header + 10, zip->entry_compression);
archive_le32enc(zip->file_header + 12,
- dos_time(archive_entry_mtime(zip->entry)));
+ unix_to_dos(archive_entry_mtime(zip->entry)));
archive_le16enc(zip->file_header + 28, (uint16_t)filename_length);
/* Following Info-Zip, store mode in the "external attributes" field. */
archive_le32enc(zip->file_header + 38,
return (ARCHIVE_OK);
}
-/* Convert into MSDOS-style date/time. */
-static unsigned int
-dos_time(const time_t unix_time)
-{
- struct tm *t;
- unsigned int dt;
-#if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S)
- struct tm tmbuf;
-#endif
-
-#if defined(HAVE_LOCALTIME_S)
- t = localtime_s(&tmbuf, &unix_time) ? NULL : &tmbuf;
-#elif defined(HAVE_LOCALTIME_R)
- t = localtime_r(&unix_time, &tmbuf);
-#else
- t = localtime(&unix_time);
-#endif
-
- /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */
- if (t->tm_year < 1980 - 1900)
- /* Set minimum date/time '1980-01-01 00:00:00'. */
- dt = 0x00210000U;
- else if (t->tm_year > 2107 - 1900)
- /* Set maximum date/time '2107-12-31 23:59:58'. */
- dt = 0xff9fbf7dU;
- else {
- dt = 0;
- dt += ((t->tm_year - 80) & 0x7f) << 9;
- dt += ((t->tm_mon + 1) & 0x0f) << 5;
- dt += (t->tm_mday & 0x1f);
- dt <<= 16;
- dt += (t->tm_hour & 0x1f) << 11;
- dt += (t->tm_min & 0x3f) << 5;
- dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */
- }
- return dt;
-}
-
static size_t
path_length(struct archive_entry *entry)
{
return (0);
archive_hmac_sha1_cleanup(&hctx);
return (1);
-}
+}
\ No newline at end of file