MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / createDirectoryAndChown

Function createDirectoryAndChown

programs/docker-init/docker-init.cpp:293–361  ·  view source on GitHub ↗

Create a directory (and all parents) and optionally chown it. Three cases: 1. do_chown=true (root, normal mode): create with fs::create_directories, then chown. 2. do_chown=false, running as root (CLICKHOUSE_DO_NOT_CHOWN=1): delegate to `clickhouse su UID:GID` so the directory is created as the target user. This handles NFS mounts where root is mapped to nobody. 3. do_chown=false, running as non-

Source from the content-addressed store, hash-verified

291/// This handles NFS mounts where root is mapped to nobody.
292/// 3. do_chown=false, running as non-root: create directly — we are already the target user.
293bool createDirectoryAndChown(const std::string & dir, uid_t uid, gid_t gid, bool do_chown)
294{
295 if (dir.empty())
296 return true;
297
298 if (do_chown)
299 {
300 std::error_code ec;
301 fs::create_directories(dir, ec);
302 if (ec)
303 {
304 std::cerr << "docker-init: couldn't create directory " << dir << ": " << ec.message() << "\n";
305 return false;
306 }
307
308 /// Chown only if the owner needs to change (avoids slow recursive chown on already-correct dirs).
309 struct stat st{};
310 if (stat(dir.c_str(), &st) == 0 && (st.st_uid != uid || st.st_gid != gid))
311 recursiveChown(dir, uid, gid);
312
313 return true;
314 }
315
316 if (getuid() == 0)
317 {
318 /// Running as root with CLICKHOUSE_DO_NOT_CHOWN or CLICKHOUSE_RUN_AS_ROOT.
319 /// On NFS mounts root may be remapped to nobody, so create the directory as
320 /// the target user. Fork a child that drops privileges before calling
321 /// fs::create_directories — distroless has no mkdir binary.
322 pid_t pid = fork();
323 if (pid < 0)
324 {
325 std::cerr << "docker-init: fork failed for directory creation: " << strerror(errno) << "\n"; // NOLINT(concurrency-mt-unsafe)
326 return false;
327 }
328 if (pid == 0)
329 {
330 if (setgroups(0, nullptr) < 0 || setgid(gid) < 0 || setuid(uid) < 0)
331 _exit(1);
332 std::error_code ec;
333 fs::create_directories(dir, ec);
334 _exit(ec ? 1 : 0);
335 }
336 int status = 0;
337 while (waitpid(pid, &status, 0) < 0 && errno == EINTR) {}
338 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
339 {
340 /// Fallback: try direct creation (works when root is not remapped).
341 std::error_code ec;
342 fs::create_directories(dir, ec);
343 if (ec)
344 {
345 std::cerr << "docker-init: couldn't create directory " << dir << ": " << ec.message() << "\n";
346 return false;
347 }
348 }
349 return true;
350 }

Callers 1

Calls 4

recursiveChownFunction · 0.85
statClass · 0.70
emptyMethod · 0.45
messageMethod · 0.45

Tested by

no test coverage detected