3535 ***** END LICENSE BLOCK *****/
3636package org .jruby ;
3737
38+ import jnr .constants .platform .OpenFlags ;
39+ import jnr .posix .POSIX ;
40+ import jnr .posix .util .Platform ;
41+ import org .jcodings .Encoding ;
42+ import org .jruby .anno .JRubyClass ;
43+ import org .jruby .anno .JRubyMethod ;
44+ import org .jruby .runtime .*;
45+ import org .jruby .runtime .JavaSites .FileSites ;
46+ import org .jruby .runtime .builtin .IRubyObject ;
47+ import org .jruby .runtime .encoding .EncodingCapable ;
48+ import org .jruby .runtime .encoding .EncodingService ;
49+ import org .jruby .util .*;
50+ import org .jruby .util .io .EncodingUtils ;
51+ import org .jruby .util .io .IOEncodable ;
52+ import org .jruby .util .io .OpenFile ;
53+ import org .jruby .util .io .PosixShim ;
54+
3855import java .io .File ;
3956import java .io .IOException ;
4057import java .io .InputStream ;
5875import java .util .zip .ZipEntry ;
5976import java .util .zip .ZipFile ;
6077
61- import jnr .constants .platform .OpenFlags ;
62- import jnr .posix .POSIX ;
63- import jnr .posix .util .Platform ;
64- import org .jcodings .Encoding ;
65- import org .jruby .anno .JRubyClass ;
66- import org .jruby .anno .JRubyMethod ;
67- import org .jruby .runtime .Block ;
68- import org .jruby .runtime .ClassIndex ;
69- import org .jruby .runtime .JavaSites .FileSites ;
70- import org .jruby .runtime .ObjectAllocator ;
71- import org .jruby .runtime .ThreadContext ;
72- import static org .jruby .runtime .Visibility .*;
73- import org .jruby .runtime .builtin .IRubyObject ;
74- import org .jruby .runtime .encoding .EncodingCapable ;
75- import org .jruby .util .ByteList ;
76- import org .jruby .util .FileResource ;
77- import org .jruby .util .JRubyFile ;
78- import org .jruby .util .StringSupport ;
79- import org .jruby .util .TypeConverter ;
80- import org .jruby .util .io .EncodingUtils ;
81- import org .jruby .util .io .IOEncodable ;
82- import org .jruby .util .io .OpenFile ;
83- import org .jruby .runtime .Helpers ;
84- import org .jruby .runtime .encoding .EncodingService ;
85- import org .jruby .util .io .PosixShim ;
86-
78+ import static org .jruby .runtime .Visibility .PRIVATE ;
8779import static org .jruby .util .io .EncodingUtils .vmode ;
8880import static org .jruby .util .io .EncodingUtils .vperm ;
8981
@@ -1150,12 +1142,12 @@ public static IRubyObject umask(ThreadContext context, IRubyObject recv, IRubyOb
11501142 @ JRubyMethod (required = 2 , rest = true , meta = true )
11511143 public static IRubyObject utime (ThreadContext context , IRubyObject recv , IRubyObject [] args ) {
11521144 Ruby runtime = context .runtime ;
1153- long [] atimeval = null ;
1154- long [] mtimeval = null ;
1145+ long [] atimespec = null ;
1146+ long [] mtimespec = null ;
11551147
11561148 if (args [0 ] != context .nil || args [1 ] != context .nil ) {
1157- atimeval = extractTimeval (context , args [0 ]);
1158- mtimeval = extractTimeval (context , args [1 ]);
1149+ atimespec = extractTimespec (context , args [0 ]);
1150+ mtimespec = extractTimespec (context , args [1 ]);
11591151 }
11601152
11611153 for (int i = 2 , j = args .length ; i < j ; i ++) {
@@ -1167,7 +1159,8 @@ public static IRubyObject utime(ThreadContext context, IRubyObject recv, IRubyOb
11671159 throw runtime .newErrnoENOENTError (filename .toString ());
11681160 }
11691161
1170- int result = runtime .getPosix ().utimes (fileToTouch .getAbsolutePath (), atimeval , mtimeval );
1162+ int fd = runtime .getPosix ().open (fileToTouch .getAbsolutePath (), OpenFlags .O_RDWR .intValue (), 0444 );
1163+ int result = runtime .getPosix ().futimens (fd , atimespec , mtimespec );
11711164 if (result == -1 ) {
11721165 throw runtime .newErrnoFromInt (runtime .getPosix ().errno ());
11731166 }
@@ -1552,31 +1545,31 @@ static String adjustRootPathOnWindows(Ruby runtime, String path, String dir) {
15521545 }
15531546
15541547 /**
1555- * Extract a timeval (an array of 2 longs: seconds and microseconds from epoch) from
1548+ * Extract a timespec (an array of 2 longs: seconds and nanoseconds from epoch) from
15561549 * an IRubyObject.
15571550 */
1558- private static long [] extractTimeval (ThreadContext context , IRubyObject value ) {
1559- long [] timeval = new long [2 ];
1551+ private static long [] extractTimespec (ThreadContext context , IRubyObject value ) {
1552+ long [] timespec = new long [2 ];
15601553
15611554 if (value instanceof RubyFloat ) {
1562- timeval [0 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (value ) : RubyNumeric .num2long (value );
1555+ timespec [0 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (value ) : RubyNumeric .num2long (value );
15631556 double fraction = ((RubyFloat ) value ).getDoubleValue () % 1.0 ;
1564- timeval [1 ] = (long )(fraction * 1e6 + 0.5 );
1557+ timespec [1 ] = (long )(fraction * 1e9 + 0.5 );
15651558 } else if (value instanceof RubyNumeric ) {
1566- timeval [0 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (value ) : RubyNumeric .num2long (value );
1567- timeval [1 ] = 0 ;
1559+ timespec [0 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (value ) : RubyNumeric .num2long (value );
1560+ timespec [1 ] = 0 ;
15681561 } else {
15691562 RubyTime time ;
15701563 if (value instanceof RubyTime ) {
15711564 time = ((RubyTime ) value );
15721565 } else {
15731566 time = (RubyTime ) TypeConverter .convertToType (context , value , context .runtime .getTime (), sites (context ).to_time_checked , true );
15741567 }
1575- timeval [0 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (time .to_i ()) : RubyNumeric .num2long (time .to_i ());
1576- timeval [1 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (time .usec ()) : RubyNumeric .num2long (time .usec ());
1568+ timespec [0 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (time .to_i ()) : RubyNumeric .num2long (time .to_i ());
1569+ timespec [1 ] = Platform .IS_32_BIT ? RubyNumeric .num2int (time .nsec ()) : RubyNumeric .num2long (time .nsec ());
15771570 }
15781571
1579- return timeval ;
1572+ return timespec ;
15801573 }
15811574
15821575 private void checkClosed (ThreadContext context ) {
0 commit comments