11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
51cb0ef41Sopenharmony_citmpdir.refresh();
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst assert = require('assert');
81cb0ef41Sopenharmony_ciconst fs = require('fs');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci// Check for Y2K38 support. For Windows, assume it's there. Windows
111cb0ef41Sopenharmony_ci// doesn't have `touch` and `date -r` which are used in the check for support.
121cb0ef41Sopenharmony_ciif (!common.isWindows) {
131cb0ef41Sopenharmony_ci  const testFilePath = `${tmpdir.path}/y2k38-test`;
141cb0ef41Sopenharmony_ci  const testFileDate = '204001020304';
151cb0ef41Sopenharmony_ci  const { spawnSync } = require('child_process');
161cb0ef41Sopenharmony_ci  const touchResult = spawnSync('touch',
171cb0ef41Sopenharmony_ci                                ['-t', testFileDate, testFilePath],
181cb0ef41Sopenharmony_ci                                { encoding: 'utf8' });
191cb0ef41Sopenharmony_ci  if (touchResult.status !== 0) {
201cb0ef41Sopenharmony_ci    common.skip('File system appears to lack Y2K38 support (touch failed)');
211cb0ef41Sopenharmony_ci  }
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  // On some file systems that lack Y2K38 support, `touch` will succeed but
241cb0ef41Sopenharmony_ci  // the time will be incorrect.
251cb0ef41Sopenharmony_ci  const dateResult = spawnSync('date',
261cb0ef41Sopenharmony_ci                               ['-r', testFilePath, '+%Y%m%d%H%M'],
271cb0ef41Sopenharmony_ci                               { encoding: 'utf8' });
281cb0ef41Sopenharmony_ci  if (dateResult.status === 0) {
291cb0ef41Sopenharmony_ci    if (dateResult.stdout.trim() !== testFileDate) {
301cb0ef41Sopenharmony_ci      common.skip('File system appears to lack Y2k38 support (date failed)');
311cb0ef41Sopenharmony_ci    }
321cb0ef41Sopenharmony_ci  } else {
331cb0ef41Sopenharmony_ci    // On some platforms `date` may not support the `-r` option. Usually
341cb0ef41Sopenharmony_ci    // this will result in a non-zero status and usage information printed.
351cb0ef41Sopenharmony_ci    // In this case optimistically proceed -- the earlier `touch` succeeded
361cb0ef41Sopenharmony_ci    // but validation that the file has the correct time is not easily possible.
371cb0ef41Sopenharmony_ci    assert.match(dateResult.stderr, /[Uu]sage:/);
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci}
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci// Ref: https://github.com/nodejs/node/issues/13255
421cb0ef41Sopenharmony_ciconst path = `${tmpdir.path}/test-utimes-precision`;
431cb0ef41Sopenharmony_cifs.writeFileSync(path, '');
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ciconst Y2K38_mtime = 2 ** 31;
461cb0ef41Sopenharmony_cifs.utimesSync(path, Y2K38_mtime, Y2K38_mtime);
471cb0ef41Sopenharmony_ciconst Y2K38_stats = fs.statSync(path);
481cb0ef41Sopenharmony_ciassert.strictEqual(Y2K38_stats.mtime.getTime() / 1000, Y2K38_mtime);
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ciif (common.isWindows) {
511cb0ef41Sopenharmony_ci  // This value would get converted to (double)1713037251359.9998
521cb0ef41Sopenharmony_ci  const truncate_mtime = 1713037251360;
531cb0ef41Sopenharmony_ci  fs.utimesSync(path, truncate_mtime / 1000, truncate_mtime / 1000);
541cb0ef41Sopenharmony_ci  const truncate_stats = fs.statSync(path);
551cb0ef41Sopenharmony_ci  assert.strictEqual(truncate_stats.mtime.getTime(), truncate_mtime);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  // test Y2K38 for windows
581cb0ef41Sopenharmony_ci  // This value if treaded as a `signed long` gets converted to -2135622133469.
591cb0ef41Sopenharmony_ci  // POSIX systems stores timestamps in {long t_sec, long t_usec}.
601cb0ef41Sopenharmony_ci  // NTFS stores times in nanoseconds in a single `uint64_t`, so when libuv
611cb0ef41Sopenharmony_ci  // calculates (long)`uv_timespec_t.tv_sec` we get 2's complement.
621cb0ef41Sopenharmony_ci  const overflow_mtime = 2159345162531;
631cb0ef41Sopenharmony_ci  fs.utimesSync(path, overflow_mtime / 1000, overflow_mtime / 1000);
641cb0ef41Sopenharmony_ci  const overflow_stats = fs.statSync(path);
651cb0ef41Sopenharmony_ci  assert.strictEqual(overflow_stats.mtime.getTime(), overflow_mtime);
661cb0ef41Sopenharmony_ci}
67