1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
32 #include "alloc-util.h"
33 #include "btrfs-util.h"
34 #include "chattr-util.h"
36 #include "dirent-util.h"
37 #include "dissect-image.h"
43 #include "hostname-util.h"
44 #include "id128-util.h"
45 #include "lockfile-util.h"
47 #include "loop-util.h"
48 #include "machine-image.h"
51 #include "path-util.h"
53 #include "string-table.h"
54 #include "string-util.h"
56 #include "time-util.h"
59 #include "xattr-util.h"
61 static const char image_search_path
[] =
63 "/var/lib/container\0" /* legacy */
64 "/usr/local/lib/machines\0"
65 "/usr/lib/machines\0";
67 Image
*image_unref(Image
*i
) {
75 strv_free(i
->machine_info
);
76 strv_free(i
->os_release
);
81 static char **image_settings_path(Image
*image
) {
82 _cleanup_strv_free_
char **l
= NULL
;
93 fn
= strjoina(image
->name
, ".nspawn");
95 FOREACH_STRING(s
, "/etc/systemd/nspawn/", "/run/systemd/nspawn/") {
96 l
[i
] = strappend(s
, fn
);
103 l
[i
] = file_in_same_dir(image
->path
, fn
);
113 static char *image_roothash_path(Image
*image
) {
118 fn
= strjoina(image
->name
, ".roothash");
120 return file_in_same_dir(image
->path
, fn
);
123 static int image_new(
127 const char *filename
,
133 _cleanup_(image_unrefp
) Image
*i
= NULL
;
136 assert(t
< _IMAGE_TYPE_MAX
);
146 i
->read_only
= read_only
;
149 i
->usage
= i
->usage_exclusive
= (uint64_t) -1;
150 i
->limit
= i
->limit_exclusive
= (uint64_t) -1;
152 i
->name
= strdup(pretty
);
157 i
->path
= strjoin(path
, "/", filename
);
159 i
->path
= strdup(filename
);
164 path_kill_slashes(i
->path
);
172 static int image_make(
176 const char *filename
,
185 /* We explicitly *do* follow symlinks here, since we want to allow symlinking trees, raw files and block
186 * devices into /var/lib/machines/, and treat them normally. */
188 if (fstatat(dfd
, filename
, &st
, 0) < 0)
192 (path
&& path_startswith(path
, "/usr")) ||
193 (faccessat(dfd
, filename
, W_OK
, AT_EACCESS
) < 0 && errno
== EROFS
);
195 if (S_ISDIR(st
.st_mode
)) {
196 _cleanup_close_
int fd
= -1;
197 unsigned file_attr
= 0;
205 fd
= openat(dfd
, filename
, O_CLOEXEC
|O_NOCTTY
|O_DIRECTORY
);
209 /* btrfs subvolumes have inode 256 */
210 if (st
.st_ino
== 256) {
212 r
= btrfs_is_filesystem(fd
);
216 BtrfsSubvolInfo info
;
218 /* It's a btrfs subvolume */
220 r
= btrfs_subvol_get_info_fd(fd
, 0, &info
);
224 r
= image_new(IMAGE_SUBVOLUME
,
228 info
.read_only
|| read_only
,
235 if (btrfs_quota_scan_ongoing(fd
) == 0) {
236 BtrfsQuotaInfo quota
;
238 r
= btrfs_subvol_get_subtree_quota_fd(fd
, 0, "a
);
240 (*ret
)->usage
= quota
.referenced
;
241 (*ret
)->usage_exclusive
= quota
.exclusive
;
243 (*ret
)->limit
= quota
.referenced_max
;
244 (*ret
)->limit_exclusive
= quota
.exclusive_max
;
252 /* If the IMMUTABLE bit is set, we consider the
253 * directory read-only. Since the ioctl is not
254 * supported everywhere we ignore failures. */
255 (void) read_attr_fd(fd
, &file_attr
);
257 /* It's just a normal directory. */
258 r
= image_new(IMAGE_DIRECTORY
,
262 read_only
|| (file_attr
& FS_IMMUTABLE_FL
),
271 } else if (S_ISREG(st
.st_mode
) && endswith(filename
, ".raw")) {
274 /* It's a RAW disk image */
279 fd_getcrtime_at(dfd
, filename
, &crtime
, 0);
282 pretty
= strndupa(filename
, strlen(filename
) - 4);
284 r
= image_new(IMAGE_RAW
,
288 !(st
.st_mode
& 0222) || read_only
,
290 timespec_load(&st
.st_mtim
),
295 (*ret
)->usage
= (*ret
)->usage_exclusive
= st
.st_blocks
* 512;
296 (*ret
)->limit
= (*ret
)->limit_exclusive
= st
.st_size
;
300 } else if (S_ISBLK(st
.st_mode
)) {
301 _cleanup_close_
int block_fd
= -1;
302 uint64_t size
= UINT64_MAX
;
312 block_fd
= openat(dfd
, filename
, O_RDONLY
|O_NONBLOCK
|O_CLOEXEC
|O_NOCTTY
);
314 log_debug_errno(errno
, "Failed to open block device %s/%s, ignoring: %m", path
, filename
);
316 if (fstat(block_fd
, &st
) < 0)
318 if (!S_ISBLK(st
.st_mode
)) /* Verify that what we opened is actually what we think it is */
324 if (ioctl(block_fd
, BLKROGET
, &state
) < 0)
325 log_debug_errno(errno
, "Failed to issue BLKROGET on device %s/%s, ignoring: %m", path
, filename
);
330 if (ioctl(block_fd
, BLKGETSIZE64
, &size
) < 0)
331 log_debug_errno(errno
, "Failed to issue BLKFLSBUF on device %s/%s, ignoring: %m", path
, filename
);
333 block_fd
= safe_close(block_fd
);
336 r
= image_new(IMAGE_BLOCK
,
340 !(st
.st_mode
& 0222) || read_only
,
347 if (size
!= 0 && size
!= UINT64_MAX
)
348 (*ret
)->usage
= (*ret
)->usage_exclusive
= (*ret
)->limit
= (*ret
)->limit_exclusive
= size
;
356 int image_find(const char *name
, Image
**ret
) {
362 /* There are no images with invalid names */
363 if (!image_name_is_valid(name
))
366 NULSTR_FOREACH(path
, image_search_path
) {
367 _cleanup_closedir_
DIR *d
= NULL
;
377 r
= image_make(NULL
, dirfd(d
), path
, name
, ret
);
378 if (IN_SET(r
, 0, -ENOENT
)) {
379 _cleanup_free_
char *raw
= NULL
;
381 raw
= strappend(name
, ".raw");
385 r
= image_make(NULL
, dirfd(d
), path
, raw
, ret
);
386 if (IN_SET(r
, 0, -ENOENT
))
395 if (streq(name
, ".host"))
396 return image_make(".host", AT_FDCWD
, NULL
, "/", ret
);
401 int image_discover(Hashmap
*h
) {
407 NULSTR_FOREACH(path
, image_search_path
) {
408 _cleanup_closedir_
DIR *d
= NULL
;
419 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
420 _cleanup_(image_unrefp
) Image
*image
= NULL
;
422 if (!image_name_is_valid(de
->d_name
))
425 if (hashmap_contains(h
, de
->d_name
))
428 r
= image_make(NULL
, dirfd(d
), path
, de
->d_name
, &image
);
429 if (IN_SET(r
, 0, -ENOENT
))
434 r
= hashmap_put(h
, image
->name
, image
);
442 if (!hashmap_contains(h
, ".host")) {
443 _cleanup_(image_unrefp
) Image
*image
= NULL
;
445 r
= image_make(".host", AT_FDCWD
, NULL
, "/", &image
);
449 r
= hashmap_put(h
, image
->name
, image
);
460 void image_hashmap_free(Hashmap
*map
) {
463 while ((i
= hashmap_steal_first(map
)))
469 int image_remove(Image
*i
) {
470 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
;
471 _cleanup_strv_free_
char **settings
= NULL
;
472 _cleanup_free_
char *roothash
= NULL
;
478 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
481 settings
= image_settings_path(i
);
485 roothash
= image_roothash_path(i
);
489 /* Make sure we don't interfere with a running nspawn */
490 r
= image_path_lock(i
->path
, LOCK_EX
|LOCK_NB
, &global_lock
, &local_lock
);
496 case IMAGE_SUBVOLUME
:
498 /* Let's unlink first, maybe it is a symlink? If that works we are happy. Otherwise, let's get out the
500 if (unlink(i
->path
) < 0) {
501 r
= btrfs_subvol_remove(i
->path
, BTRFS_REMOVE_RECURSIVE
|BTRFS_REMOVE_QUOTA
);
508 case IMAGE_DIRECTORY
:
509 /* Allow deletion of read-only directories */
510 (void) chattr_path(i
->path
, 0, FS_IMMUTABLE_FL
);
511 r
= rm_rf(i
->path
, REMOVE_ROOT
|REMOVE_PHYSICAL
|REMOVE_SUBVOLUME
);
519 /* If this is inside of /dev, then it's a real block device, hence let's not touch the device node
520 * itself (but let's remove the stuff stored alongside it). If it's anywhere else, let's try to unlink
521 * the thing (it's most likely a symlink after all). */
523 if (path_startswith(i
->path
, "/dev"))
528 if (unlink(i
->path
) < 0)
536 STRV_FOREACH(j
, settings
) {
537 if (unlink(*j
) < 0 && errno
!= ENOENT
)
538 log_debug_errno(errno
, "Failed to unlink %s, ignoring: %m", *j
);
541 if (unlink(roothash
) < 0 && errno
!= ENOENT
)
542 log_debug_errno(errno
, "Failed to unlink %s, ignoring: %m", roothash
);
547 static int rename_auxiliary_file(const char *path
, const char *new_name
, const char *suffix
) {
548 _cleanup_free_
char *rs
= NULL
;
551 fn
= strjoina(new_name
, suffix
);
553 rs
= file_in_same_dir(path
, fn
);
557 return rename_noreplace(AT_FDCWD
, path
, AT_FDCWD
, rs
);
560 int image_rename(Image
*i
, const char *new_name
) {
561 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
, name_lock
= LOCK_FILE_INIT
;
562 _cleanup_free_
char *new_path
= NULL
, *nn
= NULL
, *roothash
= NULL
;
563 _cleanup_strv_free_
char **settings
= NULL
;
564 unsigned file_attr
= 0;
570 if (!image_name_is_valid(new_name
))
573 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
576 settings
= image_settings_path(i
);
580 roothash
= image_roothash_path(i
);
584 /* Make sure we don't interfere with a running nspawn */
585 r
= image_path_lock(i
->path
, LOCK_EX
|LOCK_NB
, &global_lock
, &local_lock
);
589 /* Make sure nobody takes the new name, between the time we
590 * checked it is currently unused in all search paths, and the
591 * time we take possession of it */
592 r
= image_name_lock(new_name
, LOCK_EX
|LOCK_NB
, &name_lock
);
596 r
= image_find(new_name
, NULL
);
604 case IMAGE_DIRECTORY
:
605 /* Turn of the immutable bit while we rename the image, so that we can rename it */
606 (void) read_attr_path(i
->path
, &file_attr
);
608 if (file_attr
& FS_IMMUTABLE_FL
)
609 (void) chattr_path(i
->path
, 0, FS_IMMUTABLE_FL
);
612 case IMAGE_SUBVOLUME
:
613 new_path
= file_in_same_dir(i
->path
, new_name
);
618 /* Refuse renaming raw block devices in /dev, the names are picked by udev after all. */
619 if (path_startswith(i
->path
, "/dev"))
622 new_path
= file_in_same_dir(i
->path
, new_name
);
628 fn
= strjoina(new_name
, ".raw");
629 new_path
= file_in_same_dir(i
->path
, fn
);
640 nn
= strdup(new_name
);
644 r
= rename_noreplace(AT_FDCWD
, i
->path
, AT_FDCWD
, new_path
);
648 /* Restore the immutable bit, if it was set before */
649 if (file_attr
& FS_IMMUTABLE_FL
)
650 (void) chattr_path(new_path
, FS_IMMUTABLE_FL
, FS_IMMUTABLE_FL
);
660 STRV_FOREACH(j
, settings
) {
661 r
= rename_auxiliary_file(*j
, new_name
, ".nspawn");
662 if (r
< 0 && r
!= -ENOENT
)
663 log_debug_errno(r
, "Failed to rename settings file %s, ignoring: %m", *j
);
666 r
= rename_auxiliary_file(roothash
, new_name
, ".roothash");
667 if (r
< 0 && r
!= -ENOENT
)
668 log_debug_errno(r
, "Failed to rename roothash file %s, ignoring: %m", roothash
);
673 static int clone_auxiliary_file(const char *path
, const char *new_name
, const char *suffix
) {
674 _cleanup_free_
char *rs
= NULL
;
677 fn
= strjoina(new_name
, suffix
);
679 rs
= file_in_same_dir(path
, fn
);
683 return copy_file_atomic(path
, rs
, 0664, 0, COPY_REFLINK
);
686 int image_clone(Image
*i
, const char *new_name
, bool read_only
) {
687 _cleanup_release_lock_file_ LockFile name_lock
= LOCK_FILE_INIT
;
688 _cleanup_strv_free_
char **settings
= NULL
;
689 _cleanup_free_
char *roothash
= NULL
;
690 const char *new_path
;
696 if (!image_name_is_valid(new_name
))
699 settings
= image_settings_path(i
);
703 roothash
= image_roothash_path(i
);
707 /* Make sure nobody takes the new name, between the time we
708 * checked it is currently unused in all search paths, and the
709 * time we take possession of it */
710 r
= image_name_lock(new_name
, LOCK_EX
|LOCK_NB
, &name_lock
);
714 r
= image_find(new_name
, NULL
);
722 case IMAGE_SUBVOLUME
:
723 case IMAGE_DIRECTORY
:
724 /* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain
727 new_path
= strjoina("/var/lib/machines/", new_name
);
729 r
= btrfs_subvol_snapshot(i
->path
, new_path
,
730 (read_only
? BTRFS_SNAPSHOT_READ_ONLY
: 0) |
731 BTRFS_SNAPSHOT_FALLBACK_COPY
|
732 BTRFS_SNAPSHOT_FALLBACK_DIRECTORY
|
733 BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE
|
734 BTRFS_SNAPSHOT_RECURSIVE
|
735 BTRFS_SNAPSHOT_QUOTA
);
737 /* Enable "subtree" quotas for the copy, if we didn't copy any quota from the source. */
738 (void) btrfs_subvol_auto_qgroup(new_path
, 0, true);
743 new_path
= strjoina("/var/lib/machines/", new_name
, ".raw");
745 r
= copy_file_atomic(i
->path
, new_path
, read_only
? 0444 : 0644, FS_NOCOW_FL
, COPY_REFLINK
);
756 STRV_FOREACH(j
, settings
) {
757 r
= clone_auxiliary_file(*j
, new_name
, ".nspawn");
758 if (r
< 0 && r
!= -ENOENT
)
759 log_debug_errno(r
, "Failed to clone settings %s, ignoring: %m", *j
);
762 r
= clone_auxiliary_file(roothash
, new_name
, ".roothash");
763 if (r
< 0 && r
!= -ENOENT
)
764 log_debug_errno(r
, "Failed to clone root hash file %s, ignoring: %m", roothash
);
769 int image_read_only(Image
*i
, bool b
) {
770 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
;
775 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
778 /* Make sure we don't interfere with a running nspawn */
779 r
= image_path_lock(i
->path
, LOCK_EX
|LOCK_NB
, &global_lock
, &local_lock
);
785 case IMAGE_SUBVOLUME
:
787 /* Note that we set the flag only on the top-level
788 * subvolume of the image. */
790 r
= btrfs_subvol_set_read_only(i
->path
, b
);
796 case IMAGE_DIRECTORY
:
797 /* For simple directory trees we cannot use the access
798 mode of the top-level directory, since it has an
799 effect on the container itself. However, we can
800 use the "immutable" flag, to at least make the
801 top-level directory read-only. It's not as good as
802 a read-only subvolume, but at least something, and
803 we can read the value back. */
805 r
= chattr_path(i
->path
, b
? FS_IMMUTABLE_FL
: 0, FS_IMMUTABLE_FL
);
814 if (stat(i
->path
, &st
) < 0)
817 if (chmod(i
->path
, (st
.st_mode
& 0444) | (b
? 0000 : 0200)) < 0)
820 /* If the images is now read-only, it's a good time to
821 * defrag it, given that no write patterns will
822 * fragment it again. */
824 (void) btrfs_defrag(i
->path
);
829 _cleanup_close_
int fd
= -1;
833 fd
= open(i
->path
, O_CLOEXEC
|O_RDONLY
|O_NONBLOCK
|O_NOCTTY
);
837 if (fstat(fd
, &st
) < 0)
839 if (!S_ISBLK(st
.st_mode
))
842 if (ioctl(fd
, BLKROSET
, &state
) < 0)
855 int image_path_lock(const char *path
, int operation
, LockFile
*global
, LockFile
*local
) {
856 _cleanup_free_
char *p
= NULL
;
857 LockFile t
= LOCK_FILE_INIT
;
865 /* Locks an image path. This actually creates two locks: one
866 * "local" one, next to the image path itself, which might be
867 * shared via NFS. And another "global" one, in /run, that
868 * uses the device/inode number. This has the benefit that we
869 * can even lock a tree that is a mount point, correctly. */
871 if (!path_is_absolute(path
))
874 if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) {
875 *local
= *global
= (LockFile
) LOCK_FILE_INIT
;
879 if (path_equal(path
, "/"))
882 if (stat(path
, &st
) >= 0) {
883 if (S_ISBLK(st
.st_mode
))
884 r
= asprintf(&p
, "/run/systemd/nspawn/locks/block-%u:%u", major(st
.st_rdev
), minor(st
.st_rdev
));
885 else if (S_ISDIR(st
.st_mode
) || S_ISREG(st
.st_mode
))
886 r
= asprintf(&p
, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st
.st_dev
, (unsigned long) st
.st_ino
);
894 /* For block devices we don't need the "local" lock, as the major/minor lock above should be sufficient, since
895 * block devices are device local anyway. */
896 if (!path_startswith(path
, "/dev")) {
897 r
= make_lock_file_for(path
, operation
, &t
);
903 mkdir_p("/run/systemd/nspawn/locks", 0700);
905 r
= make_lock_file(p
, operation
, global
);
907 release_lock_file(&t
);
911 *global
= (LockFile
) LOCK_FILE_INIT
;
917 int image_set_limit(Image
*i
, uint64_t referenced_max
) {
920 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
923 if (i
->type
!= IMAGE_SUBVOLUME
)
926 /* We set the quota both for the subvolume as well as for the
927 * subtree. The latter is mostly for historical reasons, since
928 * we didn't use to have a concept of subtree quota, and hence
929 * only modified the subvolume quota. */
931 (void) btrfs_qgroup_set_limit(i
->path
, 0, referenced_max
);
932 (void) btrfs_subvol_auto_qgroup(i
->path
, 0, true);
933 return btrfs_subvol_set_subtree_quota_limit(i
->path
, 0, referenced_max
);
936 int image_read_metadata(Image
*i
) {
937 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
;
942 r
= image_path_lock(i
->path
, LOCK_SH
|LOCK_NB
, &global_lock
, &local_lock
);
948 case IMAGE_SUBVOLUME
:
949 case IMAGE_DIRECTORY
: {
950 _cleanup_strv_free_
char **machine_info
= NULL
, **os_release
= NULL
;
951 sd_id128_t machine_id
= SD_ID128_NULL
;
952 _cleanup_free_
char *hostname
= NULL
;
953 _cleanup_free_
char *path
= NULL
;
955 r
= chase_symlinks("/etc/hostname", i
->path
, CHASE_PREFIX_ROOT
, &path
);
956 if (r
< 0 && r
!= -ENOENT
)
957 log_debug_errno(r
, "Failed to chase /etc/hostname in image %s: %m", i
->name
);
959 r
= read_etc_hostname(path
, &hostname
);
961 log_debug_errno(errno
, "Failed to read /etc/hostname of image %s: %m", i
->name
);
966 r
= chase_symlinks("/etc/machine-id", i
->path
, CHASE_PREFIX_ROOT
, &path
);
967 if (r
< 0 && r
!= -ENOENT
)
968 log_debug_errno(r
, "Failed to chase /etc/machine-id in image %s: %m", i
->name
);
970 _cleanup_close_
int fd
= -1;
972 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
974 log_debug_errno(errno
, "Failed to open %s: %m", path
);
976 r
= id128_read_fd(fd
, ID128_PLAIN
, &machine_id
);
978 log_debug_errno(r
, "Image %s contains invalid machine ID.", i
->name
);
984 r
= chase_symlinks("/etc/machine-info", i
->path
, CHASE_PREFIX_ROOT
, &path
);
985 if (r
< 0 && r
!= -ENOENT
)
986 log_debug_errno(r
, "Failed to chase /etc/machine-info in image %s: %m", i
->name
);
988 r
= load_env_file_pairs(NULL
, path
, NULL
, &machine_info
);
990 log_debug_errno(r
, "Failed to parse machine-info data of %s: %m", i
->name
);
995 r
= chase_symlinks("/etc/os-release", i
->path
, CHASE_PREFIX_ROOT
, &path
);
997 r
= chase_symlinks("/usr/lib/os-release", i
->path
, CHASE_PREFIX_ROOT
, &path
);
998 if (r
< 0 && r
!= -ENOENT
)
999 log_debug_errno(r
, "Failed to chase os-release in image: %m");
1001 r
= load_env_file_pairs(NULL
, path
, NULL
, &os_release
);
1003 log_debug_errno(r
, "Failed to parse os-release data of %s: %m", i
->name
);
1006 free_and_replace(i
->hostname
, hostname
);
1007 i
->machine_id
= machine_id
;
1008 strv_free_and_replace(i
->machine_info
, machine_info
);
1009 strv_free_and_replace(i
->os_release
, os_release
);
1016 _cleanup_(loop_device_unrefp
) LoopDevice
*d
= NULL
;
1017 _cleanup_(dissected_image_unrefp
) DissectedImage
*m
= NULL
;
1019 r
= loop_device_make_by_path(i
->path
, O_RDONLY
, &d
);
1023 r
= dissect_image(d
->fd
, NULL
, 0, DISSECT_IMAGE_REQUIRE_ROOT
, &m
);
1027 r
= dissected_image_acquire_metadata(m
);
1031 free_and_replace(i
->hostname
, m
->hostname
);
1032 i
->machine_id
= m
->machine_id
;
1033 strv_free_and_replace(i
->machine_info
, m
->machine_info
);
1034 strv_free_and_replace(i
->os_release
, m
->os_release
);
1043 i
->metadata_valid
= true;
1048 int image_name_lock(const char *name
, int operation
, LockFile
*ret
) {
1054 /* Locks an image name, regardless of the precise path used. */
1056 if (!image_name_is_valid(name
))
1059 if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) {
1060 *ret
= (LockFile
) LOCK_FILE_INIT
;
1064 if (streq(name
, ".host"))
1067 mkdir_p("/run/systemd/nspawn/locks", 0700);
1068 p
= strjoina("/run/systemd/nspawn/locks/name-", name
);
1070 return make_lock_file(p
, operation
, ret
);
1073 bool image_name_is_valid(const char *s
) {
1074 if (!filename_is_valid(s
))
1077 if (string_has_cc(s
, NULL
))
1080 if (!utf8_is_valid(s
))
1083 /* Temporary files for atomically creating new files */
1084 if (startswith(s
, ".#"))
1090 static const char* const image_type_table
[_IMAGE_TYPE_MAX
] = {
1091 [IMAGE_DIRECTORY
] = "directory",
1092 [IMAGE_SUBVOLUME
] = "subvolume",
1093 [IMAGE_RAW
] = "raw",
1094 [IMAGE_BLOCK
] = "block",
1097 DEFINE_STRING_TABLE_LOOKUP(image_type
, ImageType
);