1 /// Helper to run tape commands as root. Currently only required
2 /// to read and set the encryption key.
4 /// This command can use STDIN as tape device handle.
7 use std
::os
::unix
::io
::{AsRawFd, FromRawFd}
;
9 use anyhow
::{bail, Error}
;
10 use serde_json
::Value
;
22 Fingerprint
, LTO_DRIVE_PATH_SCHEMA
, DRIVE_NAME_SCHEMA
, TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
23 MEDIA_SET_UUID_SCHEMA
, LtoTapeDrive
,
26 use pbs_tape
::linux_list_drives
::{open_lto_tape_device, check_tape_is_lto_tape_device}
;
38 fn get_tape_handle(param
: &Value
) -> Result
<LtoTapeHandle
, Error
> {
40 let handle
= if let Some(name
) = param
["drive"].as_str() {
41 let (config
, _digest
) = pbs_config
::drive
::config()?
;
42 let drive
: LtoTapeDrive
= config
.lookup("lto", &name
)?
;
43 eprintln
!("using device {}", drive
.path
);
44 open_lto_tape_drive(&drive
)?
45 } else if let Some(device
) = param
["device"].as_str() {
46 eprintln
!("using device {}", device
);
47 LtoTapeHandle
::new(open_lto_tape_device(&device
)?
)?
48 } else if let Some(true) = param
["stdin"].as_bool() {
49 eprintln
!("using stdin");
50 let fd
= std
::io
::stdin().as_raw_fd();
51 let file
= unsafe { File::from_raw_fd(fd) }
;
52 check_tape_is_lto_tape_device(&file
)?
;
53 LtoTapeHandle
::new(file
)?
54 } else if let Ok(name
) = std
::env
::var("PROXMOX_TAPE_DRIVE") {
55 let (config
, _digest
) = pbs_config
::drive
::config()?
;
56 let drive
: LtoTapeDrive
= config
.lookup("lto", &name
)?
;
57 eprintln
!("using device {}", drive
.path
);
58 open_lto_tape_drive(&drive
)?
60 let (config
, _digest
) = pbs_config
::drive
::config()?
;
62 let mut drive_names
= Vec
::new();
63 for (name
, (section_type
, _
)) in config
.sections
.iter() {
64 if section_type
!= "lto" { continue; }
65 drive_names
.push(name
);
68 if drive_names
.len() == 1 {
69 let name
= drive_names
[0];
70 let drive
: LtoTapeDrive
= config
.lookup("lto", &name
)?
;
71 eprintln
!("using device {}", drive
.path
);
72 open_lto_tape_drive(&drive
)?
74 bail
!("no drive/device specified");
85 schema
: TAPE_ENCRYPTION_KEY_FINGERPRINT_SCHEMA
,
89 schema
: MEDIA_SET_UUID_SCHEMA
,
93 schema
: DRIVE_NAME_SCHEMA
,
97 schema
: LTO_DRIVE_PATH_SCHEMA
,
101 description
: "Use standard input as device handle.",
108 /// Set or clear encryption key
110 fingerprint
: Option
<Fingerprint
>,
113 ) -> Result
<(), Error
> {
115 let result
= proxmox
::try_block
!({
116 let mut handle
= get_tape_handle(¶m
)?
;
118 match (fingerprint
, uuid
) {
119 (Some(fingerprint
), Some(uuid
)) => {
120 handle
.set_encryption(Some((fingerprint
, uuid
)))?
;
123 bail
!("missing media set uuid");
126 handle
.set_encryption(None
)?
;
131 }).map_err(|err
: Error
| err
.to_string());
133 println
!("{}", serde_json
::to_string_pretty(&result
)?
);
138 fn main() -> Result
<(), Error
> {
140 // check if we are user root or backup
141 let backup_uid
= pbs_config
::backup_user()?
.uid
;
142 let backup_gid
= pbs_config
::backup_group()?
.gid
;
143 let running_uid
= nix
::unistd
::Uid
::current();
144 let running_gid
= nix
::unistd
::Gid
::current();
146 let effective_uid
= nix
::unistd
::Uid
::effective();
147 if !effective_uid
.is_root() {
148 bail
!("this program needs to be run with setuid root");
151 if !running_uid
.is_root() && (running_uid
!= backup_uid
|| running_gid
!= backup_gid
) {
153 "Not running as backup user or group (got uid {} gid {})",
154 running_uid
, running_gid
,
158 let cmd_def
= CliCommandMap
::new()
161 CliCommand
::new(&API_METHOD_SET_ENCRYPTION
)
165 let mut rpcenv
= CliEnvironment
::new();
166 rpcenv
.set_auth_id(Some(String
::from("root@pam")));
168 run_cli_command(cmd_def
, rpcenv
, None
);