Remove all references to hand-craftes sysfs code
[multipath-tools/.git] / libmultipath / sysfs.c
1 /*
2  * Copyright (C) 2005-2006 Kay Sievers <kay.sievers@vrfy.org>
3  *
4  *      This program is free software; you can redistribute it and/or modify it
5  *      under the terms of the GNU General Public License as published by the
6  *      Free Software Foundation version 2 of the License.
7  *
8  *      This program is distributed in the hope that it will be useful, but
9  *      WITHOUT ANY WARRANTY; without even the implied warranty of
10  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  *      General Public License for more details.
12  *
13  *      You should have received a copy of the GNU General Public License along
14  *      with this program; if not, write to the Free Software Foundation, Inc.,
15  *      51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16  *
17  */
18
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stddef.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <sys/stat.h>
28 #include <string.h>
29 #include <dirent.h>
30 #include <libudev.h>
31
32 #include "checkers.h"
33 #include "vector.h"
34 #include "structs.h"
35 #include "sysfs.h"
36 #include "list.h"
37 #include "util.h"
38 #include "debug.h"
39 #include "devmapper.h"
40
41 ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
42                              char * value, size_t value_len)
43 {
44         const char *devpath;
45         struct stat statbuf;
46         int fd;
47         ssize_t size = -1;
48
49         if (!dev || !attr_name || !value)
50                 return 0;
51
52         devpath = udev_device_get_syspath(dev);
53         condlog(4, "open '%s'/'%s'", devpath, attr_name);
54         if (stat(devpath, &statbuf) != 0) {
55                 condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
56                 return 0;
57         }
58
59         /* skip directories */
60         if (S_ISDIR(statbuf.st_mode))
61                 return 0;
62
63         /* skip non-writeable files */
64         if ((statbuf.st_mode & S_IWUSR) == 0)
65                 return 0;
66
67         /* write attribute value */
68         fd = open(devpath, O_WRONLY);
69         if (fd < 0) {
70                 condlog(4, "attribute '%s' can not be opened: %s",
71                         devpath, strerror(errno));
72                 return 0;
73         }
74         size = write(fd, value, value_len);
75         if (size < 0) {
76                 condlog(4, "write to %s failed: %s", devpath, strerror(errno));
77                 size = 0;
78         } else if (size < value_len) {
79                 condlog(4, "tried to write %ld to %s. Wrote %ld\n",
80                         (long)value_len, devpath, (long)size);
81                 size = 0;
82         }
83
84         close(fd);
85         return size;
86 }
87
88 int
89 sysfs_get_size (struct path *pp, unsigned long long * size)
90 {
91         const char * attr;
92         int r;
93
94         if (!pp->udev)
95                 return 1;
96
97         attr = udev_device_get_sysattr_value(pp->udev, "size");
98         if (!attr) {
99                 condlog(3, "%s: No size attribute in sysfs", pp->dev);
100                 return 1;
101         }
102
103         r = sscanf(attr, "%llu\n", size);
104
105         if (r != 1) {
106                 condlog(3, "%s: Cannot parse size attribute '%s'",
107                         pp->dev, attr);
108                 return 1;
109         }
110
111         return 0;
112 }
113
114 int sysfs_check_holders(char * check_devt, char * new_devt)
115 {
116         unsigned int major, new_minor, table_minor;
117         char path[PATH_SIZE], check_dev[PATH_SIZE];
118         char * table_name;
119         DIR *dirfd;
120         struct dirent *holder;
121
122         if (sscanf(new_devt,"%d:%d", &major, &new_minor) != 2) {
123                 condlog(1, "invalid device number %s", new_devt);
124                 return 0;
125         }
126
127         if (devt2devname(check_dev, PATH_SIZE, check_devt))
128                 return 0;
129
130         condlog(3, "%s: checking holder", check_dev);
131
132         snprintf(path, PATH_SIZE, "/sys/block/%s/holders", check_dev);
133         dirfd = opendir(path);
134         if (dirfd == NULL) {
135                 condlog(3, "%s: failed to open directory %s (%d)",
136                         check_dev, path, errno);
137                 return 0;
138         }
139         while ((holder = readdir(dirfd)) != NULL) {
140                 if ((strcmp(holder->d_name,".") == 0) ||
141                     (strcmp(holder->d_name,"..") == 0))
142                         continue;
143
144                 if (sscanf(holder->d_name, "dm-%d", &table_minor) != 1) {
145                         condlog(3, "%s: %s is not a dm-device",
146                                 check_dev, holder->d_name);
147                         continue;
148                 }
149                 if (table_minor == new_minor) {
150                         condlog(3, "%s: holder already correct", check_dev);
151                         continue;
152                 }
153                 table_name = dm_mapname(major, table_minor);
154
155                 condlog(3, "%s: reassign table %s old %s new %s", check_dev,
156                         table_name, check_devt, new_devt);
157
158                 dm_reassign_table(table_name, check_devt, new_devt);
159                 FREE(table_name);
160         }
161         closedir(dirfd);
162
163         return 0;
164 }