1/*
2 * Copyright 2015, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "Utility.h"
8
9#include <errno.h>
10#include <stdio.h>
11#include <string.h>
12
13#include <device/scsi.h>
14#include <DiskDevice.h>
15#include <DiskDeviceRoster.h>
16#include <fs_info.h>
17#include <Volume.h>
18
19
20namespace {
21
22
23status_t
24IssueDeviceCommand(const char* path, int opcode, void* buffer,
25	size_t bufferSize)
26{
27	fs_info info;
28	if (fs_stat_dev(dev_for_path(path), &info) == B_OK) {
29		if (strcmp(info.fsh_name, "devfs") != 0)
30			path = info.device_name;
31	}
32
33	int device = open(path, O_RDONLY);
34	if (device < 0)
35		return device;
36
37	status_t status = B_OK;
38
39	if (ioctl(device, opcode, buffer, bufferSize) != 0) {
40		fprintf(stderr, "Failed to process %d on %s: %s\n", opcode, path,
41			strerror(errno));
42		status = errno;
43	}
44	close(device);
45	return status;
46}
47
48
49}	// private namespace
50
51
52namespace Utility {
53
54
55bool
56IsReadOnlyVolume(dev_t device)
57{
58	BVolume volume;
59	status_t status = volume.SetTo(device);
60	if (status != B_OK) {
61		fprintf(stderr, "Failed to get BVolume for device %" B_PRIdDEV
62			": %s\n", device, strerror(status));
63		return false;
64	}
65
66	BDiskDeviceRoster roster;
67	BDiskDevice diskDevice;
68	BPartition* partition;
69	status = roster.FindPartitionByVolume(volume, &diskDevice, &partition);
70	if (status != B_OK) {
71		fprintf(stderr, "Failed to get partition for device %" B_PRIdDEV
72			": %s\n", device, strerror(status));
73		return false;
74	}
75
76	return partition->IsReadOnly();
77}
78
79
80bool
81IsReadOnlyVolume(const char* path)
82{
83	return IsReadOnlyVolume(dev_for_path(path));
84}
85
86
87status_t
88BlockMedia(const char* path, bool block)
89{
90	return IssueDeviceCommand(path, B_SCSI_PREVENT_ALLOW, &block,
91		sizeof(block));
92}
93
94
95status_t
96EjectMedia(const char* path)
97{
98	return IssueDeviceCommand(path, B_EJECT_DEVICE, NULL, 0);
99}
100
101
102BString
103TranslatePath(const char* originalPath)
104{
105	BString path = originalPath;
106
107	// TODO: get actual home directory!
108	const char* home = "/boot/home";
109	path.ReplaceAll("$HOME", home);
110	path.ReplaceAll("${HOME}", home);
111	if (path.StartsWith("~/"))
112		path.ReplaceFirst("~", home);
113
114	return path;
115}
116
117
118}	// namespace Utility
119