Feature #4052: File.lutime Patch
http://redmine.ruby-lang.org/issues/show/4052

Author: Run Paint Run Run
Status: Open, Priority: Normal
Category: core

This patch implements File.lutime, which behaves as File.utime except if =
given a symlink it acts upon the link itself rather than the referent. Th=
e naming convention follows that of the other singleton methods of File w=
hich treat symlinks specially. This functionality could be implemented by=
 a gem, but given we already define File.lchmod, File.lchown, and File.ls=
tat, it is inconsistent not to also define File.lutime.

This functionality is provided by either lutimes(3), or utimensat(2) with=
 the AT_SYMLINK_NOFOLLOW flag. The latter is standardised by POSIX <http:=
//goo.gl/38pHx>

Platform support is as follows:
* FreeBSD - Has lutimes(2) since version 3. <http://goo.gl/9OWRF>
* Mac OS - Has lutimes since at least version 10.5. <http://goo.gl/pSvM1>=

* OpenBSD - Appears to lack both APIs.
* Linux - Supported lutimes(3) and utimensat(2) since version 2.6.22. (lu=
times() is just a wrapper for utimensat()). <http://goo.gl/p29ja>
* Windows - No support.

For the status of esoteric platforms, consult http://goo.gl/Bf4Qm and htt=
p://goo.gl/7h6cj .

On platforms that don't support either function, File.lutime raises a Not=
ImplementedError.

The portability logic is a bit hairy, so I'll summarise:

1 - File.lutime requires either lutimes() to be defined or both utimensat=
() and AT_SYMLINK_NOFOLLOW. I'm not aware of a practical case where utime=
nsat() would be defined without AT_SYMLINK_NOFOLLOW. Further, File.lutime=
 requires utimes(). This isn't strictly necessary, but simplifies the log=
ic: it seems most unlikely that a platform would support either lutimes()=
 or utimensat() without also supporting utimes().
2 - Like File.utime, we prefer to use utimensat() as it provides better r=
esolution than utimes(). =

