From c16361c49ce8db183df0a9c7abea0b5f1bc30581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 18 May 2015 18:29:10 +0200 Subject: [PATCH] launch_daemon: Initialize /tmp & /var/shared_memory, clock. * Added initializing /tmp & /var/shared_memory to the launch_daemon. * Moved clockconfig.cpp code into the launch_daemon. * This follows systemd design; since those jobs are fixed, it doesn't matter where you maintain them. * The init jobs are BJobs, but the JobQueue is only used for that one use for now. At a later time, I intend to put the job launching in there, as well. BJob allows to represent the dependencies already. --- build/jam/images/definitions/minimum | 3 +- src/bin/Jamfile | 1 - .../launch/AbstractEmptyDirectoryJob.cpp | 55 +++++++++++++++ .../launch/AbstractEmptyDirectoryJob.h | 28 ++++++++ .../launch/InitRealTimeClockJob.cpp} | 70 ++++++++++--------- src/servers/launch/InitRealTimeClockJob.h | 26 +++++++ .../launch/InitSharedMemoryDirectoryJob.cpp | 24 +++++++ .../launch/InitSharedMemoryDirectoryJob.h | 21 ++++++ .../launch/InitTemporaryDirectoryJob.cpp | 34 +++++++++ .../launch/InitTemporaryDirectoryJob.h | 21 ++++++ src/servers/launch/Jamfile | 8 ++- src/servers/launch/LaunchDaemon.cpp | 65 +++++++++++++---- 12 files changed, 305 insertions(+), 51 deletions(-) create mode 100644 src/servers/launch/AbstractEmptyDirectoryJob.cpp create mode 100644 src/servers/launch/AbstractEmptyDirectoryJob.h rename src/{bin/clockconfig.cpp => servers/launch/InitRealTimeClockJob.cpp} (62%) create mode 100644 src/servers/launch/InitRealTimeClockJob.h create mode 100644 src/servers/launch/InitSharedMemoryDirectoryJob.cpp create mode 100644 src/servers/launch/InitSharedMemoryDirectoryJob.h create mode 100644 src/servers/launch/InitTemporaryDirectoryJob.cpp create mode 100644 src/servers/launch/InitTemporaryDirectoryJob.h diff --git a/build/jam/images/definitions/minimum b/build/jam/images/definitions/minimum index b6033258bc..cee093ef9f 100644 --- a/build/jam/images/definitions/minimum +++ b/build/jam/images/definitions/minimum @@ -3,8 +3,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures addattr alert arp bc beep bfsinfo - catattr checkfs checkitout chop clear - clockconfig cmp collectcatkeys compress copyattr + catattr checkfs checkitout chop clear cmp collectcatkeys compress copyattr dc desklink df diff diff3 diskimage draggers driveinfo dstcheck dumpcatalog eject error diff --git a/src/bin/Jamfile b/src/bin/Jamfile index abec585e05..f8cb28c287 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -81,7 +81,6 @@ StdBinCommands catattr.cpp checkfs.cpp clipboard.cpp - clockconfig.cpp df.cpp diskimage.cpp dpms.cpp diff --git a/src/servers/launch/AbstractEmptyDirectoryJob.cpp b/src/servers/launch/AbstractEmptyDirectoryJob.cpp new file mode 100644 index 0000000000..44b14d1753 --- /dev/null +++ b/src/servers/launch/AbstractEmptyDirectoryJob.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include "AbstractEmptyDirectoryJob.h" + +#include + +#include +#include + + +AbstractEmptyDirectoryJob::AbstractEmptyDirectoryJob(const BString& name) + : + BJob(name) +{ +} + + +status_t +AbstractEmptyDirectoryJob::CreateAndEmpty(const char* path) const +{ + BEntry entry(path); + if (entry.InitCheck() != B_OK) { + create_directory(path, 0777); + + status_t status = entry.SetTo(path); + if (status != B_OK) { + fprintf(stderr, "Cannot create directory \"%s\": %s\n", path, + strerror(status)); + return status; + } + } + + return _EmptyDirectory(entry, false); +} + + +status_t +AbstractEmptyDirectoryJob::_EmptyDirectory(BEntry& directoryEntry, + bool remove) const +{ + BDirectory directory(&directoryEntry); + BEntry entry; + while (directory.GetNextEntry(&entry) == B_OK) { + if (entry.IsDirectory()) + _EmptyDirectory(entry, true); + else + entry.Remove(); + } + + return remove ? directoryEntry.Remove() : B_OK; +} diff --git a/src/servers/launch/AbstractEmptyDirectoryJob.h b/src/servers/launch/AbstractEmptyDirectoryJob.h new file mode 100644 index 0000000000..5c7a1ec932 --- /dev/null +++ b/src/servers/launch/AbstractEmptyDirectoryJob.h @@ -0,0 +1,28 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef ABSTRACT_EMPTY_DIRECTORY_JOB_H +#define ABSTRACT_EMPTY_DIRECTORY_JOB_H + + +#include + + +class BEntry; + + +class AbstractEmptyDirectoryJob : public BSupportKit::BJob { +public: + AbstractEmptyDirectoryJob(const BString& name); + +protected: + status_t CreateAndEmpty(const char* path) const; + +private: + status_t _EmptyDirectory(BEntry& directoryEntry, + bool remove) const; +}; + + +#endif // ABSTRACT_EMPTY_DIRECTORY_JOB_H diff --git a/src/bin/clockconfig.cpp b/src/servers/launch/InitRealTimeClockJob.cpp similarity index 62% rename from src/bin/clockconfig.cpp rename to src/servers/launch/InitRealTimeClockJob.cpp index 78c73520f7..2739e0ffc5 100644 --- a/src/bin/clockconfig.cpp +++ b/src/servers/launch/InitRealTimeClockJob.cpp @@ -1,43 +1,64 @@ /* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. * Copyright 2004, Jérôme Duval, jerome.duval@free.fr. * Copyright 2010, 2012, Oliver Tappe - * All rights reserved. Distributed under the terms of the MIT License. + * Distributed under the terms of the MIT License. */ +//! Initialize real time clock, and time zone offset + + +#include "InitRealTimeClockJob.h" + +#include + #include #include #include -#include -#include -#include #include #include -#include -#include -#include + +using BSupportKit::BJob; -static char* program; +InitRealTimeClockJob::InitRealTimeClockJob() + : + BJob("init real time clock") +{ +} + + +status_t +InitRealTimeClockJob::Execute() +{ + BPath path; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (status == B_OK) { + _SetRealTimeClockIsGMT(path); + _SetTimeZoneOffset(path); + } + return status; +} void -setRealTimeClockIsGMT(BPath path) +InitRealTimeClockJob::_SetRealTimeClockIsGMT(BPath path) const { path.Append("RTC_time_settings"); BFile file; status_t status = file.SetTo(path.Path(), B_READ_ONLY); if (status != B_OK) { - fprintf(stderr, "%s: can't open RTC settings file\n", program); + fprintf(stderr, "Can't open RTC settings file\n"); return; } char buffer[10]; ssize_t bytesRead = file.Read(buffer, sizeof(buffer)); if (bytesRead < 0) { - fprintf(stderr, "%s: unable to read RTC settings file\n", program); + fprintf(stderr, "Unable to read RTC settings file\n"); return; } bool isGMT = strncmp(buffer, "local", 5) != 0; @@ -48,25 +69,25 @@ setRealTimeClockIsGMT(BPath path) void -setTimeZoneOffset(BPath path) +InitRealTimeClockJob::_SetTimeZoneOffset(BPath path) const { path.Append("Time settings"); BFile file; status_t status = file.SetTo(path.Path(), B_READ_ONLY); if (status != B_OK) { - fprintf(stderr, "%s: can't open Time settings file\n", program); + fprintf(stderr, "Can't open Time settings file\n"); return; } BMessage settings; status = settings.Unflatten(&file); if (status != B_OK) { - fprintf(stderr, "%s: unable to parse Time settings file\n", program); + fprintf(stderr, "Unable to parse Time settings file\n"); return; } BString timeZoneID; if (settings.FindString("timezone", &timeZoneID) != B_OK) { - fprintf(stderr, "%s: no timezone found\n", program); + fprintf(stderr, "No timezone found\n"); return; } int32 timeZoneOffset = BTimeZone(timeZoneID.String()).OffsetFromGMT(); @@ -76,22 +97,3 @@ setTimeZoneOffset(BPath path) printf("timezone is %s, offset is %" B_PRId32 " seconds from GMT.\n", timeZoneID.String(), timeZoneOffset); } - - -int -main(int argc, char **argv) -{ - program = argv[0]; - - BPath path; - status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); - if (status != B_OK) { - fprintf(stderr, "%s: can't find settings directory\n", program); - return EXIT_FAILURE; - } - - setRealTimeClockIsGMT(path); - setTimeZoneOffset(path); - - return 0; -} diff --git a/src/servers/launch/InitRealTimeClockJob.h b/src/servers/launch/InitRealTimeClockJob.h new file mode 100644 index 0000000000..f2ecaa4760 --- /dev/null +++ b/src/servers/launch/InitRealTimeClockJob.h @@ -0,0 +1,26 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef INIT_REAL_TIME_CLOCK_JOB_H +#define INIT_REAL_TIME_CLOCK_JOB_H + + +#include +#include + + +class InitRealTimeClockJob : public BSupportKit::BJob { +public: + InitRealTimeClockJob(); + +protected: + virtual status_t Execute(); + +private: + void _SetRealTimeClockIsGMT(BPath path) const; + void _SetTimeZoneOffset(BPath path) const; +}; + + +#endif // INIT_REAL_TIME_CLOCK_JOB_H diff --git a/src/servers/launch/InitSharedMemoryDirectoryJob.cpp b/src/servers/launch/InitSharedMemoryDirectoryJob.cpp new file mode 100644 index 0000000000..00423dcb3b --- /dev/null +++ b/src/servers/launch/InitSharedMemoryDirectoryJob.cpp @@ -0,0 +1,24 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +//! Empty main temporary directory + + +#include "InitSharedMemoryDirectoryJob.h" + + +InitSharedMemoryDirectoryJob::InitSharedMemoryDirectoryJob() + : + AbstractEmptyDirectoryJob("init /var/shared_memory") +{ +} + + +status_t +InitSharedMemoryDirectoryJob::Execute() +{ + return CreateAndEmpty("/var/shared_memory"); +} diff --git a/src/servers/launch/InitSharedMemoryDirectoryJob.h b/src/servers/launch/InitSharedMemoryDirectoryJob.h new file mode 100644 index 0000000000..bf98b2f273 --- /dev/null +++ b/src/servers/launch/InitSharedMemoryDirectoryJob.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef INIT_SHARED_MEMORY_DIRECTORY_JOB_H +#define INIT_SHARED_MEMORY_DIRECTORY_JOB_H + + +#include "AbstractEmptyDirectoryJob.h" + + +class InitSharedMemoryDirectoryJob : public AbstractEmptyDirectoryJob { +public: + InitSharedMemoryDirectoryJob(); + +protected: + virtual status_t Execute(); +}; + + +#endif // INIT_SHARED_MEMORY_DIRECTORY_JOB_H diff --git a/src/servers/launch/InitTemporaryDirectoryJob.cpp b/src/servers/launch/InitTemporaryDirectoryJob.cpp new file mode 100644 index 0000000000..dc12e3e124 --- /dev/null +++ b/src/servers/launch/InitTemporaryDirectoryJob.cpp @@ -0,0 +1,34 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +//! Empty main temporary directory + + +#include "InitTemporaryDirectoryJob.h" + +#include +#include + + +InitTemporaryDirectoryJob::InitTemporaryDirectoryJob() + : + AbstractEmptyDirectoryJob("init /tmp") +{ +} + + +status_t +InitTemporaryDirectoryJob::Execute() +{ + // TODO: the /tmp entries could be scanned synchronously, and deleted + // later + BPath path; + status_t status = find_directory(B_SYSTEM_TEMP_DIRECTORY, &path, true); + if (status == B_OK) + return CreateAndEmpty(path.Path()); + + return status; +} diff --git a/src/servers/launch/InitTemporaryDirectoryJob.h b/src/servers/launch/InitTemporaryDirectoryJob.h new file mode 100644 index 0000000000..a51898673f --- /dev/null +++ b/src/servers/launch/InitTemporaryDirectoryJob.h @@ -0,0 +1,21 @@ +/* + * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef INIT_TEMPORARY_DIRECTORY_JOB_H +#define INIT_TEMPORARY_DIRECTORY_JOB_H + + +#include "AbstractEmptyDirectoryJob.h" + + +class InitTemporaryDirectoryJob : public AbstractEmptyDirectoryJob { +public: + InitTemporaryDirectoryJob(); + +protected: + virtual status_t Execute(); +}; + + +#endif // INIT_TEMPORARY_DIRECTORY_JOB_H diff --git a/src/servers/launch/Jamfile b/src/servers/launch/Jamfile index 59dd449b1c..0ba38ee892 100644 --- a/src/servers/launch/Jamfile +++ b/src/servers/launch/Jamfile @@ -1,11 +1,17 @@ SubDir HAIKU_TOP src servers launch ; -UsePrivateHeaders app shared ; +UsePrivateHeaders app package shared storage support ; UsePrivateSystemHeaders ; Server launch_daemon : LaunchDaemon.cpp + + # init jobs + AbstractEmptyDirectoryJob.cpp + InitRealTimeClockJob.cpp + InitSharedMemoryDirectoryJob.cpp + InitTemporaryDirectoryJob.cpp : be libshared.a [ TargetLibstdc++ ] : diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index 5de107a03d..963beafd17 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,11 +21,18 @@ #include #include +#include #include #include +#include "InitRealTimeClockJob.h" +#include "InitSharedMemoryDirectoryJob.h" +#include "InitTemporaryDirectoryJob.h" + using namespace BPrivate; +using namespace BSupportKit; +using BSupportKit::BPrivate::JobQueue; static const char* kLaunchDirectory = "launch"; @@ -127,11 +135,16 @@ private: void _InitJobs(); void _LaunchJobs(); + void _RetrieveKernelOptions(); void _SetupEnvironment(); + void _InitSystem(); + bool _IsSafeMode() const; private: JobMap fJobs; + JobQueue fJobQueue; + bool fSafeMode; }; @@ -410,7 +423,9 @@ LaunchDaemon::~LaunchDaemon() void LaunchDaemon::ReadyToRun() { + _RetrieveKernelOptions(); _SetupEnvironment(); + _InitSystem(); BStringList paths; BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, kLaunchDirectory, @@ -609,29 +624,52 @@ LaunchDaemon::_LaunchJobs() void -LaunchDaemon::_SetupEnvironment() -{ - // Determine safemode kernel option - BString safemode = "SAFEMODE="; - safemode << _IsSafeMode() ? "yes" : "no"; -} - - -bool -LaunchDaemon::_IsSafeMode() const +LaunchDaemon::_RetrieveKernelOptions() { char buffer[32]; size_t size = sizeof(buffer); status_t status = _kern_get_safemode_option(B_SAFEMODE_SAFE_MODE, buffer, &size); if (status == B_OK) { - return !strncasecmp(buffer, "true", size) + fSafeMode = !strncasecmp(buffer, "true", size) || !strncasecmp(buffer, "yes", size) || !strncasecmp(buffer, "on", size) || !strncasecmp(buffer, "enabled", size); - } + } else + fSafeMode = false; +} - return false; + +void +LaunchDaemon::_SetupEnvironment() +{ + // Determine safemode kernel option + BString safemode = "SAFEMODE="; + safemode << _IsSafeMode() ? "yes" : "no"; + + putenv(safemode.String()); +} + + +/*! Basic system initialization that must happen before any jobs are launched. +*/ +void +LaunchDaemon::_InitSystem() +{ + fJobQueue.AddJob(new InitRealTimeClockJob()); + fJobQueue.AddJob(new InitSharedMemoryDirectoryJob()); + fJobQueue.AddJob(new InitTemporaryDirectoryJob()); + + // TODO: these should be done in parallel + while (BJob* job = fJobQueue.Pop()) + job->Run(); +} + + +bool +LaunchDaemon::_IsSafeMode() const +{ + return fSafeMode; } @@ -647,6 +685,7 @@ main() if (fd != STDOUT_FILENO) dup2(fd, STDOUT_FILENO); puts("launch_daemon is alive and kicking."); + fflush(stdout); status_t status; LaunchDaemon* daemon = new LaunchDaemon(status);