* file.c (utime_failed): refined the error message for EINVAL on
DOSISH platforms, where it may fail depending on filesystems. see [ruby-dev:38277]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a3a88c6bcd
commit
228d3e46a3
@ -1,3 +1,9 @@
|
|||||||
|
Mon Apr 6 19:26:18 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* file.c (utime_failed): refined the error message for EINVAL on
|
||||||
|
DOSISH platforms, where it may fail depending on filesystems.
|
||||||
|
see [ruby-dev:38277].
|
||||||
|
|
||||||
Mon Apr 6 16:38:50 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Mon Apr 6 16:38:50 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* file.c (sys_fail2, rb_file_s_readlink, BUFCHECK, rmext),
|
* file.c (sys_fail2, rb_file_s_readlink, BUFCHECK, rmext),
|
||||||
|
72
file.c
72
file.c
@ -2080,25 +2080,68 @@ rb_file_s_lchown(int argc, VALUE *argv)
|
|||||||
|
|
||||||
struct timespec rb_time_timespec(VALUE time);
|
struct timespec rb_time_timespec(VALUE time);
|
||||||
|
|
||||||
|
struct utime_args {
|
||||||
|
const struct timespec* tsp;
|
||||||
|
VALUE atime, mtime;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined DOSISH || defined __CYGWIN__
|
||||||
|
NORETURN(static void utime_failed(const char *, const struct timespec *, VALUE, VALUE));
|
||||||
|
|
||||||
|
static void
|
||||||
|
utime_failed(const char *path, const struct timespec *tsp, VALUE atime, VALUE mtime)
|
||||||
|
{
|
||||||
|
if (tsp && errno == EINVAL) {
|
||||||
|
VALUE e[2], a = Qnil, m = Qnil;
|
||||||
|
int d = 0;
|
||||||
|
if (!NIL_P(atime)) {
|
||||||
|
a = rb_inspect(atime);
|
||||||
|
}
|
||||||
|
if (!NIL_P(mtime) && mtime != atime && !rb_equal(atime, mtime)) {
|
||||||
|
m = rb_inspect(mtime);
|
||||||
|
}
|
||||||
|
if (NIL_P(a)) e[0] = m;
|
||||||
|
else if (NIL_P(m) || rb_str_cmp(a, m) == 0) e[0] = a;
|
||||||
|
else {
|
||||||
|
e[0] = rb_str_plus(a, rb_str_new_cstr(" or "));
|
||||||
|
rb_str_append(e[0], m);
|
||||||
|
d = 1;
|
||||||
|
}
|
||||||
|
if (!NIL_P(e[0])) {
|
||||||
|
if (path) {
|
||||||
|
if (!d) e[0] = rb_str_dup(e[0]);
|
||||||
|
rb_str_cat2(rb_str_cat2(e[0], " for "), path);
|
||||||
|
}
|
||||||
|
e[1] = INT2FIX(EINVAL);
|
||||||
|
rb_exc_raise(rb_class_new_instance(2, e, rb_eSystemCallError));
|
||||||
|
}
|
||||||
|
errno = EINVAL;
|
||||||
|
}
|
||||||
|
rb_sys_fail(path);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define utime_failed(path, tsp, atime, mtime) rb_sys_fail(path)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_UTIMES)
|
#if defined(HAVE_UTIMES)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
utime_internal(const char *path, void *arg)
|
utime_internal(const char *path, void *arg)
|
||||||
{
|
{
|
||||||
struct timespec *tsp = arg;
|
struct utime_args *v = arg;
|
||||||
struct timeval tvbuf[2], *tvp = arg;
|
const struct timespec *tsp = v->tsp;
|
||||||
|
struct timeval tvbuf[2], *tvp = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_UTIMENSAT
|
#ifdef HAVE_UTIMENSAT
|
||||||
static int try_utimensat = 1;
|
static int try_utimensat = 1;
|
||||||
|
|
||||||
if (try_utimensat) {
|
if (try_utimensat) {
|
||||||
struct timespec *tsp = arg;
|
|
||||||
if (utimensat(AT_FDCWD, path, tsp, 0) < 0) {
|
if (utimensat(AT_FDCWD, path, tsp, 0) < 0) {
|
||||||
if (errno == ENOSYS) {
|
if (errno == ENOSYS) {
|
||||||
try_utimensat = 0;
|
try_utimensat = 0;
|
||||||
goto no_utimensat;
|
goto no_utimensat;
|
||||||
}
|
}
|
||||||
rb_sys_fail(path);
|
utime_failed(path, tsp, v->atime, v->mtime);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2113,7 +2156,7 @@ no_utimensat:
|
|||||||
tvp = tvbuf;
|
tvp = tvbuf;
|
||||||
}
|
}
|
||||||
if (utimes(path, tvp) < 0)
|
if (utimes(path, tvp) < 0)
|
||||||
rb_sys_fail(path);
|
utime_failed(path, tsp, v->atime, v->mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -2128,7 +2171,8 @@ struct utimbuf {
|
|||||||
static void
|
static void
|
||||||
utime_internal(const char *path, void *arg)
|
utime_internal(const char *path, void *arg)
|
||||||
{
|
{
|
||||||
struct timespec *tsp = arg;
|
struct utime_args *v = arg;
|
||||||
|
const struct timespec *tsp = v->tsp;
|
||||||
struct utimbuf utbuf, *utp = NULL;
|
struct utimbuf utbuf, *utp = NULL;
|
||||||
if (tsp) {
|
if (tsp) {
|
||||||
utbuf.actime = tsp[0].tv_sec;
|
utbuf.actime = tsp[0].tv_sec;
|
||||||
@ -2136,7 +2180,7 @@ utime_internal(const char *path, void *arg)
|
|||||||
utp = &utbuf;
|
utp = &utbuf;
|
||||||
}
|
}
|
||||||
if (utime(path, utp) < 0)
|
if (utime(path, utp) < 0)
|
||||||
rb_sys_fail(path);
|
utime_failed(path, tsp, v->atime, v->mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -2153,20 +2197,22 @@ utime_internal(const char *path, void *arg)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_file_s_utime(int argc, VALUE *argv)
|
rb_file_s_utime(int argc, VALUE *argv)
|
||||||
{
|
{
|
||||||
VALUE atime, mtime, rest;
|
VALUE rest;
|
||||||
|
struct utime_args args;
|
||||||
struct timespec tss[2], *tsp = NULL;
|
struct timespec tss[2], *tsp = NULL;
|
||||||
long n;
|
long n;
|
||||||
|
|
||||||
rb_secure(2);
|
rb_secure(2);
|
||||||
rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest);
|
rb_scan_args(argc, argv, "2*", &args.atime, &args.mtime, &rest);
|
||||||
|
|
||||||
if (!NIL_P(atime) || !NIL_P(mtime)) {
|
if (!NIL_P(args.atime) || !NIL_P(args.mtime)) {
|
||||||
tsp = tss;
|
tsp = tss;
|
||||||
tsp[0] = rb_time_timespec(atime);
|
tsp[0] = rb_time_timespec(args.atime);
|
||||||
tsp[1] = rb_time_timespec(mtime);
|
tsp[1] = rb_time_timespec(args.mtime);
|
||||||
}
|
}
|
||||||
|
args.tsp = tsp;
|
||||||
|
|
||||||
n = apply2files(utime_internal, rest, tsp);
|
n = apply2files(utime_internal, rest, &args);
|
||||||
return LONG2FIX(n);
|
return LONG2FIX(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user