GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/swissknife_overlay.h
Date: 2026-03-01 02:36:14
Exec Total Coverage
Lines: 0 6 0.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * Swissknife command for performing catalog-level overlays of multiple
5 * subdirectories from a CVMFS repository, similar to OverlayFS or how
6 * container engines merge container image layers.
7 *
8 * The overlay tool merges the catalog entries of multiple layer subdirectories,
9 * typically corresponding to container layers, and publishes the result as
10 * a new subdirectory in the CVMFS repository, typically corresponding to the flat
11 * root file system of the container image.
12 *
13 * The publish workflow is taken from swissknife ingest.
14 */
15
16 #ifndef CVMFS_SWISSKNIFE_OVERLAY_H_
17 #define CVMFS_SWISSKNIFE_OVERLAY_H_
18
19 #include <map>
20 #include <string>
21 #include <vector>
22
23 #include "catalog.h"
24 #include "catalog_mgr_rw.h"
25 #include "directory_entry.h"
26 #include "shortstring.h"
27 #include "swissknife.h"
28 #include "xattr.h"
29
30 namespace swissknife {
31
32 /**
33 * Represents a single entry in the merged overlay catalog, tracking
34 * which layer it came from and its metadata.
35 */
36 struct OverlayEntry {
37 catalog::DirectoryEntry entry;
38 XattrList xattrs;
39 std::string path; // relative path in the merged view
40 std::string parent; // parent directory relative path in the merged view
41 bool is_whiteout; // true if this is a whiteout marker
42 bool is_opaque_dir; // true if directory has opaque marker
43
44 OverlayEntry()
45 : is_whiteout(false), is_opaque_dir(false) {}
46 };
47
48 class CommandOverlay : public Command {
49 public:
50 virtual ~CommandOverlay() {}
51
52 virtual std::string GetName() const { return "overlay"; }
53 virtual std::string GetDescription() const {
54 return "Merge multiple CVMFS subdirectory catalogs using overlay "
55 "semantics and publish the result as a repository subdirectory";
56 }
57 virtual ParameterList GetParams() const;
58 virtual int Main(const ArgumentList &args);
59
60 private:
61 /**
62 * Recursively read all entries from a catalog rooted at the given path.
63 * The entries are stored with paths relative to the layer root.
64 * When a nested catalog mountpoint is encountered and repo_base/temp_dir
65 * are non-empty, the nested catalog is loaded and recursed into.
66 */
67 bool ReadCatalogEntries(
68 catalog::Catalog *catalog,
69 const std::string &catalog_root_path,
70 const std::string &relative_prefix,
71 const std::string &repo_base,
72 const std::string &temp_dir,
73 std::map<std::string, OverlayEntry> *entries);
74
75 /**
76 * Check if a filename represents a whiteout file (.wh.<name>).
77 */
78 static bool IsWhiteoutFile(const std::string &name);
79
80 /**
81 * Get the original filename from a whiteout filename.
82 * E.g., ".wh.foo" -> "foo"
83 */
84 static std::string GetWhiteoutTarget(const std::string &name);
85
86 /**
87 * Check if a filename represents an opaque directory marker (.wh..wh..opq).
88 */
89 static bool IsOpaqueMarker(const std::string &name);
90
91 /**
92 * Merge entries from a higher layer into the accumulated overlay map.
93 * Implements overlay semantics: whiteout handling, opaque dirs, overrides.
94 */
95 void MergeLayer(
96 const std::map<std::string, OverlayEntry> &layer_entries,
97 std::map<std::string, OverlayEntry> *merged) const;
98
99 /**
100 * Publish the merged overlay entries into the repository under dest_path
101 * using the WritableCatalogManager. This adds directory and file entries
102 * to the live catalog, then commits the changes to produce a new manifest.
103 */
104 bool PublishMergedEntries(
105 catalog::WritableCatalogManager *catalog_mgr,
106 const std::map<std::string, OverlayEntry> &merged,
107 const std::string &dest_path) const;
108
109 /**
110 * Load a catalog from the repository for a given subdirectory path.
111 * Handles both local and remote repositories.
112 */
113 catalog::Catalog *LoadCatalogForPath(
114 const std::string &repo_base,
115 const std::string &subdirectory,
116 const std::string &temp_dir,
117 const shash::Any &root_hash);
118
119 /**
120 * Find the catalog that contains the given layer path by walking the
121 * nested catalog hierarchy. The layer path may be deep inside a nested
122 * catalog (e.g. /.layers/ab/abcdef.../layerfs where /.layers is a nested
123 * catalog mountpoint). Returns the catalog that can look up layer_path,
124 * or NULL on failure. The caller takes ownership of any additionally
125 * loaded catalogs returned via loaded_catalogs.
126 */
127 catalog::Catalog *FindCatalogForLayer(
128 const std::string &repo_base,
129 const std::string &temp_dir,
130 catalog::Catalog *root_catalog,
131 const std::string &layer_path,
132 std::vector<catalog::Catalog *> *loaded_catalogs);
133 };
134
135 } // namespace swissknife
136
137 #endif // CVMFS_SWISSKNIFE_OVERLAY_H_
138
139