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

This commit is contained in:
Axel Dörfler 2015-07-08 22:14:05 +02:00
parent 634aefe4fd
commit 19a4ba1015
6 changed files with 135 additions and 23 deletions

View File

@ -13,9 +13,7 @@
#include <Message.h>
#include <StringList.h>
#include <DiskDevice.h>
#include <DiskDeviceRoster.h>
#include <Volume.h>
#include "Utility.h"
class ConditionContainer : public Condition {
@ -86,7 +84,9 @@ public:
virtual BString ToString() const;
private:
dev_t fDevice;
BString fPath;
mutable bool fIsReadOnly;
mutable bool fTestPerformed;
};
@ -365,33 +365,28 @@ SafeModeCondition::ToString() const
ReadOnlyCondition::ReadOnlyCondition(const BMessage& args)
:
fPath(args.GetString("args")),
fIsReadOnly(false),
fTestPerformed(false)
{
fDevice = dev_for_path(args.GetString("args", "/boot"));
}
bool
ReadOnlyCondition::Test(ConditionContext& context) const
{
BVolume volume;
status_t status = volume.SetTo(fDevice);
if (status != B_OK) {
fprintf(stderr, "Failed to get BVolume for device %" B_PRIdDEV
": %s\n", fDevice, strerror(status));
return false;
}
if (fTestPerformed)
return fIsReadOnly;
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", fDevice, strerror(status));
return false;
}
if (fPath.IsEmpty() || fPath == "/boot")
fIsReadOnly = context.BootVolumeIsReadOnly();
else
fIsReadOnly = Utility::IsReadOnlyVolume(fPath);
return partition->IsReadOnly();
fTestPerformed = true;
return fIsReadOnly;
}
@ -406,7 +401,7 @@ BString
ReadOnlyCondition::ToString() const
{
BString string = "readonly ";
string << fDevice;
string << fPath;
return string;
}

View File

@ -15,6 +15,7 @@ class BMessage;
class ConditionContext {
public:
virtual bool IsSafeMode() const = 0;
virtual bool BootVolumeIsReadOnly() const = 0;
};

View File

@ -14,6 +14,7 @@ Server launch_daemon
Job.cpp
SettingsParser.cpp
Target.cpp
Utility.cpp
Worker.cpp
# init jobs

View File

@ -37,6 +37,7 @@
#include "Job.h"
#include "SettingsParser.h"
#include "Target.h"
#include "Utility.h"
#include "Worker.h"
@ -78,6 +79,7 @@ public:
Session* FindSession(uid_t user) const;
virtual bool IsSafeMode() const;
virtual bool BootVolumeIsReadOnly() const;
virtual void ReadyToRun();
virtual void MessageReceived(BMessage* message);
@ -123,6 +125,7 @@ private:
MainWorker* fMainWorker;
Target* fInitTarget;
bool fSafeMode;
bool fReadOnlyBootVolume;
bool fUserMode;
};
@ -221,11 +224,23 @@ LaunchDaemon::IsSafeMode() const
}
bool
LaunchDaemon::BootVolumeIsReadOnly() const
{
return fReadOnlyBootVolume;
}
void
LaunchDaemon::ReadyToRun()
{
_RetrieveKernelOptions();
_SetupEnvironment();
fReadOnlyBootVolume = Utility::IsReadOnlyVolume("/boot");
if (fReadOnlyBootVolume)
Utility::BlockMedia("/boot", true);
if (fUserMode) {
BLaunchRoster roster;
BLaunchRoster::Private(roster).RegisterSessionDaemon(this);

View File

@ -0,0 +1,80 @@
/*
* Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
* 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

View File

@ -0,0 +1,20 @@
/*
* Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
* 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