Project

General

Profile

Feature #7106 » 0001-Add-support-for-lutimes-3-to-file.c-as-File-lutime.patch

kwilczynski (Krzysztof Wilczynski), 10/19/2012 03:54 AM

View differences:

configure.in
AC_LIBOBJ([signbit])
fi
AC_CHECK_FUNCS(fmod killpg wait4 waitpid fork spawnv syscall __syscall chroot getcwd eaccess\
truncate ftruncate ftello chsize times utimes utimensat fcntl lockf lstat\
truncate ftruncate ftello chsize times utimes lutimes utimensat fcntl lockf lstat\
truncate64 ftruncate64 ftello64 fseeko fseeko64 \
link symlink readlink readdir_r fsync fdatasync fchown posix_fadvise\
setitimer setruid seteuid setreuid setresuid socketpair\
file.c
#define rb_file_s_lchown rb_f_notimplement
#endif
typedef enum utime_mode utime_mode_t;
enum utime_mode {
M_SYMLINK_FOLLOW = 0,
M_SYMLINK_NOFOLLOW
};
struct utime_args {
const struct timespec* tsp;
VALUE atime, mtime;
utime_mode_t mode;
};
#if !defined(FOLLOW_SYMLINK_P)
# define FOLLOW_SYMLINK_P(x) ((x)->mode == M_SYMLINK_FOLLOW)
#endif
#if defined DOSISH || defined __CYGWIN__
NORETURN(static void utime_failed(VALUE, const struct timespec *, VALUE, VALUE));
......
#if defined(HAVE_UTIMES)
static void
utime_internal(const char *path, VALUE pathv, void *arg)
utime_helper(const char *path, VALUE pathv, void *arg)
{
struct utime_args *v = arg;
const struct timespec *tsp = v->tsp;
......
#ifdef HAVE_UTIMENSAT
static int try_utimensat = 1;
const int flags = FOLLOW_SYMLINK_P(v) ? 0 : AT_SYMLINK_NOFOLLOW;
if (try_utimensat) {
if (utimensat(AT_FDCWD, path, tsp, 0) < 0) {
if (utimensat(AT_FDCWD, path, tsp, flags) < 0) {
if (errno == ENOSYS) {
try_utimensat = 0;
goto no_utimensat;
......
tvbuf[1].tv_usec = (int)(tsp[1].tv_nsec / 1000);
tvp = tvbuf;
}
if (utimes(path, tvp) < 0)
if ((FOLLOW_SYMLINK_P(v) ? utimes(path, tvp) : lutimes(path, tvp)) < 0)
utime_failed(pathv, tsp, v->atime, v->mtime);
}
......
#endif
static void
utime_internal(const char *path, VALUE pathv, void *arg)
utime_helper(const char *path, VALUE pathv, void *arg)
{
struct utime_args *v = arg;
const struct timespec *tsp = v->tsp;
......
utbuf.modtime = tsp[1].tv_sec;
utp = &utbuf;
}
if (utime(path, utp) < 0)
if ((FOLLOW_SYMLINK_P(v) ? utimes(path, utp) : lutimes(path, utp)) < 0)
utime_failed(pathv, 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(int argc, VALUE *argv, utime_mode_t mode)
{
VALUE rest;
struct utime_args args;
......
tsp[1] = rb_time_timespec(args.mtime);
}
args.tsp = tsp;
#ifdef HAVE_LUTIMES
args.mode = mode;
#else
args.mode = M_SYMLINK_FOLLOW;
#endif
n = apply2files(utime_internal, rest, &args);
n = apply2files(utime_helper, rest, &args);
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. Returns
* the number of file names in the argument list.
* See also File::lutime.
*/
static inline VALUE
rb_file_s_utime(int argc, VALUE *argv)
{
return utime_internal(argc, argv, M_SYMLINK_FOLLOW);
}
#ifdef HAVE_LUTIMES
/*
* call-seq:
* File.lutime(atime, mtime, file_name,...) -> integer
*
* Equivalent to File::utime, but does not follow
* symbolic links (so it will change the +atime+
* and +mtime+ associated with the link, not the
* file referenced by the link). Often not available.
*
* See also File::utime.
*/
static VALUE
rb_file_s_lutime(int argc, VALUE *argv)
{
return utime_internal(argc, argv, M_SYMLINK_NOFOLLOW);
}
#else
#define rb_file_s_lutime rb_f_notimplement
#endif
#if defined(FOLLOW_SYMLINK_P)
# undef FOLLOW_SYMLINK_P
#endif
NORETURN(static void sys_fail2(VALUE,VALUE));
static void
sys_fail2(VALUE s1, VALUE s2)
......
rb_define_singleton_method(rb_cFile, "ctime", rb_file_s_ctime, 1);
rb_define_singleton_method(rb_cFile, "utime", rb_file_s_utime, -1);
rb_define_singleton_method(rb_cFile, "lutime", rb_file_s_lutime, -1);
rb_define_singleton_method(rb_cFile, "chmod", rb_file_s_chmod, -1);
rb_define_singleton_method(rb_cFile, "chown", rb_file_s_chown, -1);
rb_define_singleton_method(rb_cFile, "lchmod", rb_file_s_lchmod, -1);
test/ruby/test_file_exhaustive.rb
assert_equal(t + 2, File.mtime(@zerofile))
end
def test_lutime
return unless @symlinkfile
t = Time.local(2000)
assert_equal(1, File.lutime(t + 1, t + 2, @symlinkfile))
assert_equal(2, File.lutime(t + 1, t + 2, @symlinkfile, @symlinkfile))
assert_equal(t + 1, File.lstat(@symlinkfile).atime)
assert_equal(t + 2, File.lstat(@symlinkfile).mtime)
assert_not_equal(t + 1, File.atime(@symlinkfile))
assert_not_equal(t + 2, File.mtime(@symlinkfile))
assert_raise(Errno::ENOENT) { File.lutime(t + 1, t + 2, @nofile) }
rescue NotImplementedError
end
def test_hardlink
return unless @hardlinkfile
assert_equal("file", File.ftype(@hardlinkfile))
(1-1/5)