15 static int parse_opts(const char *str, char *ow_path, size_t pathlen, double *offset)
18 const char *start_str = str;
19 const char offset_str[] = "offset=";
25 * Skip the onewire path entry. Options begin after the first
32 /* Copy the onewire path without options */
33 strncpy(ow_path, start_str, pathlen);
34 ow_path[str - start_str] = '\0';
36 /* Get the next non-space, which is where the argument begins */
41 if (strncmp(str, offset_str, sizeof(offset_str) - 1))
43 str += sizeof(offset_str) - 1;
45 *offset = strtod(str, &endptr);
53 static int make_uncached(char *path, size_t len)
55 char p1[32], p2[32], *p = path;
57 if (strstr(path, "/uncached/"))
61 * Naively assume the "uncached" string can be put after the
64 while (*p && *p != '/')
73 strncpy(p1, path, sizeof(p1));
74 strncpy(p2, p, sizeof(p2));
75 snprintf(path, len, "%s/uncached/%s", p1, p2);
80 static int owfs_read(const char *mount_point, const char *path, char **res)
86 snprintf(file, sizeof(file), "%s/%s", mount_point, path);
88 fd = open(file, O_RDONLY | O_CLOEXEC);
90 pr_err("Failed to open file %s: %m\n", file);
94 ret = read(fd, result, sizeof(result));
96 pr_err("Failed to read from file %s: %m\n", file);
100 *res = strndup(result, sizeof(result));
108 static int is_mount_point(const char *str)
111 * Filesystem paths begin with a slash, everything else must
112 * be a network addresses
120 static int onewire_parser(char *rrd_data, const char **parser_data)
123 const char *server_addr, *mount_point;
126 int max_str = RRD_DATA_MAX_LEN;
127 int is_mountpoint = is_mount_point(parser_data[0]);
130 pr_err("No parser data available\n");
135 mount_point = parser_data[0];
138 pr_err("Server address not specified\n");
142 server_addr = parser_data[0];
145 pr_err("Server address not specified\n");
149 h = OWNET_init(server_addr);
151 pr_err("Failed to connect to server %s\n", server_addr);
156 while (parser_data[i]) {
157 double offset = 0, data;
162 if (!strcmp("U", parser_data[i])) {
164 ret = snprintf(rrd_data, max_str, "U");
170 parse_opts(parser_data[i], ow_path, sizeof(ow_path), &offset);
177 pr_info("Reading data for entry %s with offset of %.2f\n",
181 ret = owfs_read(mount_point, ow_path, &tmp);
183 ret = OWNET_read(h, ow_path, &tmp);
185 /* Skip leading white space */
187 for (j = 0; j < ret && *tmp2 == ' '; j++)
191 fail = !strncmp(tmp2, "85", 2);
196 * In case of failure, retry with uncached
197 * data. This is likely to help as it forces a
198 * retry even if the sensor is missing from
199 * the cache. We thread "85" also as a failure
200 * above, as temp sensors some times report 85
201 * under faulty conditions.
203 if (ret > 0 && !fail)
206 ret = make_uncached(ow_path, sizeof(ow_path));
207 if (retries >= 10 || ret < 0) {
208 pr_err("Failed to read entry %s: %m\n",
217 /* The data from OWNET_read appears to not be NULL terminated */
218 memcpy(buf, tmp, MIN(ret, sizeof(buf) -1));
222 data = strtod(buf, &endptr);
225 pr_err("Failed to parse data %s\n", buf);
231 ret = snprintf(rrd_data, max_str, "%f", data);
240 ret = snprintf(rrd_data, max_str, ":");
252 static struct parser_info onewire_parser_info = {
254 .parse = onewire_parser,
257 static int init_onewire_parser(void)
259 return register_parser(&onewire_parser_info);
262 struct plugin_info plugin_info = {
263 .name = "onewire_parser",
264 .init = init_onewire_parser,
265 .version = RRDD_VERSION,