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 int image_remove(Image
*i
) {
461 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
;
462 _cleanup_strv_free_
char **settings
= NULL
;
463 _cleanup_free_
char *roothash
= NULL
;
469 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
472 settings
= image_settings_path(i
);
476 roothash
= image_roothash_path(i
);
480 /* Make sure we don't interfere with a running nspawn */
481 r
= image_path_lock(i
->path
, LOCK_EX
|LOCK_NB
, &global_lock
, &local_lock
);
487 case IMAGE_SUBVOLUME
:
489 /* Let's unlink first, maybe it is a symlink? If that works we are happy. Otherwise, let's get out the
491 if (unlink(i
->path
) < 0) {
492 r
= btrfs_subvol_remove(i
->path
, BTRFS_REMOVE_RECURSIVE
|BTRFS_REMOVE_QUOTA
);
499 case IMAGE_DIRECTORY
:
500 /* Allow deletion of read-only directories */
501 (void) chattr_path(i
->path
, 0, FS_IMMUTABLE_FL
);
502 r
= rm_rf(i
->path
, REMOVE_ROOT
|REMOVE_PHYSICAL
|REMOVE_SUBVOLUME
);
510 /* If this is inside of /dev, then it's a real block device, hence let's not touch the device node
511 * itself (but let's remove the stuff stored alongside it). If it's anywhere else, let's try to unlink
512 * the thing (it's most likely a symlink after all). */
514 if (path_startswith(i
->path
, "/dev"))
519 if (unlink(i
->path
) < 0)
527 STRV_FOREACH(j
, settings
) {
528 if (unlink(*j
) < 0 && errno
!= ENOENT
)
529 log_debug_errno(errno
, "Failed to unlink %s, ignoring: %m", *j
);
532 if (unlink(roothash
) < 0 && errno
!= ENOENT
)
533 log_debug_errno(errno
, "Failed to unlink %s, ignoring: %m", roothash
);
538 static int rename_auxiliary_file(const char *path
, const char *new_name
, const char *suffix
) {
539 _cleanup_free_
char *rs
= NULL
;
542 fn
= strjoina(new_name
, suffix
);
544 rs
= file_in_same_dir(path
, fn
);
548 return rename_noreplace(AT_FDCWD
, path
, AT_FDCWD
, rs
);
551 int image_rename(Image
*i
, const char *new_name
) {
552 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
, name_lock
= LOCK_FILE_INIT
;
553 _cleanup_free_
char *new_path
= NULL
, *nn
= NULL
, *roothash
= NULL
;
554 _cleanup_strv_free_
char **settings
= NULL
;
555 unsigned file_attr
= 0;
561 if (!image_name_is_valid(new_name
))
564 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
567 settings
= image_settings_path(i
);
571 roothash
= image_roothash_path(i
);
575 /* Make sure we don't interfere with a running nspawn */
576 r
= image_path_lock(i
->path
, LOCK_EX
|LOCK_NB
, &global_lock
, &local_lock
);
580 /* Make sure nobody takes the new name, between the time we
581 * checked it is currently unused in all search paths, and the
582 * time we take possession of it */
583 r
= image_name_lock(new_name
, LOCK_EX
|LOCK_NB
, &name_lock
);
587 r
= image_find(new_name
, NULL
);
595 case IMAGE_DIRECTORY
:
596 /* Turn of the immutable bit while we rename the image, so that we can rename it */
597 (void) read_attr_path(i
->path
, &file_attr
);
599 if (file_attr
& FS_IMMUTABLE_FL
)
600 (void) chattr_path(i
->path
, 0, FS_IMMUTABLE_FL
);
603 case IMAGE_SUBVOLUME
:
604 new_path
= file_in_same_dir(i
->path
, new_name
);
609 /* Refuse renaming raw block devices in /dev, the names are picked by udev after all. */
610 if (path_startswith(i
->path
, "/dev"))
613 new_path
= file_in_same_dir(i
->path
, new_name
);
619 fn
= strjoina(new_name
, ".raw");
620 new_path
= file_in_same_dir(i
->path
, fn
);
631 nn
= strdup(new_name
);
635 r
= rename_noreplace(AT_FDCWD
, i
->path
, AT_FDCWD
, new_path
);
639 /* Restore the immutable bit, if it was set before */
640 if (file_attr
& FS_IMMUTABLE_FL
)
641 (void) chattr_path(new_path
, FS_IMMUTABLE_FL
, FS_IMMUTABLE_FL
);
643 free_and_replace(i
->path
, new_path
);
644 free_and_replace(i
->name
, nn
);
646 STRV_FOREACH(j
, settings
) {
647 r
= rename_auxiliary_file(*j
, new_name
, ".nspawn");
648 if (r
< 0 && r
!= -ENOENT
)
649 log_debug_errno(r
, "Failed to rename settings file %s, ignoring: %m", *j
);
652 r
= rename_auxiliary_file(roothash
, new_name
, ".roothash");
653 if (r
< 0 && r
!= -ENOENT
)
654 log_debug_errno(r
, "Failed to rename roothash file %s, ignoring: %m", roothash
);
659 static int clone_auxiliary_file(const char *path
, const char *new_name
, const char *suffix
) {
660 _cleanup_free_
char *rs
= NULL
;
663 fn
= strjoina(new_name
, suffix
);
665 rs
= file_in_same_dir(path
, fn
);
669 return copy_file_atomic(path
, rs
, 0664, 0, COPY_REFLINK
);
672 int image_clone(Image
*i
, const char *new_name
, bool read_only
) {
673 _cleanup_release_lock_file_ LockFile name_lock
= LOCK_FILE_INIT
;
674 _cleanup_strv_free_
char **settings
= NULL
;
675 _cleanup_free_
char *roothash
= NULL
;
676 const char *new_path
;
682 if (!image_name_is_valid(new_name
))
685 settings
= image_settings_path(i
);
689 roothash
= image_roothash_path(i
);
693 /* Make sure nobody takes the new name, between the time we
694 * checked it is currently unused in all search paths, and the
695 * time we take possession of it */
696 r
= image_name_lock(new_name
, LOCK_EX
|LOCK_NB
, &name_lock
);
700 r
= image_find(new_name
, NULL
);
708 case IMAGE_SUBVOLUME
:
709 case IMAGE_DIRECTORY
:
710 /* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain
713 new_path
= strjoina("/var/lib/machines/", new_name
);
715 r
= btrfs_subvol_snapshot(i
->path
, new_path
,
716 (read_only
? BTRFS_SNAPSHOT_READ_ONLY
: 0) |
717 BTRFS_SNAPSHOT_FALLBACK_COPY
|
718 BTRFS_SNAPSHOT_FALLBACK_DIRECTORY
|
719 BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE
|
720 BTRFS_SNAPSHOT_RECURSIVE
|
721 BTRFS_SNAPSHOT_QUOTA
);
723 /* Enable "subtree" quotas for the copy, if we didn't copy any quota from the source. */
724 (void) btrfs_subvol_auto_qgroup(new_path
, 0, true);
729 new_path
= strjoina("/var/lib/machines/", new_name
, ".raw");
731 r
= copy_file_atomic(i
->path
, new_path
, read_only
? 0444 : 0644, FS_NOCOW_FL
, COPY_REFLINK
);
742 STRV_FOREACH(j
, settings
) {
743 r
= clone_auxiliary_file(*j
, new_name
, ".nspawn");
744 if (r
< 0 && r
!= -ENOENT
)
745 log_debug_errno(r
, "Failed to clone settings %s, ignoring: %m", *j
);
748 r
= clone_auxiliary_file(roothash
, new_name
, ".roothash");
749 if (r
< 0 && r
!= -ENOENT
)
750 log_debug_errno(r
, "Failed to clone root hash file %s, ignoring: %m", roothash
);
755 int image_read_only(Image
*i
, bool b
) {
756 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
;
761 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
764 /* Make sure we don't interfere with a running nspawn */
765 r
= image_path_lock(i
->path
, LOCK_EX
|LOCK_NB
, &global_lock
, &local_lock
);
771 case IMAGE_SUBVOLUME
:
773 /* Note that we set the flag only on the top-level
774 * subvolume of the image. */
776 r
= btrfs_subvol_set_read_only(i
->path
, b
);
782 case IMAGE_DIRECTORY
:
783 /* For simple directory trees we cannot use the access
784 mode of the top-level directory, since it has an
785 effect on the container itself. However, we can
786 use the "immutable" flag, to at least make the
787 top-level directory read-only. It's not as good as
788 a read-only subvolume, but at least something, and
789 we can read the value back. */
791 r
= chattr_path(i
->path
, b
? FS_IMMUTABLE_FL
: 0, FS_IMMUTABLE_FL
);
800 if (stat(i
->path
, &st
) < 0)
803 if (chmod(i
->path
, (st
.st_mode
& 0444) | (b
? 0000 : 0200)) < 0)
806 /* If the images is now read-only, it's a good time to
807 * defrag it, given that no write patterns will
808 * fragment it again. */
810 (void) btrfs_defrag(i
->path
);
815 _cleanup_close_
int fd
= -1;
819 fd
= open(i
->path
, O_CLOEXEC
|O_RDONLY
|O_NONBLOCK
|O_NOCTTY
);
823 if (fstat(fd
, &st
) < 0)
825 if (!S_ISBLK(st
.st_mode
))
828 if (ioctl(fd
, BLKROSET
, &state
) < 0)
841 int image_path_lock(const char *path
, int operation
, LockFile
*global
, LockFile
*local
) {
842 _cleanup_free_
char *p
= NULL
;
843 LockFile t
= LOCK_FILE_INIT
;
851 /* Locks an image path. This actually creates two locks: one
852 * "local" one, next to the image path itself, which might be
853 * shared via NFS. And another "global" one, in /run, that
854 * uses the device/inode number. This has the benefit that we
855 * can even lock a tree that is a mount point, correctly. */
857 if (!path_is_absolute(path
))
860 if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) {
861 *local
= *global
= (LockFile
) LOCK_FILE_INIT
;
865 if (path_equal(path
, "/"))
868 if (stat(path
, &st
) >= 0) {
869 if (S_ISBLK(st
.st_mode
))
870 r
= asprintf(&p
, "/run/systemd/nspawn/locks/block-%u:%u", major(st
.st_rdev
), minor(st
.st_rdev
));
871 else if (S_ISDIR(st
.st_mode
) || S_ISREG(st
.st_mode
))
872 r
= asprintf(&p
, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st
.st_dev
, (unsigned long) st
.st_ino
);
880 /* For block devices we don't need the "local" lock, as the major/minor lock above should be sufficient, since
881 * block devices are device local anyway. */
882 if (!path_startswith(path
, "/dev")) {
883 r
= make_lock_file_for(path
, operation
, &t
);
889 mkdir_p("/run/systemd/nspawn/locks", 0700);
891 r
= make_lock_file(p
, operation
, global
);
893 release_lock_file(&t
);
897 *global
= (LockFile
) LOCK_FILE_INIT
;
903 int image_set_limit(Image
*i
, uint64_t referenced_max
) {
906 if (IMAGE_IS_VENDOR(i
) || IMAGE_IS_HOST(i
))
909 if (i
->type
!= IMAGE_SUBVOLUME
)
912 /* We set the quota both for the subvolume as well as for the
913 * subtree. The latter is mostly for historical reasons, since
914 * we didn't use to have a concept of subtree quota, and hence
915 * only modified the subvolume quota. */
917 (void) btrfs_qgroup_set_limit(i
->path
, 0, referenced_max
);
918 (void) btrfs_subvol_auto_qgroup(i
->path
, 0, true);
919 return btrfs_subvol_set_subtree_quota_limit(i
->path
, 0, referenced_max
);
922 int image_read_metadata(Image
*i
) {
923 _cleanup_release_lock_file_ LockFile global_lock
= LOCK_FILE_INIT
, local_lock
= LOCK_FILE_INIT
;
928 r
= image_path_lock(i
->path
, LOCK_SH
|LOCK_NB
, &global_lock
, &local_lock
);
934 case IMAGE_SUBVOLUME
:
935 case IMAGE_DIRECTORY
: {
936 _cleanup_strv_free_
char **machine_info
= NULL
, **os_release
= NULL
;
937 sd_id128_t machine_id
= SD_ID128_NULL
;
938 _cleanup_free_
char *hostname
= NULL
;
939 _cleanup_free_
char *path
= NULL
;
941 r
= chase_symlinks("/etc/hostname", i
->path
, CHASE_PREFIX_ROOT
, &path
);
942 if (r
< 0 && r
!= -ENOENT
)
943 log_debug_errno(r
, "Failed to chase /etc/hostname in image %s: %m", i
->name
);
945 r
= read_etc_hostname(path
, &hostname
);
947 log_debug_errno(errno
, "Failed to read /etc/hostname of image %s: %m", i
->name
);
952 r
= chase_symlinks("/etc/machine-id", i
->path
, CHASE_PREFIX_ROOT
, &path
);
953 if (r
< 0 && r
!= -ENOENT
)
954 log_debug_errno(r
, "Failed to chase /etc/machine-id in image %s: %m", i
->name
);
956 _cleanup_close_
int fd
= -1;
958 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
960 log_debug_errno(errno
, "Failed to open %s: %m", path
);
962 r
= id128_read_fd(fd
, ID128_PLAIN
, &machine_id
);
964 log_debug_errno(r
, "Image %s contains invalid machine ID.", i
->name
);
970 r
= chase_symlinks("/etc/machine-info", i
->path
, CHASE_PREFIX_ROOT
, &path
);
971 if (r
< 0 && r
!= -ENOENT
)
972 log_debug_errno(r
, "Failed to chase /etc/machine-info in image %s: %m", i
->name
);
974 r
= load_env_file_pairs(NULL
, path
, NULL
, &machine_info
);
976 log_debug_errno(r
, "Failed to parse machine-info data of %s: %m", i
->name
);
981 r
= chase_symlinks("/etc/os-release", i
->path
, CHASE_PREFIX_ROOT
, &path
);
983 r
= chase_symlinks("/usr/lib/os-release", i
->path
, CHASE_PREFIX_ROOT
, &path
);
984 if (r
< 0 && r
!= -ENOENT
)
985 log_debug_errno(r
, "Failed to chase os-release in image: %m");
987 r
= load_env_file_pairs(NULL
, path
, NULL
, &os_release
);
989 log_debug_errno(r
, "Failed to parse os-release data of %s: %m", i
->name
);
992 free_and_replace(i
->hostname
, hostname
);
993 i
->machine_id
= machine_id
;
994 strv_free_and_replace(i
->machine_info
, machine_info
);
995 strv_free_and_replace(i
->os_release
, os_release
);
1002 _cleanup_(loop_device_unrefp
) LoopDevice
*d
= NULL
;
1003 _cleanup_(dissected_image_unrefp
) DissectedImage
*m
= NULL
;
1005 r
= loop_device_make_by_path(i
->path
, O_RDONLY
, &d
);
1009 r
= dissect_image(d
->fd
, NULL
, 0, DISSECT_IMAGE_REQUIRE_ROOT
, &m
);
1013 r
= dissected_image_acquire_metadata(m
);
1017 free_and_replace(i
->hostname
, m
->hostname
);
1018 i
->machine_id
= m
->machine_id
;
1019 strv_free_and_replace(i
->machine_info
, m
->machine_info
);
1020 strv_free_and_replace(i
->os_release
, m
->os_release
);
1029 i
->metadata_valid
= true;
1034 int image_name_lock(const char *name
, int operation
, LockFile
*ret
) {
1040 /* Locks an image name, regardless of the precise path used. */
1042 if (!image_name_is_valid(name
))
1045 if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) {
1046 *ret
= (LockFile
) LOCK_FILE_INIT
;
1050 if (streq(name
, ".host"))
1053 mkdir_p("/run/systemd/nspawn/locks", 0700);
1054 p
= strjoina("/run/systemd/nspawn/locks/name-", name
);
1056 return make_lock_file(p
, operation
, ret
);
1059 bool image_name_is_valid(const char *s
) {
1060 if (!filename_is_valid(s
))
1063 if (string_has_cc(s
, NULL
))
1066 if (!utf8_is_valid(s
))
1069 /* Temporary files for atomically creating new files */
1070 if (startswith(s
, ".#"))
1076 static const char* const image_type_table
[_IMAGE_TYPE_MAX
] = {
1077 [IMAGE_DIRECTORY
] = "directory",
1078 [IMAGE_SUBVOLUME
] = "subvolume",
1079 [IMAGE_RAW
] = "raw",
1080 [IMAGE_BLOCK
] = "block",
1083 DEFINE_STRING_TABLE_LOOKUP(image_type
, ImageType
);