Feature #4052 ยป lutime.patch
configure.in | ||
---|---|---|
fi
|
||
AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall chroot getcwd eaccess\
|
||
truncate ftruncate chsize times utimes utimensat fcntl lockf lstat\
|
||
link symlink readlink readdir_r fsync fdatasync fchown\
|
||
link lutimes symlink readlink readdir_r fsync fdatasync fchown\
|
||
setitimer setruid seteuid setreuid setresuid setproctitle socketpair\
|
||
setrgid setegid setregid setresgid issetugid pause lchown lchmod\
|
||
getpgrp setpgrp getpgid setpgid initgroups getgroups setgroups\
|
file.c | ||
---|---|---|
struct utime_args {
|
||
const struct timespec* tsp;
|
||
VALUE atime, mtime;
|
||
int follow; /* Whether to act on symlinks (1) or their referent (0) */
|
||
};
|
||
#if defined DOSISH || defined __CYGWIN__
|
||
... | ... | |
#ifdef HAVE_UTIMENSAT
|
||
static int try_utimensat = 1;
|
||
static int try_utimensat_follow = 1;
|
||
int flags = 0;
|
||
if (try_utimensat) {
|
||
if (utimensat(AT_FDCWD, path, tsp, 0) < 0) {
|
||
if ((v->follow && try_utimensat_follow) || (!v->follow && try_utimensat)) {
|
||
if (v->follow) {
|
||
#ifdef AT_SYMLINK_NOFOLLOW
|
||
flags = AT_SYMLINK_NOFOLLOW;
|
||
#else
|
||
try_utimensat_follow = 0;
|
||
goto no_utimensat;
|
||
#endif
|
||
}
|
||
if (utimensat(AT_FDCWD, path, tsp, flags) < 0) {
|
||
if (errno == ENOSYS) {
|
||
try_utimensat = 0;
|
||
try_utimensat_follow = 0;
|
||
if (!v->follow)
|
||
try_utimensat = 0;
|
||
goto no_utimensat;
|
||
}
|
||
utime_failed(path, tsp, v->atime, v->mtime);
|
||
... | ... | |
tvbuf[1].tv_usec = (int)(tsp[1].tv_nsec / 1000);
|
||
tvp = tvbuf;
|
||
}
|
||
if (utimes(path, tvp) < 0)
|
||
if (v->follow) {
|
||
#ifdef HAVE_LUTIMES
|
||
if (lutimes(path, tvp) < 0)
|
||
utime_failed(path, tsp, v->atime, v->mtime);
|
||
#else
|
||
rb_notimplement();
|
||
#endif
|
||
}
|
||
else if (utimes(path, tvp) < 0)
|
||
utime_failed(path, tsp, v->atime, v->mtime);
|
||
}
|
||
... | ... | |
#endif
|
||
/*
|
||
* call-seq:
|
||
* File.utime(atime, mtime, file_name,...) -> integer
|
||
*
|
||
* Sets the access and modification times of each
|
||
* named file to the first two arguments. Returns
|
||
* the number of file names in the argument list.
|
||
*/
|
||
static VALUE
|
||
rb_file_s_utime(int argc, VALUE *argv)
|
||
utime_internal_i(int argc, VALUE *argv, int follow)
|
||
{
|
||
VALUE rest;
|
||
struct utime_args args;
|
||
... | ... | |
rb_secure(2);
|
||
rb_scan_args(argc, argv, "2*", &args.atime, &args.mtime, &rest);
|
||
args.follow = follow;
|
||
if (!NIL_P(args.atime) || !NIL_P(args.mtime)) {
|
||
tsp = tss;
|
||
tsp[0] = rb_time_timespec(args.atime);
|
||
... | ... | |
return LONG2FIX(n);
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* File.utime(atime, mtime, file_name,...) -> integer
|
||
*
|
||
* Sets the access and modification times of each named file to the
|
||
* first two arguments. If a file is a symlink, this method acts upon
|
||
* its referent rather than the link itself; for the inverse
|
||
* behavior see <code>File.lutime</code>. Returns the number of file
|
||
* names in the argument list.
|
||
*/
|
||
static VALUE
|
||
rb_file_s_utime(int argc, VALUE *argv)
|
||
{
|
||
return utime_internal_i(argc, argv, 0);
|
||
}
|
||
#if defined(HAVE_UTIMES) && (defined(HAVE_LUTIMES) || (defined(HAVE_UTIMENSAT) && defined(AT_SYMLINK_NOFOLLOW)))
|
||
/*
|
||
* call-seq:
|
||
* File.lutime(atime, mtime, file_name,...) -> integer
|
||
*
|
||
* Sets the access and modification times of each named file to the
|
||
* first two arguments. If a file is a symlink, this method acts upon
|
||
* the link itself as opposed to its referent; for the inverse
|
||
* behavior, see <code>File.utime</code>. Returns the number of file
|
||
* names in the argument list.
|
||
*/
|
||
static VALUE
|
||
rb_file_s_lutime(int argc, VALUE *argv)
|
||
{
|
||
return utime_internal_i(argc, argv, 1);
|
||
}
|
||
#else
|
||
#define rb_file_s_lutime rb_f_notimplement
|
||
#endif
|
||
NORETURN(static void sys_fail2(VALUE,VALUE));
|
||
static void
|
||
sys_fail2(VALUE s1, VALUE s2)
|
||
... | ... | |
rb_define_singleton_method(rb_cFile, "chown", rb_file_s_chown, -1);
|
||
rb_define_singleton_method(rb_cFile, "lchmod", rb_file_s_lchmod, -1);
|
||
rb_define_singleton_method(rb_cFile, "lchown", rb_file_s_lchown, -1);
|
||
rb_define_singleton_method(rb_cFile, "lutime", rb_file_s_lutime, -1);
|
||
rb_define_singleton_method(rb_cFile, "link", rb_file_s_link, 2);
|
||
rb_define_singleton_method(rb_cFile, "symlink", rb_file_s_symlink, 2);
|
test/ruby/test_file_exhaustive.rb | ||
---|---|---|
File.utime(t + 1, t + 2, @zerofile)
|
||
assert_equal(t + 1, File.atime(@zerofile))
|
||
assert_equal(t + 2, File.mtime(@zerofile))
|
||
skip("File.symlink not implemented") unless (File.respond_to?(:symlink) and @symlinkfile)
|
||
stat_ln = File.lstat(@symlinkfile)
|
||
assert_equal(File.utime(t, t, @symlinkfile), 1)
|
||
assert_equal(File.stat(@file).atime, t)
|
||
assert_equal(File.stat(@file).mtime, t)
|
||
assert_equal(File.lstat(@symlinkfile).atime, stat_ln.atime)
|
||
assert_equal(File.lstat(@symlinkfile).mtime, stat_ln.mtime)
|
||
end
|
||
def test_lutime
|
||
skip("File.lutime not implemented") unless File.respond_to?(:lutime)
|
||
Dir.mktmpdir('rubytest-lutime') do |tmp|
|
||
Dir.chdir(tmp) do
|
||
open('f',?w){}
|
||
times = [Time.now - 24*100, Time.now - 24*1_000].map(&:round)
|
||
assert_equal(File.lutime(times[0], times[0], ?f), 1)
|
||
assert_equal(File.stat(?f).atime.round, times[0])
|
||
assert_equal(File.stat(?f).mtime.round, times[0])
|
||
# Assume that a platform supporting changing utimens on symlinks
|
||
# also supports symlinks
|
||
File.symlink(?f, ?l)
|
||
assert_equal(File.lutime(times[1], times[1], ?l), 1)
|
||
assert_equal(File.stat(?f).atime.round, times[0])
|
||
assert_equal(File.stat(?f).mtime.round, times[0])
|
||
assert_equal(File.lstat(?l).atime.round, times[1])
|
||
assert_equal(File.lstat(?l).mtime.round, times[1])
|
||
assert_equal(File.lutime(times[1], times[0], ?l, ?f), 2)
|
||
assert_equal(File.stat(?f).atime.round, times[1])
|
||
assert_equal(File.stat(?f).mtime.round, times[0])
|
||
assert_equal(File.lstat(?l).atime.round, times[1])
|
||
assert_equal(File.lstat(?l).mtime.round, times[0])
|
||
end
|
||
end
|
||
end
|
||
def test_hardlink
|