source: mainline/uspace/app/vol/vol.c@ 4285f384

Last change on this file since 4285f384 was 4285f384, checked in by Jiri Svoboda <jiri@…>, 4 months ago

Allow physically ejecting CD-ROM using vol eject -s

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup vol
30 * @{
31 */
32/** @file Volume administration (interface to volsrv).
33 */
34
35#include <errno.h>
36#include <io/table.h>
37#include <loc.h>
38#include <stdbool.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <str.h>
42#include <vfs/vfs.h>
43#include <vol.h>
44
45#define NAME "vol"
46
47typedef enum {
48 vcmd_eject,
49 vcmd_insert,
50 vcmd_insert_by_path,
51 vcmd_help,
52 vcmd_list,
53 vcmd_cfglist,
54} vol_cmd_t;
55
56/** Find volume by current mount point. */
57static errno_t vol_cmd_part_by_mp(vol_t *vol, const char *mp,
58 service_id_t *rid)
59{
60 vol_part_info_t vinfo;
61 service_id_t *part_ids = NULL;
62 char *canon_mp_buf = NULL;
63 char *canon_mp;
64 size_t nparts;
65 size_t i;
66 errno_t rc;
67
68 canon_mp_buf = str_dup(mp);
69 if (canon_mp_buf == NULL) {
70 printf("Out of memory.\n");
71 rc = ENOMEM;
72 goto out;
73 }
74
75 canon_mp = vfs_absolutize(canon_mp_buf, NULL);
76 if (canon_mp == NULL) {
77 printf("Invalid volume path '%s'.\n", mp);
78 rc = EINVAL;
79 goto out;
80 }
81
82 rc = vol_get_parts(vol, &part_ids, &nparts);
83 if (rc != EOK) {
84 printf("Error getting list of volumes.\n");
85 goto out;
86 }
87
88 for (i = 0; i < nparts; i++) {
89 rc = vol_part_info(vol, part_ids[i], &vinfo);
90 if (rc != EOK) {
91 printf("Error getting volume information.\n");
92 rc = EIO;
93 goto out;
94 }
95
96 if (str_cmp(vinfo.cur_mp, canon_mp) == 0) {
97 *rid = part_ids[i];
98 rc = EOK;
99 goto out;
100 }
101 }
102
103 rc = ENOENT;
104out:
105 free(part_ids);
106 free(canon_mp_buf);
107 return rc;
108}
109
110static errno_t vol_cmd_eject(const char *volspec, bool physical)
111{
112 vol_t *vol = NULL;
113 service_id_t part_id;
114 errno_t rc;
115
116 rc = vol_create(&vol);
117 if (rc != EOK) {
118 printf("Error contacting volume service.\n");
119 goto out;
120 }
121
122 rc = vol_cmd_part_by_mp(vol, volspec, &part_id);
123 if (rc != EOK) {
124 printf("Error looking up volume '%s'.\n", volspec);
125 goto out;
126 }
127
128 rc = vol_part_eject(vol, part_id, physical ? vef_physical :
129 vef_none);
130 if (rc != EOK) {
131 printf("Error ejecting volume.\n");
132 goto out;
133 }
134
135 rc = EOK;
136out:
137 vol_destroy(vol);
138 return rc;
139}
140
141static errno_t vol_cmd_insert(const char *volspec)
142{
143 vol_t *vol = NULL;
144 service_id_t svc_id;
145 errno_t rc;
146
147 rc = loc_service_get_id(volspec, &svc_id, 0);
148 if (rc != EOK) {
149 printf("Error looking up service '%s'.\n", volspec);
150 goto out;
151 }
152
153 rc = vol_create(&vol);
154 if (rc != EOK) {
155 printf("Error contacting volume service.\n");
156 goto out;
157 }
158
159 rc = vol_part_insert(vol, svc_id);
160 if (rc != EOK) {
161 printf("Error inserting volume.\n");
162 goto out;
163 }
164
165 rc = EOK;
166out:
167 vol_destroy(vol);
168 return rc;
169}
170
171static errno_t vol_cmd_insert_by_path(const char *volspec)
172{
173 vol_t *vol = NULL;
174 errno_t rc;
175
176 rc = vol_create(&vol);
177 if (rc != EOK) {
178 printf("Error contacting volume service.\n");
179 goto out;
180 }
181
182 rc = vol_part_insert_by_path(vol, volspec);
183 if (rc != EOK) {
184 printf("Error inserting volume.\n");
185 goto out;
186 }
187
188 rc = EOK;
189out:
190 vol_destroy(vol);
191 return rc;
192}
193
194static errno_t vol_cmd_list(void)
195{
196 vol_t *vol = NULL;
197 vol_part_info_t vinfo;
198 service_id_t *part_ids = NULL;
199 char *svc_name;
200 char *sfstype;
201 size_t nparts;
202 size_t i;
203 table_t *table = NULL;
204 errno_t rc;
205
206 rc = vol_create(&vol);
207 if (rc != EOK) {
208 printf("Error contacting volume service.\n");
209 goto out;
210 }
211
212 rc = vol_get_parts(vol, &part_ids, &nparts);
213 if (rc != EOK) {
214 printf("Error getting list of volumes.\n");
215 goto out;
216 }
217
218 rc = table_create(&table);
219 if (rc != EOK) {
220 printf("Out of memory.\n");
221 goto out;
222 }
223
224 table_header_row(table);
225 table_printf(table, "Volume Name\t" "Resource\t" "Content\t" "Auto\t"
226 "Mounted at\n");
227
228 for (i = 0; i < nparts; i++) {
229 rc = vol_part_info(vol, part_ids[i], &vinfo);
230 if (rc != EOK) {
231 printf("Error getting volume information.\n");
232 return EIO;
233 }
234
235 rc = loc_service_get_name(part_ids[i], &svc_name);
236 if (rc != EOK) {
237 printf("Error getting service name.\n");
238 return EIO;
239 }
240
241 rc = vol_pcnt_fs_format(vinfo.pcnt, vinfo.fstype, &sfstype);
242 if (rc != EOK) {
243 printf("Out of memory.\n");
244 free(svc_name);
245 return ENOMEM;
246 }
247
248 table_printf(table, "%s\t" "%s\t" "%s\t" "%s\t" "%s\n",
249 vinfo.label, svc_name, sfstype,
250 vinfo.cur_mp_auto ? "Yes" : "", vinfo.cur_mp);
251
252 free(svc_name);
253 free(sfstype);
254 svc_name = NULL;
255 }
256
257 rc = table_print_out(table, stdout);
258 if (rc != EOK)
259 printf("Error printing table.\n");
260out:
261 table_destroy(table);
262 vol_destroy(vol);
263 free(part_ids);
264
265 return rc;
266}
267
268/** List volume configuration entries.
269 *
270 * @return EOK on success or an error code
271 */
272static errno_t vol_cmd_cfglist(void)
273{
274 vol_t *vol = NULL;
275 vol_info_t vinfo;
276 volume_id_t *volume_ids = NULL;
277 size_t nvols;
278 size_t i;
279 table_t *table = NULL;
280 errno_t rc;
281
282 rc = vol_create(&vol);
283 if (rc != EOK) {
284 printf("Error contacting volume service.\n");
285 goto out;
286 }
287
288 rc = vol_get_volumes(vol, &volume_ids, &nvols);
289 if (rc != EOK) {
290 printf("Error getting list of volumes.\n");
291 goto out;
292 }
293
294 rc = table_create(&table);
295 if (rc != EOK) {
296 printf("Out of memory.\n");
297 goto out;
298 }
299
300 table_header_row(table);
301 table_printf(table, "Volume Name\t" "Path\n");
302
303 for (i = 0; i < nvols; i++) {
304 rc = vol_info(vol, volume_ids[i], &vinfo);
305 if (rc != EOK) {
306 printf("Error getting volume information.\n");
307 return EIO;
308 }
309
310 table_printf(table, "%s\t" "%s\n", vinfo.label, vinfo.path);
311 }
312
313 rc = table_print_out(table, stdout);
314 if (rc != EOK)
315 printf("Error printing table.\n");
316out:
317 table_destroy(table);
318 vol_destroy(vol);
319 free(volume_ids);
320
321 return rc;
322}
323
324static void print_syntax(void)
325{
326 printf("Syntax:\n");
327 printf(" %s List present volumes\n", NAME);
328 printf(" %s -c List volume configuration entries\n", NAME);
329 printf(" %s -h Print help\n", NAME);
330 printf(" %s eject [-s] <mp> Eject volume mounted in a directory\n", NAME);
331 printf(" -s to eject physically\n");
332 printf(" %s insert <svc> Insert volume based on service identifier\n", NAME);
333 printf(" %s insert -p <mp> Insert volume based on filesystem path\n", NAME);
334}
335
336int main(int argc, char *argv[])
337{
338 char *cmd;
339 char *volspec;
340 vol_cmd_t vcmd;
341 bool physical = false;
342 int i;
343 errno_t rc = EINVAL;
344
345 if (argc < 2) {
346 vcmd = vcmd_list;
347 i = 1;
348 } else {
349 cmd = argv[1];
350 i = 2;
351 if (str_cmp(cmd, "-h") == 0) {
352 vcmd = vcmd_help;
353 } else if (str_cmp(cmd, "-c") == 0) {
354 vcmd = vcmd_cfglist;
355 } else if (str_cmp(cmd, "eject") == 0) {
356 vcmd = vcmd_eject;
357 if (str_cmp(argv[i], "-s") == 0) {
358 physical = true;
359 ++i;
360 }
361
362 if (argc <= i) {
363 printf("Parameter missing.\n");
364 goto syntax_error;
365 }
366 volspec = argv[i++];
367 } else if (str_cmp(cmd, "insert") == 0) {
368 if (str_cmp(argv[i], "-p") == 0) {
369 vcmd = vcmd_insert_by_path;
370 ++i;
371 } else {
372 vcmd = vcmd_insert;
373 }
374
375 if (argc <= i) {
376 printf("Parameter missing.\n");
377 goto syntax_error;
378 }
379 volspec = argv[i++];
380 } else {
381 printf("Invalid sub-command '%s'.\n", cmd);
382 goto syntax_error;
383 }
384 }
385
386 if (argc > i) {
387 printf("Unexpected argument '%s'.\n", argv[i]);
388 goto syntax_error;
389 }
390
391 switch (vcmd) {
392 case vcmd_eject:
393 rc = vol_cmd_eject(volspec, physical);
394 break;
395 case vcmd_insert:
396 rc = vol_cmd_insert(volspec);
397 break;
398 case vcmd_insert_by_path:
399 rc = vol_cmd_insert_by_path(volspec);
400 break;
401 case vcmd_help:
402 print_syntax();
403 rc = EOK;
404 break;
405 case vcmd_list:
406 rc = vol_cmd_list();
407 break;
408 case vcmd_cfglist:
409 rc = vol_cmd_cfglist();
410 break;
411 }
412
413 if (rc != EOK)
414 return 1;
415
416 return 0;
417
418syntax_error:
419 printf("Use %s -h to get help.\n", NAME);
420 return 1;
421}
422
423/** @}
424 */
Note: See TracBrowser for help on using the repository browser.