launch_daemon: Now blocks the CD tray on read-only /boot.

This commit is contained in:
Axel Dörfler
2015-07-22 20:44:21 +02:00
parent 634aefe4fd
commit 19a4ba1015
6 changed files with 135 additions and 23 deletions
+18 -23
View File
@@ -13,9 +13,7 @@
#include <Message.h> #include <Message.h>
#include <StringList.h> #include <StringList.h>
#include <DiskDevice.h> #include "Utility.h"
#include <DiskDeviceRoster.h>
#include <Volume.h>
class ConditionContainer : public Condition { class ConditionContainer : public Condition {
@@ -86,7 +84,9 @@ public:
virtual BString ToString() const; virtual BString ToString() const;
private: private:
dev_t fDevice; BString fPath;
mutable bool fIsReadOnly;
mutable bool fTestPerformed;
}; };
@@ -365,33 +365,28 @@ SafeModeCondition::ToString() const
ReadOnlyCondition::ReadOnlyCondition(const BMessage& args) ReadOnlyCondition::ReadOnlyCondition(const BMessage& args)
:
fPath(args.GetString("args")),
fIsReadOnly(false),
fTestPerformed(false)
{ {
fDevice = dev_for_path(args.GetString("args", "/boot"));
} }
bool bool
ReadOnlyCondition::Test(ConditionContext& context) const ReadOnlyCondition::Test(ConditionContext& context) const
{ {
BVolume volume; if (fTestPerformed)
status_t status = volume.SetTo(fDevice); return fIsReadOnly;
if (status != B_OK) {
fprintf(stderr, "Failed to get BVolume for device %" B_PRIdDEV
": %s\n", fDevice, strerror(status));
return false;
}
BDiskDeviceRoster roster; if (fPath.IsEmpty() || fPath == "/boot")
BDiskDevice diskDevice; fIsReadOnly = context.BootVolumeIsReadOnly();
BPartition* partition; else
status = roster.FindPartitionByVolume(volume, &diskDevice, &partition); fIsReadOnly = Utility::IsReadOnlyVolume(fPath);
if (status != B_OK) {
fprintf(stderr, "Failed to get partition for device %" B_PRIdDEV
": %s\n", fDevice, strerror(status));
return false;
}
return partition->IsReadOnly(); fTestPerformed = true;
return fIsReadOnly;
} }
@@ -406,7 +401,7 @@ BString
ReadOnlyCondition::ToString() const ReadOnlyCondition::ToString() const
{ {
BString string = "readonly "; BString string = "readonly ";
string << fDevice; string << fPath;
return string; return string;
} }
+1
View File
@@ -15,6 +15,7 @@ class BMessage;
class ConditionContext { class ConditionContext {
public: public:
virtual bool IsSafeMode() const = 0; virtual bool IsSafeMode() const = 0;
virtual bool BootVolumeIsReadOnly() const = 0;
}; };
+1
View File
@@ -14,6 +14,7 @@ Server launch_daemon
Job.cpp Job.cpp
SettingsParser.cpp SettingsParser.cpp
Target.cpp Target.cpp
Utility.cpp
Worker.cpp Worker.cpp
# init jobs # init jobs
+15
View File
@@ -37,6 +37,7 @@
#include "Job.h" #include "Job.h"
#include "SettingsParser.h" #include "SettingsParser.h"
#include "Target.h" #include "Target.h"
#include "Utility.h"
#include "Worker.h" #include "Worker.h"
@@ -78,6 +79,7 @@ public:
Session* FindSession(uid_t user) const; Session* FindSession(uid_t user) const;
virtual bool IsSafeMode() const; virtual bool IsSafeMode() const;
virtual bool BootVolumeIsReadOnly() const;
virtual void ReadyToRun(); virtual void ReadyToRun();
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
@@ -123,6 +125,7 @@ private:
MainWorker* fMainWorker; MainWorker* fMainWorker;
Target* fInitTarget; Target* fInitTarget;
bool fSafeMode; bool fSafeMode;
bool fReadOnlyBootVolume;
bool fUserMode; bool fUserMode;
}; };
@@ -221,11 +224,23 @@ LaunchDaemon::IsSafeMode() const
} }
bool
LaunchDaemon::BootVolumeIsReadOnly() const
{
return fReadOnlyBootVolume;
}
void void
LaunchDaemon::ReadyToRun() LaunchDaemon::ReadyToRun()
{ {
_RetrieveKernelOptions(); _RetrieveKernelOptions();
_SetupEnvironment(); _SetupEnvironment();
fReadOnlyBootVolume = Utility::IsReadOnlyVolume("/boot");
if (fReadOnlyBootVolume)
Utility::BlockMedia("/boot", true);
if (fUserMode) { if (fUserMode) {
BLaunchRoster roster; BLaunchRoster roster;
BLaunchRoster::Private(roster).RegisterSessionDaemon(this); BLaunchRoster::Private(roster).RegisterSessionDaemon(this);
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright 2015, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "Utility.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <device/scsi.h>
#include <DiskDevice.h>
#include <DiskDeviceRoster.h>
#include <fs_info.h>
#include <Volume.h>
namespace Utility {
bool
IsReadOnlyVolume(dev_t device)
{
BVolume volume;
status_t status = volume.SetTo(device);
if (status != B_OK) {
fprintf(stderr, "Failed to get BVolume for device %" B_PRIdDEV
": %s\n", device, strerror(status));
return false;
}
BDiskDeviceRoster roster;
BDiskDevice diskDevice;
BPartition* partition;
status = roster.FindPartitionByVolume(volume, &diskDevice, &partition);
if (status != B_OK) {
fprintf(stderr, "Failed to get partition for device %" B_PRIdDEV
": %s\n", device, strerror(status));
return false;
}
return partition->IsReadOnly();
}
bool
IsReadOnlyVolume(const char* path)
{
return IsReadOnlyVolume(dev_for_path(path));
}
status_t
BlockMedia(const char* path, bool block)
{
fs_info info;
if (fs_stat_dev(dev_for_path(path), &info) == B_OK) {
if (strcmp(info.fsh_name, "devfs") != 0)
path = info.device_name;
}
int device = open(path, O_RDONLY);
if (device < 0)
return device;
status_t status = B_OK;
if (ioctl(device, B_SCSI_PREVENT_ALLOW, &block, sizeof(block)) != 0) {
fprintf(stderr, "Failed to block media on %s: %s\n", path,
strerror(errno));
status = errno;
}
close(device);
return status;
}
} // namespace Utility
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright 2015, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef UTILITY_H
#define UTILITY_H
#include <SupportDefs.h>
namespace Utility {
bool IsReadOnlyVolume(dev_t device);
bool IsReadOnlyVolume(const char* path);
status_t BlockMedia(const char* path, bool block);
}
#endif // UTILITY_H