/** * Internal worker function which setups RTFSOBJINFO based on a UNIX stat struct. * * @param pObjInfo The file system object info structure to setup. * @param pStat The stat structure to use. * @param pszName The filename which this applies to (exe/hidden check). * @param cbName The length of that filename. (optional, set 0) */ void rtFsConvertStatToObjInfo(PRTFSOBJINFO pObjInfo, const struct stat *pStat, const char *pszName, unsigned cbName) { pObjInfo->cbObject = pStat->st_size; pObjInfo->cbAllocated = pStat->st_blocks * DEV_BSIZE; #ifdef HAVE_STAT_NSEC RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->AccessTime, pStat->st_atime), pStat->st_atimensec); RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, pStat->st_mtime), pStat->st_mtimensec); RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, pStat->st_ctime), pStat->st_ctimensec); # ifdef HAVE_STAT_BIRTHTIME RTTimeSpecAddNano(RTTimeSpecSetSeconds(&pObjInfo->BirthTime, pStat->st_birthtime), pStat->st_birthtimensec); # endif #elif defined(HAVE_STAT_TIMESPEC_BRIEF) RTTimeSpecSetTimespec(&pObjInfo->AccessTime, &pStat->st_atim); RTTimeSpecSetTimespec(&pObjInfo->ModificationTime, &pStat->st_mtim); RTTimeSpecSetTimespec(&pObjInfo->ChangeTime, &pStat->st_ctim); # ifdef HAVE_STAT_BIRTHTIME RTTimeSpecSetTimespec(&pObjInfo->BirthTime, &pStat->st_birthtim); # endif #elif defined(HAVE_STAT_TIMESPEC) RTTimeSpecSetTimespec(&pObjInfo->AccessTime, pStat->st_atimespec); RTTimeSpecSetTimespec(&pObjInfo->ModificationTime, pStat->st_mtimespec); RTTimeSpecSetTimespec(&pObjInfo->ChangeTime, pStat->st_ctimespec); # ifdef HAVE_STAT_BIRTHTIME RTTimeSpecSetTimespec(&pObjInfo->BirthTime, pStat->st_birthtimespec); # endif #else /* just the normal stuff */ RTTimeSpecSetSeconds(&pObjInfo->AccessTime, pStat->st_atime); RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, pStat->st_mtime); RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, pStat->st_ctime); # ifdef HAVE_STAT_BIRTHTIME RTTimeSpecSetSeconds(&pObjInfo->BirthTime, pStat->st_birthtime); # endif #endif #ifndef HAVE_STAT_BIRTHTIME pObjInfo->BirthTime = pObjInfo->ChangeTime; #endif /* the file mode */ RTFMODE fMode = pStat->st_mode & RTFS_UNIX_MASK; Assert(RTFS_UNIX_ISUID == S_ISUID); Assert(RTFS_UNIX_ISGID == S_ISGID); #ifdef S_ISTXT Assert(RTFS_UNIX_ISTXT == S_ISTXT); #elif defined(S_ISVTX) Assert(RTFS_UNIX_ISTXT == S_ISVTX); #else #error "S_ISVTX / S_ISTXT isn't defined" #endif Assert(RTFS_UNIX_IRWXU == S_IRWXU); Assert(RTFS_UNIX_IRUSR == S_IRUSR); Assert(RTFS_UNIX_IWUSR == S_IWUSR); Assert(RTFS_UNIX_IXUSR == S_IXUSR); Assert(RTFS_UNIX_IRWXG == S_IRWXG); Assert(RTFS_UNIX_IRGRP == S_IRGRP); Assert(RTFS_UNIX_IWGRP == S_IWGRP); Assert(RTFS_UNIX_IXGRP == S_IXGRP); Assert(RTFS_UNIX_IRWXO == S_IRWXO); Assert(RTFS_UNIX_IROTH == S_IROTH); Assert(RTFS_UNIX_IWOTH == S_IWOTH); Assert(RTFS_UNIX_IXOTH == S_IXOTH); Assert(RTFS_TYPE_FIFO == S_IFIFO); Assert(RTFS_TYPE_DEV_CHAR == S_IFCHR); Assert(RTFS_TYPE_DIRECTORY == S_IFDIR); Assert(RTFS_TYPE_DEV_BLOCK == S_IFBLK); Assert(RTFS_TYPE_FILE == S_IFREG); Assert(RTFS_TYPE_SYMLINK == S_IFLNK); Assert(RTFS_TYPE_SOCKET == S_IFSOCK); #ifdef S_IFWHT Assert(RTFS_TYPE_WHITEOUT == S_IFWHT); #endif Assert(RTFS_TYPE_MASK == S_IFMT); pObjInfo->Attr.fMode = rtFsModeFromUnix(fMode, pszName, cbName); /* additional unix attribs */ pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX; pObjInfo->Attr.u.Unix.uid = pStat->st_uid; pObjInfo->Attr.u.Unix.gid = pStat->st_gid; pObjInfo->Attr.u.Unix.cHardlinks = pStat->st_nlink; pObjInfo->Attr.u.Unix.INodeIdDevice = pStat->st_dev; pObjInfo->Attr.u.Unix.INodeId = pStat->st_ino; #ifdef HAVE_STAT_FLAGS pObjInfo->Attr.u.Unix.fFlags = pStat->st_flags; #else pObjInfo->Attr.u.Unix.fFlags = 0; #endif #ifdef HAVE_STAT_GEN pObjInfo->Attr.u.Unix.GenerationId = pStat->st_gen; #else pObjInfo->Attr.u.Unix.GenerationId = 0; #endif pObjInfo->Attr.u.Unix.Device = pStat->st_rdev; }
/** * Translate a TAR header to an IPRT object info structure with additional UNIX * attributes. * * This completes the validation done by rtZipTarHdrValidate. * * @returns VINF_SUCCESS if valid, appropriate VERR_TAR_XXX if not. * @param pThis The TAR reader instance. * @param pObjInfo The object info structure (output). */ static int rtZipTarReaderGetFsObjInfo(PRTZIPTARREADER pThis, PRTFSOBJINFO pObjInfo) { /* * Zap the whole structure, this takes care of unused space in the union. */ RT_ZERO(*pObjInfo); /* * Convert the TAR field in RTFSOBJINFO order. */ int rc; int64_t i64Tmp; #define GET_TAR_NUMERIC_FIELD_RET(a_Var, a_Field) \ do { \ rc = rtZipTarHdrFieldToNum(a_Field, sizeof(a_Field), false /*fOctalOnly*/, &i64Tmp); \ if (RT_FAILURE(rc)) \ return rc; \ (a_Var) = i64Tmp; \ if ((a_Var) != i64Tmp) \ return VERR_TAR_NUM_VALUE_TOO_LARGE; \ } while (0) GET_TAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pThis->Hdr.Common.size); pObjInfo->cbAllocated = RT_ALIGN_64(pObjInfo->cbObject, 512); int64_t c64SecModTime; GET_TAR_NUMERIC_FIELD_RET(c64SecModTime, pThis->Hdr.Common.mtime); RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, c64SecModTime); RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, c64SecModTime); RTTimeSpecSetSeconds(&pObjInfo->AccessTime, c64SecModTime); RTTimeSpecSetSeconds(&pObjInfo->BirthTime, c64SecModTime); if (c64SecModTime != RTTimeSpecGetSeconds(&pObjInfo->ModificationTime)) return VERR_TAR_NUM_VALUE_TOO_LARGE; GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.fMode, pThis->Hdr.Common.mode); pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX; GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.uid, pThis->Hdr.Common.uid); GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.gid, pThis->Hdr.Common.gid); pObjInfo->Attr.u.Unix.cHardlinks = 1; pObjInfo->Attr.u.Unix.INodeIdDevice = 0; pObjInfo->Attr.u.Unix.INodeId = 0; pObjInfo->Attr.u.Unix.fFlags = 0; pObjInfo->Attr.u.Unix.GenerationId = 0; pObjInfo->Attr.u.Unix.Device = 0; switch (pThis->enmType) { case RTZIPTARTYPE_POSIX: case RTZIPTARTYPE_GNU: if ( pThis->Hdr.Common.typeflag == RTZIPTAR_TF_CHR || pThis->Hdr.Common.typeflag == RTZIPTAR_TF_BLK) { uint32_t uMajor, uMinor; GET_TAR_NUMERIC_FIELD_RET(uMajor, pThis->Hdr.Common.devmajor); GET_TAR_NUMERIC_FIELD_RET(uMinor, pThis->Hdr.Common.devminor); pObjInfo->Attr.u.Unix.Device = RTDEV_MAKE(uMajor, uMinor); if ( uMajor != RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device) || uMinor != RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device)) return VERR_TAR_DEV_VALUE_TOO_LARGE; } break; default: if ( pThis->Hdr.Common.typeflag == RTZIPTAR_TF_CHR || pThis->Hdr.Common.typeflag == RTZIPTAR_TF_BLK) return VERR_TAR_UNKNOWN_TYPE_FLAG; } #undef GET_TAR_NUMERIC_FIELD_RET /* * Massage the result a little bit. * Also validate some more now that we've got the numbers to work with. */ if ( (pObjInfo->Attr.fMode & ~RTFS_UNIX_MASK) && pThis->enmType == RTZIPTARTYPE_POSIX) return VERR_TAR_BAD_MODE_FIELD; pObjInfo->Attr.fMode &= RTFS_UNIX_MASK; RTFMODE fModeType = 0; switch (pThis->Hdr.Common.typeflag) { case RTZIPTAR_TF_OLDNORMAL: case RTZIPTAR_TF_NORMAL: case RTZIPTAR_TF_CONTIG: { const char *pszEnd = strchr(pThis->szName, '\0'); if (pszEnd == &pThis->szName[0] || pszEnd[-1] != '/') fModeType |= RTFS_TYPE_FILE; else fModeType |= RTFS_TYPE_DIRECTORY; break; } case RTZIPTAR_TF_LINK: if (pObjInfo->cbObject != 0) #if 0 /* too strict */ return VERR_TAR_SIZE_NOT_ZERO; #else pObjInfo->cbObject = pObjInfo->cbAllocated = 0; #endif fModeType |= RTFS_TYPE_FILE; /* no better idea for now */ break; case RTZIPTAR_TF_SYMLINK: fModeType |= RTFS_TYPE_SYMLINK; break; case RTZIPTAR_TF_CHR: fModeType |= RTFS_TYPE_DEV_CHAR; break; case RTZIPTAR_TF_BLK: fModeType |= RTFS_TYPE_DEV_BLOCK; break; case RTZIPTAR_TF_DIR: fModeType |= RTFS_TYPE_DIRECTORY; break; case RTZIPTAR_TF_FIFO: fModeType |= RTFS_TYPE_FIFO; break; case RTZIPTAR_TF_GNU_LONGLINK: case RTZIPTAR_TF_GNU_LONGNAME: /* ASSUMES RTFS_TYPE_XXX uses the same values as GNU stored in the mode field. */ fModeType = pObjInfo->Attr.fMode & RTFS_TYPE_MASK; switch (fModeType) { case RTFS_TYPE_FILE: case RTFS_TYPE_DIRECTORY: case RTFS_TYPE_SYMLINK: case RTFS_TYPE_DEV_BLOCK: case RTFS_TYPE_DEV_CHAR: case RTFS_TYPE_FIFO: break; default: case 0: return VERR_TAR_UNKNOWN_TYPE_FLAG; /** @todo new status code */ } default: return VERR_TAR_UNKNOWN_TYPE_FLAG; /* Should've been caught in validate. */ } if ( (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) && (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) != fModeType) return VERR_TAR_MODE_WITH_TYPE; pObjInfo->Attr.fMode &= ~RTFS_TYPE_MASK; pObjInfo->Attr.fMode |= fModeType; switch (pThis->Hdr.Common.typeflag) { case RTZIPTAR_TF_CHR: case RTZIPTAR_TF_BLK: case RTZIPTAR_TF_DIR: case RTZIPTAR_TF_FIFO: pObjInfo->cbObject = 0; pObjInfo->cbAllocated = 0; break; } return VINF_SUCCESS; }
int main() { RTTIMESPEC Now; RTTIMESPEC Ts1; RTTIMESPEC Ts2; RTTIME T1; RTTIME T2; #ifdef RTTIME_INCL_TIMEVAL struct timeval Tv1; struct timeval Tv2; struct timespec Tsp1; struct timespec Tsp2; #endif RTTEST hTest; int rc = RTTestInitAndCreate("tstRTTimeSpec", &hTest); if (rc) return rc; /* * Simple test with current time. */ RTTestSub(hTest, "Current time (UTC)"); CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Simple test with current local time. */ RTTestSub(hTest, "Current time (local)"); CHECK_NZ(RTTimeLocalNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); RTTestIPrintf(RTTESTLVL_ALWAYS, " %RI64 ns - %s\n", RTTimeSpecGetNano(&Now), ToString(&T1)); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); if (!RTTimeSpecIsEqual(&Ts1, &Now)) RTTestIFailed("%RI64 != %RI64\n", RTTimeSpecGetNano(&Ts1), RTTimeSpecGetNano(&Now)); /* * Some simple tests with fixed dates (just checking for smoke). */ RTTestSub(hTest, "Smoke"); TEST_NS(INT64_C(0)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(86400000000000)); CHECK_TIME(&T1, 1970,01,02, 00,00,00, 0, 2, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); TEST_NS(INT64_C(-1)); CHECK_TIME(&T1, 1969,12,31, 23,59,59,999999999, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Test the limits. */ RTTestSub(hTest, "Extremes"); TEST_NS(INT64_MAX); TEST_NS(INT64_MIN); TEST_SEC(1095379198); CHECK_TIME(&T1, 2004, 9,16, 23,59,58, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379199); CHECK_TIME(&T1, 2004, 9,16, 23,59,59, 0, 260, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379200); CHECK_TIME(&T1, 2004, 9,17, 00,00,00, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); TEST_SEC(1095379201); CHECK_TIME(&T1, 2004, 9,17, 00,00,01, 0, 261, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); /* * Test normalization (UTC). */ RTTestSub(hTest, "Normalization (UTC)"); /* simple */ CHECK_NZ(RTTimeNow(&Now)); CHECK_NZ(RTTimeExplode(&T1, &Now)); T2 = T1; CHECK_NZ(RTTimeNormalize(&T1)); if (memcmp(&T1, &T2, sizeof(T1))) RTTestIFailed("simple normalization failed\n"); CHECK_NZ(RTTimeImplode(&Ts1, &T1)); CHECK_NZ(RTTimeSpecIsEqual(&Ts1, &Now)); /* a few partial dates. */ memset(&T1, 0, sizeof(T1)); SET_TIME( &T1, 1970,01,01, 00,00,00, 0, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1970,00,00, 00,00,00, 1, 1, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01,01, 00,00,00, 1, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,12,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1968,01,30, 00,19,24, 5, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1968,01,30, 00,19,24, 5, 30, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 1969,01,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,01,31, 00, 9, 2, 7, 31, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,03,31, 00, 9, 2, 7, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,03,31, 00, 9, 2, 7, 90, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,31, 00,00,00, 9, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,31, 00,00,00, 9, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,30, 00,00,00, 30, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,30, 00,00,00, 30, 364, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 363, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,29, 00,00,00, 30, 363, 0, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 362, 6, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,28, 00,00,00, 30, 362, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,27, 00,00,00, 30, 0, 5, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,27, 00,00,00, 30, 361, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,00,00, 00,00,00, 30, 360, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,26, 00,00,00, 30, 360, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,25, 00,00,00, 12, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,25, 00,00,00, 12, 359, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 1969,12,24, 00,00,00, 16, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1969,12,24, 00,00,00, 16, 358, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* outside the year table range */ SET_TIME( &T1, 1200,01,30, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1200,01,30, 00,00,00, 2, 30, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2555,11,29, 00,00,00, 2, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 2, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2555,00,00, 00,00,00, 3, 333, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2555,11,29, 00,00,00, 3, 333, 5, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* time overflow */ SET_TIME( &T1, 1969,12,30, 255,255,255, UINT32_MAX, 364, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 1970,01, 9, 19,19,19,294967295, 9, 4, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* date overflow */ SET_TIME( &T1, 2007,11,36, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,67, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2007,10,98, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2006,24,06, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); SET_TIME( &T1, 2003,60,37, 02,15,23, 1, 0, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2008,01,06, 02,15,23, 1, 6, 6, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); SET_TIME( &T1, 2003,00,00, 02,15,23, 1,1801, 0, 0, 0); CHECK_NZ(RTTimeNormalize(&T1)); CHECK_TIME(&T1, 2007,12,06, 02,15,23, 1, 340, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); /* * Conversions. */ #define CHECK_NSEC(Ts1, T2) \ do { \ RTTIMESPEC TsTmp; \ RTTESTI_CHECK_MSG( RTTimeSpecGetNano(&(Ts1)) == RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2))), \ ("line %d: %RI64, %RI64\n", __LINE__, \ RTTimeSpecGetNano(&(Ts1)), RTTimeSpecGetNano(RTTimeImplode(&TsTmp, &(T2)))) ); \ } while (0) RTTestSub(hTest, "Conversions, positive"); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetDosSeconds(&Ts2, 0) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetDosSeconds(&Ts2) == 0); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1980,01,01, 00,00,00, 0, 1, 1, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_LEAP_YEAR); RTTESTI_CHECK(RTTimeSpecSetNtTime(&Ts2, INT64_C(119600064000000000)) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNtTime(&Ts2) == INT64_C(119600064000000000)); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetSeconds(&Ts2, 1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetSeconds(&Ts2) == 1); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMilli(&Ts2, 1000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMilli(&Ts2) == 1000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetMicro(&Ts2, 1000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000000); CHECK_NSEC(Ts2, T1); SET_TIME(&T1, 1970,01,01, 00,00,01, 0, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); RTTESTI_CHECK(RTTimeSpecSetNano(&Ts2, 1000000000) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000000); CHECK_NSEC(Ts2, T1); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1970,01,01, 00,00,01, 5000, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = 1; Tv1.tv_usec = 5; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetMicro(&Ts2) == 1000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1970,01,01, 00,00,01, 5, 1, 3, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = 1; Tsp1.tv_nsec = 5; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK(RTTimeSpecGetNano(&Ts2) == 1000000005); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif RTTestSub(hTest, "Conversions, negative"); #ifdef RTTIME_INCL_TIMEVAL SET_TIME(&T1, 1969,12,31, 23,59,58,999995000, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tv1.tv_sec = -2; Tv1.tv_usec = 999995; RTTESTI_CHECK(RTTimeSpecSetTimeval(&Ts2, &Tv1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetMicro(&Ts2) == -1000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimeval(&Ts2, &Tv2) == &Tv2); RTTESTI_CHECK(Tv1.tv_sec == Tv2.tv_sec); RTTESTI_CHECK(Tv1.tv_usec == Tv2.tv_usec); #endif #ifdef RTTIME_INCL_TIMESPEC SET_TIME(&T1, 1969,12,31, 23,59,58,999999995, 365, 2, 0, RTTIME_FLAGS_TYPE_UTC | RTTIME_FLAGS_COMMON_YEAR); Tsp1.tv_sec = -2; Tsp1.tv_nsec = 999999995; RTTESTI_CHECK(RTTimeSpecSetTimespec(&Ts2, &Tsp1) == &Ts2); RTTESTI_CHECK_MSG(RTTimeSpecGetNano(&Ts2) == -1000000005, ("%RI64\n", RTTimeSpecGetMicro(&Ts2))); CHECK_NSEC(Ts2, T1); RTTESTI_CHECK(RTTimeSpecGetTimespec(&Ts2, &Tsp2) == &Tsp2); RTTESTI_CHECK(Tsp1.tv_sec == Tsp2.tv_sec); RTTESTI_CHECK(Tsp1.tv_nsec == Tsp2.tv_nsec); #endif /* * Summary */ return RTTestSummaryAndDestroy(hTest); }