mirror of https://github.com/schoebel/mars
sy_generic: workaround low timestamp resolution
This commit is contained in:
parent
9fdc0ff41f
commit
02289207e0
|
@ -115,21 +115,42 @@ int mars_symlink(const char *oldpath, const char *newpath, const struct timespec
|
||||||
{
|
{
|
||||||
char *tmp = backskip_replace(newpath, '/', true, "/.tmp-");
|
char *tmp = backskip_replace(newpath, '/', true, "/.tmp-");
|
||||||
mm_segment_t oldfs;
|
mm_segment_t oldfs;
|
||||||
|
struct kstat stat = {};
|
||||||
|
struct timespec new_stamp = {};
|
||||||
int status = -ENOMEM;
|
int status = -ENOMEM;
|
||||||
|
|
||||||
if (unlikely(!tmp))
|
if (unlikely(!tmp))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
if (stamp)
|
||||||
|
memcpy(&new_stamp, stamp, sizeof(new_stamp));
|
||||||
|
|
||||||
oldfs = get_fs();
|
oldfs = get_fs();
|
||||||
set_fs(get_ds());
|
set_fs(get_ds());
|
||||||
|
/* Some filesystems have only full second resolution.
|
||||||
|
* Thus it may happen that the new timestamp is not
|
||||||
|
* truly moving forward when called twice shortly.
|
||||||
|
* This is a _workaround_, to be replaced by a better
|
||||||
|
* method somewhen.
|
||||||
|
*/
|
||||||
|
if (stamp) {
|
||||||
|
status = vfs_lstat((char*)newpath, &stat);
|
||||||
|
if (status >= 0 &&
|
||||||
|
!stat.mtime.tv_nsec &&
|
||||||
|
new_stamp.tv_sec <= stat.mtime.tv_sec) {
|
||||||
|
new_stamp.tv_sec = stat.mtime.tv_sec + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(void)sys_unlink(tmp);
|
(void)sys_unlink(tmp);
|
||||||
|
|
||||||
status = sys_symlink(oldpath, tmp);
|
status = sys_symlink(oldpath, tmp);
|
||||||
|
|
||||||
if (stamp) {
|
if (stamp) {
|
||||||
struct timespec times[2];
|
struct timespec times[2];
|
||||||
sys_lchown(tmp, uid, 0);
|
sys_lchown(tmp, uid, 0);
|
||||||
memcpy(×[0], stamp, sizeof(struct timespec));
|
memcpy(×[0], &new_stamp, sizeof(struct timespec));
|
||||||
memcpy(×[1], stamp, sizeof(struct timespec));
|
memcpy(×[1], &new_stamp, sizeof(struct timespec));
|
||||||
status = do_utimes(AT_FDCWD, tmp, times, AT_SYMLINK_NOFOLLOW);
|
status = do_utimes(AT_FDCWD, tmp, times, AT_SYMLINK_NOFOLLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue