From: arai Date: Sun, 25 Aug 2002 19:58:07 +0000 (+0000) Subject: * src/header.c (wintime_to_unix_stamp): newly added for converting X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=42bb2b86412782aca5bad56ac0920f4dd026d098;p=lha%2Flha.git * src/header.c (wintime_to_unix_stamp): newly added for converting from `FILETIME' to `time_t'. (get_extended_header): use `wintime_to_unix_stamp()' to recognize the Windows time stamp header (0x41). * src/lha.h: define `uint64_t' unless system has it. * configure.ac: check existence of the type `uint64_t'. * config.h.in: ditto. git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/lha/lha/trunk@527 6a8cc165-1e22-0410-a132-eb4e3f353aba --- diff --git a/config.h.in b/config.h.in index 6e63aee..4dff470 100644 --- a/config.h.in +++ b/config.h.in @@ -61,6 +61,9 @@ /* Define to 1 if you have the `link' function. */ #undef HAVE_LINK +/* Define to 1 if the system has the type `long long'. */ +#undef HAVE_LONG_LONG + /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY @@ -161,6 +164,9 @@ /* Define to 1 if the system has the type `uid_t'. */ #undef HAVE_UID_T +/* Define to 1 if the system has the type `uint64_t'. */ +#undef HAVE_UINT64_T + /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H @@ -224,6 +230,9 @@ /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE +/* The size of a `long', as computed by sizeof. */ +#undef SIZEOF_LONG + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/configure.ac b/configure.ac index 9a9453d..4ae8db9 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_SEARCH_LIBS(opendir, [mingwex]) AC_HEADER_DIRENT AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h limits.h sys/file.h sys/param.h sys/time.h) -AC_CHECK_HEADERS(pwd.h grp.h utime.h) +AC_CHECK_HEADERS(pwd.h grp.h utime.h inttypes.h stdint.h) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -30,7 +30,8 @@ AC_HEADER_TIME AC_STRUCT_TM AC_STRUCT_TIMEZONE -AC_CHECK_TYPES([uid_t, gid_t]) +AC_CHECK_SIZEOF(long) +AC_CHECK_TYPES([uid_t, gid_t, long long, uint64_t]) AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct stat.st_ino],,, [ #if HAVE_SYS_TYPES_H diff --git a/src/header.c b/src/header.c index 625a1b7..355d8e5 100644 --- a/src/header.c +++ b/src/header.c @@ -494,6 +494,44 @@ unix_to_generic_stamp(t) (tm->tm_sec / 2))); } +static unsigned long +wintime_to_unix_stamp() +{ +#if HAVE_UINT64_T + uint64_t t; + uint64_t epoch = 0x019db1ded53e8000; /* 1970-01-01 00:00:00 (UTC) */ + + t = get_longword(); + t += (uint64_t)get_longword() << 32; + t = (t - epoch) / 10000000; + return t; +#else + int i, borrow; + unsigned long t, q, x; + unsigned long wintime[8]; + unsigned long epoch[8] = {0x01,0x9d,0xb1,0xde, 0xd5,0x3e,0x80,0x00}; + /* 1970-01-01 00:00:00 (UTC) */ + /* wintime -= epoch */ + borrow = 0; + for (i = 7; i >= 0; i--) { + wintime[i] = (unsigned)get_byte() - epoch[i] - borrow; + borrow = (wintime[i] > 0xff) ? 1 : 0; + wintime[i] &= 0xff; + } + + /* q = wintime / 10000000 */ + t = q = 0; + x = 10000000; /* x: 24bit */ + for (i = 0; i < 8; i++) { + t = (t << 8) + wintime[i]; /* 24bit + 8bit. t must be 32bit variable */ + q <<= 8; /* q must be 32bit (time_t) */ + q += t / x; + t %= x; /* 16bit */ + } + return q; +#endif +} + /* ------------------------------------------------------------------------ */ /* build header functions */ /* ------------------------------------------------------------------------ */ @@ -516,6 +554,7 @@ unix_to_generic_stamp(t) * on level 3 header: * size field is 4 bytes */ + static long get_extended_header(fp, hdr, header_size, hcrc) FILE *fp; @@ -575,7 +614,18 @@ get_extended_header(fp, hdr, header_size, hcrc) break; case 0x41: /* Windows time stamp (FILETIME structure) */ - skip_bytes(header_size - n); /* ignored */ + /* it is time in 100 nano seconds since 1601-01-01 00:00:00 */ + + skip_bytes(8); /* create time is ignored */ + + /* set last modified time */ + if (hdr->header_level >= 2) + skip_bytes(8); /* time_t has been already set */ + else + hdr->unix_last_modified_stamp = wintime_to_unix_stamp(); + + skip_bytes(8); /* last access time is ignored */ + break; case 0x50: /* UNIX permission */ diff --git a/src/lha.h b/src/lha.h index 6a53c5c..9232778 100644 --- a/src/lha.h +++ b/src/lha.h @@ -23,6 +23,14 @@ #include #include +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif + #if STDC_HEADERS # include #else @@ -81,6 +89,17 @@ typedef int uid_t; typedef int gid_t; #endif +#if !HAVE_UINT64_T +# define HAVE_UINT64_T 1 +# if SIZEOF_LONG == 8 + typedef unsigned long uint64_t; +# elif HAVE_LONG_LONG + typedef unsigned long long uint64_t; +# else +# undef HAVE_UINT64_T +# endif +#endif + #if TIME_WITH_SYS_TIME # include # include