1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/statfs.h>
26 #include "btrfs-util.h"
28 #include "bus-label.h"
30 Image *image_unref(Image *i) {
49 _cleanup_(image_unrefp) Image *i = NULL;
54 assert(t < _IMAGE_TYPE_MAX);
62 i->read_only = read_only;
66 i->name = strdup(name);
71 i->path = strdup(path);
76 r = hashmap_put(h, i->name, i);
84 int image_discover(Hashmap *h) {
90 FOREACH_STRING(path, "/var/lib/container", "/var/lib/machine") {
91 _cleanup_closedir_ DIR *d = NULL;
102 FOREACH_DIRENT_ALL(de, d, return -errno) {
105 if (STR_IN_SET(de->d_name, ".", ".."))
108 /* Temporary files for atomically creating new files */
109 if (startswith(de->d_name, ".#"))
112 if (string_has_cc(de->d_name, NULL))
115 if (!utf8_is_valid(de->d_name))
118 if (hashmap_contains(h, de->d_name))
121 /* We explicitly *do* follow symlinks here,
122 * since we want to allow symlinking trees
123 * into /var/lib/container/, and treat them
125 if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) {
132 if (S_ISDIR(st.st_mode)) {
134 /* btrfs subvolumes have inode 256 */
135 if (st.st_ino == 256) {
136 _cleanup_close_ int fd = -1;
139 fd = openat(dirfd(d), de->d_name, O_CLOEXEC|O_NOCTTY|O_DIRECTORY);
147 if (fstatfs(fd, &sfs) < 0)
150 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) {
154 /* It's a btrfs subvolume */
156 ro = btrfs_subvol_is_read_only_fd(fd);
160 /* r = btrfs_subvol_get_btime(fd, &btime); */
179 /* It's just a normal directory. */
191 } else if (S_ISREG(st.st_mode) &&
192 endswith(de->d_name, ".gpt")) {
194 /* It's a GPT block device */
200 !!(st.st_mode & 0111),
201 timespec_load(&st.st_mtim),
212 void image_hashmap_free(Hashmap *map) {
215 while ((i = hashmap_steal_first(map)))
221 char *image_bus_path(const char *name) {
222 _cleanup_free_ char *e = NULL;
226 e = bus_label_escape(name);
230 return strappend("/org/freedesktop/machine1/image/", e);
233 static const char* const image_type_table[_IMAGE_TYPE_MAX] = {
234 [IMAGE_DIRECTORY] = "directory",
235 [IMAGE_SUBVOLUME] = "subvolume",
239 DEFINE_STRING_TABLE_LOOKUP(image_type, ImageType);