xref: /aosp_15_r20/external/sg3_utils/src/sg_prevent.c (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
1 /*
2  * Copyright (c) 2004-2022 Douglas Gilbert.
3  * All rights reserved.
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the BSD_LICENSE file.
6  *
7  * SPDX-License-Identifier: BSD-2-Clause
8  */
9 
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <stdbool.h>
16 #include <string.h>
17 #include <getopt.h>
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 #include "sg_lib.h"
23 #include "sg_cmds_basic.h"
24 #include "sg_pr2serr.h"
25 
26 /* A utility program originally written for the Linux OS SCSI subsystem.
27  *
28  * This program issues the SCSI PREVENT ALLOW MEDIUM REMOVAL command to the
29  * given SCSI device.
30  */
31 
32 static const char * version_str = "1.13 20220826";
33 
34 #define ME "sg_prevent: "
35 
36 
37 static struct option long_options[] = {
38     {"allow", no_argument, 0, 'a'},
39     {"help", no_argument, 0, 'h'},
40     {"prevent", required_argument, 0, 'p'},
41     {"verbose", no_argument, 0, 'v'},
42     {"version", no_argument, 0, 'V'},
43     {0, 0, 0, 0},
44 };
45 
46 
47 static void
usage()48 usage()
49 {
50     pr2serr("Usage: "
51             "sg_prevent [--allow] [--help] [--prevent=PC] [--verbose] "
52             "[--version]\n"
53             "                  DEVICE\n"
54             "  where:\n"
55             "    --allow|-a            allow media removal\n"
56             "    --help|-h             print usage message then exit\n"
57             "    --prevent=PC|-p PC    prevent code value (def: 1 -> "
58             "prevent)\n"
59             "                            0 -> allow, 1 -> prevent\n"
60             "                            2 -> persistent allow, 3 -> "
61             "persistent prevent\n"
62             "    --verbose|-v          increase verbosity\n"
63             "    --version|-V          print version string and exit\n\n"
64             "Performs a SCSI PREVENT ALLOW MEDIUM REMOVAL command\n");
65 
66 }
67 
68 int
main(int argc,char * argv[])69 main(int argc, char * argv[])
70 {
71     bool allow = false;
72     bool verbose_given = false;
73     bool version_given = false;
74     int sg_fd, res, c;
75     int prevent = -1;
76     int verbose = 0;
77     const char * device_name = NULL;
78     int ret = 0;
79 
80     while (1) {
81         int option_index = 0;
82 
83         c = getopt_long(argc, argv, "ahp:vV", long_options,
84                         &option_index);
85         if (c == -1)
86             break;
87 
88         switch (c) {
89         case 'a':
90             allow = true;
91             break;
92         case 'h':
93         case '?':
94             usage();
95             return 0;
96         case 'p':
97             prevent = sg_get_num(optarg);
98             if ((prevent < 0) || (prevent > 3)) {
99                 pr2serr("bad argument to '--prevent'\n");
100                 return SG_LIB_SYNTAX_ERROR;
101             }
102             break;
103         case 'v':
104             verbose_given = true;
105             ++verbose;
106             break;
107         case 'V':
108             version_given = true;
109             break;
110         default:
111             pr2serr("unrecognised option code 0x%x ??\n", c);
112             usage();
113             return SG_LIB_SYNTAX_ERROR;
114         }
115     }
116     if (optind < argc) {
117         if (NULL == device_name) {
118             device_name = argv[optind];
119             ++optind;
120         }
121         if (optind < argc) {
122             for (; optind < argc; ++optind)
123                 pr2serr("Unexpected extra argument: %s\n", argv[optind]);
124             usage();
125             return SG_LIB_SYNTAX_ERROR;
126         }
127     }
128 #ifdef DEBUG
129     pr2serr("In DEBUG mode, ");
130     if (verbose_given && version_given) {
131         pr2serr("but override: '-vV' given, zero verbose and continue\n");
132         verbose_given = false;
133         version_given = false;
134         verbose = 0;
135     } else if (! verbose_given) {
136         pr2serr("set '-vv'\n");
137         verbose = 2;
138     } else
139         pr2serr("keep verbose=%d\n", verbose);
140 #else
141     if (verbose_given && version_given)
142         pr2serr("Not in DEBUG mode, so '-vV' has no special action\n");
143 #endif
144     if (version_given) {
145         pr2serr(ME "version: %s\n", version_str);
146         return 0;
147     }
148 
149     if (NULL == device_name) {
150         pr2serr("missing device name!\n");
151         usage();
152         return SG_LIB_SYNTAX_ERROR;
153     }
154     if (allow && (prevent >= 0)) {
155         pr2serr("can't give both '--allow' and '--prevent='\n");
156         usage();
157         return SG_LIB_CONTRADICT;
158     }
159     if (allow)
160         prevent = 0;
161     else if (prevent < 0)
162         prevent = 1;    /* default is to prevent, as utility name suggests */
163 
164     sg_fd = sg_cmds_open_device(device_name, false /* rw */, verbose);
165     if (sg_fd < 0) {
166         if (verbose)
167             pr2serr(ME "open error: %s: %s\n", device_name,
168                     safe_strerror(-sg_fd));
169         ret = sg_convert_errno(-sg_fd);
170         goto fini;
171     }
172     res = sg_ll_prevent_allow(sg_fd, prevent, true, verbose);
173     ret = res;
174     if (res) {
175         char b[80];
176 
177         sg_get_category_sense_str(res, sizeof(b), b, verbose);
178         pr2serr("Prevent allow medium removal: %s\n", b);
179     }
180     res = sg_cmds_close_device(sg_fd);
181     if (res < 0) {
182         pr2serr("close error: %s\n", safe_strerror(-res));
183         if (0 == ret)
184             ret = sg_convert_errno(-res);
185     }
186 fini:
187     if (0 == verbose) {
188         if (! sg_if_can2stderr("sg_prevent failed: ", ret))
189             pr2serr("Some error occurred, try again with '-v' "
190                     "or '-vv' for more information\n");
191     }
192     return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
193 }
194