~ruther/guix-local

e134baae774eaa78e7ae8c3d87db50170f023536 — Eelco Dolstra 10 years ago 14fb686
daemon: optimizePath: Detect some .links corruptions.

If automatic store optimisation is enabled, and a hard-linked file in
the store gets corrupted, then the corresponding .links entry will
also be corrupted. In that case, trying to repair with --repair or
--repair-path won't work, because the new "good" file will be replaced
by a hard link to the corrupted file. We can catch most of these cases
by doing a sanity-check on the file sizes.
1 files changed, 9 insertions(+), 2 deletions(-)

M nix/libstore/optimise-store.cc
M nix/libstore/optimise-store.cc => nix/libstore/optimise-store.cc +9 -2
@@ 120,7 120,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
        return;
    }

    /* This can still happen on top-level files */
    /* This can still happen on top-level files. */
    if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
        printMsg(lvlDebug, format("`%1%' is already linked, with %2% other file(s).") % path % (st.st_nlink - 2));
        return;


@@ 141,6 141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
    /* Check if this is a known hash. */
    Path linkPath = linksDir + "/" + printHash32(hash);

 retry:
    if (!pathExists(linkPath)) {
        /* Nope, create a hard link in the links directory. */
        if (link(path.c_str(), linkPath.c_str()) == 0) {


@@ 164,7 165,13 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
        return;
    }

    printMsg(lvlTalkative, format("linking `%1%' to `%2%'") % path % linkPath);
    if (st.st_size != stLink.st_size) {
        printMsg(lvlError, format("removing corrupted link ‘%1%’") % linkPath);
        unlink(linkPath.c_str());
        goto retry;
    }

    printMsg(lvlTalkative, format("linking ‘%1%’ to ‘%2%’") % path % linkPath);

    /* Make the containing directory writable, but only if it's not
       the store itself (we don't want or need to mess with its