Preserve timestamps across renames.

This commit is contained in:
Adiel Mittmann 2018-12-20 14:58:27 -02:00
parent 4f21701c1a
commit a1e3fa214c

View File

@ -137,6 +137,8 @@ struct RenameEl {
string newPName; string newPName;
bool isDirectory; bool isDirectory;
bool preserve_mtime;
struct timespec times[2];
}; };
class RenameOp { class RenameOp {
@ -179,13 +181,21 @@ RenameOp::~RenameOp() {
bool RenameOp::apply() { bool RenameOp::apply() {
try { try {
for (auto it = renameList->begin(); it != renameList->end(); ++it)
{
struct stat st;
it->preserve_mtime = ::stat(it->oldCName.c_str(), &st) == 0;
if (it->preserve_mtime)
{
it->times[0] = st.st_atim;
it->times[1] = st.st_mtim;
}
}
while (last != renameList->end()) { while (last != renameList->end()) {
// backing store rename. // backing store rename.
VLOG(1) << "renaming " << last->oldCName << " -> " << last->newCName; VLOG(1) << "renaming " << last->oldCName << " -> " << last->newCName;
struct stat st;
bool preserve_mtime = ::stat(last->oldCName.c_str(), &st) == 0;
// internal node rename.. // internal node rename..
dn->renameNode(last->oldPName.c_str(), last->newPName.c_str()); dn->renameNode(last->oldPName.c_str(), last->newPName.c_str());
@ -198,11 +208,8 @@ bool RenameOp::apply() {
return false; return false;
} }
if (preserve_mtime) { if (last->preserve_mtime) {
struct utimbuf ut; ::utimensat(AT_FDCWD, last->newCName.c_str(), last->times, AT_SYMLINK_NOFOLLOW);
ut.actime = st.st_atime;
ut.modtime = st.st_mtime;
::utime(last->newCName.c_str(), &ut);
} }
++last; ++last;
@ -565,6 +572,9 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
VLOG(1) << "rename " << fromCName << " -> " << toCName; VLOG(1) << "rename " << fromCName << " -> " << toCName;
struct stat st;
bool preserve_mtime = ::stat(fromCName.c_str(), &st) == 0;
std::shared_ptr<FileNode> toNode = findOrCreate(toPlaintext); std::shared_ptr<FileNode> toNode = findOrCreate(toPlaintext);
std::shared_ptr<RenameOp> renameOp; std::shared_ptr<RenameOp> renameOp;
@ -585,8 +595,6 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
int res = 0; int res = 0;
try { try {
struct stat st;
bool preserve_mtime = ::stat(fromCName.c_str(), &st) == 0;
renameNode(fromPlaintext, toPlaintext); renameNode(fromPlaintext, toPlaintext);
res = ::rename(fromCName.c_str(), toCName.c_str()); res = ::rename(fromCName.c_str(), toCName.c_str());
@ -614,10 +622,10 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) {
} }
#endif #endif
if (preserve_mtime) { if (preserve_mtime) {
struct utimbuf ut; struct timespec times[2];
ut.actime = st.st_atime; times[0] = st.st_atim;
ut.modtime = st.st_mtime; times[1] = st.st_mtim;
::utime(toCName.c_str(), &ut); ::utimensat(AT_FDCWD, toCName.c_str(), times, AT_SYMLINK_NOFOLLOW);
} }
} }
} catch (encfs::Error &err) { } catch (encfs::Error &err) {