diff --git a/cmdline/app.h b/cmdline/app.h index c4935455..751c7d6c 100644 --- a/cmdline/app.h +++ b/cmdline/app.h @@ -76,7 +76,7 @@ struct fssnapshot_struct { /** * Root directory of the volume/dataset mountpoint. * It ALWAYS terminates with / - * - Btrfs/Bcachefs: subvolume root + * - Btrfs/Bcachefs: subvolume root (canonical path via realpath) * - ZFS: dataset mountpoint (canonical path via realpath) * - Windows: volume mountpoint (via GetVolumePathName) */ @@ -97,8 +97,8 @@ struct fssnapshot_struct { * It NEVER starts with '/'. * It is empty if the configured data directory is exactly root_dir. * If non-empty, it ALWAYS terminates with '/'. - * - ZFS: relative suffix computed from realpath() canonical representation - * - Btrfs/Bcachefs/Windows: relative suffix computed from configured path + * - Unix: relative suffix computed from the realpath() canonical representation + * - Windows: relative suffix computed from the configured path */ char sub_dir[PATH_MAX]; diff --git a/cmdline/unixapp.c b/cmdline/unixapp.c index 7a57323b..3044a51b 100644 --- a/cmdline/unixapp.c +++ b/cmdline/unixapp.c @@ -2144,9 +2144,14 @@ int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_har #if HAVE_LINUX_DEVICE static int fssnapshot_inode(const char* path, uint32_t magic, uint64_t root_inode, struct fssnapshot_struct* fss) { + char resolved[PATH_MAX]; char current_path[PATH_MAX]; - pathcpy(current_path, sizeof(current_path), path); + if (realpath(path, resolved) == 0) + return -1; + + pathslash(resolved, sizeof(resolved)); + pathcpy(current_path, sizeof(current_path), resolved); /* walk up the directory tree to find the subvolume root (Inode 256) */ while (1) { @@ -2172,7 +2177,13 @@ static int fssnapshot_inode(const char* path, uint32_t magic, uint64_t root_inod } size_t root_len = strlen(fss->root_dir); - pathcpy(fss->sub_dir, sizeof(fss->sub_dir), path + root_len); + + if (pathncmp(fss->root_dir, resolved, root_len) != 0) { + errno = EINVAL; + return -1; + } + + pathcpy(fss->sub_dir, sizeof(fss->sub_dir), resolved + root_len); fss->magic = magic; return 0;