1 /***************************************************************************
2 *
3 * devinfo_storage.c : storage devices
4 *
5 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 **************************************************************************/
10
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <strings.h>
18 #include <ctype.h>
19 #include <libdevinfo.h>
20 #include <sys/types.h>
21 #include <sys/mkdev.h>
22 #include <sys/stat.h>
23 #include <sys/mntent.h>
24 #include <sys/mnttab.h>
25
26 #include "../osspec.h"
27 #include "../logger.h"
28 #include "../hald.h"
29 #include "../hald_dbus.h"
30 #include "../device_info.h"
31 #include "../util.h"
32 #include "../hald_runner.h"
33 #include "hotplug.h"
34 #include "devinfo.h"
35 #include "devinfo_misc.h"
36 #include "devinfo_storage.h"
37 #include "osspec_solaris.h"
38
39 #ifdef sparc
40 #define WHOLE_DISK "s2"
41 #else
42 #define WHOLE_DISK "p0"
43 #endif
44
45 /* some devices,especially CDROMs, may take a while to be probed (values in ms) */
46 #define DEVINFO_PROBE_STORAGE_TIMEOUT 60000
47 #define DEVINFO_PROBE_VOLUME_TIMEOUT 60000
48
49 typedef struct devinfo_storage_minor {
50 char *devpath;
51 char *devlink;
52 char *slice;
53 dev_t dev;
54 int dosnum; /* dos disk number or -1 */
55 } devinfo_storage_minor_t;
56
57 HalDevice *devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
58 static HalDevice *devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path);
59 static HalDevice *devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path);
60 static HalDevice *devinfo_ide_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
61 HalDevice *devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
62 static HalDevice *devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
63 HalDevice *devinfo_pcata_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
64 static HalDevice *devinfo_pcata_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
65 HalDevice *devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
66 static HalDevice *devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
67 HalDevice *devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
68 static void devinfo_floppy_add_volume(HalDevice *parent, di_node_t node);
69 static HalDevice *devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
70 static void devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev);
71 static void devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean);
72 static struct devinfo_storage_minor *devinfo_storage_new_minor(char *maindev_path, char *slice,
73 char *devlink, dev_t dev, int dosnum);
74 static void devinfo_storage_free_minor(struct devinfo_storage_minor *m);
75 HalDevice *devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m);
76 static void devinfo_volume_preprobing_done(HalDevice *d, gpointer userdata1, gpointer userdata2);
77 static void devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
78 static void devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token);
79 static void devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2);
80 const gchar *devinfo_volume_get_prober (HalDevice *d, int *timeout);
81 const gchar *devinfo_storage_get_prober (HalDevice *d, int *timeout);
82
83 static char *devinfo_scsi_dtype2str(int dtype);
84 static char *devinfo_volume_get_slice_name (char *devlink);
85 static gboolean dos_to_dev(char *path, char **devpath, int *partnum);
86 static gboolean is_dos_path(char *path, int *partnum);
87
88 static void devinfo_storage_set_nicknames (HalDevice *d);
89
90 DevinfoDevHandler devinfo_ide_handler = {
91 devinfo_ide_add,
92 NULL,
93 NULL,
94 NULL,
95 NULL,
96 NULL
97 };
98 DevinfoDevHandler devinfo_scsi_handler = {
99 devinfo_scsi_add,
100 NULL,
101 NULL,
102 NULL,
103 NULL,
104 NULL
105 };
106 DevinfoDevHandler devinfo_pcata_handler = {
107 devinfo_pcata_add,
108 NULL,
109 NULL,
110 NULL,
111 NULL,
112 NULL
113 };
114 DevinfoDevHandler devinfo_blkdev_handler = {
115 devinfo_blkdev_add,
116 NULL,
117 NULL,
118 NULL,
119 NULL,
120 NULL
121 };
122 DevinfoDevHandler devinfo_floppy_handler = {
123 devinfo_floppy_add,
124 NULL,
125 NULL,
126 NULL,
127 NULL,
128 NULL
129 };
130 DevinfoDevHandler devinfo_lofi_handler = {
131 devinfo_lofi_add,
132 NULL,
133 NULL,
134 NULL,
135 NULL,
136 NULL
137 };
138 DevinfoDevHandler devinfo_storage_handler = {
139 NULL,
140 NULL,
141 devinfo_storage_hotplug_begin_add,
142 NULL,
143 devinfo_storage_probing_done,
144 devinfo_storage_get_prober
145 };
146 DevinfoDevHandler devinfo_volume_handler = {
147 NULL,
148 NULL,
149 devinfo_volume_hotplug_begin_add,
150 NULL,
151 NULL,
152 devinfo_volume_get_prober
153 };
154
155 /* IDE */
156
157 HalDevice *
devinfo_ide_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)158 devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
159 {
160 char *s;
161
162 if ((device_type != NULL) && (strcmp(device_type, "ide") == 0)) {
163 return (devinfo_ide_host_add(parent, node, devfs_path));
164 }
165
166 if ((di_prop_lookup_strings (DDI_DEV_T_ANY, node, "class", &s) > 0) &&
167 (strcmp (s, "dada") == 0)) {
168 return (devinfo_ide_device_add(parent, node, devfs_path));
169 }
170
171 return (NULL);
172 }
173
174 static HalDevice *
devinfo_ide_host_add(HalDevice * parent,di_node_t node,char * devfs_path)175 devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path)
176 {
177 HalDevice *d;
178
179 d = hal_device_new ();
180
181 devinfo_set_default_properties (d, parent, node, devfs_path);
182 hal_device_property_set_string (d, "info.product", "IDE host controller");
183 hal_device_property_set_string (d, "info.subsystem", "ide_host");
184 hal_device_property_set_int (d, "ide_host.number", 0); /* XXX */
185
186 devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
187
188 return (d);
189 }
190
191 static HalDevice *
devinfo_ide_device_add(HalDevice * parent,di_node_t node,char * devfs_path)192 devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path)
193 {
194 HalDevice *d;
195
196 d = hal_device_new();
197
198 devinfo_set_default_properties (d, parent, node, devfs_path);
199 hal_device_property_set_string (parent, "info.product", "IDE device");
200 hal_device_property_set_string (parent, "info.subsystem", "ide");
201 hal_device_property_set_int (parent, "ide.host", 0); /* XXX */
202 hal_device_property_set_int (parent, "ide.channel", 0);
203
204 devinfo_add_enqueue (d, devfs_path, &devinfo_ide_handler);
205
206 return (devinfo_ide_storage_add (d, node, devfs_path));
207 }
208
209 static HalDevice *
devinfo_ide_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)210 devinfo_ide_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
211 {
212 HalDevice *d;
213 char *s;
214 int *i;
215 char *driver_name;
216 char udi[HAL_PATH_MAX];
217
218 if ((driver_name = di_driver_name (node)) == NULL) {
219 return (NULL);
220 }
221
222 d = hal_device_new ();
223
224 devinfo_set_default_properties (d, parent, node, devfs_path);
225 hal_device_property_set_string (d, "info.category", "storage");
226
227 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
228 "%s/%s%d", hal_device_get_udi (parent), driver_name, di_instance (node));
229 hal_device_set_udi (d, udi);
230 hal_device_property_set_string (d, "info.udi", udi);
231 PROP_STR(d, node, s, "devid", "info.product");
232
233 hal_device_add_capability (d, "storage");
234 hal_device_property_set_string (d, "storage.bus", "ide");
235 hal_device_property_set_int (d, "storage.lun", 0);
236 hal_device_property_set_string (d, "storage.drive_type", "disk");
237
238 PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
239 PROP_BOOL(d, node, i, "removable-media", "storage.removable");
240
241 hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
242
243 /* XXX */
244 hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
245
246 hal_device_add_capability (d, "block");
247
248 devinfo_storage_minors (d, node, (char *)devfs_path, FALSE);
249
250 return (d);
251 }
252
253 /* SCSI */
254
255 HalDevice *
devinfo_scsi_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)256 devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
257 {
258 int *i;
259 char *driver_name;
260 HalDevice *d;
261 char udi[HAL_PATH_MAX];
262
263 driver_name = di_driver_name (node);
264 if ((driver_name == NULL) || (strcmp (driver_name, "sd") != 0)) {
265 return (NULL);
266 }
267
268 d = hal_device_new ();
269
270 devinfo_set_default_properties (d, parent, node, devfs_path);
271 hal_device_property_set_string (d, "info.subsystem", "scsi");
272
273 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
274 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
275 hal_device_set_udi (d, udi);
276 hal_device_property_set_string (d, "info.udi", udi);
277
278 hal_device_property_set_int (d, "scsi.host",
279 hal_device_property_get_int (parent, "scsi_host.host"));
280 hal_device_property_set_int (d, "scsi.bus", 0);
281 PROP_INT(d, node, i, "target", "scsi.target");
282 PROP_INT(d, node, i, "lun", "scsi.lun");
283 hal_device_property_set_string (d, "info.product", "SCSI Device");
284
285 devinfo_add_enqueue (d, devfs_path, &devinfo_scsi_handler);
286
287 return (devinfo_scsi_storage_add (d, node, devfs_path));
288 }
289
290 static HalDevice *
devinfo_scsi_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)291 devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
292 {
293 HalDevice *d;
294 int *i;
295 char *s;
296 char udi[HAL_PATH_MAX];
297
298 d = hal_device_new ();
299
300 devinfo_set_default_properties (d, parent, node, devfs_path);
301 hal_device_property_set_string (d, "info.category", "storage");
302
303 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
304 "%s/sd%d", hal_device_get_udi (parent), di_instance (node));
305 hal_device_set_udi (d, udi);
306 hal_device_property_set_string (d, "info.udi", udi);
307 PROP_STR(d, node, s, "inquiry-product-id", "info.product");
308
309 hal_device_add_capability (d, "storage");
310
311 hal_device_property_set_int (d, "storage.lun",
312 hal_device_property_get_int (parent, "scsi.lun"));
313 PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
314 PROP_BOOL(d, node, i, "removable-media", "storage.removable");
315 hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
316
317 /*
318 * We have to enable polling not only for drives with removable media,
319 * but also for hotpluggable devices, because when a disk is
320 * unplugged while busy/mounted, there is not sysevent generated.
321 * Instead, the HBA driver (scsa2usb, scsa1394) will notify sd driver
322 * and the latter will report DKIO_DEV_GONE via DKIOCSTATE ioctl.
323 * So we have to enable media check so that hald-addon-storage notices
324 * the "device gone" condition and unmounts all associated volumes.
325 */
326 hal_device_property_set_bool (d, "storage.media_check_enabled",
327 ((di_prop_lookup_ints(DDI_DEV_T_ANY, node, "removable-media", &i) >= 0) ||
328 (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "hotpluggable", &i) >= 0)));
329
330 if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type",
331 &i) > 0) {
332 s = devinfo_scsi_dtype2str (*i);
333 hal_device_property_set_string (d, "storage.drive_type", s);
334
335 if (strcmp (s, "cdrom") == 0) {
336 hal_device_add_capability (d, "storage.cdrom");
337 hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
338 hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
339 }
340 }
341
342 hal_device_add_capability (d, "block");
343
344 devinfo_storage_minors (d, node, devfs_path, FALSE);
345
346 return (d);
347 }
348
349 static char *
devinfo_scsi_dtype2str(int dtype)350 devinfo_scsi_dtype2str(int dtype)
351 {
352 char *dtype2str[] = {
353 "disk" , /* DTYPE_DIRECT 0x00 */
354 "tape" , /* DTYPE_SEQUENTIAL 0x01 */
355 "printer", /* DTYPE_PRINTER 0x02 */
356 "processor", /* DTYPE_PROCESSOR 0x03 */
357 "worm" , /* DTYPE_WORM 0x04 */
358 "cdrom" , /* DTYPE_RODIRECT 0x05 */
359 "scanner", /* DTYPE_SCANNER 0x06 */
360 "cdrom" , /* DTYPE_OPTICAL 0x07 */
361 "changer", /* DTYPE_CHANGER 0x08 */
362 "comm" , /* DTYPE_COMM 0x09 */
363 "scsi" , /* DTYPE_??? 0x0A */
364 "scsi" , /* DTYPE_??? 0x0B */
365 "array_ctrl", /* DTYPE_ARRAY_CTRL 0x0C */
366 "esi" , /* DTYPE_ESI 0x0D */
367 "disk" /* DTYPE_RBC 0x0E */
368 };
369
370 if (dtype < NELEM(dtype2str)) {
371 return (dtype2str[dtype]);
372 } else {
373 return ("scsi");
374 }
375
376 }
377
378 /* PCMCIA */
379
380 HalDevice *
devinfo_pcata_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)381 devinfo_pcata_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
382 {
383 int *i;
384 char *driver_name;
385 HalDevice *d;
386 char udi[HAL_PATH_MAX];
387
388 driver_name = di_driver_name (node);
389 if ((driver_name == NULL) || (strcmp (driver_name, "pcata") != 0)) {
390 return (NULL);
391 }
392
393 d = hal_device_new ();
394
395 devinfo_set_default_properties (d, parent, node, devfs_path);
396 hal_device_property_set_string (d, "info.subsystem", "pcmcia");
397
398 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
399 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
400 hal_device_set_udi (d, udi);
401 hal_device_property_set_string (d, "info.udi", udi);
402 hal_device_property_set_string (d, "info.product", "PCMCIA Disk");
403
404 devinfo_add_enqueue (d, devfs_path, &devinfo_pcata_handler);
405
406 return (devinfo_pcata_storage_add (d, node, devfs_path));
407 }
408
409 static HalDevice *
devinfo_pcata_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)410 devinfo_pcata_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
411 {
412 HalDevice *d;
413 char *driver_name;
414 int *i;
415 char *s;
416 char udi[HAL_PATH_MAX];
417
418 d = hal_device_new ();
419
420 devinfo_set_default_properties (d, parent, node, devfs_path);
421 hal_device_property_set_string (d, "info.category", "storage");
422
423 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
424 "%s/sd%d", hal_device_get_udi (parent), di_instance (node));
425 hal_device_set_udi (d, udi);
426 hal_device_property_set_string (d, "info.udi", udi);
427
428 hal_device_add_capability (d, "storage");
429
430 hal_device_property_set_int (d, "storage.lun", 0);
431 hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
432 hal_device_property_set_bool (d, "storage.removable", FALSE);
433 hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
434 hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
435 hal_device_property_set_string (d, "storage.drive_type", "disk");
436 hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
437
438 hal_device_add_capability (d, "block");
439
440 devinfo_storage_minors (d, node, devfs_path, FALSE);
441
442 return (d);
443 }
444
445 /* blkdev */
446
447 HalDevice *
devinfo_blkdev_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)448 devinfo_blkdev_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
449 {
450 int *i;
451 char *driver_name;
452 HalDevice *d;
453 char udi[HAL_PATH_MAX];
454
455 driver_name = di_driver_name (node);
456 if ((driver_name == NULL) || (strcmp (driver_name, "blkdev") != 0)) {
457 return (NULL);
458 }
459
460 d = hal_device_new ();
461
462 devinfo_set_default_properties (d, parent, node, devfs_path);
463 hal_device_property_set_string (d, "info.subsystem", "pseudo");
464
465 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
466 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
467 hal_device_set_udi (d, udi);
468 hal_device_property_set_string (d, "info.udi", udi);
469 hal_device_property_set_string (d, "info.product", "Block Device");
470
471 devinfo_add_enqueue (d, devfs_path, &devinfo_blkdev_handler);
472
473 return (devinfo_blkdev_storage_add (d, node, devfs_path));
474 }
475
476 static HalDevice *
devinfo_blkdev_storage_add(HalDevice * parent,di_node_t node,char * devfs_path)477 devinfo_blkdev_storage_add(HalDevice *parent, di_node_t node, char *devfs_path)
478 {
479 HalDevice *d;
480 char *driver_name;
481 int *i;
482 char *s;
483 char udi[HAL_PATH_MAX];
484
485 d = hal_device_new ();
486
487 devinfo_set_default_properties (d, parent, node, devfs_path);
488 hal_device_property_set_string (d, "info.category", "storage");
489
490 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
491 "%s/blkdev%d", hal_device_get_udi (parent), di_instance (node));
492 hal_device_set_udi (d, udi);
493 hal_device_property_set_string (d, "info.udi", udi);
494
495 hal_device_add_capability (d, "storage");
496
497 hal_device_property_set_int (d, "storage.lun", 0);
498
499 PROP_BOOL(d, node, i, "hotpluggable", "storage.hotpluggable");
500 PROP_BOOL(d, node, i, "removable-media", "storage.removable");
501
502 hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
503 hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
504 hal_device_property_set_string (d, "storage.drive_type", "disk");
505
506 hal_device_add_capability (d, "block");
507
508 devinfo_storage_minors (d, node, devfs_path, FALSE);
509
510 return (d);
511 }
512
513 /* floppy */
514
515 HalDevice *
devinfo_floppy_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)516 devinfo_floppy_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
517 {
518 char *driver_name;
519 char *raw;
520 char udi[HAL_PATH_MAX];
521 di_devlink_handle_t devlink_hdl;
522 int major;
523 di_minor_t minor;
524 dev_t dev;
525 HalDevice *d = NULL;
526 char *minor_path = NULL;
527 char *devlink = NULL;
528
529 driver_name = di_driver_name (node);
530 if ((driver_name == NULL) || (strcmp (driver_name, "fd") != 0)) {
531 return (NULL);
532 }
533
534 /*
535 * The only minor node we're interested in is /dev/diskette*
536 */
537 major = di_driver_major(node);
538 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
539 return (NULL);
540 }
541 minor = DI_MINOR_NIL;
542 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
543 dev = di_minor_devt(minor);
544 if ((major != major(dev)) ||
545 (di_minor_type(minor) != DDM_MINOR) ||
546 (di_minor_spectype(minor) != S_IFBLK) ||
547 ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
548 continue;
549 }
550 if ((devlink = get_devlink(devlink_hdl, "diskette.+" , minor_path)) != NULL) {
551 break;
552 }
553 di_devfs_path_free (minor_path);
554 minor_path = NULL;
555 free(devlink);
556 devlink = NULL;
557 }
558 di_devlink_fini (&devlink_hdl);
559
560 if ((devlink == NULL) || (minor_path == NULL)) {
561 HAL_INFO (("floppy devlink not found %s", devfs_path));
562 goto out;
563 }
564
565 d = hal_device_new ();
566
567 devinfo_set_default_properties (d, parent, node, devfs_path);
568 hal_device_property_set_string (d, "info.category", "storage");
569 hal_device_add_capability (d, "storage");
570 hal_device_property_set_string (d, "storage.bus", "platform");
571 hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
572 hal_device_property_set_bool (d, "storage.removable", TRUE);
573 hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
574 hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
575 hal_device_property_set_string (d, "storage.drive_type", "floppy");
576
577 hal_device_add_capability (d, "block");
578 hal_device_property_set_bool (d, "block.is_volume", FALSE);
579 hal_device_property_set_int (d, "block.major", major(dev));
580 hal_device_property_set_int (d, "block.minor", minor(dev));
581 hal_device_property_set_string (d, "block.device", devlink);
582 raw = dsk_to_rdsk (devlink);
583 hal_device_property_set_string (d, "block.solaris.raw_device", raw);
584 free (raw);
585
586 devinfo_add_enqueue (d, devfs_path, &devinfo_storage_handler);
587
588 /* trigger initial probe-volume */
589 devinfo_floppy_add_volume(d, node);
590
591 out:
592 di_devfs_path_free (minor_path);
593 free(devlink);
594
595 return (d);
596 }
597
598 static void
devinfo_floppy_add_volume(HalDevice * parent,di_node_t node)599 devinfo_floppy_add_volume(HalDevice *parent, di_node_t node)
600 {
601 char *devlink;
602 char *devfs_path;
603 int minor, major;
604 dev_t dev;
605 struct devinfo_storage_minor *m;
606
607 devfs_path = (char *)hal_device_property_get_string (parent, "solaris.devfs_path");
608 devlink = (char *)hal_device_property_get_string (parent, "block.device");
609 major = hal_device_property_get_int (parent, "block.major");
610 minor = hal_device_property_get_int (parent, "block.minor");
611 dev = makedev (major, minor);
612
613 m = devinfo_storage_new_minor (devfs_path, WHOLE_DISK, devlink, dev, -1);
614 devinfo_volume_add (parent, node, m);
615 devinfo_storage_free_minor (m);
616 }
617
618 /*
619 * After reprobing storage, reprobe its volumes.
620 */
621 static void
devinfo_floppy_rescan_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)622 devinfo_floppy_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code,
623 char **error, gpointer userdata1, gpointer userdata2)
624 {
625 void *end_token = (void *) userdata1;
626 const char *devfs_path;
627 di_node_t node;
628 HalDevice *v;
629
630 if (!hal_device_property_get_bool (d, "storage.removable.media_available")) {
631 HAL_INFO (("no floppy media", hal_device_get_udi (d)));
632
633 /* remove child (can only be single volume) */
634 if (((v = hal_device_store_match_key_value_string (hald_get_gdl(),
635 "info.parent", hal_device_get_udi (d))) != NULL) &&
636 ((devfs_path = hal_device_property_get_string (v,
637 "solaris.devfs_path")) != NULL)) {
638 devinfo_remove_enqueue ((char *)devfs_path, NULL);
639 }
640 } else {
641 HAL_INFO (("floppy media found", hal_device_get_udi (d)));
642
643 if ((devfs_path = hal_device_property_get_string(d, "solaris.devfs_path")) == NULL) {
644 HAL_INFO (("no devfs_path", hal_device_get_udi (d)));
645 hotplug_event_process_queue ();
646 return;
647 }
648 if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
649 HAL_INFO (("di_init %s failed %d", devfs_path, errno));
650 hotplug_event_process_queue ();
651 return;
652 }
653
654 devinfo_floppy_add_volume (d, node);
655
656 di_fini (node);
657 }
658
659 hotplug_event_process_queue ();
660 }
661
662 /* lofi */
663
664 HalDevice *
devinfo_lofi_add(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type)665 devinfo_lofi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type)
666 {
667 return (devinfo_lofi_add_major(parent,node, devfs_path, device_type, FALSE, NULL));
668 }
669
670 HalDevice *
devinfo_lofi_add_major(HalDevice * parent,di_node_t node,char * devfs_path,char * device_type,gboolean rescan,HalDevice * lofi_d)671 devinfo_lofi_add_major(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type,
672 gboolean rescan, HalDevice *lofi_d)
673 {
674 char *driver_name;
675 HalDevice *d = NULL;
676 char udi[HAL_PATH_MAX];
677 di_devlink_handle_t devlink_hdl;
678 int major;
679 di_minor_t minor;
680 dev_t dev;
681 char *minor_path = NULL;
682 char *devlink = NULL;
683
684 driver_name = di_driver_name (node);
685 if ((driver_name == NULL) || (strcmp (driver_name, "lofi") != 0)) {
686 return (NULL);
687 }
688
689 if (!rescan) {
690 d = hal_device_new ();
691
692 devinfo_set_default_properties (d, parent, node, devfs_path);
693 hal_device_property_set_string (d, "info.subsystem", "pseudo");
694
695 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
696 "%s/%s%d", hal_device_get_udi (parent), di_node_name(node), di_instance (node));
697 hal_device_set_udi (d, udi);
698 hal_device_property_set_string (d, "info.udi", udi);
699
700 devinfo_add_enqueue (d, devfs_path, &devinfo_lofi_handler);
701 } else {
702 d = lofi_d;
703 }
704
705 /*
706 * Unlike normal storage, as in devinfo_storage_minors(), where
707 * sd instance -> HAL storage, sd minor node -> HAL volume,
708 * lofi always has one instance, lofi minor -> HAL storage.
709 * lofi storage never has slices, but it can have
710 * embedded pcfs partitions that fstyp would recognize
711 */
712 major = di_driver_major(node);
713 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
714 return (d);
715 }
716 minor = DI_MINOR_NIL;
717 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
718 dev = di_minor_devt(minor);
719 if ((major != major(dev)) ||
720 (di_minor_type(minor) != DDM_MINOR) ||
721 (di_minor_spectype(minor) != S_IFBLK) ||
722 ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
723 continue;
724 }
725 if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
726 di_devfs_path_free (minor_path);
727 continue;
728 }
729
730 if (!rescan ||
731 (hal_device_store_match_key_value_string (hald_get_gdl (),
732 "solaris.devfs_path", minor_path) == NULL)) {
733 devinfo_lofi_add_minor(d, node, minor_path, devlink, dev);
734 }
735
736 di_devfs_path_free (minor_path);
737 free(devlink);
738 }
739 di_devlink_fini (&devlink_hdl);
740
741 return (d);
742 }
743
744 static void
devinfo_lofi_add_minor(HalDevice * parent,di_node_t node,char * minor_path,char * devlink,dev_t dev)745 devinfo_lofi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, char *devlink, dev_t dev)
746 {
747 HalDevice *d;
748 char *raw;
749 char *doslink;
750 char dospath[64];
751 struct devinfo_storage_minor *m;
752 int i;
753
754 /* add storage */
755 d = hal_device_new ();
756
757 devinfo_set_default_properties (d, parent, node, minor_path);
758 hal_device_property_set_string (d, "info.category", "storage");
759 hal_device_add_capability (d, "storage");
760 hal_device_property_set_string (d, "storage.bus", "lofi");
761 hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
762 hal_device_property_set_bool (d, "storage.removable", FALSE);
763 hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
764 hal_device_property_set_string (d, "storage.drive_type", "disk");
765 hal_device_add_capability (d, "block");
766 hal_device_property_set_int (d, "block.major", major(dev));
767 hal_device_property_set_int (d, "block.minor", minor(dev));
768 hal_device_property_set_string (d, "block.device", devlink);
769 raw = dsk_to_rdsk (devlink);
770 hal_device_property_set_string (d, "block.solaris.raw_device", raw);
771 free (raw);
772 hal_device_property_set_bool (d, "block.is_volume", FALSE);
773
774 devinfo_add_enqueue (d, minor_path, &devinfo_storage_handler);
775
776 /* add volumes: one on main device and a few pcfs candidates */
777 m = devinfo_storage_new_minor(minor_path, WHOLE_DISK, devlink, dev, -1);
778 devinfo_volume_add (d, node, m);
779 devinfo_storage_free_minor (m);
780
781 doslink = (char *)calloc (1, strlen (devlink) + sizeof (":NNN") + 1);
782 if (doslink != NULL) {
783 for (i = 1; i < 16; i++) {
784 snprintf(dospath, sizeof (dospath), WHOLE_DISK":%d", i);
785 sprintf(doslink, "%s:%d", devlink, i);
786 m = devinfo_storage_new_minor(minor_path, dospath, doslink, dev, i);
787 devinfo_volume_add (d, node, m);
788 devinfo_storage_free_minor (m);
789 }
790 free (doslink);
791 }
792 }
793
794 void
devinfo_lofi_remove_minor(char * parent_devfs_path,char * name)795 devinfo_lofi_remove_minor(char *parent_devfs_path, char *name)
796 {
797 GSList *i;
798 GSList *devices;
799 HalDevice *d = NULL;
800 const char *devfs_path;
801
802 devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
803 "block.solaris.raw_device", name);
804 for (i = devices; i != NULL; i = g_slist_next (i)) {
805 if (hal_device_has_capability (HAL_DEVICE (i->data), "storage")) {
806 d = HAL_DEVICE (i->data);
807 break;
808 }
809 }
810 g_slist_free (devices);
811
812 if (d == NULL) {
813 HAL_INFO (("device not found %s", name));
814 return;
815 }
816
817 if ((devfs_path = hal_device_property_get_string (d,
818 "solaris.devfs_path")) == NULL) {
819 HAL_INFO (("devfs_path not found %s", hal_device_get_udi (d)));
820 return;
821 }
822
823 if (d != NULL) {
824 devinfo_remove_branch ((char *)devfs_path, d);
825 }
826 }
827
828 /* common storage */
829
830 static void
devinfo_storage_free_minor(struct devinfo_storage_minor * m)831 devinfo_storage_free_minor(struct devinfo_storage_minor *m)
832 {
833 if (m != NULL) {
834 free (m->slice);
835 free (m->devlink);
836 free (m->devpath);
837 free (m);
838 }
839 }
840
841 static struct devinfo_storage_minor *
devinfo_storage_new_minor(char * maindev_path,char * slice,char * devlink,dev_t dev,int dosnum)842 devinfo_storage_new_minor(char *maindev_path, char *slice, char *devlink, dev_t dev, int dosnum)
843 {
844 struct devinfo_storage_minor *m;
845 int pathlen;
846 char *devpath;
847
848 m = (struct devinfo_storage_minor *)calloc (sizeof (struct devinfo_storage_minor), 1);
849 if (m != NULL) {
850 /*
851 * For volume's devfs_path we'll use minor_path/slice instead of
852 * minor_path which we use for parent storage device.
853 */
854 pathlen = strlen (maindev_path) + strlen (slice) + 2;
855 devpath = (char *)calloc (1, pathlen);
856 snprintf(devpath, pathlen, "%s/%s", maindev_path, slice);
857
858 m->devpath = devpath;
859 m->devlink = strdup (devlink);
860 m->slice = strdup (slice);
861 m->dev = dev;
862 m->dosnum = dosnum;
863 if ((m->devpath == NULL) || (m->devlink == NULL)) {
864 devinfo_storage_free_minor (m);
865 m = NULL;
866 }
867 }
868 return (m);
869 }
870
871 /*
872 * Storage minor nodes are potential "volume" objects.
873 * This function also completes building the parent object (main storage device).
874 */
875 static void
devinfo_storage_minors(HalDevice * parent,di_node_t node,gchar * devfs_path,gboolean rescan)876 devinfo_storage_minors(HalDevice *parent, di_node_t node, gchar *devfs_path, gboolean rescan)
877 {
878 di_devlink_handle_t devlink_hdl;
879 gboolean is_cdrom;
880 const char *whole_disk;
881 int major;
882 di_minor_t minor;
883 dev_t dev;
884 char *minor_path = NULL;
885 char *maindev_path = NULL;
886 char *devpath, *devlink;
887 int doslink_len;
888 char *doslink;
889 char dospath[64];
890 char *slice;
891 int pathlen;
892 int i;
893 char *raw;
894 boolean_t maindev_is_d0;
895 GQueue *mq;
896 HalDevice *volume;
897 struct devinfo_storage_minor *m;
898 struct devinfo_storage_minor *maindev = NULL;
899
900 /* for cdroms whole disk is always s2 */
901 is_cdrom = hal_device_has_capability (parent, "storage.cdrom");
902 whole_disk = is_cdrom ? "s2" : WHOLE_DISK;
903
904 major = di_driver_major(node);
905
906 /* the "whole disk" p0/s2/d0 node must come first in the hotplug queue
907 * so we put other minor nodes on the local queue and move to the
908 * hotplug queue up in the end
909 */
910 if ((mq = g_queue_new()) == NULL) {
911 goto err;
912 }
913 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) {
914 g_queue_free (mq);
915 goto err;
916 }
917 minor = DI_MINOR_NIL;
918 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
919 dev = di_minor_devt(minor);
920 if ((major != major(dev)) ||
921 (di_minor_type(minor) != DDM_MINOR) ||
922 (di_minor_spectype(minor) != S_IFBLK) ||
923 ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
924 continue;
925 }
926 if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
927 di_devfs_path_free (minor_path);
928 continue;
929 }
930
931 slice = devinfo_volume_get_slice_name (devlink);
932 if (strlen (slice) < 2) {
933 free (devlink);
934 di_devfs_path_free (minor_path);
935 continue;
936 }
937
938 /* ignore p1..N - we'll use p0:N instead */
939 if ((strlen (slice) > 1) && (slice[0] == 'p') && isdigit(slice[1]) &&
940 ((atol(&slice[1])) > 0)) {
941 free (devlink);
942 di_devfs_path_free (minor_path);
943 continue;
944 }
945
946 m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
947 if (m == NULL) {
948 free (devlink);
949 di_devfs_path_free (minor_path);
950 continue;
951 }
952
953 /* main device is either s2/p0 or d0, the latter taking precedence */
954 if ((strcmp (slice, "d0") == 0) ||
955 (((strcmp (slice, whole_disk) == 0) && (maindev == NULL)))) {
956 if (maindev_path != NULL) {
957 di_devfs_path_free (maindev_path);
958 }
959 maindev_path = minor_path;
960 maindev = m;
961 g_queue_push_head (mq, maindev);
962 } else {
963 di_devfs_path_free (minor_path);
964 g_queue_push_tail (mq, m);
965 }
966
967 free (devlink);
968 }
969 di_devlink_fini (&devlink_hdl);
970
971 if (maindev == NULL) {
972 /* shouldn't typically happen */
973 while (!g_queue_is_empty (mq)) {
974 devinfo_storage_free_minor (g_queue_pop_head (mq));
975 }
976 goto err;
977 }
978
979 /* first enqueue main storage device */
980 if (!rescan) {
981 hal_device_property_set_int (parent, "block.major", major);
982 hal_device_property_set_int (parent, "block.minor", minor(maindev->dev));
983 hal_device_property_set_string (parent, "block.device", maindev->devlink);
984 raw = dsk_to_rdsk (maindev->devlink);
985 hal_device_property_set_string (parent, "block.solaris.raw_device", raw);
986 free (raw);
987 hal_device_property_set_bool (parent, "block.is_volume", FALSE);
988 hal_device_property_set_string (parent, "solaris.devfs_path", maindev_path);
989 devinfo_add_enqueue (parent, maindev_path, &devinfo_storage_handler);
990 }
991
992 /* add virtual dos volumes to enable pcfs probing */
993 if (!is_cdrom) {
994 doslink_len = strlen (maindev->devlink) + sizeof (":NNN") + 1;
995 if ((doslink = (char *)calloc (1, doslink_len)) != NULL) {
996 for (i = 1; i < 16; i++) {
997 snprintf(dospath, sizeof (dospath), "%s:%d", maindev->slice, i);
998 snprintf(doslink, doslink_len, "%s:%d", maindev->devlink, i);
999 m = devinfo_storage_new_minor(maindev_path, dospath, doslink, maindev->dev, i);
1000 g_queue_push_tail (mq, m);
1001 }
1002 free (doslink);
1003 }
1004 }
1005
1006 maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
1007
1008 /* enqueue all volumes */
1009 while (!g_queue_is_empty (mq)) {
1010 m = g_queue_pop_head (mq);
1011
1012 /* if main device is d0, we'll throw away s2/p0 */
1013 if (maindev_is_d0 && (strcmp (m->slice, whole_disk) == 0)) {
1014 devinfo_storage_free_minor (m);
1015 continue;
1016 }
1017 /* don't do p0 on cdrom */
1018 if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
1019 devinfo_storage_free_minor (m);
1020 continue;
1021 }
1022 if (rescan) {
1023 /* in rescan mode, don't reprobe existing volumes */
1024 /* XXX detect volume removal? */
1025 volume = hal_device_store_match_key_value_string (hald_get_gdl (),
1026 "solaris.devfs_path", m->devpath);
1027 if ((volume == NULL) || !hal_device_has_capability(volume, "volume")) {
1028 devinfo_volume_add (parent, node, m);
1029 } else {
1030 HAL_INFO(("rescan volume exists %s", m->devpath));
1031 }
1032 } else {
1033 devinfo_volume_add (parent, node, m);
1034 }
1035 devinfo_storage_free_minor (m);
1036 }
1037
1038 if (maindev_path != NULL) {
1039 di_devfs_path_free (maindev_path);
1040 }
1041
1042 return;
1043
1044 err:
1045 if (maindev_path != NULL) {
1046 di_devfs_path_free (maindev_path);
1047 }
1048 if (!rescan) {
1049 devinfo_add_enqueue (parent, devfs_path, &devinfo_storage_handler);
1050 }
1051 }
1052
1053 HalDevice *
devinfo_volume_add(HalDevice * parent,di_node_t node,devinfo_storage_minor_t * m)1054 devinfo_volume_add(HalDevice *parent, di_node_t node, devinfo_storage_minor_t *m)
1055 {
1056 HalDevice *d;
1057 char *raw;
1058 char udi[HAL_PATH_MAX];
1059 char *devfs_path = m->devpath;
1060 char *devlink = m->devlink;
1061 dev_t dev = m->dev;
1062 int dosnum = m->dosnum;
1063 char *slice = m->slice;
1064
1065 HAL_INFO (("volume_add: devfs_path=%s devlink=%s", devfs_path, devlink));
1066 d = hal_device_new ();
1067
1068 devinfo_set_default_properties (d, parent, node, devfs_path);
1069 hal_device_property_set_string (d, "info.category", "volume");
1070
1071 hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
1072 "%s/%s", hal_device_get_udi (parent), slice);
1073 hal_device_set_udi (d, udi);
1074 hal_device_property_set_string (d, "info.udi", udi);
1075 hal_device_property_set_string (d, "info.product", slice);
1076
1077 hal_device_add_capability (d, "volume");
1078 hal_device_add_capability (d, "block");
1079 hal_device_property_set_int (d, "block.major", major (dev));
1080 hal_device_property_set_int (d, "block.minor", minor (dev));
1081 hal_device_property_set_string (d, "block.device", devlink);
1082 raw = dsk_to_rdsk (devlink);
1083 hal_device_property_set_string (d, "block.solaris.raw_device", raw);
1084 free (raw);
1085 hal_device_property_set_string (d, "block.solaris.slice", slice);
1086 hal_device_property_set_bool (d, "block.is_volume", TRUE); /* XXX */
1087
1088 hal_device_property_set_string (d, "block.storage_device", hal_device_get_udi (parent));
1089
1090 /* set volume defaults */
1091 hal_device_property_set_string (d, "volume.fstype", "");
1092 hal_device_property_set_string (d, "volume.fsusage", "");
1093 hal_device_property_set_string (d, "volume.fsversion", "");
1094 hal_device_property_set_string (d, "volume.uuid", "");
1095 hal_device_property_set_string (d, "volume.label", "");
1096 hal_device_property_set_string (d, "volume.mount_point", "");
1097 hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
1098 if (strcmp (hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0) {
1099 hal_device_property_set_bool (d, "volume.is_disc", TRUE);
1100 hal_device_add_capability (d, "volume.disc");
1101 } else {
1102 hal_device_property_set_bool (d, "volume.is_disc", FALSE);
1103 }
1104
1105 if (dosnum > 0) {
1106 hal_device_property_set_bool (d, "volume.is_partition", TRUE);
1107 hal_device_property_set_int (d, "volume.partition.number", dosnum);
1108 } else {
1109 hal_device_property_set_bool (d, "volume.is_partition", FALSE);
1110 }
1111
1112 /* prober may override these */
1113 hal_device_property_set_int (d, "volume.block_size", 512);
1114
1115 devinfo_add_enqueue (d, devfs_path, &devinfo_volume_handler);
1116
1117 return (d);
1118 }
1119
1120 static void
devinfo_volume_preprobing_done(HalDevice * d,gpointer userdata1,gpointer userdata2)1121 devinfo_volume_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
1122 {
1123 void *end_token = (void *) userdata1;
1124 char *whole_disk;
1125 char *block_device;
1126 const char *storage_udi;
1127 HalDevice *storage_d;
1128 const char *slice;
1129 int dos_num;
1130
1131 if (hal_device_property_get_bool (d, "info.ignore")) {
1132 HAL_INFO (("Preprobing merged info.ignore==TRUE %s", hal_device_get_udi (d)));
1133 goto skip;
1134 }
1135
1136 /*
1137 * Optimizations: only probe if there's a chance to find something
1138 */
1139 block_device = (char *)hal_device_property_get_string (d, "block.device");
1140 storage_udi = hal_device_property_get_string (d, "block.storage_device");
1141 slice = hal_device_property_get_string(d, "block.solaris.slice");
1142 if ((block_device == NULL) || (storage_udi == NULL) ||
1143 (slice == NULL) || (strlen (slice) < 2)) {
1144 HAL_INFO (("Malformed volume properties %s", hal_device_get_udi (d)));
1145 goto skip;
1146 }
1147 storage_d = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", storage_udi);
1148 if (storage_d == NULL) {
1149 HAL_INFO (("Storage device not found %s", hal_device_get_udi (d)));
1150 goto skip;
1151 }
1152
1153 whole_disk = hal_device_has_capability (storage_d,
1154 "storage.cdrom") ? "s2" : WHOLE_DISK;
1155
1156 if (is_dos_path(block_device, &dos_num)) {
1157 /* don't probe more dos volumes than probe-storage found */
1158 if ((hal_device_property_get_bool (storage_d, "storage.no_partitions_hint") ||
1159 (dos_num > hal_device_property_get_int (storage_d, "storage.solaris.num_dos_partitions")))) {
1160 HAL_INFO (("%d > %d %s", dos_num, hal_device_property_get_int (storage_d,
1161 "storage.solaris.num_dos_partitions"), hal_device_get_udi (storage_d)));
1162 goto skip;
1163 }
1164 } else {
1165 /* if no VTOC slices found, don't probe slices except s2 */
1166 if ((slice[0] == 's') && (isdigit(slice[1])) && ((strcmp (slice, whole_disk)) != 0) &&
1167 !hal_device_property_get_bool (storage_d, "storage.solaris.vtoc_slices")) {
1168 HAL_INFO (("Not probing slice %s", hal_device_get_udi (d)));
1169 goto skip;
1170 }
1171 }
1172
1173 HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
1174 hald_runner_run (d,
1175 "hald-probe-volume", NULL,
1176 DEVINFO_PROBE_VOLUME_TIMEOUT,
1177 devinfo_callouts_probing_done,
1178 (gpointer) end_token, userdata2);
1179
1180 return;
1181
1182 skip:
1183 hal_device_store_remove (hald_get_tdl (), d);
1184 g_object_unref (d);
1185 hotplug_event_end (end_token);
1186 }
1187
1188 static void
devinfo_volume_hotplug_begin_add(HalDevice * d,HalDevice * parent,DevinfoDevHandler * handler,void * end_token)1189 devinfo_volume_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
1190 {
1191 HAL_INFO(("Preprobing volume udi=%s", hal_device_get_udi (d)));
1192
1193 if (parent == NULL) {
1194 HAL_INFO (("no parent %s", hal_device_get_udi (d)));
1195 goto skip;
1196 }
1197
1198 if (hal_device_property_get_bool (parent, "info.ignore")) {
1199 HAL_INFO (("Ignoring volume: parent's info.ignore is TRUE"));
1200 goto skip;
1201 }
1202
1203 /* add to TDL so preprobing callouts and prober can access it */
1204 hal_device_store_add (hald_get_tdl (), d);
1205
1206 /* Process preprobe fdi files */
1207 di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
1208
1209 /* Run preprobe callouts */
1210 hal_util_callout_device_preprobe (d, devinfo_volume_preprobing_done, end_token, handler);
1211
1212 return;
1213
1214 skip:
1215 g_object_unref (d);
1216 hotplug_event_end (end_token);
1217 }
1218
1219 void
devinfo_storage_hotplug_begin_add(HalDevice * d,HalDevice * parent,DevinfoDevHandler * handler,void * end_token)1220 devinfo_storage_hotplug_begin_add (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
1221 {
1222 const char *drive_type;
1223 const char *p_udi;
1224 HalDevice *p_d;
1225 HalDevice *phys_d = NULL;
1226 const char *phys_bus;
1227 const char *bus;
1228 static const char *busses[] = { "usb", "ide", "scsi", "ieee1394",
1229 "pseudo" };
1230 int i;
1231
1232 HAL_INFO (("Preprobing udi=%s", hal_device_get_udi (d)));
1233
1234 if (parent == NULL) {
1235 HAL_INFO (("no parent %s", hal_device_get_udi (d)));
1236 goto error;
1237 }
1238
1239 /*
1240 * figure out physical device and bus, except for floppy
1241 */
1242 drive_type = hal_device_property_get_string (d, "storage.drive_type");
1243 if ((drive_type != NULL) && (strcmp (drive_type, "floppy") == 0)) {
1244 goto skip_bus;
1245 }
1246
1247 p_d = parent;
1248 for (;;) {
1249 bus = hal_device_property_get_string (p_d, "info.subsystem");
1250 if (bus != NULL) {
1251 for (i = 0; i < NELEM(busses); i++) {
1252 if (strcmp(bus, busses[i]) == 0) {
1253 phys_d = p_d;
1254 phys_bus = busses[i];
1255 break;
1256 }
1257 }
1258 }
1259 /* up the tree */
1260 p_udi = hal_device_property_get_string (p_d, "info.parent");
1261 if (p_udi == NULL) {
1262 break;
1263 }
1264 p_d = hal_device_store_find (hald_get_gdl (), p_udi);
1265 }
1266 if (phys_d == NULL) {
1267 HAL_INFO (("no physical device %s", hal_device_get_udi (d)));
1268 } else {
1269 hal_device_property_set_string (d, "storage.physical_device", hal_device_get_udi (phys_d));
1270 hal_device_property_set_string (d, "storage.bus", phys_bus);
1271 }
1272
1273 skip_bus:
1274
1275 /* add to TDL so preprobing callouts and prober can access it */
1276 hal_device_store_add (hald_get_tdl (), d);
1277
1278 /* Process preprobe fdi files */
1279 di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
1280
1281 /* Run preprobe callouts */
1282 hal_util_callout_device_preprobe (d, devinfo_callouts_preprobing_done, end_token, handler);
1283
1284 return;
1285
1286 error:
1287 g_object_unref (d);
1288 hotplug_event_end (end_token);
1289 }
1290
1291 static void
devinfo_storage_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)1292 devinfo_storage_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
1293 {
1294 void *end_token = (void *) userdata1;
1295
1296 HAL_INFO (("devinfo_storage_probing_done %s", hal_device_get_udi (d)));
1297
1298 /* Discard device if probing reports failure */
1299 if (exit_type != HALD_RUN_SUCCESS || return_code != 0) {
1300 HAL_INFO (("devinfo_storage_probing_done returning exit_type=%d return_code=%d", exit_type, return_code));
1301 hal_device_store_remove (hald_get_tdl (), d);
1302 g_object_unref (d);
1303 hotplug_event_end (end_token);
1304 return;
1305 }
1306
1307 devinfo_storage_set_nicknames (d);
1308
1309 /* Merge properties from .fdi files */
1310 di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
1311 di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
1312
1313 hal_util_callout_device_add (d, devinfo_callouts_add_done, end_token, NULL);
1314 }
1315
1316 const gchar *
devinfo_storage_get_prober(HalDevice * d,int * timeout)1317 devinfo_storage_get_prober (HalDevice *d, int *timeout)
1318 {
1319 *timeout = DEVINFO_PROBE_STORAGE_TIMEOUT;
1320 return "hald-probe-storage";
1321 }
1322
1323 const gchar *
devinfo_volume_get_prober(HalDevice * d,int * timeout)1324 devinfo_volume_get_prober (HalDevice *d, int *timeout)
1325 {
1326 *timeout = DEVINFO_PROBE_VOLUME_TIMEOUT;
1327 return "hald-probe-volume";
1328 }
1329
1330 /*
1331 * After reprobing storage, reprobe its volumes.
1332 */
1333 static void
devinfo_storage_rescan_probing_done(HalDevice * d,guint32 exit_type,gint return_code,char ** error,gpointer userdata1,gpointer userdata2)1334 devinfo_storage_rescan_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
1335 {
1336 void *end_token = (void *) userdata1;
1337 const char *devfs_path_orig = NULL;
1338 char *devfs_path = NULL;
1339 char *p;
1340 di_node_t node;
1341
1342 HAL_INFO (("devinfo_storage_rescan_probing_done %s", hal_device_get_udi (d)));
1343
1344 devfs_path_orig = hal_device_property_get_string (d, "solaris.devfs_path");
1345 if (devfs_path_orig == NULL) {
1346 HAL_INFO (("device has no solaris.devfs_path"));
1347 hotplug_event_process_queue ();
1348 return;
1349 }
1350
1351 /* strip trailing minor part if any */
1352 if (strrchr(devfs_path_orig, ':') != NULL) {
1353 if ((devfs_path = strdup (devfs_path_orig)) != NULL) {
1354 p = strrchr(devfs_path, ':');
1355 *p = '\0';
1356 }
1357 } else {
1358 devfs_path = (char *)devfs_path_orig;
1359 }
1360
1361 if ((node = di_init (devfs_path, DINFOCPYALL)) == DI_NODE_NIL) {
1362 HAL_INFO (("di_init %s failed %d %s", devfs_path, errno, hal_device_get_udi (d)));
1363 hotplug_event_process_queue ();
1364 return;
1365 } else {
1366 devinfo_storage_minors (d, node, (char *)devfs_path, TRUE);
1367 di_fini (node);
1368 }
1369
1370 if (devfs_path != devfs_path_orig) {
1371 free (devfs_path);
1372 }
1373
1374 hotplug_event_process_queue ();
1375 }
1376
1377 /*
1378 * For removable media devices, check for "storage.removable.media_available".
1379 * For non-removable media devices, assume media is always there.
1380 *
1381 * If media is gone, enqueue remove events for all children volumes.
1382 * If media is there, first reprobe storage, then probe for new volumes (but leave existing volumes alone).
1383 */
1384 gboolean
devinfo_storage_device_rescan(HalDevice * d)1385 devinfo_storage_device_rescan (HalDevice *d)
1386 {
1387 GSList *i;
1388 GSList *volumes;
1389 HalDevice *v;
1390 gchar *v_devfs_path;
1391 const char *drive_type;
1392 gboolean is_floppy;
1393 gboolean media_available;
1394
1395 HAL_INFO (("devinfo_storage_device_rescan udi=%s", hal_device_get_udi (d)));
1396
1397 if (hal_device_property_get_bool (d, "block.is_volume")) {
1398 HAL_INFO (("nothing to do for volume"));
1399 return (FALSE);
1400 }
1401
1402 drive_type = hal_device_property_get_string (d, "storage.drive_type");
1403 is_floppy = (drive_type != NULL) && (strcmp (drive_type, "floppy") == 0);
1404
1405 media_available = !hal_device_property_get_bool (d, "storage.removable") ||
1406 hal_device_property_get_bool (d, "storage.removable.media_available");
1407
1408 if (!media_available && !is_floppy) {
1409 HAL_INFO (("media gone %s", hal_device_get_udi (d)));
1410
1411 volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
1412 "block.storage_device", hal_device_get_udi (d));
1413 for (i = volumes; i != NULL; i = g_slist_next (i)) {
1414 v = HAL_DEVICE (i->data);
1415 v_devfs_path = (gchar *)hal_device_property_get_string (v, "solaris.devfs_path");
1416 HAL_INFO (("child volume %s", hal_device_get_udi (v)));
1417 if ((v_devfs_path != NULL) && hal_device_has_capability (v, "volume")) {
1418 HAL_INFO (("removing volume %s", hal_device_get_udi (v)));
1419 devinfo_remove_enqueue (v_devfs_path, NULL);
1420 } else {
1421 HAL_INFO (("not a volume %s", hal_device_get_udi (v)));
1422 }
1423 }
1424 g_slist_free (volumes);
1425
1426 hotplug_event_process_queue ();
1427 } else if (is_floppy) {
1428 HAL_INFO (("rescanning floppy %s", hal_device_get_udi (d)));
1429
1430 hald_runner_run (d,
1431 "hald-probe-storage --only-check-for-media", NULL,
1432 DEVINFO_PROBE_STORAGE_TIMEOUT,
1433 devinfo_floppy_rescan_probing_done,
1434 NULL, NULL);
1435 } else {
1436 HAL_INFO (("media available %s", hal_device_get_udi (d)));
1437
1438 hald_runner_run (d,
1439 "hald-probe-storage --only-check-for-media", NULL,
1440 DEVINFO_PROBE_STORAGE_TIMEOUT,
1441 devinfo_storage_rescan_probing_done,
1442 NULL, NULL);
1443 }
1444
1445 return TRUE;
1446 }
1447
1448 static char *
devinfo_volume_get_slice_name(char * devlink)1449 devinfo_volume_get_slice_name (char *devlink)
1450 {
1451 char *part, *slice, *disk;
1452 char *s = NULL;
1453 char *p;
1454
1455 if ((p = strstr(devlink, "/lofi/")) != 0) {
1456 return (p + sizeof ("/lofi/") - 1);
1457 }
1458
1459 part = strrchr(devlink, 'p');
1460 slice = strrchr(devlink, 's');
1461 disk = strrchr(devlink, 'd');
1462
1463 if ((part != NULL) && (part > slice) && (part > disk)) {
1464 s = part;
1465 } else if ((slice != NULL) && (slice > disk)) {
1466 s = slice;
1467 } else {
1468 s = disk;
1469 }
1470 if ((s != NULL) && isdigit(s[1])) {
1471 return (s);
1472 } else {
1473 return ("");
1474 }
1475 }
1476
1477 static gboolean
is_dos_path(char * path,int * partnum)1478 is_dos_path(char *path, int *partnum)
1479 {
1480 char *p;
1481
1482 if ((p = strrchr (path, ':')) == NULL) {
1483 return (FALSE);
1484 }
1485 return ((*partnum = atoi(p + 1)) != 0);
1486 }
1487
1488 static gboolean
dos_to_dev(char * path,char ** devpath,int * partnum)1489 dos_to_dev(char *path, char **devpath, int *partnum)
1490 {
1491 char *p;
1492
1493 if ((p = strrchr (path, ':')) == NULL) {
1494 return (FALSE);
1495 }
1496 if ((*partnum = atoi(p + 1)) == 0) {
1497 return (FALSE);
1498 }
1499 p[0] = '\0';
1500 *devpath = strdup(path);
1501 p[0] = ':';
1502 return (*devpath != NULL);
1503 }
1504
1505 static void
devinfo_storage_cleanup_mountpoint_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)1506 devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type,
1507 gint return_code, gchar **error,
1508 gpointer data1, gpointer data2)
1509 {
1510 char *mount_point = (char *) data1;
1511
1512 HAL_INFO (("Cleaned up mount point '%s'", mount_point));
1513 g_free (mount_point);
1514 }
1515
1516
1517 void
devinfo_storage_mnttab_event(HalDevice * hal_volume)1518 devinfo_storage_mnttab_event (HalDevice *hal_volume)
1519 {
1520 FILE *fp = NULL;
1521 struct extmnttab m;
1522 HalDevice *d;
1523 unsigned int major;
1524 unsigned int minor;
1525 GSList *volumes = NULL;
1526 GSList *v;
1527 char *mount_point;
1528 dbus_bool_t is_partition;
1529 const char *fstype;
1530 int partition_number;
1531
1532 if (hal_volume != NULL) {
1533 volumes = g_slist_append (NULL, hal_volume);
1534 } else {
1535 volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
1536 }
1537 if (volumes == NULL) {
1538 return;
1539 }
1540
1541 if ((fp = fopen(MNTTAB, "r")) == NULL) {
1542 HAL_ERROR (("Open failed %s errno %d", MNTTAB, errno));
1543 return;
1544 }
1545
1546 while (getextmntent(fp, &m, 1) == 0) {
1547 for (v = volumes; v != NULL; v = g_slist_next (v)) {
1548 d = HAL_DEVICE (v->data);
1549 major = hal_device_property_get_int (d, "block.major");
1550 minor = hal_device_property_get_int (d, "block.minor");
1551
1552 /*
1553 * special handling for pcfs, which encodes logical
1554 * drive number into the 6 upper bits of the minor
1555 */
1556 is_partition = hal_device_property_get_bool (d, "volume.is_partition");
1557 partition_number = hal_device_property_get_int (d, "volume.partition.number");
1558 fstype = hal_device_property_get_string (d, "volume.fstype");
1559
1560 if (is_partition && (partition_number > 0) && (strcmp (fstype, "pcfs") == 0)) {
1561 minor |= partition_number << 12;
1562 }
1563
1564 if (m.mnt_major != major || m.mnt_minor != minor) {
1565 continue;
1566 }
1567
1568 /* this volume matches the mnttab entry */
1569 device_property_atomic_update_begin ();
1570 hal_device_property_set_bool (d, "volume.is_mounted", TRUE);
1571 hal_device_property_set_bool (d, "volume.is_mounted_read_only",
1572 hasmntopt ((struct mnttab *)&m, "ro") ? TRUE : FALSE);
1573 hal_device_property_set_string (d, "volume.mount_point", m.mnt_mountp);
1574 device_property_atomic_update_end ();
1575
1576 HAL_INFO (("set %s to be mounted at %s",
1577 hal_device_get_udi (d), m.mnt_mountp));
1578 volumes = g_slist_delete_link (volumes, v);
1579 }
1580 }
1581
1582 /* all remaining volumes are not mounted */
1583 for (v = volumes; v != NULL; v = g_slist_next (v)) {
1584 d = HAL_DEVICE (v->data);
1585 mount_point = g_strdup (hal_device_property_get_string (d, "volume.mount_point"));
1586 if (mount_point == NULL || strlen (mount_point) == 0) {
1587 g_free (mount_point);
1588 continue;
1589 }
1590
1591 device_property_atomic_update_begin ();
1592 hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
1593 hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
1594 hal_device_property_set_string (d, "volume.mount_point", "");
1595 device_property_atomic_update_end ();
1596
1597 HAL_INFO (("set %s to unmounted", hal_device_get_udi (d)));
1598
1599 /* cleanup if was mounted by us */
1600 if (hal_util_is_mounted_by_hald (mount_point)) {
1601 char *cleanup_stdin;
1602 char *extra_env[2];
1603
1604 HAL_INFO (("Cleaning up '%s'", mount_point));
1605
1606 extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
1607 extra_env[1] = NULL;
1608 cleanup_stdin = "\n";
1609
1610 hald_runner_run_method (d,
1611 "hal-storage-cleanup-mountpoint",
1612 extra_env,
1613 cleanup_stdin, TRUE,
1614 0,
1615 devinfo_storage_cleanup_mountpoint_cb,
1616 g_strdup (mount_point), NULL);
1617
1618 g_free (extra_env[0]);
1619 }
1620
1621 g_free (mount_point);
1622 }
1623 g_slist_free (volumes);
1624
1625 (void) fclose (fp);
1626 }
1627
1628 static void
devinfo_volume_force_unmount_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)1629 devinfo_volume_force_unmount_cb (HalDevice *d, guint32 exit_type,
1630 gint return_code, gchar **error,
1631 gpointer data1, gpointer data2)
1632 {
1633 void *end_token = (void *) data1;
1634
1635 HAL_INFO (("devinfo_volume_force_unmount_cb for udi='%s', exit_type=%d, return_code=%d", hal_device_get_udi (d), exit_type, return_code));
1636
1637 if (exit_type == HALD_RUN_SUCCESS && error != NULL &&
1638 error[0] != NULL && error[1] != NULL) {
1639 char *exp_name = NULL;
1640 char *exp_detail = NULL;
1641
1642 exp_name = error[0];
1643 if (error[0] != NULL) {
1644 exp_detail = error[1];
1645 }
1646 HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
1647 }
1648
1649 hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
1650 }
1651
1652 static void
devinfo_volume_force_unmount(HalDevice * d,void * end_token)1653 devinfo_volume_force_unmount (HalDevice *d, void *end_token)
1654 {
1655 const char *device_file;
1656 const char *mount_point;
1657 char *unmount_stdin;
1658 char *extra_env[2];
1659 extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
1660 extra_env[1] = NULL;
1661
1662 device_file = hal_device_property_get_string (d, "block.device");
1663 mount_point = hal_device_property_get_string (d, "volume.mount_point");
1664
1665 if (mount_point == NULL || strlen (mount_point) == 0 || !hal_util_is_mounted_by_hald (mount_point)) {
1666 hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
1667 return;
1668 }
1669
1670 HAL_INFO (("devinfo_volume_force_unmount for udi='%s'", hal_device_get_udi (d)));
1671
1672 unmount_stdin = "\n";
1673
1674 hald_runner_run_method (d,
1675 "hal-storage-unmount",
1676 extra_env,
1677 unmount_stdin, TRUE,
1678 0,
1679 devinfo_volume_force_unmount_cb,
1680 end_token, NULL);
1681 }
1682
1683 void
devinfo_volume_hotplug_begin_remove(HalDevice * d,char * devfs_path,void * end_token)1684 devinfo_volume_hotplug_begin_remove (HalDevice *d, char *devfs_path, void *end_token)
1685 {
1686 if (hal_device_property_get_bool (d, "volume.is_mounted")) {
1687 devinfo_volume_force_unmount (d, end_token);
1688 } else {
1689 hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
1690 }
1691 }
1692
1693
1694 enum {
1695 LEGACY_CDROM,
1696 LEGACY_FLOPPY,
1697 LEGACY_RMDISK
1698 };
1699
1700 static const char *legacy_media_str[] = {
1701 "cdrom",
1702 "floppy",
1703 "rmdisk"
1704 };
1705
1706 struct enum_nick {
1707 const char *type;
1708 GSList *nums;
1709 };
1710
1711 static int
devinfo_storage_get_legacy_media(HalDevice * d)1712 devinfo_storage_get_legacy_media(HalDevice *d)
1713 {
1714 const char *drive_type;
1715
1716 if (hal_device_has_capability (d, "storage.cdrom")) {
1717 return (LEGACY_CDROM);
1718 } else if (((drive_type = hal_device_property_get_string (d,
1719 "storage.drive_type")) != NULL) && (strcmp (drive_type, "floppy") == 0)) {
1720 return (LEGACY_FLOPPY);
1721 } else if (hal_device_property_get_bool (d, "storage.removable") ||
1722 hal_device_property_get_bool (d, "storage.hotpluggable")) {
1723 return (LEGACY_RMDISK);
1724 } else {
1725 return (-1);
1726 }
1727 }
1728
1729 static gboolean
devinfo_storage_foreach_nick(HalDeviceStore * store,HalDevice * d,gpointer user_data)1730 devinfo_storage_foreach_nick (HalDeviceStore *store, HalDevice *d, gpointer user_data)
1731 {
1732 struct enum_nick *en = (struct enum_nick *) user_data;
1733 const char *media_type;
1734 int media_num;
1735
1736 media_type = hal_device_property_get_string (d, "storage.solaris.legacy.media_type");
1737 media_num = hal_device_property_get_int (d, "storage.solaris.legacy.media_num");
1738 if ((media_type != NULL) && (strcmp (media_type, en->type) == 0) &&
1739 (media_num >= 0)) {
1740 en->nums = g_slist_prepend (en->nums, GINT_TO_POINTER(media_num));
1741 }
1742 return TRUE;
1743 }
1744
1745 static void
devinfo_storage_append_nickname(HalDevice * d,const char * media_type,int media_num)1746 devinfo_storage_append_nickname (HalDevice *d, const char *media_type, int media_num)
1747 {
1748 char buf[64];
1749
1750 if (media_num == 0) {
1751 hal_device_property_strlist_append (d, "storage.solaris.nicknames", media_type);
1752 }
1753 snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
1754 hal_device_property_strlist_append (d, "storage.solaris.nicknames", buf);
1755 }
1756
1757 static void
devinfo_storage_set_nicknames(HalDevice * d)1758 devinfo_storage_set_nicknames (HalDevice *d)
1759 {
1760 int media;
1761 const char *media_type;
1762 int media_num;
1763 GSList *i;
1764 struct enum_nick en;
1765 char buf[64];
1766
1767 if ((media = devinfo_storage_get_legacy_media (d)) < 0) {
1768 return;
1769 }
1770 media_type = legacy_media_str[media];
1771
1772 /* enumerate all storage devices of this media type */
1773 en.type = media_type;
1774 en.nums = NULL;
1775 hal_device_store_foreach (hald_get_gdl (), devinfo_storage_foreach_nick, &en);
1776
1777 /* find a free number */
1778 for (media_num = 0; ; media_num++) {
1779 for (i = en.nums; i != NULL; i = g_slist_next (i)) {
1780 if (GPOINTER_TO_INT (i->data) == media_num) {
1781 break;
1782 }
1783 }
1784 if (i == NULL) {
1785 break;
1786 }
1787 }
1788 g_slist_free (en.nums);
1789
1790 hal_device_property_set_string (d, "storage.solaris.legacy.media_type", media_type);
1791 hal_device_property_set_int (d, "storage.solaris.legacy.media_num", media_num);
1792
1793 /* primary nickname, and also vold-style symdev */
1794 snprintf(buf, sizeof (buf), "%s%d", media_type, media_num);
1795 hal_device_property_set_string (d, "storage.solaris.legacy.symdev", buf);
1796 devinfo_storage_append_nickname(d, media_type, media_num);
1797
1798 /* additional nicknames */
1799 if (media == LEGACY_CDROM) {
1800 devinfo_storage_append_nickname(d, "cd", media_num);
1801 devinfo_storage_append_nickname(d, "sr", media_num);
1802 } else if (media == LEGACY_FLOPPY) {
1803 devinfo_storage_append_nickname(d, "fd", media_num);
1804 devinfo_storage_append_nickname(d, "diskette", media_num);
1805 devinfo_storage_append_nickname(d, "rdiskette", media_num);
1806 }
1807 }
1808