Feature #13696 » patch.diff
| file.c | ||
|---|---|---|
|
#include <sys/time.h>
|
||
|
#endif
|
||
|
#ifdef HAVE_SYSCALL_H
|
||
|
# include <syscall.h>
|
||
|
#elif defined HAVE_SYS_SYSCALL_H
|
||
|
# include <sys/syscall.h>
|
||
|
#endif
|
||
|
#ifndef RENAME_NOREPLACE
|
||
|
# define RENAME_NOREPLACE 1
|
||
|
#endif
|
||
|
#ifndef RENAME_EXCHANGE
|
||
|
# define RENAME_EXCHANGE 2
|
||
|
#endif
|
||
|
#if !defined HAVE_LSTAT && !defined lstat
|
||
|
#define lstat stat
|
||
|
#endif
|
||
| ... | ... | |
|
/*
|
||
|
* call-seq:
|
||
|
* File.rename(old_name, new_name) -> 0
|
||
|
* File.rename(old_name, new_name, replace: bool) -> 0
|
||
|
*
|
||
|
* Renames the given file to the new name. Raises a
|
||
|
* <code>SystemCallError</code> if the file cannot be renamed.
|
||
|
*
|
||
|
* File.rename("afile", "afile.bak") #=> 0
|
||
|
*
|
||
|
* If <i>replace<i> is false (default is true), new_name will not be
|
||
|
* overwritten and an exception will be raised.
|
||
|
*/
|
||
|
static VALUE
|
||
|
rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
|
||
|
rb_file_s_rename(int argc, VALUE *argv, VALUE klass)
|
||
|
{
|
||
|
static ID keyword_id;
|
||
|
const char *src, *dst;
|
||
|
VALUE f, t;
|
||
|
unsigned int flags = 0;
|
||
|
VALUE from, to, f, t, opt, vreplace;
|
||
|
if (!keyword_id) {
|
||
|
CONST_ID(keyword_id, "replace");
|
||
|
}
|
||
|
rb_scan_args(argc, argv, "2:", &from, &to, &opt);
|
||
|
FilePathValue(from);
|
||
|
FilePathValue(to);
|
||
|
f = rb_str_encode_ospath(from);
|
||
| ... | ... | |
|
#if defined __CYGWIN__
|
||
|
errno = 0;
|
||
|
#endif
|
||
|
if (!NIL_P(opt)) {
|
||
|
rb_get_kwargs(opt, &keyword_id, 0, 1, &vreplace);
|
||
|
if (vreplace != Qundef && !RTEST(vreplace)) { /* replace: false */
|
||
|
flags |= RENAME_NOREPLACE;
|
||
|
}
|
||
|
if (flags) { /* use renameat2 */
|
||
|
#if defined __linux__ && defined __NR_renameat2
|
||
|
if (syscall(__NR_renameat2, AT_FDCWD, src, AT_FDCWD, dst, flags) < 0) {
|
||
|
int e = errno;
|
||
|
syserr_fail2(e, from, to);
|
||
|
}
|
||
|
return INT2FIX(0);
|
||
|
#else
|
||
|
rb_raise(rb_eNotImpError, "additional flags are not supported");
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
if (rename(src, dst) < 0) {
|
||
|
int e = errno;
|
||
|
#if defined DOSISH
|
||
| ... | ... | |
|
/*
|
||
|
* call-seq:
|
||
|
* File.exchange(old_name, new_name) -> 0
|
||
|
*
|
||
|
* Exchange two files atomically. This will cause NotImplementedError if
|
||
|
* renameat2(2) is not available.
|
||
|
*/
|
||
|
static VALUE
|
||
|
rb_file_s_exchange(VALUE klass, VALUE from, VALUE to)
|
||
|
{
|
||
|
const char *src, *dst;
|
||
|
VALUE f, t;
|
||
|
FilePathValue(from);
|
||
|
FilePathValue(to);
|
||
|
f = rb_str_encode_ospath(from);
|
||
|
t = rb_str_encode_ospath(to);
|
||
|
src = StringValueCStr(f);
|
||
|
dst = StringValueCStr(t);
|
||
|
#if defined __CYGWIN__
|
||
|
errno = 0;
|
||
|
#endif
|
||
|
#if defined __linux__ && defined __NR_renameat2
|
||
|
if (syscall(__NR_renameat2, AT_FDCWD, src, AT_FDCWD, dst, RENAME_EXCHANGE) < 0) {
|
||
|
int e = errno;
|
||
|
syserr_fail2(e, from, to);
|
||
|
}
|
||
|
#else
|
||
|
rb_raise(rb_eNotImpError, "atomic exchange is not supported");
|
||
|
#endif
|
||
|
return INT2FIX(0);
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* File.umask() -> integer
|
||
|
* File.umask(integer) -> integer
|
||
|
*
|
||
| ... | ... | |
|
rb_define_singleton_method(rb_cFile, "unlink", rb_file_s_unlink, -1);
|
||
|
rb_define_singleton_method(rb_cFile, "delete", rb_file_s_unlink, -1);
|
||
|
rb_define_singleton_method(rb_cFile, "rename", rb_file_s_rename, 2);
|
||
|
rb_define_singleton_method(rb_cFile, "rename", rb_file_s_rename, -1);
|
||
|
rb_define_singleton_method(rb_cFile, "exchange", rb_file_s_exchange, 2);
|
||
|
rb_define_singleton_method(rb_cFile, "umask", rb_file_s_umask, -1);
|
||
|
rb_define_singleton_method(rb_cFile, "truncate", rb_file_s_truncate, 2);
|
||
|
rb_define_singleton_method(rb_cFile, "mkfifo", rb_file_s_mkfifo, -1);
|
||
| test/ruby/test_file_exhaustive.rb | ||
|---|---|---|
|
end
|
||
|
end
|
||
|
def test_rename_replace
|
||
|
assert_equal(0, File.rename(regular_file, nofile, replace: false))
|
||
|
assert_file.not_exist?(regular_file)
|
||
|
assert_file.exist?(nofile)
|
||
|
assert_equal(0, File.rename(nofile, regular_file, replace: false))
|
||
|
assert_raise(Errno::EEXIST) { assert_equal(0, File.rename(regular_file, zerofile, replace: false)) }
|
||
|
rescue NotImplementedError
|
||
|
end if POSIX
|
||
|
def test_exchange
|
||
|
content = File.read(regular_file)
|
||
|
assert_equal(0, File.exchange(regular_file, zerofile))
|
||
|
assert_file.exist?(regular_file)
|
||
|
assert_equal(true, File.empty?(regular_file))
|
||
|
assert_equal(content, File.read(zerofile))
|
||
|
assert_raise(Errno::ENOENT) { File.exchange(regular_file, nofile) }
|
||
|
rescue NotImplementedError
|
||
|
end if POSIX
|
||
|
def test_umask
|
||
|
prev = File.umask(0777)
|
||
|
assert_equal(0777, File.umask)
|
||
- « Previous
- 1
- 2
- Next »