2206 |
2206 |
#define rb_file_s_lchown rb_f_notimplement
|
2207 |
2207 |
#endif
|
2208 |
2208 |
|
|
2209 |
typedef enum utime_mode utime_mode_t;
|
|
2210 |
|
|
2211 |
enum utime_mode {
|
|
2212 |
M_SYMLINK_FOLLOW = 0,
|
|
2213 |
M_SYMLINK_NOFOLLOW
|
|
2214 |
};
|
|
2215 |
|
2209 |
2216 |
struct utime_args {
|
2210 |
2217 |
const struct timespec* tsp;
|
2211 |
2218 |
VALUE atime, mtime;
|
|
2219 |
utime_mode_t mode;
|
2212 |
2220 |
};
|
2213 |
2221 |
|
|
2222 |
#if !defined(FOLLOW_SYMLINK_P)
|
|
2223 |
# define FOLLOW_SYMLINK_P(x) ((x)->mode == M_SYMLINK_FOLLOW)
|
|
2224 |
#endif
|
|
2225 |
|
2214 |
2226 |
#if defined DOSISH || defined __CYGWIN__
|
2215 |
2227 |
NORETURN(static void utime_failed(VALUE, const struct timespec *, VALUE, VALUE));
|
2216 |
2228 |
|
... | ... | |
2252 |
2264 |
#if defined(HAVE_UTIMES)
|
2253 |
2265 |
|
2254 |
2266 |
static void
|
2255 |
|
utime_internal(const char *path, VALUE pathv, void *arg)
|
|
2267 |
utime_helper(const char *path, VALUE pathv, void *arg)
|
2256 |
2268 |
{
|
2257 |
2269 |
struct utime_args *v = arg;
|
2258 |
2270 |
const struct timespec *tsp = v->tsp;
|
... | ... | |
2260 |
2272 |
|
2261 |
2273 |
#ifdef HAVE_UTIMENSAT
|
2262 |
2274 |
static int try_utimensat = 1;
|
|
2275 |
const int flags = FOLLOW_SYMLINK_P(v) ? 0 : AT_SYMLINK_NOFOLLOW;
|
2263 |
2276 |
|
2264 |
2277 |
if (try_utimensat) {
|
2265 |
|
if (utimensat(AT_FDCWD, path, tsp, 0) < 0) {
|
|
2278 |
if (utimensat(AT_FDCWD, path, tsp, flags) < 0) {
|
2266 |
2279 |
if (errno == ENOSYS) {
|
2267 |
2280 |
try_utimensat = 0;
|
2268 |
2281 |
goto no_utimensat;
|
... | ... | |
2281 |
2294 |
tvbuf[1].tv_usec = (int)(tsp[1].tv_nsec / 1000);
|
2282 |
2295 |
tvp = tvbuf;
|
2283 |
2296 |
}
|
2284 |
|
if (utimes(path, tvp) < 0)
|
|
2297 |
if ((FOLLOW_SYMLINK_P(v) ? utimes(path, tvp) : lutimes(path, tvp)) < 0)
|
2285 |
2298 |
utime_failed(pathv, tsp, v->atime, v->mtime);
|
2286 |
2299 |
}
|
2287 |
2300 |
|
... | ... | |
2295 |
2308 |
#endif
|
2296 |
2309 |
|
2297 |
2310 |
static void
|
2298 |
|
utime_internal(const char *path, VALUE pathv, void *arg)
|
|
2311 |
utime_helper(const char *path, VALUE pathv, void *arg)
|
2299 |
2312 |
{
|
2300 |
2313 |
struct utime_args *v = arg;
|
2301 |
2314 |
const struct timespec *tsp = v->tsp;
|
... | ... | |
2305 |
2318 |
utbuf.modtime = tsp[1].tv_sec;
|
2306 |
2319 |
utp = &utbuf;
|
2307 |
2320 |
}
|
2308 |
|
if (utime(path, utp) < 0)
|
|
2321 |
if ((FOLLOW_SYMLINK_P(v) ? utimes(path, utp) : lutimes(path, utp)) < 0)
|
2309 |
2322 |
utime_failed(pathv, tsp, v->atime, v->mtime);
|
2310 |
2323 |
}
|
2311 |
2324 |
|
2312 |
2325 |
#endif
|
2313 |
2326 |
|
2314 |
|
/*
|
2315 |
|
* call-seq:
|
2316 |
|
* File.utime(atime, mtime, file_name,...) -> integer
|
2317 |
|
*
|
2318 |
|
* Sets the access and modification times of each
|
2319 |
|
* named file to the first two arguments. Returns
|
2320 |
|
* the number of file names in the argument list.
|
2321 |
|
*/
|
2322 |
|
|
2323 |
2327 |
static VALUE
|
2324 |
|
rb_file_s_utime(int argc, VALUE *argv)
|
|
2328 |
utime_internal(int argc, VALUE *argv, utime_mode_t mode)
|
2325 |
2329 |
{
|
2326 |
2330 |
VALUE rest;
|
2327 |
2331 |
struct utime_args args;
|
... | ... | |
2337 |
2341 |
tsp[1] = rb_time_timespec(args.mtime);
|
2338 |
2342 |
}
|
2339 |
2343 |
args.tsp = tsp;
|
|
2344 |
#ifdef HAVE_LUTIMES
|
|
2345 |
args.mode = mode;
|
|
2346 |
#else
|
|
2347 |
args.mode = M_SYMLINK_FOLLOW;
|
|
2348 |
#endif
|
2340 |
2349 |
|
2341 |
|
n = apply2files(utime_internal, rest, &args);
|
|
2350 |
n = apply2files(utime_helper, rest, &args);
|
2342 |
2351 |
return LONG2FIX(n);
|
2343 |
2352 |
}
|
2344 |
2353 |
|
|
2354 |
/*
|
|
2355 |
* call-seq:
|
|
2356 |
* File.utime(atime, mtime, file_name,...) -> integer
|
|
2357 |
*
|
|
2358 |
* Sets the access and modification times of each
|
|
2359 |
* named file to the first two arguments. Returns
|
|
2360 |
* the number of file names in the argument list.
|
|
2361 |
* See also File::lutime.
|
|
2362 |
*/
|
|
2363 |
|
|
2364 |
static inline VALUE
|
|
2365 |
rb_file_s_utime(int argc, VALUE *argv)
|
|
2366 |
{
|
|
2367 |
return utime_internal(argc, argv, M_SYMLINK_FOLLOW);
|
|
2368 |
}
|
|
2369 |
|
|
2370 |
#ifdef HAVE_LUTIMES
|
|
2371 |
/*
|
|
2372 |
* call-seq:
|
|
2373 |
* File.lutime(atime, mtime, file_name,...) -> integer
|
|
2374 |
*
|
|
2375 |
* Equivalent to File::utime, but does not follow
|
|
2376 |
* symbolic links (so it will change the +atime+
|
|
2377 |
* and +mtime+ associated with the link, not the
|
|
2378 |
* file referenced by the link). Often not available.
|
|
2379 |
*
|
|
2380 |
* See also File::utime.
|
|
2381 |
*/
|
|
2382 |
|
|
2383 |
static VALUE
|
|
2384 |
rb_file_s_lutime(int argc, VALUE *argv)
|
|
2385 |
{
|
|
2386 |
return utime_internal(argc, argv, M_SYMLINK_NOFOLLOW);
|
|
2387 |
}
|
|
2388 |
#else
|
|
2389 |
#define rb_file_s_lutime rb_f_notimplement
|
|
2390 |
#endif
|
|
2391 |
|
|
2392 |
#if defined(FOLLOW_SYMLINK_P)
|
|
2393 |
# undef FOLLOW_SYMLINK_P
|
|
2394 |
#endif
|
|
2395 |
|
2345 |
2396 |
NORETURN(static void sys_fail2(VALUE,VALUE));
|
2346 |
2397 |
static void
|
2347 |
2398 |
sys_fail2(VALUE s1, VALUE s2)
|
... | ... | |
5439 |
5490 |
rb_define_singleton_method(rb_cFile, "ctime", rb_file_s_ctime, 1);
|
5440 |
5491 |
|
5441 |
5492 |
rb_define_singleton_method(rb_cFile, "utime", rb_file_s_utime, -1);
|
|
5493 |
rb_define_singleton_method(rb_cFile, "lutime", rb_file_s_lutime, -1);
|
5442 |
5494 |
rb_define_singleton_method(rb_cFile, "chmod", rb_file_s_chmod, -1);
|
5443 |
5495 |
rb_define_singleton_method(rb_cFile, "chown", rb_file_s_chown, -1);
|
5444 |
5496 |
rb_define_singleton_method(rb_cFile, "lchmod", rb_file_s_lchmod, -1);
|