]> git.proxmox.com Git - proxmox-backup.git/blob - src/bin/sg-tape-cmd.rs
proxy: expose qrcodejs
[proxmox-backup.git] / src / bin / sg-tape-cmd.rs
1 /// Tape command implemented using scsi-generic raw commands
2 ///
3 /// SCSI-generic command needs root priviledges, so this binary need
4 /// to be setuid root.
5 ///
6 /// This command can use STDIN as tape device handle.
7
8 use std::fs::File;
9 use std::os::unix::io::{AsRawFd, FromRawFd};
10
11 use anyhow::{bail, Error};
12
13 use proxmox::{
14 api::{
15 api,
16 cli::*,
17 RpcEnvironment,
18 },
19 };
20
21 use proxmox_backup::{
22 api2::types::{
23 LINUX_DRIVE_PATH_SCHEMA,
24 },
25 tape::{
26 TapeDriver,
27 linux_tape::{
28 LinuxTapeHandle,
29 open_linux_tape_device,
30 check_tape_is_linux_tape_device,
31 },
32 },
33 };
34
35 fn get_tape_handle(device: Option<String>) -> Result<LinuxTapeHandle, Error> {
36
37 let file = if let Some(device) = device {
38 open_linux_tape_device(&device)?
39 } else {
40 let fd = std::io::stdin().as_raw_fd();
41 let file = unsafe { File::from_raw_fd(fd) };
42 check_tape_is_linux_tape_device(&file)?;
43 file
44 };
45 Ok(LinuxTapeHandle::new(file))
46 }
47
48 #[api(
49 input: {
50 properties: {
51 device: {
52 schema: LINUX_DRIVE_PATH_SCHEMA,
53 optional: true,
54 },
55 },
56 },
57 )]
58 /// Tape/Media Status
59 fn status(
60 device: Option<String>,
61 ) -> Result<(), Error> {
62
63 let result = proxmox::try_block!({
64 let mut handle = get_tape_handle(device)?;
65 handle.get_drive_and_media_status()
66 }).map_err(|err: Error| err.to_string());
67
68 println!("{}", serde_json::to_string_pretty(&result)?);
69
70 Ok(())
71 }
72
73 #[api(
74 input: {
75 properties: {
76 device: {
77 schema: LINUX_DRIVE_PATH_SCHEMA,
78 optional: true,
79 },
80 },
81 },
82 )]
83 /// Read Cartridge Memory (Medium auxiliary memory attributes)
84 fn cartridge_memory(
85 device: Option<String>,
86 ) -> Result<(), Error> {
87
88 let result = proxmox::try_block!({
89 let mut handle = get_tape_handle(device)?;
90
91 handle.cartridge_memory()
92 }).map_err(|err| err.to_string());
93
94 println!("{}", serde_json::to_string_pretty(&result)?);
95
96 Ok(())
97 }
98
99 #[api(
100 input: {
101 properties: {
102 device: {
103 schema: LINUX_DRIVE_PATH_SCHEMA,
104 optional: true,
105 },
106 },
107 },
108 )]
109 /// Read Tape Alert Flags
110 fn tape_alert_flags(
111 device: Option<String>,
112 ) -> Result<(), Error> {
113
114 let result = proxmox::try_block!({
115 let mut handle = get_tape_handle(device)?;
116
117 let flags = handle.tape_alert_flags()?;
118 Ok(flags.bits())
119 }).map_err(|err: Error| err.to_string());
120
121 println!("{}", serde_json::to_string_pretty(&result)?);
122
123 Ok(())
124 }
125
126 #[api(
127 input: {
128 properties: {
129 device: {
130 schema: LINUX_DRIVE_PATH_SCHEMA,
131 optional: true,
132 },
133 },
134 },
135 )]
136 /// Read volume statistics
137 fn volume_statistics(
138 device: Option<String>,
139 ) -> Result<(), Error> {
140
141 let result = proxmox::try_block!({
142 let mut handle = get_tape_handle(device)?;
143 handle.volume_statistics()
144 }).map_err(|err: Error| err.to_string());
145
146 println!("{}", serde_json::to_string_pretty(&result)?);
147
148 Ok(())
149 }
150
151 fn main() -> Result<(), Error> {
152
153 // check if we are user root or backup
154 let backup_uid = proxmox_backup::backup::backup_user()?.uid;
155 let backup_gid = proxmox_backup::backup::backup_group()?.gid;
156 let running_uid = nix::unistd::Uid::current();
157 let running_gid = nix::unistd::Gid::current();
158
159 let effective_uid = nix::unistd::Uid::effective();
160 if !effective_uid.is_root() {
161 bail!("this program needs to be run with setuid root");
162 }
163
164 if !running_uid.is_root() {
165 if running_uid != backup_uid || running_gid != backup_gid {
166 bail!(
167 "Not running as backup user or group (got uid {} gid {})",
168 running_uid, running_gid,
169 );
170 }
171 }
172
173 let cmd_def = CliCommandMap::new()
174 .insert(
175 "status",
176 CliCommand::new(&API_METHOD_STATUS)
177 )
178 .insert(
179 "cartridge-memory",
180 CliCommand::new(&API_METHOD_CARTRIDGE_MEMORY)
181 )
182 .insert(
183 "tape-alert-flags",
184 CliCommand::new(&API_METHOD_TAPE_ALERT_FLAGS)
185 )
186 .insert(
187 "volume-statistics",
188 CliCommand::new(&API_METHOD_VOLUME_STATISTICS)
189 )
190 ;
191
192 let mut rpcenv = CliEnvironment::new();
193 rpcenv.set_auth_id(Some(String::from("root@pam")));
194
195 run_cli_command(cmd_def, rpcenv, None);
196
197 Ok(())
198 }