3 - If utimensat(..., AT_SYMLINK_NOFOLLOW) sets errno to ENOSYS, there ar=
e two possibilities: either the platform doesn't support the system call,=
 or, like Linux 2.6.22 (<http://goo.gl/Bf4Qm>), utimensat() is defined bu=
t raises ENOSYS when given this flag. If utimensat() gives ENOSYS when it=
 wasn't passed AT_SYMLINK_NOFOLLOW, we assume the syscall really doesn't =
exist, and bypass it for all future invocations of File.utime and File.lu=
time. If utimensat() gives ENOSYS when passed AT_SYMLINK_NOFOLLOW, or AT_=
SYMLINK_NOFOLLOW_ isn't defined, we bypass utimensat() for all future Fil=
e.lutime invocations, but still consider it for future File.utime invocat=
ions.
4 - If we can't use utimensat() we fall back on lutimes().
5 - If a platform defines utimensat() and AT_SYMLINK_NOFOLLOW, but the fo=
rmer gives ENOSYS when passed the latter, we also fall back on lutimes().=
 However, if the platform doesn't define lutimes(), we raise NotImplement=
edError.

Tests are attached for File.utime when given a symlink and File.lutime.


----------------------------------------
http://redmine.ruby-lang.org
ZGlmZiAtLWdpdCBhL2NvbmZpZ3VyZS5pbiBiL2NvbmZpZ3VyZS5pbgppbmRl
eCBhZjUyNzRkLi5kNDFkNzBiIDEwMDY0NAotLS0gYS9jb25maWd1cmUuaW4K
KysrIGIvY29uZmlndXJlLmluCkBAIC0xMjkxLDcgKzEyOTEsNyBAQCBlbHNl
CiBmaQogQUNfQ0hFQ0tfRlVOQ1MoZm1vZCBraWxscGcgd2FpdDQgd2FpdHBp
ZCBmb3JrIHNwYXdudiBzeXNjYWxsIGNocm9vdCBnZXRjd2QgZWFjY2Vzc1wK
IAkgICAgICB0cnVuY2F0ZSBmdHJ1bmNhdGUgY2hzaXplIHRpbWVzIHV0aW1l
cyB1dGltZW5zYXQgZmNudGwgbG9ja2YgbHN0YXRcCi0JICAgICAgbGluayBz
eW1saW5rIHJlYWRsaW5rIHJlYWRkaXJfciBmc3luYyBmZGF0YXN5bmMgZmNo
b3duXAorCSAgICAgIGxpbmsgbHV0aW1lcyBzeW1saW5rIHJlYWRsaW5rIHJl
YWRkaXJfciBmc3luYyBmZGF0YXN5bmMgZmNob3duXAogCSAgICAgIHNldGl0
aW1lciBzZXRydWlkIHNldGV1aWQgc2V0cmV1aWQgc2V0cmVzdWlkIHNldHBy
b2N0aXRsZSBzb2NrZXRwYWlyXAogCSAgICAgIHNldHJnaWQgc2V0ZWdpZCBz
ZXRyZWdpZCBzZXRyZXNnaWQgaXNzZXR1Z2lkIHBhdXNlIGxjaG93biBsY2ht
b2RcCiAJICAgICAgZ2V0cGdycCBzZXRwZ3JwIGdldHBnaWQgc2V0cGdpZCBp
bml0Z3JvdXBzIGdldGdyb3VwcyBzZXRncm91cHNcCmRpZmYgLS1naXQgYS9m
aWxlLmMgYi9maWxlLmMKaW5kZXggZGM5ZjgzMC4uMGU4MDczMSAxMDA2NDQK
LS0tIGEvZmlsZS5jCisrKyBiL2ZpbGUuYwpAQCAtMjE5NSw2ICsyMTk1LDcg
QEAgc3RydWN0IHRpbWVzcGVjIHJiX3RpbWVfdGltZXNwZWMoVkFMVUUgdGlt
ZSk7CiBzdHJ1Y3QgdXRpbWVfYXJncyB7CiAgICAgY29uc3Qgc3RydWN0IHRp
bWVzcGVjKiB0c3A7CiAgICAgVkFMVUUgYXRpbWUsIG10aW1lOworICAgIGlu
dCBmb2xsb3c7IC8qIFdoZXRoZXIgdG8gYWN0IG9uIHN5bWxpbmtzICgxKSBv
ciB0aGVpciByZWZlcmVudCAoMCkgKi8KIH07CiAKICNpZiBkZWZpbmVkIERP
U0lTSCB8fCBkZWZpbmVkIF9fQ1lHV0lOX18KQEAgLTIyNDYsMTEgKzIyNDcs
MjQgQEAgdXRpbWVfaW50ZXJuYWwoY29uc3QgY2hhciAqcGF0aCwgdm9pZCAq
YXJnKQogCiAjaWZkZWYgSEFWRV9VVElNRU5TQVQKICAgICBzdGF0aWMgaW50
IHRyeV91dGltZW5zYXQgPSAxOworICAgIHN0YXRpYyBpbnQgdHJ5X3V0aW1l
bnNhdF9mb2xsb3cgPSAxOworICAgIGludCBmbGFncyA9IDA7CiAKLSAgICBp
ZiAodHJ5X3V0aW1lbnNhdCkgewotICAgICAgICBpZiAodXRpbWVuc2F0KEFU
X0ZEQ1dELCBwYXRoLCB0c3AsIDApIDwgMCkgeworICAgIGlmICgodi0+Zm9s
bG93ICYmIHRyeV91dGltZW5zYXRfZm9sbG93KSB8fCAoIXYtPmZvbGxvdyAm
JiB0cnlfdXRpbWVuc2F0KSkgeworCWlmICh2LT5mb2xsb3cpIHsKKyNpZmRl
ZiBBVF9TWU1MSU5LX05PRk9MTE9XCisJICAgIGZsYWdzID0gQVRfU1lNTElO
S19OT0ZPTExPVzsKKyNlbHNlCisJICAgIHRyeV91dGltZW5zYXRfZm9sbG93
ID0gMDsKKwkgICAgZ290byBub191dGltZW5zYXQ7CisjZW5kaWYKKwl9CisK
KyAgICAgICAgaWYgKHV0aW1lbnNhdChBVF9GRENXRCwgcGF0aCwgdHNwLCBm
bGFncykgPCAwKSB7CiAgICAgICAgICAgICBpZiAoZXJybm8gPT0gRU5PU1lT
KSB7Ci0gICAgICAgICAgICAgICAgdHJ5X3V0aW1lbnNhdCA9IDA7CisJCXRy
eV91dGltZW5zYXRfZm9sbG93ID0gMDsKKyAgICAgICAgICAgICAgICBpZiAo
IXYtPmZvbGxvdykKKwkJICAgIHRyeV91dGltZW5zYXQgPSAwOwogICAgICAg
ICAgICAgICAgIGdvdG8gbm9fdXRpbWVuc2F0OwogICAgICAgICAgICAgfQog
ICAgICAgICAgICAgdXRpbWVfZmFpbGVkKHBhdGgsIHRzcCwgdi0+YXRpbWUs
IHYtPm10aW1lKTsKQEAgLTIyNjcsNyArMjI4MSwxNiBAQCBub191dGltZW5z
YXQ6CiAgICAgICAgIHR2YnVmWzFdLnR2X3VzZWMgPSAoaW50KSh0c3BbMV0u
dHZfbnNlYyAvIDEwMDApOwogICAgICAgICB0dnAgPSB0dmJ1ZjsKICAgICB9
Ci0gICAgaWYgKHV0aW1lcyhwYXRoLCB0dnApIDwgMCkKKworICAgIGlmICh2
LT5mb2xsb3cpIHsKKyNpZmRlZiBIQVZFX0xVVElNRVMKKwlpZiAobHV0aW1l
cyhwYXRoLCB0dnApIDwgMCkKKwkgICAgdXRpbWVfZmFpbGVkKHBhdGgsIHRz
cCwgdi0+YXRpbWUsIHYtPm10aW1lKTsKKyNlbHNlCisJcmJfbm90aW1wbGVt
ZW50KCk7CisjZW5kaWYKKyAgICB9CisgICAgZWxzZSBpZiAodXRpbWVzKHBh
dGgsIHR2cCkgPCAwKQogCXV0aW1lX2ZhaWxlZChwYXRoLCB0c3AsIHYtPmF0
aW1lLCB2LT5tdGltZSk7CiB9CiAKQEAgLTIyOTcsMTcgKzIzMjAsOCBAQCB1
dGltZV9pbnRlcm5hbChjb25zdCBjaGFyICpwYXRoLCB2b2lkICphcmcpCiAK
ICNlbmRpZgogCi0vKgotICogY2FsbC1zZXE6Ci0gKiAgRmlsZS51dGltZShh
dGltZSwgbXRpbWUsIGZpbGVfbmFtZSwuLi4pICAgLT4gIGludGVnZXIKLSAq
Ci0gKiBTZXRzIHRoZSBhY2Nlc3MgYW5kIG1vZGlmaWNhdGlvbiB0aW1lcyBv
ZiBlYWNoCi0gKiBuYW1lZCBmaWxlIHRvIHRoZSBmaXJzdCB0d28gYXJndW1l
bnRzLiBSZXR1cm5zCi0gKiB0aGUgbnVtYmVyIG9mIGZpbGUgbmFtZXMgaW4g
dGhlIGFyZ3VtZW50IGxpc3QuCi0gKi8KLQogc3RhdGljIFZBTFVFCi1yYl9m
aWxlX3NfdXRpbWUoaW50IGFyZ2MsIFZBTFVFICphcmd2KQordXRpbWVfaW50
ZXJuYWxfaShpbnQgYXJnYywgVkFMVUUgKmFyZ3YsIGludCBmb2xsb3cpCiB7
CiAgICAgVkFMVUUgcmVzdDsKICAgICBzdHJ1Y3QgdXRpbWVfYXJncyBhcmdz
OwpAQCAtMjMxNyw2ICsyMzMxLDggQEAgcmJfZmlsZV9zX3V0aW1lKGludCBh
cmdjLCBWQUxVRSAqYXJndikKICAgICByYl9zZWN1cmUoMik7CiAgICAgcmJf
c2Nhbl9hcmdzKGFyZ2MsIGFyZ3YsICIyKiIsICZhcmdzLmF0aW1lLCAmYXJn
cy5tdGltZSwgJnJlc3QpOwogCisgICAgYXJncy5mb2xsb3cgPSBmb2xsb3c7
CisKICAgICBpZiAoIU5JTF9QKGFyZ3MuYXRpbWUpIHx8ICFOSUxfUChhcmdz
Lm10aW1lKSkgewogCXRzcCA9IHRzczsKIAl0c3BbMF0gPSByYl90aW1lX3Rp
bWVzcGVjKGFyZ3MuYXRpbWUpOwpAQCAtMjMyOCw2ICsyMzQ0LDQ1IEBAIHJi
X2ZpbGVfc191dGltZShpbnQgYXJnYywgVkFMVUUgKmFyZ3YpCiAgICAgcmV0
dXJuIExPTkcyRklYKG4pOwogfQogCisvKgorICogY2FsbC1zZXE6CisgKiAg
RmlsZS51dGltZShhdGltZSwgbXRpbWUsIGZpbGVfbmFtZSwuLi4pICAgLT4g
IGludGVnZXIKKyAqCisgKiBTZXRzIHRoZSBhY2Nlc3MgYW5kIG1vZGlmaWNh
dGlvbiB0aW1lcyBvZiBlYWNoIG5hbWVkIGZpbGUgdG8gdGhlCisgKiBmaXJz
dCB0d28gYXJndW1lbnRzLiBJZiBhIGZpbGUgaXMgYSBzeW1saW5rLCB0aGlz
IG1ldGhvZCBhY3RzIHVwb24KKyAqIGl0cyByZWZlcmVudCByYXRoZXIgdGhh
biB0aGUgbGluayBpdHNlbGY7IGZvciB0aGUgaW52ZXJzZQorICogYmVoYXZp
b3Igc2VlIDxjb2RlPkZpbGUubHV0aW1lPC9jb2RlPi4gUmV0dXJucyB0aGUg
bnVtYmVyIG9mIGZpbGUKKyAqIG5hbWVzIGluIHRoZSBhcmd1bWVudCBsaXN0
LgorICovCisKK3N0YXRpYyBWQUxVRQorcmJfZmlsZV9zX3V0aW1lKGludCBh
cmdjLCBWQUxVRSAqYXJndikKK3sKKyAgICByZXR1cm4gdXRpbWVfaW50ZXJu
YWxfaShhcmdjLCBhcmd2LCAwKTsKK30KKworI2lmIGRlZmluZWQoSEFWRV9V
VElNRVMpICYmIChkZWZpbmVkKEhBVkVfTFVUSU1FUykgfHwgKGRlZmluZWQo
SEFWRV9VVElNRU5TQVQpICYmIGRlZmluZWQoQVRfU1lNTElOS19OT0ZPTExP
VykpKQorCisvKgorICogY2FsbC1zZXE6CisgKiAgRmlsZS5sdXRpbWUoYXRp
bWUsIG10aW1lLCBmaWxlX25hbWUsLi4uKSAgIC0+ICBpbnRlZ2VyCisgKgor
ICogU2V0cyB0aGUgYWNjZXNzIGFuZCBtb2RpZmljYXRpb24gdGltZXMgb2Yg
ZWFjaCBuYW1lZCBmaWxlIHRvIHRoZQorICogZmlyc3QgdHdvIGFyZ3VtZW50
cy4gSWYgYSBmaWxlIGlzIGEgc3ltbGluaywgdGhpcyBtZXRob2QgYWN0cyB1
cG9uCisgKiB0aGUgbGluayBpdHNlbGYgYXMgb3Bwb3NlZCB0byBpdHMgcmVm
ZXJlbnQ7IGZvciB0aGUgaW52ZXJzZQorICogYmVoYXZpb3IsIHNlZSA8Y29k
ZT5GaWxlLnV0aW1lPC9jb2RlPi4gUmV0dXJucyB0aGUgbnVtYmVyIG9mIGZp
bGUKKyAqIG5hbWVzIGluIHRoZSBhcmd1bWVudCBsaXN0LgorICovCisKK3N0
YXRpYyBWQUxVRQorcmJfZmlsZV9zX2x1dGltZShpbnQgYXJnYywgVkFMVUUg
KmFyZ3YpCit7CisgICAgcmV0dXJuIHV0aW1lX2ludGVybmFsX2koYXJnYywg
YXJndiwgMSk7Cit9CisjZWxzZQorI2RlZmluZSByYl9maWxlX3NfbHV0aW1l
IHJiX2Zfbm90aW1wbGVtZW50CisjZW5kaWYKKwogTk9SRVRVUk4oc3RhdGlj
IHZvaWQgc3lzX2ZhaWwyKFZBTFVFLFZBTFVFKSk7CiBzdGF0aWMgdm9pZAog
c3lzX2ZhaWwyKFZBTFVFIHMxLCBWQUxVRSBzMikKQEAgLTUzMTksNiArNTM3
NCw3IEBAIEluaXRfRmlsZSh2b2lkKQogICAgIHJiX2RlZmluZV9zaW5nbGV0
b25fbWV0aG9kKHJiX2NGaWxlLCAiY2hvd24iLCByYl9maWxlX3NfY2hvd24s
IC0xKTsKICAgICByYl9kZWZpbmVfc2luZ2xldG9uX21ldGhvZChyYl9jRmls
ZSwgImxjaG1vZCIsIHJiX2ZpbGVfc19sY2htb2QsIC0xKTsKICAgICByYl9k
ZWZpbmVfc2luZ2xldG9uX21ldGhvZChyYl9jRmlsZSwgImxjaG93biIsIHJi
X2ZpbGVfc19sY2hvd24sIC0xKTsKKyAgICByYl9kZWZpbmVfc2luZ2xldG9u
X21ldGhvZChyYl9jRmlsZSwgImx1dGltZSIsIHJiX2ZpbGVfc19sdXRpbWUs
IC0xKTsKIAogICAgIHJiX2RlZmluZV9zaW5nbGV0b25fbWV0aG9kKHJiX2NG
aWxlLCAibGluayIsIHJiX2ZpbGVfc19saW5rLCAyKTsKICAgICByYl9kZWZp
bmVfc2luZ2xldG9uX21ldGhvZChyYl9jRmlsZSwgInN5bWxpbmsiLCByYl9m
aWxlX3Nfc3ltbGluaywgMik7CmRpZmYgLS1naXQgYS90ZXN0L3J1YnkvdGVz
dF9maWxlX2V4aGF1c3RpdmUucmIgYi90ZXN0L3J1YnkvdGVzdF9maWxlX2V4
aGF1c3RpdmUucmIKaW5kZXggMWQ0NWI5Ny4uMWQxNmMzZCAxMDA2NDQKLS0t
IGEvdGVzdC9ydWJ5L3Rlc3RfZmlsZV9leGhhdXN0aXZlLnJiCisrKyBiL3Rl
c3QvcnVieS90ZXN0X2ZpbGVfZXhoYXVzdGl2ZS5yYgpAQCAtMzQ2LDYgKzM0
Niw0MSBAQCBjbGFzcyBUZXN0RmlsZUV4aGF1c3RpdmUgPCBUZXN0OjpVbml0
OjpUZXN0Q2FzZQogICAgIEZpbGUudXRpbWUodCArIDEsIHQgKyAyLCBAemVy
b2ZpbGUpCiAgICAgYXNzZXJ0X2VxdWFsKHQgKyAxLCBGaWxlLmF0aW1lKEB6
ZXJvZmlsZSkpCiAgICAgYXNzZXJ0X2VxdWFsKHQgKyAyLCBGaWxlLm10aW1l
KEB6ZXJvZmlsZSkpCisgICAgc2tpcCgiRmlsZS5zeW1saW5rIG5vdCBpbXBs
ZW1lbnRlZCIpIHVubGVzcyAoRmlsZS5yZXNwb25kX3RvPyg6c3ltbGluaykg
YW5kIEBzeW1saW5rZmlsZSkKKyAgICBzdGF0X2xuID0gRmlsZS5sc3RhdChA
c3ltbGlua2ZpbGUpCisgICAgYXNzZXJ0X2VxdWFsKEZpbGUudXRpbWUodCwg
dCwgQHN5bWxpbmtmaWxlKSwgMSkKKyAgICBhc3NlcnRfZXF1YWwoRmlsZS5z
dGF0KEBmaWxlKS5hdGltZSwgdCkKKyAgICBhc3NlcnRfZXF1YWwoRmlsZS5z
dGF0KEBmaWxlKS5tdGltZSwgdCkKKyAgICBhc3NlcnRfZXF1YWwoRmlsZS5s
c3RhdChAc3ltbGlua2ZpbGUpLmF0aW1lLCBzdGF0X2xuLmF0aW1lKQorICAg
IGFzc2VydF9lcXVhbChGaWxlLmxzdGF0KEBzeW1saW5rZmlsZSkubXRpbWUs
IHN0YXRfbG4ubXRpbWUpCisgIGVuZAorCisgIGRlZiB0ZXN0X2x1dGltZQor
ICAgIHNraXAoIkZpbGUubHV0aW1lIG5vdCBpbXBsZW1lbnRlZCIpIHVubGVz
cyBGaWxlLnJlc3BvbmRfdG8/KDpsdXRpbWUpCisgICAgRGlyLm1rdG1wZGly
KCdydWJ5dGVzdC1sdXRpbWUnKSBkbyB8dG1wfAorICAgICAgRGlyLmNoZGly
KHRtcCkgZG8KKyAgICAgICAgb3BlbignZicsP3cpe30KKyAgICAgICAgdGlt
ZXMgPSBbVGltZS5ub3cgLSAyNCoxMDAsIFRpbWUubm93IC0gMjQqMV8wMDBd
Lm1hcCgmOnJvdW5kKQorICAgICAgICBhc3NlcnRfZXF1YWwoRmlsZS5sdXRp
bWUodGltZXNbMF0sIHRpbWVzWzBdLCA/ZiksIDEpCisgICAgICAgIGFzc2Vy
dF9lcXVhbChGaWxlLnN0YXQoP2YpLmF0aW1lLnJvdW5kLCB0aW1lc1swXSkK
KyAgICAgICAgYXNzZXJ0X2VxdWFsKEZpbGUuc3RhdCg/ZikubXRpbWUucm91
bmQsIHRpbWVzWzBdKQorCisgICAgICAgICMgQXNzdW1lIHRoYXQgYSBwbGF0
Zm9ybSBzdXBwb3J0aW5nIGNoYW5naW5nIHV0aW1lbnMgb24gc3ltbGlua3MK
KyAgICAgICAgIyBhbHNvIHN1cHBvcnRzIHN5bWxpbmtzCisgICAgICAgIEZp
bGUuc3ltbGluayg/ZiwgP2wpCisgICAgICAgIGFzc2VydF9lcXVhbChGaWxl
Lmx1dGltZSh0aW1lc1sxXSwgdGltZXNbMV0sID9sKSwgMSkKKyAgICAgICAg
YXNzZXJ0X2VxdWFsKEZpbGUuc3RhdCg/ZikuYXRpbWUucm91bmQsIHRpbWVz
WzBdKQorICAgICAgICBhc3NlcnRfZXF1YWwoRmlsZS5zdGF0KD9mKS5tdGlt
ZS5yb3VuZCwgdGltZXNbMF0pCisgICAgICAgIGFzc2VydF9lcXVhbChGaWxl
LmxzdGF0KD9sKS5hdGltZS5yb3VuZCwgdGltZXNbMV0pCisgICAgICAgIGFz
c2VydF9lcXVhbChGaWxlLmxzdGF0KD9sKS5tdGltZS5yb3VuZCwgdGltZXNb
MV0pCisKKyAgICAgICAgYXNzZXJ0X2VxdWFsKEZpbGUubHV0aW1lKHRpbWVz
WzFdLCB0aW1lc1swXSwgP2wsID9mKSwgMikKKyAgICAgICAgYXNzZXJ0X2Vx
dWFsKEZpbGUuc3RhdCg/ZikuYXRpbWUucm91bmQsIHRpbWVzWzFdKQorICAg
ICAgICBhc3NlcnRfZXF1YWwoRmlsZS5zdGF0KD9mKS5tdGltZS5yb3VuZCwg
dGltZXNbMF0pCisgICAgICAgIGFzc2VydF9lcXVhbChGaWxlLmxzdGF0KD9s
KS5hdGltZS5yb3VuZCwgdGltZXNbMV0pCisgICAgICAgIGFzc2VydF9lcXVh
bChGaWxlLmxzdGF0KD9sKS5tdGltZS5yb3VuZCwgdGltZXNbMF0pCisgICAg
ICBlbmQKKyAgICBlbmQKICAgZW5kCiAKICAgZGVmIHRlc3RfaGFyZGxpbmsK