]>
git.ipfire.org Git - ipfire-2.x.git/blob - src/install+setup/install/hw.c
1fca9fdfa9d3d2dee5c471f517ebdcfd5d9aef4f
1 /*#############################################################################
3 # IPFire - An Open Source Firewall Distribution #
4 # Copyright (C) 2014 IPFire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
22 #include <blkid/blkid.h>
29 #include <sys/ioctl.h>
30 #include <sys/mount.h>
37 struct hw
* hw_init() {
38 struct hw
* hw
= malloc(sizeof(*hw
));
42 hw
->udev
= udev_new();
44 fprintf(stderr
, "Could not create udev instance\n");
51 void hw_free(struct hw
* hw
) {
58 static int strstartswith(const char* a
, const char* b
) {
59 return (strncmp(a
, b
, strlen(b
)) == 0);
62 int hw_mount(const char* source
, const char* target
, int flags
) {
63 return mount(source
, target
, "iso9660", flags
, NULL
);
66 int hw_umount(const char* target
) {
67 return umount2(target
, MNT_DETACH
);
70 static int hw_test_source_medium(const char* path
) {
71 int ret
= hw_mount(path
, SOURCE_MOUNT_PATH
, MS_RDONLY
);
73 // If the source could not be mounted we
78 // Check if the test file exists.
79 ret
= access(SOURCE_TEST_FILE
, F_OK
);
81 // Umount the test device.
82 hw_umount(SOURCE_MOUNT_PATH
);
87 char* hw_find_source_medium(struct hw
* hw
) {
90 struct udev_enumerate
* enumerate
= udev_enumerate_new(hw
->udev
);
92 udev_enumerate_add_match_subsystem(enumerate
, "block");
93 udev_enumerate_scan_devices(enumerate
);
95 struct udev_list_entry
* devices
= udev_enumerate_get_list_entry(enumerate
);
97 struct udev_list_entry
* dev_list_entry
;
98 udev_list_entry_foreach(dev_list_entry
, devices
) {
99 const char* path
= udev_list_entry_get_name(dev_list_entry
);
100 struct udev_device
* dev
= udev_device_new_from_syspath(hw
->udev
, path
);
102 const char* dev_path
= udev_device_get_devnode(dev
);
104 // Skip everything what we cannot work with
105 if (strstartswith(dev_path
, "/dev/loop") || strstartswith(dev_path
, "/dev/fd") ||
106 strstartswith(dev_path
, "/dev/ram"))
109 if (hw_test_source_medium(dev_path
)) {
110 ret
= strdup(dev_path
);
113 udev_device_unref(dev
);
115 // If a suitable device was found the search will end.
120 udev_enumerate_unref(enumerate
);
125 static struct hw_disk
** hw_create_disks() {
126 struct hw_disk
** ret
= malloc(sizeof(*ret
) * (HW_MAX_DISKS
+ 1));
131 static unsigned long long hw_block_device_get_size(const char* dev
) {
132 int fd
= open(dev
, O_RDONLY
);
136 unsigned long long size
= blkid_get_dev_size(fd
);
142 struct hw_disk
** hw_find_disks(struct hw
* hw
) {
143 struct hw_disk
** ret
= hw_create_disks();
144 struct hw_disk
** disks
= ret
;
146 struct udev_enumerate
* enumerate
= udev_enumerate_new(hw
->udev
);
148 udev_enumerate_add_match_subsystem(enumerate
, "block");
149 udev_enumerate_scan_devices(enumerate
);
151 struct udev_list_entry
* devices
= udev_enumerate_get_list_entry(enumerate
);
153 struct udev_list_entry
* dev_list_entry
;
154 unsigned int i
= HW_MAX_DISKS
;
155 udev_list_entry_foreach(dev_list_entry
, devices
) {
156 const char* path
= udev_list_entry_get_name(dev_list_entry
);
157 struct udev_device
* dev
= udev_device_new_from_syspath(hw
->udev
, path
);
159 const char* dev_path
= udev_device_get_devnode(dev
);
161 // Skip everything what we cannot work with
162 if (strstartswith(dev_path
, "/dev/loop") || strstartswith(dev_path
, "/dev/fd") ||
163 strstartswith(dev_path
, "/dev/ram") || strstartswith(dev_path
, "/dev/sr")) {
164 udev_device_unref(dev
);
168 // DEVTYPE must be disk (otherwise we will see all sorts of partitions here)
169 const char* devtype
= udev_device_get_property_value(dev
, "DEVTYPE");
170 if (devtype
&& (strcmp(devtype
, "disk") != 0)) {
171 udev_device_unref(dev
);
175 // Skip all source mediums
176 if (hw_test_source_medium(dev_path
) == 0) {
177 udev_device_unref(dev
);
181 // Skip devices with a size of zero
182 unsigned long long size
= hw_block_device_get_size(dev_path
);
184 udev_device_unref(dev
);
188 struct hw_disk
* disk
= malloc(sizeof(*disk
));
194 strncpy(disk
->path
, dev_path
, sizeof(disk
->path
));
199 const char* vendor
= udev_device_get_property_value(dev
, "ID_VENDOR");
201 vendor
= udev_device_get_sysattr_value(dev
, "vendor");
203 vendor
= udev_device_get_sysattr_value(dev
, "manufacturer");
207 strncpy(disk
->vendor
, vendor
, sizeof(disk
->vendor
));
210 const char* model
= udev_device_get_property_value(dev
, "ID_MODEL");
212 model
= udev_device_get_sysattr_value(dev
, "model");
214 model
= udev_device_get_sysattr_value(dev
, "product");
218 strncpy(disk
->model
, model
, sizeof(disk
->model
));
220 snprintf(disk
->description
, sizeof(disk
->description
),
221 "%4.1fGB %s - %s", (double)disk
->size
/ pow(1024, 3),
222 disk
->vendor
, disk
->model
);
229 udev_device_unref(dev
);
232 udev_enumerate_unref(enumerate
);
239 void hw_free_disks(struct hw_disk
** disks
) {
240 struct hw_disk
** disk
= disks
;
242 while (*disk
!= NULL
) {
243 if (--(*disk
)->ref
== 0)
252 unsigned int hw_count_disks(struct hw_disk
** disks
) {
253 unsigned int ret
= 0;
261 struct hw_disk
** hw_select_disks(struct hw_disk
** disks
, int* selection
) {
262 struct hw_disk
** ret
= hw_create_disks();
263 struct hw_disk
** selected_disks
= ret
;
265 unsigned int num_disks
= hw_count_disks(disks
);
267 for (unsigned int i
= 0; i
< num_disks
; i
++) {
268 if (selection
&& selection
[i
]) {
269 struct hw_disk
*selected_disk
= disks
[i
];
270 selected_disk
->ref
++;
272 *selected_disks
++ = selected_disk
;
277 *selected_disks
= NULL
;
282 struct hw_destination
* hw_make_destination(int part_type
, struct hw_disk
** disks
) {
283 struct hw_destination
* dest
= malloc(sizeof(*dest
));
285 if (part_type
== HW_PART_TYPE_NORMAL
) {
286 dest
->disk1
= *disks
;
289 strncpy(dest
->path
, dest
->disk1
->path
, sizeof(dest
->path
));
291 } else if (part_type
== HW_PART_TYPE_RAID1
) {
292 dest
->disk1
= *disks
++;
293 dest
->disk2
= *disks
;
295 snprintf(dest
->path
, sizeof(dest
->path
), "/dev/md0");
298 // Is this a RAID device?
299 dest
->is_raid
= (part_type
> HW_PART_TYPE_NORMAL
);
301 // Set partition names
303 snprintf(path
, sizeof(path
), "%s%s", dest
->path
, (dest
->is_raid
) ? "p" : "");
304 snprintf(dest
->part_boot
, sizeof(dest
->part_boot
), "%s1", path
);
305 snprintf(dest
->part_swap
, sizeof(dest
->part_swap
), "%s2", path
);
306 snprintf(dest
->part_root
, sizeof(dest
->part_root
), "%s3", path
);
307 snprintf(dest
->part_data
, sizeof(dest
->part_data
), "%s4", path
);
310 dest
->size
= (dest
->disk1
->size
>= dest
->disk2
->size
) ?
311 dest
->disk1
->size
: dest
->disk2
->size
;
313 dest
->size
= dest
->disk1
->size
;