[multipathd] unix socket daemon control interface
[multipath-tools/.git] / libmultipath / dmparser.c
1 /*
2  * Christophe Varoqui (2004)
3  * This code is GPLv2, see license file
4  *
5  */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "vector.h"
11 #include "memory.h"
12 #include "structs.h"
13 #include "util.h"
14 #include "debug.h"
15
16 #define WORD_SIZE 64
17
18 static int
19 merge_words (char ** dst, char * word, int space)
20 {
21         char * p;
22         int len;
23
24         len = strlen(*dst) + strlen(word) + space;
25         *dst = REALLOC(*dst, len + 1);
26
27         if (!*dst)
28                 return 1;
29
30         p = *dst;
31
32         while (*p != '\0')
33                 p++;
34
35         while (space) {
36                 *p = ' ';
37                 p++;
38                 space--;
39         }
40         strncpy(p, word, strlen(word) + 1);
41
42         return 0;
43 }
44
45 extern int
46 disassemble_map (vector pathvec, char * params, struct multipath * mpp)
47 {
48         char * word;
49         char * p;
50         int i, j, k;
51         int num_features = 0;
52         int num_hwhandler = 0;
53         int num_pg = 0;
54         int num_pg_args = 0;
55         int num_paths = 0;
56         int num_paths_args = 0;
57         struct path * pp;
58         struct pathgroup * pgp;
59
60         p = params;
61
62         /*
63          * features
64          */
65         p += get_word(p, &mpp->features);
66
67         if (!mpp->features)
68                 return 1;
69
70         num_features = atoi(mpp->features);
71
72         for (i = 0; i < num_features; i++) {
73                 p += get_word(p, &word);
74
75                 if (!word)
76                         return 1;
77
78                 if (merge_words(&mpp->features, word, 1)) {
79                         FREE(word);
80                         return 1;
81                 }
82                 FREE(word);
83         }
84
85         /*
86          * hwhandler
87          */
88         p += get_word(p, &mpp->hwhandler);
89
90         if (!mpp->hwhandler)
91                 return 1;
92
93         num_hwhandler = atoi(mpp->hwhandler);
94
95         for (i = 0; i < num_hwhandler; i++) {
96                 p += get_word(p, &word);
97
98                 if (!word)
99                         return 1;
100
101                 if (merge_words(&mpp->hwhandler, word, 1)) {
102                         FREE(word);
103                         return 1;
104                 }
105                 FREE(word);
106         }
107
108         /*
109          * nb of path groups
110          */
111         p += get_word(p, &word);
112
113         if (!word)
114                 return 1;
115
116         num_pg = atoi(word);
117         FREE(word);
118
119         if (num_pg > 0 && !mpp->pg)
120                 mpp->pg = vector_alloc();
121         
122         if (!mpp->pg)
123                 return 1;
124         /*
125          * first pg to try
126          */
127         p += get_word(p, &word);
128
129         if (!word)
130                 goto out;
131
132         mpp->nextpg = atoi(word);
133         FREE(word);
134
135         for (i = 0; i < num_pg; i++) {
136                 /*
137                  * selector
138                  */
139
140                 if (!mpp->selector) {
141                         p += get_word(p, &mpp->selector);
142
143                         if (!mpp->selector)
144                                 goto out;
145
146                         /*
147                          * selector args
148                          */
149                         p += get_word(p, &word);
150
151                         if (!word)
152                                 goto out;
153
154                         num_pg_args = atoi(word);
155                         
156                         if (merge_words(&mpp->selector, word, 1)) {
157                                 FREE(word);
158                                 goto out1;
159                         }
160                         FREE(word);
161                 } else {
162                         p += get_word(p, NULL);
163                         p += get_word(p, NULL);
164                 }
165
166                 for (j = 0; j < num_pg_args; j++)
167                         p += get_word(p, NULL);
168
169                 /*
170                  * paths
171                  */
172                 pgp = alloc_pathgroup();
173                 
174                 if (!pgp)
175                         goto out;
176
177                 if (store_pathgroup(mpp->pg, pgp))
178                         goto out;
179
180                 p += get_word(p, &word);
181
182                 if (!word)
183                         goto out;
184
185                 num_paths = atoi(word);
186                 FREE(word);
187
188                 p += get_word(p, &word);
189
190                 if (!word)
191                         goto out;
192
193                 num_paths_args = atoi(word);
194                 FREE(word);
195
196                 for (j = 0; j < num_paths; j++) {
197                         pp = NULL;
198                         p += get_word(p, &word);
199
200                         if (!word)
201                                 goto out;
202
203                         if (pathvec)
204                                 pp = find_path_by_devt(pathvec, word);
205
206                         if (!pp) {
207                                 pp = alloc_path();
208
209                                 if (!pp)
210                                         goto out1;
211
212                                 strncpy(pp->dev_t, word, BLK_DEV_SIZE);
213                         }
214                         FREE(word);
215
216                         if (store_path(pgp->paths, pp))
217                                 goto out;
218
219                         if (!strlen(mpp->wwid))
220                                 strncpy(mpp->wwid, pp->wwid, WWID_SIZE);
221
222                         for (k = 0; k < num_paths_args; k++)
223                                 p += get_word(p, NULL);
224                 }
225         }
226         return 0;
227 out1:
228         FREE(word);
229 out:
230         free_pgvec(mpp->pg, KEEP_PATHS);
231         return 1;
232 }
233
234 extern int
235 disassemble_status (char * params, struct multipath * mpp)
236 {
237         char * word;
238         char * p;
239         int i, j;
240         int num_feature_args;
241         int num_hwhandler_args;
242         int num_pg;
243         int num_pg_args;
244         int num_paths;
245         struct path * pp;
246         struct pathgroup * pgp;
247
248         p = params;
249
250         /*
251          * features
252          */
253         p += get_word(p, &word);
254
255         if (!word)
256                 return 1;
257
258         num_feature_args = atoi(word);
259         FREE(word);
260
261         for (i = 0; i < num_feature_args; i++) {
262                 if (i == 1) {
263                         p += get_word(p, &word);
264
265                         if (!word)
266                                 return 1;
267
268                         mpp->queuedio = atoi(word);
269                         FREE(word);
270                         continue;
271                 }
272                 /* unknown */
273                 p += get_word(p, NULL);
274         }
275         /*
276          * hwhandler
277          */
278         p += get_word(p, &word);
279
280         if (!word)
281                 return 1;
282
283         num_hwhandler_args = atoi(word);
284         FREE(word);
285
286         for (i = 0; i < num_hwhandler_args; i++)
287                 p += get_word(p, NULL);
288
289         /*
290          * nb of path groups
291          */
292         p += get_word(p, &word);
293
294         if (!word)
295                 return 1;
296
297         num_pg = atoi(word);
298         FREE(word);
299
300         /*
301          * next pg to try
302          */
303         p += get_word(p, NULL);
304
305         if (VECTOR_SIZE(mpp->pg) < num_pg)
306                 return 1;
307
308         for (i = 0; i < num_pg; i++) {
309                 pgp = VECTOR_SLOT(mpp->pg, i);
310                 /*
311                  * PG status
312                  */
313                 p += get_word(p, &word);
314
315                 if (!word)
316                         return 1;
317
318                 switch (*word) {
319                 case 'D':
320                         pgp->status = PGSTATE_DISABLED;
321                         break;
322                 case 'A':
323                         pgp->status = PGSTATE_ACTIVE;
324                         break;
325                 case 'E':
326                         pgp->status = PGSTATE_ENABLED;
327                         break;
328                 default:
329                         pgp->status = PGSTATE_RESERVED;
330                         break;
331                 }
332                 FREE(word);
333
334                 /*
335                  * undef ?
336                  */
337                 p += get_word(p, NULL);
338
339                 p += get_word(p, &word);
340
341                 if (!word)
342                         return 1;
343
344                 num_paths = atoi(word);
345                 FREE(word);
346
347                 p += get_word(p, &word);
348
349                 if (!word)
350                         return 1;
351
352                 num_pg_args = atoi(word);
353                 FREE(word);
354
355                 if (VECTOR_SIZE(pgp->paths) < num_paths)
356                         return 1;
357
358                 for (j = 0; j < num_paths; j++) {
359                         pp = VECTOR_SLOT(pgp->paths, j);
360                         /*
361                          * path
362                          */
363                         p += get_word(p, NULL);
364
365                         /*
366                          * path status
367                          */
368                         p += get_word(p, &word);
369
370                         if (!word)
371                                 return 1;
372
373                         switch (*word) {
374                         case 'F':
375                                 pp->dmstate = PSTATE_FAILED;
376                                 break;
377                         case 'A':
378                                 pp->dmstate = PSTATE_ACTIVE;
379                                 break;
380                         default:
381                                 break;
382                         }
383                         FREE(word);
384                         /*
385                          * fail count
386                          */
387                         p += get_word(p, &word);
388
389                         if (!word)
390                                 return 1;
391
392                         pp->failcount = atoi(word);
393                         FREE(word);
394                 }
395                 /*
396                  * selector args
397                  */
398                 for (j = 0; j < num_pg_args; j++)
399                         p += get_word(p, NULL);
400         }
401         return 0;
402 }