LibCore: Add ensure_parent_directories to LibCore::File

Moved the implementation in SystemServer/Service.cpp to LibCore.
This commit is contained in:
Itamar 2020-09-28 10:09:05 +03:00 committed by Andreas Kling
parent c1fc27cab2
commit fec4152220
Notes: sideshowbarker 2024-07-19 02:07:19 +09:00
3 changed files with 38 additions and 25 deletions

View file

@ -27,10 +27,13 @@
#ifdef __serenity__
# include <Kernel/API/Syscall.h>
#endif
#include <AK/ScopeGuard.h>
#include <LibCore/File.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
@ -132,6 +135,37 @@ String File::real_path_for(const String& filename)
return real_path;
}
bool File::ensure_parent_directories(const String& path)
{
ASSERT(path.starts_with("/"));
int saved_errno = 0;
ScopeGuard restore_errno = [&saved_errno] { errno = saved_errno; };
char* parent_buffer = strdup(path.characters());
ScopeGuard free_buffer = [parent_buffer] { free(parent_buffer); };
const char* parent = dirname(parent_buffer);
int rc = mkdir(parent, 0755);
saved_errno = errno;
if (rc == 0 || errno == EEXIST)
return true;
if (errno != ENOENT)
return false;
bool ok = ensure_parent_directories(parent);
saved_errno = errno;
if (!ok)
return false;
rc = mkdir(parent, 0755);
saved_errno = errno;
return rc == 0;
}
#ifdef __serenity__
String File::read_link(const StringView& link_path)

View file

@ -48,6 +48,7 @@ public:
static bool exists(const String& filename);
static String real_path_for(const String& filename);
static String read_link(const StringView& link_path);
static bool ensure_parent_directories(const String& path);
virtual bool open(IODevice::OpenMode) override;

View file

@ -29,6 +29,7 @@
#include <AK/JsonArray.h>
#include <AK/JsonObject.h>
#include <LibCore/ConfigFile.h>
#include <LibCore/File.h>
#include <LibCore/Socket.h>
#include <grp.h>
#include <libgen.h>
@ -84,36 +85,13 @@ Service* Service::find_by_pid(pid_t pid)
return (*it).value;
}
static int ensure_parent_directories(const char* path)
{
ASSERT(path[0] == '/');
char* parent_buffer = strdup(path);
const char* parent = dirname(parent_buffer);
int rc = 0;
while (true) {
int rc = mkdir(parent, 0755);
if (rc == 0)
break;
if (errno != ENOENT)
break;
ensure_parent_directories(parent);
};
free(parent_buffer);
return rc;
}
void Service::setup_socket()
{
ASSERT(!m_socket_path.is_null());
ASSERT(m_socket_fd == -1);
ensure_parent_directories(m_socket_path.characters());
auto ok = Core::File::ensure_parent_directories(m_socket_path);
ASSERT(ok);
// Note: we use SOCK_CLOEXEC here to make sure we don't leak every socket to
// all the clients. We'll make the one we do need to pass down !CLOEXEC later