From: Franck Bui Date: Fri, 22 Apr 2022 09:30:09 +0000 (+0200) Subject: libmount: when moving a mount point, all sub mount entries in utab should also be... X-Git-Tag: v2.39-rc1~673^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a04149fbb7c1952da1194d1514e298ff07dbc7ca;p=thirdparty%2Futil-linux.git libmount: when moving a mount point, all sub mount entries in utab should also be updated Given that /run/mount/utab stores paths, this file needs to be adjusted when a mount tree is moved. However the moved tree may contains sub mount points in which case their utab entries (if any) need to also be translated. This patch takes care of that. As suggested in https://github.com/systemd/systemd/issues/15266, a better approach might be to store mount IDs instead of paths since mount IDs remain unchanged when mount trees are moved. Fixes: #1659 --- diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c index b685535151..51f2fae260 100644 --- a/libmount/src/tab_update.c +++ b/libmount/src/tab_update.c @@ -30,6 +30,7 @@ #include "mountP.h" #include "mangle.h" #include "pathnames.h" +#include "strutils.h" struct libmnt_update { char *target; @@ -762,13 +763,44 @@ static int update_modify_target(struct libmnt_update *upd, struct libmnt_lock *l tb = __mnt_new_table_from_file(upd->filename, upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB, 1); if (tb) { - struct libmnt_fs *cur = mnt_table_find_target(tb, - mnt_fs_get_srcpath(upd->fs), MNT_ITER_BACKWARD); - if (cur) { - rc = mnt_fs_set_target(cur, mnt_fs_get_target(upd->fs)); - if (!rc) - rc = update_table(upd, tb); + const char *upd_source = mnt_fs_get_srcpath(upd->fs); + const char *upd_target = mnt_fs_get_target(upd->fs); + struct libmnt_iter itr; + struct libmnt_fs *fs; + + mnt_reset_iter(&itr, MNT_ITER_BACKWARD); + while(mnt_table_next_fs(tb, &itr, &fs) == 0) { + char *p, *e; + size_t len; + + e = startswith(mnt_fs_get_target(fs), upd_source); + if (!e) + continue; + + len = strlen(upd_target) + strlen(e) + 2; + p = malloc(len); + if (!p) + rc = -ENOMEM; + else { + char *cn; + + strcpy(p, upd_target); + strcat(p, "/"); + strcat(p, e); + + cn = mnt_resolve_path(p, NULL); + rc = mnt_fs_set_target(fs, cn); + + free(cn); + free(p); + } + + if (rc < 0) + break; } + + if (!rc) + rc = update_table(upd, tb); } if (lc)