2 * Access helpers for sysfs.
3 * Copyright (c) Mark Lord 2008
5 * You may use/distribute this freely, under the terms of either
6 * (your choice) the GNU General Public License version 2,
7 * or a BSD style license.
17 #include <linux/types.h>
21 static char *path_append (char *path, const char *new)
23 char *pathtail = path + strlen(path);
26 strcpy(pathtail+1, new);
30 static int sysfs_write_attr (char *path, const char *attr, const char *fmt, void *val, int verbose)
33 int count = -1, err = 0;
34 char *pathtail = path_append(path, attr);
36 fp = fopen(path, "w");
39 } else if (fmt[0] != '%') {
44 count = fprintf(fp, fmt, val);
48 count = fprintf(fp, fmt, *(unsigned int *)val);
52 count = fprintf(fp, fmt, *(unsigned long long *)val);
54 count = fprintf(fp, fmt, *(unsigned long *)val);
63 if (err && verbose) perror(path);
68 static int sysfs_read_attr (char *path, const char *attr, const char *fmt, void *val1, void *val2, int verbose)
72 char *pathtail = path_append(path, attr);
74 fp = fopen(path, "r");
78 count = fscanf(fp, fmt, val1, val2);
79 if (count != (val2 ? 2 : 1))
80 err = (count == EOF) ? errno : EINVAL;
83 if (err && verbose) perror(path);
88 static int sysfs_find_dev2 (char *path, dev_t dev, int recurse, int verbose)
94 if (!(dp = opendir(path))) {
96 if (verbose) perror(path);
99 pathtail = path + strlen(path);
100 while ((entry = readdir(dp)) != NULL) {
101 if ((entry->d_type == DT_DIR || entry->d_type == DT_LNK) && entry->d_name[0] != '.') {
102 unsigned int maj, min;
103 sprintf(pathtail, "/%s", entry->d_name);
104 if (sysfs_read_attr(path, "/dev", "%u:%u", &maj, &min, verbose))
106 else if (maj != major(dev))
108 if (min == minor(dev)
109 || (recurse && sysfs_find_dev2(path, dev, recurse - 1, verbose) == 0)) {
118 fprintf(stderr, "%u,%u: device not found in /sys\n", major(dev), minor(dev));
122 static int sysfs_find_dev (dev_t dev, char *path, int verbose)
124 int err, recurse = 1;
126 strcpy(path, "/sys/block");
127 err = sysfs_find_dev2(path, dev, recurse, 0);
129 fprintf(stderr, "%s(%u:%u): %s\n", __func__,
130 major(dev), minor(dev), strerror(err));
134 static int get_dev_from_fd (int fd, dev_t *dev, int verbose)
138 if (0 != fstat(fd, &st)) {
140 if (verbose) perror(" fstat() failed");
143 if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
150 static int sysfs_find_fd (int fd, char **path_p, int verbose)
152 static int have_prev = 0;
154 static char path[PATH_MAX];
158 memset(&dev, 0, sizeof(dev));
159 err = get_dev_from_fd(fd, &dev, verbose);
161 if (have_prev && 0 == memcmp(&dev, &prev, sizeof(dev))) {
162 /*re-use previous path, since dev was unchanged from before */
166 err = sysfs_find_dev(dev, path, verbose);
176 int sysfs_get_attr (int fd, const char *attr, const char *fmt, void *val1, void *val2, int verbose)
181 err = sysfs_find_fd(fd, &path, verbose);
183 err = sysfs_read_attr(path, attr, fmt, val1, val2, verbose);
187 int sysfs_set_attr (int fd, const char *attr, const char *fmt, void *val_p, int verbose)
192 err = sysfs_find_fd(fd, &path, verbose);
194 err = sysfs_write_attr(path, attr, fmt, val_p, verbose);