diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index 2bd2f98487..bc416bf4aa 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -91,6 +91,8 @@ GFileInfo * _ostree_stbuf_to_gfileinfo (const struct stat *stbuf); void _ostree_gfileinfo_to_stbuf (GFileInfo *file_info, struct stat *out_stbuf); gboolean _ostree_gfileinfo_equal (GFileInfo *a, GFileInfo *b); gboolean _ostree_stbuf_equal (struct stat *stbuf_a, struct stat *stbuf_b); +gboolean _ostree_stbuf_is_whiteout(struct stat *stbuf); +gboolean _ostree_gfileinfo_is_whiteout(GFileInfo *file_info); GFileInfo * _ostree_mode_uidgid_to_gfileinfo (mode_t mode, uid_t uid, gid_t gid); static inline void diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 44ca8abf08..c2a5867b81 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -1732,6 +1732,7 @@ _ostree_stbuf_to_gfileinfo (const struct stat *stbuf) g_file_info_set_attribute_uint32 (ret, "unix::uid", stbuf->st_uid); g_file_info_set_attribute_uint32 (ret, "unix::gid", stbuf->st_gid); g_file_info_set_attribute_uint32 (ret, "unix::mode", mode); + g_file_info_set_attribute_uint32 (ret, "unix::rdev", stbuf->st_rdev); /* those aren't stored by ostree, but used by the devino cache */ g_file_info_set_attribute_uint32 (ret, "unix::device", stbuf->st_dev); @@ -1816,6 +1817,22 @@ _ostree_stbuf_equal (struct stat *stbuf_a, struct stat *stbuf_b) return TRUE; } +/* Check if stbuf belongs to a whiteout character device */ +gboolean +_ostree_stbuf_is_whiteout(struct stat *stbuf) +{ + return S_ISCHR(stbuf->st_mode) && stbuf->st_rdev == 0; +} + +/* Check if GFileInfo belongs to a whiteout character device */ +gboolean +_ostree_gfileinfo_is_whiteout(GFileInfo *file_info) +{ + struct stat stbuf; + _ostree_gfileinfo_to_stbuf(file_info, &stbuf); + return _ostree_stbuf_is_whiteout(&stbuf); +} + /* Many parts of libostree only care about mode,uid,gid - this creates * a new GFileInfo with those fields see. */ @@ -2014,7 +2031,7 @@ file_header_parse (GVariant *metadata, mode = GUINT32_FROM_BE (mode); g_autoptr(GFileInfo) ret_file_info = _ostree_mode_uidgid_to_gfileinfo (mode, uid, gid); - if (S_ISREG (mode) || S_ISCHR(mode)) + if (S_ISREG (mode) || _ostree_gfileinfo_is_whiteout(ret_file_info)) { ; } @@ -2065,7 +2082,7 @@ zlib_file_header_parse (GVariant *metadata, g_autoptr(GFileInfo) ret_file_info = _ostree_mode_uidgid_to_gfileinfo (mode, uid, gid); g_file_info_set_size (ret_file_info, GUINT64_FROM_BE (size)); - if (S_ISREG (mode) || S_ISCHR (mode)) + if (S_ISREG (mode) || _ostree_gfileinfo_is_whiteout(ret_file_info)) { ; } diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index ed271781e4..d8f68f52a7 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -385,9 +385,9 @@ create_file_copy_from_input_at (OstreeRepo *repo, if (g_str_equal (checksum, actual_checksum)) return TRUE; - /* Otherwise, fall through and do the link, we should - * get EEXIST. - */ + /* Otherwise, fall through and do the link, we should + * get EEXIST. + */ } } break; @@ -401,10 +401,10 @@ create_file_copy_from_input_at (OstreeRepo *repo, else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SPECIAL) { guint32 file_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode"); - g_assert(S_ISCHR(file_mode)); + g_assert(_ostree_gfileinfo_is_whiteout(file_info)); if (mknodat(destination_dfd, destination_name, file_mode, (dev_t)0) < 0) - return glnx_throw_errno_prefix (error, "Creating whiteout char device"); + return glnx_throw_errno_prefix (error, "Creating whiteout char device"); if (options->mode != OSTREE_REPO_CHECKOUT_MODE_USER) { if (xattrs != NULL && diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 1bcd6d3e5a..595446dfb1 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1010,7 +1010,7 @@ write_content_object (OstreeRepo *self, break; case G_FILE_TYPE_SPECIAL: /* Only overlayfs whiteout char 0:0 files are supported for G_FILE_TYPE_SPECIAL */ - if (S_ISCHR(mode)) + if (_ostree_gfileinfo_is_whiteout(file_info)) { /* For bare mode repositories where no side file metadata is stored we want to * avoid the creation of an empty tmp file and later setup of permissions because @@ -4152,7 +4152,7 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, } /* For regular files and whiteout char devices we continue */ - if (S_ISREG (stbuf.st_mode) || (S_ISCHR(stbuf.st_mode) && stbuf.st_rdev == 0)) + if (S_ISREG (stbuf.st_mode) || _ostree_stbuf_is_whiteout(&stbuf)) ; else if (S_ISLNK (stbuf.st_mode)) { diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 932eef4fac..013c769a7d 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -4323,7 +4323,7 @@ _ostree_repo_load_file_bare (OstreeRepo *self, } if (!(S_ISREG (stbuf.st_mode) || S_ISLNK (stbuf.st_mode) || - (S_ISCHR (stbuf.st_mode) && stbuf.st_rdev == 0))) + _ostree_stbuf_is_whiteout(&stbuf))) return glnx_throw (error, "Not a regular file, symlink or whiteout"); /* In the non-bare-user case, gather symlink info if requested */ @@ -4475,7 +4475,7 @@ ostree_repo_load_file (OstreeRepo *self, if (S_ISLNK (stbuf.st_mode)) g_file_info_set_symlink_target (*out_file_info, symlink_target); else - g_assert (S_ISREG (stbuf.st_mode) || (S_ISCHR(stbuf.st_mode) && stbuf.st_rdev == 0)); + g_assert (S_ISREG (stbuf.st_mode) || _ostree_stbuf_is_whiteout(&stbuf)); } ot_transfer_out_value (out_xattrs, &ret_xattrs);