* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License.
- *
+ *
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <stddef.h>
#include <stdarg.h>
#include <stdio.h>
+#include <stdbool.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
return 0;
}
+static bool device_has_attribute(const char *path, const char *attr,
+ mode_t mode)
+{
+ char filename[PATH_SIZE];
+ struct stat statbuf;
+
+ strlcpy(filename, path, sizeof(filename));
+ strlcat(filename, attr, sizeof(filename));
+
+ if (stat(filename, &statbuf) < 0)
+ return false;
+
+ if (!(statbuf.st_mode & mode))
+ return false;
+
+ return true;
+}
static int device_list_insert(const char *path)
{
- char filename[PATH_SIZE];
char devpath[PATH_SIZE];
struct stat statbuf;
dbg("add '%s'" , path);
- /* we only have a device, if we have an uevent file */
- strlcpy(filename, path, sizeof(filename));
- strlcat(filename, "/uevent", sizeof(filename));
- if (stat(filename, &statbuf) < 0)
- return -1;
- if (!(statbuf.st_mode & S_IWUSR))
+ /* we only have a device, if we have a dev and an uevent file */
+ if (!device_has_attribute(path, "/dev", S_IRUSR) ||
+ !device_has_attribute(path, "/uevent", S_IWUSR))
return -1;
strlcpy(devpath, &path[4], sizeof(devpath));
return 0;
}
-
-static void scan_subsystem(const char *subsys)
+static void scan_subdir(const char *base, const char *subdir,
+ bool insert, int depth)
{
- char base[PATH_SIZE];
DIR *dir;
struct dirent *dent;
- strlcpy(base, "/sys/", sizeof(base));
- strlcat(base, subsys, sizeof(base));
-
dir = opendir(base);
- if (dir != NULL) {
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- char dirname[PATH_SIZE];
- DIR *dir2;
- struct dirent *dent2;
-
- if (dent->d_name[0] == '.')
- continue;
-
- strlcpy(dirname, base, sizeof(dirname));
- strlcat(dirname, "/", sizeof(dirname));
- strlcat(dirname, dent->d_name, sizeof(dirname));
- strlcat(dirname, "/devices", sizeof(dirname));
-
- /* look for devices */
- dir2 = opendir(dirname);
- if (dir2 != NULL) {
- for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
- char dirname2[PATH_SIZE];
-
- if (dent2->d_name[0] == '.')
- continue;
-
- strlcpy(dirname2, dirname, sizeof(dirname2));
- strlcat(dirname2, "/", sizeof(dirname2));
- strlcat(dirname2, dent2->d_name, sizeof(dirname2));
- device_list_insert(dirname2);
- }
- closedir(dir2);
- }
- }
- closedir(dir);
- }
-}
+ if (dir == NULL)
+ return;
-static void scan_block(void)
-{
- char base[PATH_SIZE];
- DIR *dir;
- struct dirent *dent;
+ for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ char dirname[PATH_SIZE];
- strlcpy(base, "/sys/block", sizeof(base));
+ if (dent->d_name[0] == '.')
+ continue;
- dir = opendir(base);
- if (dir != NULL) {
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- char dirname[PATH_SIZE];
- DIR *dir2;
- struct dirent *dent2;
+ strlcpy(dirname, base, sizeof(dirname));
+ strlcat(dirname, "/", sizeof(dirname));
+ strlcat(dirname, dent->d_name, sizeof(dirname));
- if (dent->d_name[0] == '.')
- continue;
+ if (insert) {
+ int err;
- strlcpy(dirname, base, sizeof(dirname));
- strlcat(dirname, "/", sizeof(dirname));
- strlcat(dirname, dent->d_name, sizeof(dirname));
- if (device_list_insert(dirname) != 0)
+ err = device_list_insert(dirname);
+ if (err)
continue;
-
- /* look for partitions */
- dir2 = opendir(dirname);
- if (dir2 != NULL) {
- for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
- char dirname2[PATH_SIZE];
-
- if (dent2->d_name[0] == '.')
- continue;
-
- if (!strcmp(dent2->d_name,"device"))
- continue;
-
- strlcpy(dirname2, dirname, sizeof(dirname2));
- strlcat(dirname2, "/", sizeof(dirname2));
- strlcat(dirname2, dent2->d_name, sizeof(dirname2));
- device_list_insert(dirname2);
- }
- closedir(dir2);
- }
}
- closedir(dir);
- }
-}
-
-static void scan_class(void)
-{
- char base[PATH_SIZE];
- DIR *dir;
- struct dirent *dent;
- strlcpy(base, "/sys/class", sizeof(base));
+ if (subdir)
+ strlcat(dirname, subdir, sizeof(base));
- dir = opendir(base);
- if (dir != NULL) {
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
- char dirname[PATH_SIZE];
- DIR *dir2;
- struct dirent *dent2;
-
- if (dent->d_name[0] == '.')
- continue;
-
- strlcpy(dirname, base, sizeof(dirname));
- strlcat(dirname, "/", sizeof(dirname));
- strlcat(dirname, dent->d_name, sizeof(dirname));
- dir2 = opendir(dirname);
- if (dir2 != NULL) {
- for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
- char dirname2[PATH_SIZE];
-
- if (dent2->d_name[0] == '.')
- continue;
-
- if (!strcmp(dent2->d_name, "device"))
- continue;
-
- strlcpy(dirname2, dirname, sizeof(dirname2));
- strlcat(dirname2, "/", sizeof(dirname2));
- strlcat(dirname2, dent2->d_name, sizeof(dirname2));
- device_list_insert(dirname2);
- }
- closedir(dir2);
- }
- }
- closedir(dir);
+ if (depth)
+ scan_subdir(dirname, NULL, true, depth - 1);
}
+
+ closedir(dir);
}
int main(int argc, char *argv[], char *envp[])
{
- char base[PATH_SIZE];
struct stat statbuf;
int option;
/* if we have /sys/subsystem, forget all the old stuff */
- scan_subsystem("bus");
- scan_class();
+ scan_subdir("/sys/bus", "/devices", false, 1);
+ scan_subdir("/sys/class", NULL, false, 1);
/* scan "block" if it isn't a "class" */
- strlcpy(base, "/sys/class/block", sizeof(base));
- if (stat(base, &statbuf) != 0)
- scan_block();
+ if (stat("/sys/class/block", &statbuf) != 0)
+ scan_subdir("/sys/block", NULL, true, 1);
exit: