mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
Issue #13964: Split os.*utime*() subsecond tests into multiple tests to help
debugging
This commit is contained in:
parent
8b6f10dda2
commit
a2f7c00638
2 changed files with 120 additions and 115 deletions
|
@ -300,49 +300,86 @@ class StatAttributeTests(unittest.TestCase):
|
||||||
st2 = os.stat(support.TESTFN)
|
st2 = os.stat(support.TESTFN)
|
||||||
self.assertAlmostEqual(st1.st_mtime, st2.st_mtime, delta=10)
|
self.assertAlmostEqual(st1.st_mtime, st2.st_mtime, delta=10)
|
||||||
|
|
||||||
def test_utime_subsecond(self):
|
def _test_utime_subsecond(self, set_time_func):
|
||||||
asec, amsec = 1, 901
|
asec, amsec = 1, 901
|
||||||
atime = asec + amsec * 1e-3
|
atime = asec + amsec * 1e-3
|
||||||
msec, mmsec = 5, 901
|
msec, mmsec = 2, 901
|
||||||
mtime = msec + mmsec * 1e-3
|
mtime = msec + mmsec * 1e-3
|
||||||
filename = self.fname
|
filename = self.fname
|
||||||
dirname = os.path.dirname(filename)
|
os.utime(filename, (0, 0))
|
||||||
for func in ('utime', 'futimes', 'futimens', 'futimesat', 'lutimes', 'utimensat'):
|
set_time_func(filename, atime, mtime)
|
||||||
if not hasattr(os, func):
|
st = os.stat(filename)
|
||||||
continue
|
self.assertAlmostEqual(st.st_atime, atime, places=3)
|
||||||
os.utime(filename, (0, 0))
|
self.assertAlmostEqual(st.st_mtime, mtime, places=3)
|
||||||
if func == 'utime':
|
|
||||||
os.utime(filename, (atime, mtime))
|
|
||||||
elif func == 'futimes':
|
|
||||||
with open(filename, "wb") as f:
|
|
||||||
os.futimes(f.fileno(), (atime, mtime))
|
|
||||||
os.utime(filename, (atime, mtime))
|
|
||||||
elif func == 'futimens':
|
|
||||||
with open(filename, "wb") as f:
|
|
||||||
os.futimens(f.fileno(),
|
|
||||||
(asec, amsec * 1000000),
|
|
||||||
(msec, mmsec * 1000000))
|
|
||||||
elif func == 'lutimes':
|
|
||||||
os.lutimes(filename, (atime, mtime))
|
|
||||||
elif func == 'futimesat':
|
|
||||||
dirfd = os.open(dirname, os.O_RDONLY)
|
|
||||||
try:
|
|
||||||
os.futimesat(dirfd, os.path.basename(filename),
|
|
||||||
(atime, mtime))
|
|
||||||
finally:
|
|
||||||
os.close(dirfd)
|
|
||||||
else:
|
|
||||||
dirfd = os.open(dirname, os.O_RDONLY)
|
|
||||||
try:
|
|
||||||
os.utimensat(dirfd, os.path.basename(filename),
|
|
||||||
(asec, amsec * 1000000),
|
|
||||||
(msec, mmsec * 1000000))
|
|
||||||
finally:
|
|
||||||
os.close(dirfd)
|
|
||||||
st = os.stat(filename)
|
|
||||||
self.assertAlmostEqual(st.st_atime, atime, places=3)
|
|
||||||
self.assertAlmostEqual(st.st_mtime, mtime, places=3)
|
|
||||||
|
|
||||||
|
def test_utime_subsecond(self):
|
||||||
|
def set_time(filename, atime, mtime):
|
||||||
|
os.utime(filename, (atime, mtime))
|
||||||
|
self._test_utime_subsecond(set_time)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'futimes'),
|
||||||
|
"os.futimes required for this test.")
|
||||||
|
def test_futimes_subsecond(self):
|
||||||
|
def set_time(filename, atime, mtime):
|
||||||
|
with open(filename, "wb") as f:
|
||||||
|
os.futimes(f.fileno(), (atime, mtime))
|
||||||
|
self._test_utime_subsecond(set_time)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'futimens'),
|
||||||
|
"os.futimens required for this test.")
|
||||||
|
def test_futimens_subsecond(self):
|
||||||
|
def set_time(filename, atime, mtime):
|
||||||
|
with open(filename, "wb") as f:
|
||||||
|
asec, ansec = divmod(atime, 1.0)
|
||||||
|
asec = int(asec)
|
||||||
|
ansec = int(ansec * 1e9)
|
||||||
|
msec, mnsec = divmod(mtime, 1.0)
|
||||||
|
msec = int(msec)
|
||||||
|
mnsec = int(mnsec * 1e9)
|
||||||
|
os.futimens(f.fileno(),
|
||||||
|
(asec, ansec),
|
||||||
|
(msec, mnsec))
|
||||||
|
self._test_utime_subsecond(set_time)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'futimesat'),
|
||||||
|
"os.futimesat required for this test.")
|
||||||
|
def test_futimesat_subsecond(self):
|
||||||
|
def set_time(filename, atime, mtime):
|
||||||
|
dirname = os.path.dirname(filename)
|
||||||
|
dirfd = os.open(dirname, os.O_RDONLY)
|
||||||
|
try:
|
||||||
|
os.futimesat(dirfd, os.path.basename(filename),
|
||||||
|
(atime, mtime))
|
||||||
|
finally:
|
||||||
|
os.close(dirfd)
|
||||||
|
self._test_utime_subsecond(set_time)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'lutimes'),
|
||||||
|
"os.lutimes required for this test.")
|
||||||
|
def test_lutimes_subsecond(self):
|
||||||
|
def set_time(filename, atime, mtime):
|
||||||
|
os.lutimes(filename, (atime, mtime))
|
||||||
|
self._test_utime_subsecond(set_time)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(os, 'utimensat'),
|
||||||
|
"os.utimensat required for this test.")
|
||||||
|
def test_utimensat_subsecond(self):
|
||||||
|
def set_time(filename, atime, mtime):
|
||||||
|
dirname = os.path.dirname(filename)
|
||||||
|
dirfd = os.open(dirname, os.O_RDONLY)
|
||||||
|
try:
|
||||||
|
asec, ansec = divmod(atime, 1.0)
|
||||||
|
asec = int(asec)
|
||||||
|
ansec = int(ansec * 1e9)
|
||||||
|
msec, mnsec = divmod(mtime, 1.0)
|
||||||
|
msec = int(msec)
|
||||||
|
mnsec = int(mnsec * 1e9)
|
||||||
|
os.utimensat(dirfd, os.path.basename(filename),
|
||||||
|
(asec, ansec),
|
||||||
|
(msec, mnsec))
|
||||||
|
finally:
|
||||||
|
os.close(dirfd)
|
||||||
|
self._test_utime_subsecond(set_time)
|
||||||
|
|
||||||
# Restrict test to Win32, since there is no guarantee other
|
# Restrict test to Win32, since there is no guarantee other
|
||||||
# systems support centiseconds
|
# systems support centiseconds
|
||||||
|
|
|
@ -187,6 +187,9 @@ corresponding Unix manual entries for more information on calls.");
|
||||||
#endif /* ! __WATCOMC__ || __QNX__ */
|
#endif /* ! __WATCOMC__ || __QNX__ */
|
||||||
#endif /* ! __IBMC__ */
|
#endif /* ! __IBMC__ */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
|
|
||||||
#if defined(__sgi)&&_COMPILER_VERSION>=700
|
#if defined(__sgi)&&_COMPILER_VERSION>=700
|
||||||
|
@ -3525,53 +3528,18 @@ posix_uname(PyObject *self, PyObject *noargs)
|
||||||
#endif /* HAVE_UNAME */
|
#endif /* HAVE_UNAME */
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Classic POSIX utime functions supported microseconds (1m/sec).
|
|
||||||
* Newer POSIX functions support nanoseconds (1 billion per sec).
|
|
||||||
* posixmodule now uses the new functions where possible.
|
|
||||||
* This improves accuracy in many situations, for example shutil.copy2().
|
|
||||||
*
|
|
||||||
* The implementation isn't currently sophisticated enough to handle
|
|
||||||
* a platform where HAVE_UTIMENSAT is true but HAVE_FUTIMENS is false.
|
|
||||||
* Specifically, posix_futimes() would break.
|
|
||||||
*
|
|
||||||
* Supporting such a platform wouldn't be impossible; you'd need two
|
|
||||||
* extract_time() functions, or make its precision a parameter.
|
|
||||||
* Since such a platform seems unlikely we haven't bothered.
|
|
||||||
*/
|
|
||||||
#if defined(HAVE_UTIMENSAT)
|
|
||||||
#define EXTRACT_TIME_PRECISION (1e9)
|
|
||||||
#if !defined(HAVE_FUTIMENS)
|
|
||||||
#error You HAVE_UTIMENSAT but not HAVE_FUTIMENS... please see accompanying comment.
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define EXTRACT_TIME_PRECISION (1e6)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
extract_time(PyObject *t, time_t* sec, long* usec)
|
extract_time(PyObject *t, time_t* sec, long* nsec)
|
||||||
{
|
{
|
||||||
time_t intval;
|
time_t intval;
|
||||||
if (PyFloat_Check(t)) {
|
if (PyFloat_Check(t)) {
|
||||||
double tval = PyFloat_AsDouble(t);
|
double d = PyFloat_AsDouble(t);
|
||||||
PyObject *intobj = PyNumber_Long(t);
|
double mod;
|
||||||
if (!intobj)
|
*sec = (time_t)d;
|
||||||
return -1;
|
mod = fmod(d, 1.0);
|
||||||
#if SIZEOF_TIME_T > SIZEOF_LONG
|
mod *= 1e9;
|
||||||
intval = PyLong_AsUnsignedLongLongMask(intobj);
|
*nsec = (long)mod;
|
||||||
#else
|
printf("%g => (%u, %li)\n", d, *sec, *nsec);
|
||||||
intval = PyLong_AsLong(intobj);
|
|
||||||
#endif
|
|
||||||
Py_DECREF(intobj);
|
|
||||||
if (intval == -1 && PyErr_Occurred())
|
|
||||||
return -1;
|
|
||||||
*sec = intval;
|
|
||||||
|
|
||||||
*usec = (long)((tval - intval) * EXTRACT_TIME_PRECISION);
|
|
||||||
if (*usec < 0)
|
|
||||||
/* If rounding gave us a negative number,
|
|
||||||
truncate. */
|
|
||||||
*usec = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#if SIZEOF_TIME_T > SIZEOF_LONG
|
#if SIZEOF_TIME_T > SIZEOF_LONG
|
||||||
|
@ -3582,7 +3550,7 @@ extract_time(PyObject *t, time_t* sec, long* usec)
|
||||||
if (intval == -1 && PyErr_Occurred())
|
if (intval == -1 && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
*sec = intval;
|
*sec = intval;
|
||||||
*usec = 0;
|
*nsec = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3602,7 +3570,7 @@ posix_utime(PyObject *self, PyObject *args)
|
||||||
const char *apath;
|
const char *apath;
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
time_t atimesec, mtimesec;
|
time_t atimesec, mtimesec;
|
||||||
long ausec, musec;
|
long ansec, mnsec;
|
||||||
FILETIME atime, mtime;
|
FILETIME atime, mtime;
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
|
|
||||||
|
@ -3655,13 +3623,13 @@ posix_utime(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atimesec, &ausec) == -1)
|
&atimesec, &ansec) == -1)
|
||||||
goto done;
|
goto done;
|
||||||
time_t_to_FILE_TIME(atimesec, 1000*ausec, &atime);
|
time_t_to_FILE_TIME(atimesec, ansec, &atime);
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtimesec, &musec) == -1)
|
&mtimesec, &mnsec) == -1)
|
||||||
goto done;
|
goto done;
|
||||||
time_t_to_FILE_TIME(mtimesec, 1000*musec, &mtime);
|
time_t_to_FILE_TIME(mtimesec, mnsec, &mtime);
|
||||||
}
|
}
|
||||||
if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
|
if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
|
||||||
/* Avoid putting the file name into the error here,
|
/* Avoid putting the file name into the error here,
|
||||||
|
@ -3681,7 +3649,7 @@ done:
|
||||||
PyObject *opath;
|
PyObject *opath;
|
||||||
char *path;
|
char *path;
|
||||||
time_t atime, mtime;
|
time_t atime, mtime;
|
||||||
long ausec, musec;
|
long ansec, mnsec;
|
||||||
int res;
|
int res;
|
||||||
PyObject* arg = Py_None;
|
PyObject* arg = Py_None;
|
||||||
|
|
||||||
|
@ -3703,12 +3671,12 @@ done:
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ausec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &musec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3718,16 +3686,16 @@ done:
|
||||||
#ifdef HAVE_UTIMENSAT
|
#ifdef HAVE_UTIMENSAT
|
||||||
struct timespec buf[2];
|
struct timespec buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_nsec = ausec;
|
buf[0].tv_nsec = ansec;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_nsec = musec;
|
buf[1].tv_nsec = mnsec;
|
||||||
res = utimensat(AT_FDCWD, path, buf, 0);
|
res = utimensat(AT_FDCWD, path, buf, 0);
|
||||||
#elif defined(HAVE_UTIMES)
|
#elif defined(HAVE_UTIMES)
|
||||||
struct timeval buf[2];
|
struct timeval buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_usec = ausec;
|
buf[0].tv_usec = ansec / 1000;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_usec = musec;
|
buf[1].tv_usec = mnsec / 1000;
|
||||||
res = utimes(path, buf);
|
res = utimes(path, buf);
|
||||||
#elif defined(HAVE_UTIME_H)
|
#elif defined(HAVE_UTIME_H)
|
||||||
/* XXX should define struct utimbuf instead, above */
|
/* XXX should define struct utimbuf instead, above */
|
||||||
|
@ -3767,7 +3735,7 @@ posix_futimes(PyObject *self, PyObject *args)
|
||||||
int res, fd;
|
int res, fd;
|
||||||
PyObject* arg = Py_None;
|
PyObject* arg = Py_None;
|
||||||
time_t atime, mtime;
|
time_t atime, mtime;
|
||||||
long ausec, musec;
|
long ansec, mnsec;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "i|O:futimes", &fd, &arg))
|
if (!PyArg_ParseTuple(args, "i|O:futimes", &fd, &arg))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3785,11 +3753,11 @@ posix_futimes(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ausec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &musec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
@ -3797,16 +3765,16 @@ posix_futimes(PyObject *self, PyObject *args)
|
||||||
#ifdef HAVE_FUTIMENS
|
#ifdef HAVE_FUTIMENS
|
||||||
struct timespec buf[2];
|
struct timespec buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_nsec = ausec;
|
buf[0].tv_nsec = ansec;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_nsec = musec;
|
buf[1].tv_nsec = mnsec;
|
||||||
res = futimens(fd, buf);
|
res = futimens(fd, buf);
|
||||||
#else
|
#else
|
||||||
struct timeval buf[2];
|
struct timeval buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_usec = ausec;
|
buf[0].tv_usec = ansec / 1000;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_usec = musec;
|
buf[1].tv_usec = mnsec / 1000;
|
||||||
res = futimes(fd, buf);
|
res = futimes(fd, buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3831,7 +3799,7 @@ posix_lutimes(PyObject *self, PyObject *args)
|
||||||
const char *path;
|
const char *path;
|
||||||
int res;
|
int res;
|
||||||
time_t atime, mtime;
|
time_t atime, mtime;
|
||||||
long ausec, musec;
|
long ansec, mnsec;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "O&|O:lutimes",
|
if (!PyArg_ParseTuple(args, "O&|O:lutimes",
|
||||||
PyUnicode_FSConverter, &opath, &arg))
|
PyUnicode_FSConverter, &opath, &arg))
|
||||||
|
@ -3851,12 +3819,12 @@ posix_lutimes(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ausec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &musec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -3865,16 +3833,16 @@ posix_lutimes(PyObject *self, PyObject *args)
|
||||||
#ifdef HAVE_UTIMENSAT
|
#ifdef HAVE_UTIMENSAT
|
||||||
struct timespec buf[2];
|
struct timespec buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_nsec = ausec;
|
buf[0].tv_nsec = ansec;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_nsec = musec;
|
buf[1].tv_nsec = mnsec;
|
||||||
res = utimensat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
|
res = utimensat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
|
||||||
#else
|
#else
|
||||||
struct timeval buf[2];
|
struct timeval buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_usec = ausec;
|
buf[0].tv_usec = ansec / 1000;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_usec = musec;
|
buf[1].tv_usec = mnsec / 1000;
|
||||||
res = lutimes(path, buf);
|
res = lutimes(path, buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -9712,7 +9680,7 @@ posix_futimesat(PyObject *self, PyObject *args)
|
||||||
int res, dirfd;
|
int res, dirfd;
|
||||||
PyObject* arg = Py_None;
|
PyObject* arg = Py_None;
|
||||||
time_t atime, mtime;
|
time_t atime, mtime;
|
||||||
long ausec, musec;
|
long ansec, mnsec;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "iO&|O:futimesat",
|
if (!PyArg_ParseTuple(args, "iO&|O:futimesat",
|
||||||
&dirfd, PyUnicode_FSConverter, &opath, &arg))
|
&dirfd, PyUnicode_FSConverter, &opath, &arg))
|
||||||
|
@ -9732,12 +9700,12 @@ posix_futimesat(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ausec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &musec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -9747,16 +9715,16 @@ posix_futimesat(PyObject *self, PyObject *args)
|
||||||
#ifdef HAVE_UTIMENSAT
|
#ifdef HAVE_UTIMENSAT
|
||||||
struct timespec buf[2];
|
struct timespec buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_nsec = ausec;
|
buf[0].tv_nsec = ansec;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_nsec = musec;
|
buf[1].tv_nsec = mnsec;
|
||||||
res = utimensat(dirfd, path, buf, 0);
|
res = utimensat(dirfd, path, buf, 0);
|
||||||
#else
|
#else
|
||||||
struct timeval buf[2];
|
struct timeval buf[2];
|
||||||
buf[0].tv_sec = atime;
|
buf[0].tv_sec = atime;
|
||||||
buf[0].tv_usec = ausec;
|
buf[0].tv_usec = ansec / 1000;
|
||||||
buf[1].tv_sec = mtime;
|
buf[1].tv_sec = mtime;
|
||||||
buf[1].tv_usec = musec;
|
buf[1].tv_usec = mnsec / 1000;
|
||||||
res = futimesat(dirfd, path, buf);
|
res = futimesat(dirfd, path, buf);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue