]>
Commit | Line | Data |
---|---|---|
c69f60f6 ER |
1 | diff --git a/eject.c b/eject.c |
2 | index 4175756..057d2ea 100644 | |
3 | --- a/eject.c | |
4 | +++ b/eject.c | |
5 | @@ -42,6 +42,7 @@ | |
6 | #include <string.h> | |
7 | #include <fcntl.h> | |
8 | #include <limits.h> | |
9 | +#include <dirent.h> | |
10 | ||
11 | #ifdef GETOPTLONG | |
12 | #include <getopt.h> | |
13 | @@ -1133,6 +1134,145 @@ static char *MultiplePartitions(const char *name) | |
14 | return 0; | |
15 | } | |
16 | ||
17 | +/* | |
18 | + * Find device name in /sys/block/. Returns NULL if not | |
19 | + * found. The returned pointer must be free()'d. | |
20 | + */ | |
21 | +static char* FindDeviceSysBlock(const char* deviceName) | |
22 | +{ | |
23 | + DIR *dir = opendir("/sys/block"); | |
24 | + struct dirent *d; | |
25 | + const char *baseName = strrchr(deviceName, '/'); | |
26 | + char *device; | |
27 | + int len; | |
28 | + | |
29 | + baseName = baseName ? baseName + 1 : deviceName; | |
30 | + if (!dir) { | |
31 | + fprintf(stderr, _("%s: can not open directory /sys/block/"), programName); | |
32 | + return NULL; | |
33 | + } | |
34 | + while ((d = readdir(dir)) != NULL) { | |
35 | + if (d->d_type != DT_DIR && d->d_type != DT_LNK && d->d_type != DT_UNKNOWN) | |
36 | + continue; | |
37 | + len = strlen(d->d_name); | |
38 | + if (!strncmp(baseName, d->d_name, len)) { | |
39 | + if ((*(baseName+len) >= '0' && | |
40 | + *(baseName+len) <= '9') || | |
41 | + *(baseName+len) == '\0') { | |
42 | + device = strdup(d->d_name); | |
43 | + closedir(dir); | |
44 | + return device; | |
45 | + } | |
46 | + } | |
47 | + } | |
48 | + closedir(dir); | |
49 | + return NULL; | |
50 | +} | |
51 | + | |
52 | +/* | |
53 | + * From given path gets a subsystem. Returns subsystem if any found | |
54 | + * otherwise returns NULL. Returned value must not be free()'d | |
55 | + */ | |
56 | +static char *GetSubSystem(const char *sysfspath) | |
57 | +{ | |
58 | + static char subsystem[PATH_MAX]; | |
59 | + char link_subsystem[PATH_MAX]; | |
60 | + struct stat buf; | |
61 | + char *pos; | |
62 | + | |
63 | + snprintf(link_subsystem, sizeof(link_subsystem), "%s/subsystem", sysfspath); | |
64 | + | |
65 | + if (lstat(link_subsystem, &buf) == -1) | |
66 | + return NULL; | |
67 | + if (!S_ISLNK(buf.st_mode)) | |
68 | + return NULL; | |
69 | + if (readlink(link_subsystem, subsystem, sizeof(subsystem)) == -1) | |
70 | + return NULL; | |
71 | + if ((pos = strrchr(subsystem, '/')) == NULL) | |
72 | + return NULL; | |
73 | + strncpy(subsystem, pos+1, sizeof(subsystem)); | |
74 | + | |
75 | + return subsystem; | |
76 | +} | |
77 | + | |
78 | +/* | |
79 | + * Check content of /sys/block/<dev>/removable. Returns 1 if the file | |
80 | + * contains '1' otherwise returns 0. | |
81 | + */ | |
82 | +static int CheckRemovable(const char* deviceName) | |
83 | +{ | |
84 | + FILE *fp; | |
85 | + int removable = 0; | |
86 | + char *device; | |
87 | + char path[PATH_MAX]; | |
88 | + | |
89 | + if ((device = FindDeviceSysBlock(deviceName)) == NULL) { | |
90 | + fprintf(stderr, | |
91 | + _("%s: did not find a device %s in /sys/block/\n"), | |
92 | + programName, deviceName); | |
93 | + exit(1); | |
94 | + } | |
95 | + snprintf(path, sizeof(path), "/sys/block/%s/removable", device); | |
96 | + free(device); | |
97 | + if((fp = fopen(path, "r")) == NULL) | |
98 | + return removable; | |
99 | + if (fgetc(fp) == '1') | |
100 | + removable = 1; | |
101 | + | |
102 | + fclose(fp); | |
103 | + return removable; | |
104 | +} | |
105 | + | |
106 | +/* Check if a device is on hotpluggable subsystem. Returns 1 if is | |
107 | + * otherwise returns 0. | |
108 | + */ | |
109 | +static int CheckHotpluggable(const char* deviceName) | |
110 | +{ | |
111 | + int hotpluggable = 0; | |
112 | + char *device; | |
113 | + char path[PATH_MAX]; | |
114 | + char *device_chain; | |
115 | + struct stat buf; | |
116 | + char *subsystem; | |
117 | + char *pos; | |
118 | + | |
119 | + if ((device = FindDeviceSysBlock(deviceName)) == NULL) { | |
120 | + fprintf(stderr, _("%s: did not find a device %s in /sys/block/\n"), | |
121 | + programName, deviceName); | |
122 | + exit(1); | |
123 | + } | |
124 | + snprintf(path, sizeof(path), "/sys/block/%s/device", device); | |
125 | + free(device); | |
126 | + | |
127 | + if (lstat(path, &buf) == -1) | |
128 | + return hotpluggable; | |
129 | + if (!S_ISLNK(buf.st_mode)) | |
130 | + return hotpluggable; | |
131 | + if ((device_chain = SymLink(path)) == NULL) | |
132 | + return hotpluggable; | |
133 | + while ( strncmp(device_chain, "", sizeof(device_chain) != 0)) { | |
134 | + subsystem = GetSubSystem(device_chain); | |
135 | + if (subsystem) { | |
136 | + /* as hotpluggable we assume devices on these buses */ | |
137 | + if (strncmp("usb", subsystem, sizeof("usb")) == 0 || | |
138 | + strncmp("ieee1394", subsystem, sizeof("ieee1394")) == 0 || | |
139 | + strncmp("pcmcia", subsystem, sizeof("pcmcia")) == 0 || | |
140 | + strncmp("mmc", subsystem, sizeof("mmc")) == 0 || | |
141 | + strncmp("ccw", subsystem, sizeof("ccw")) == 0) { | |
142 | + hotpluggable = 1; | |
143 | + break; | |
144 | + } | |
145 | + } | |
146 | + /* remove one member from devicechain */ | |
147 | + pos = strrchr(device_chain, '/'); | |
148 | + if (pos) | |
149 | + pos[0] = '\0'; | |
150 | + else | |
151 | + device_chain[0] = '\0'; | |
152 | + } | |
153 | + | |
154 | + return hotpluggable; | |
155 | +} | |
156 | ||
157 | /* handle -x option */ | |
158 | static void HandleXOption(char *deviceName) | |
159 | @@ -1276,6 +1416,17 @@ int main(int argc, char **argv) | |
160 | exit(0); | |
161 | } | |
162 | ||
163 | + /* Check if device has removable flag*/ | |
164 | + if (v_option) | |
165 | + printf(_("%s: checking if device \"%s\" has a removable or hotpluggable flag\n"), | |
166 | + programName, deviceName); | |
167 | + if (!CheckRemovable(deviceName) && !CheckHotpluggable(deviceName)) | |
168 | + { | |
169 | + fprintf(stderr, _("%s: device \"%s\" doesn't have a removable or hotpluggable flag\n"), | |
170 | + programName, deviceName); | |
171 | + exit(1); | |
172 | + } | |
173 | + | |
174 | /* handle -i option */ | |
175 | if (i_option) { | |
176 | fd = OpenDevice(deviceName); |