]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/install+setup/install/hw.c
eb52f889d6e207bdb9d3e16ba0c3838960587944
[people/pmueller/ipfire-2.x.git] / src / install+setup / install / hw.c
1 /*#############################################################################
2 # #
3 # IPFire - An Open Source Firewall Distribution #
4 # Copyright (C) 2014 IPFire development team #
5 # #
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. #
10 # #
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. #
15 # #
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/>. #
18 # #
19 #############################################################################*/
20
21 #include <assert.h>
22 #include <libudev.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/mount.h>
27 #include <unistd.h>
28
29 #include "hw.h"
30
31 struct hw* hw_init() {
32 struct hw* hw = malloc(sizeof(*hw));
33 assert(hw);
34
35 // Initialize libudev
36 hw->udev = udev_new();
37 if (!hw->udev) {
38 fprintf(stderr, "Could not create udev instance\n");
39 exit(1);
40 }
41
42 return hw;
43 }
44
45 void hw_free(struct hw* hw) {
46 if (hw->udev)
47 udev_unref(hw->udev);
48
49 free(hw);
50 }
51
52 static int strstartswith(const char* a, const char* b) {
53 return (strncmp(a, b, strlen(b)) == 0);
54 }
55
56 int hw_mount(const char* source, const char* target, int flags) {
57 return mount(source, target, "iso9660", flags, NULL);
58 }
59
60 int hw_umount(const char* target) {
61 return umount2(target, MNT_DETACH);
62 }
63
64 static int hw_test_source_medium(const char* path) {
65 int ret = hw_mount(path, SOURCE_MOUNT_PATH, MS_RDONLY);
66
67 // If the source could not be mounted we
68 // cannot proceed.
69 if (ret)
70 return ret;
71
72 // Check if the test file exists.
73 ret = access(SOURCE_TEST_FILE, F_OK);
74
75 // Umount the test device.
76 hw_umount(SOURCE_MOUNT_PATH);
77
78 return ret;
79 }
80
81 char* hw_find_source_medium(struct hw* hw) {
82 char* ret = NULL;
83
84 struct udev_enumerate* enumerate = udev_enumerate_new(hw->udev);
85
86 udev_enumerate_add_match_subsystem(enumerate, "block");
87 udev_enumerate_scan_devices(enumerate);
88
89 struct udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);
90
91 struct udev_list_entry* dev_list_entry;
92 udev_list_entry_foreach(dev_list_entry, devices) {
93 const char* path = udev_list_entry_get_name(dev_list_entry);
94 struct udev_device* dev = udev_device_new_from_syspath(hw->udev, path);
95
96 const char* dev_path = udev_device_get_devnode(dev);
97
98 // Skip everything what we cannot work with
99 if (strstartswith(dev_path, "/dev/loop") || strstartswith(dev_path, "/dev/fd") ||
100 strstartswith(dev_path, "/dev/ram"))
101 continue;
102
103 if (hw_test_source_medium(dev_path)) {
104 ret = strdup(dev_path);
105 }
106
107 udev_device_unref(dev);
108
109 // If a suitable device was found the search will end.
110 if (ret)
111 break;
112 }
113
114 udev_enumerate_unref(enumerate);
115
116 return ret;
117 }