{
vector<string>
- filter_mount_options(vector<string>& options)
+ filter_mount_options(const vector<string>& options)
{
static const char* ign_opt[] = {
"ro", "rw",
}
#ifdef UMOUNT_NOFOLLOW
- int r2 = umount2(mount_point.c_str(), UMOUNT_NOFOLLOW);
+ int r2 = ::umount2(mount_point.c_str(), UMOUNT_NOFOLLOW);
#else
- int r2 = umount2(mount_point.c_str(), 0);
+ int r2 = ::umount2(mount_point.c_str(), 0);
#endif
if (r2 != 0)
{
}
+ SDir
+ Btrfs::openSubvolumeDir() const
+ {
+ SDir subvolume_dir = Filesystem::openSubvolumeDir();
+
+ struct stat stat;
+ if (subvolume_dir.stat(&stat) != 0)
+ {
+ throw IOErrorException();
+ }
+
+ if (!is_subvolume(stat))
+ {
+ y2err("subvolume is not a btrfs snapshot");
+ throw IOErrorException();
+ }
+
+ return subvolume_dir;
+ }
+
+
SDir
Btrfs::openInfosDir() const
{
throw IOErrorException();
}
+ if (!is_subvolume(stat))
+ {
+ y2err(".snapshots is not a btrfs snapshot");
+ throw IOErrorException();
+ }
+
if (stat.st_uid != 0 || stat.st_gid != 0)
{
y2err("owner/group of .snapshots wrong");
struct stat stat;
int r = info_dir.stat("snapshot", &stat, AT_SYMLINK_NOFOLLOW);
- // check st_ino == 256 is copied from btrfsprogs
- return r == 0 && stat.st_ino == 256 && S_ISDIR(stat.st_mode);
+ return r == 0 && is_subvolume(stat);
}
catch (const IOErrorException& e)
{
}
+ bool
+ Btrfs::is_subvolume(const struct stat& stat) const
+ {
+ // see btrfsprogs source code
+ return stat.st_ino == 256 && S_ISDIR(stat.st_mode);
+ }
+
+
bool
Btrfs::create_subvolume(int fddst, const string& name) const
{
virtual string snapshotDir(unsigned int num) const;
+ virtual SDir openSubvolumeDir() const;
virtual SDir openInfosDir() const;
virtual SDir openSnapshotDir(unsigned int num) const;
private:
+ bool is_subvolume(const struct stat& stat) const;
+
bool create_subvolume(int fddst, const string& name) const;
bool create_snapshot(int fd, int fddst, const string& name) const;
bool delete_subvolume(int fd, const string& name) const;