"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "mapscsi-0.0.11/mapscsi.c" of archive mapscsi-0.0.11.tar.gz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /*
2 * mapscsi - program for creating consistent scsi device mappings
3 *
4 * Author: Michael Clark <michael@metaparadigm.com>
5 * Copyright Metaparadigm Pte. Ltd. 2001
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <fcntl.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <libgen.h>
23 #include <signal.h>
24 #include <syslog.h>
25
26 #include "qlogic_api.h"
27 #include "scsi_api.h"
28 #include "mapscsi.h"
29
30 /* #define DEBUG 1 */
31
32
33 /* file locations */
34 static char* rules_file = "/etc/mapscsi.rules";
35 static char* devicemap_file = "/var/state/mapscsi/devicemap";
36
37
38 /* string globals */
39 static const char* device_tmpl = "/dev/%D/c%hb%ct%tu%l";
40 static const char* partition_tmpl = "/dev/%D/c%hb%ct%tu%lp%p";
41
42
43 /* command line flags */
44 static int silent_flag = 0; /* don't show mappings on stdout */
45 static int execute_flag = 0; /* process rules and make links */
46 static int bkgnd_flag = 0; /* run in the background */
47 static int print_flag = 0; /* print device scan information */
48 static int rm_links_flag = 1; /* remove links in state file */
49 static int save_state_flag = 1; /* save created links to state file */
50 static int sg_numeric = 1; /* use numeric sg device names */
51
52
53 /* daemon mode exit signal variable */
54 static volatile int running;
55
56 /* linked list globals */
57 static scsi_map_rule_t *rules_head = NULL;
58 static scsi_map_t *devmap_head = NULL;
59 static scsi_map_t *devmap_last;
60
61
62 static int subst_device(char *dest, int dest_size,
63 scsi_device_t *scsidev,
64 const char *template)
65 {
66 const char *r = template;
67 char *w = dest;
68 int len = dest_size;
69
70 while(*r) {
71 char c;
72 int l;
73
74 if(*r == '%') {
75 scsi_device_param_t *param = params;
76 r++;
77 c = *r++;
78 while(param->substchar) {
79 if(param->substchar == c) break;
80 param++;
81 }
82 if(param->enc) {
83 l = param->enc(w, ((void*)scsidev)+param->offset, len);
84 } else {
85 fprintf(stderr, "subst_device: invalid subsitution "
86 "symbol '%c'\n", *r);
87 return -1;
88 }
89
90 if(l == -1) {
91 fprintf(stderr, "subst_device: buffer overun\n");
92 return -1;
93 }
94 len -= l;
95 w += l;
96 } else {
97 *w++ = *r++;
98 len--;
99 if(len <= 0) {
100 fprintf(stderr, "subst_device: buffer overun\n");
101 return -1;
102 }
103 }
104 }
105 *w = '\0';
106 return 0;
107 }
108
109
110 static int make_link(const char *linkname, const char* device)
111 {
112 char pathtemp[PATH_MAX+1];
113 struct stat s;
114 int rc, nc;
115
116 /* make needed directories */
117 do {
118 nc = 0;
119 strcpy(pathtemp, linkname);
120 while(dirname(pathtemp) && strcmp(pathtemp, ".") != 0
121 && strcmp(pathtemp, "/") != 0) {
122 if((rc = stat(pathtemp, &s)) < 0 && errno == ENOENT) {
123 if((rc = mkdir(pathtemp, 0777)) < 0 && errno != ENOENT) {
124 return -1;
125 } else {
126 nc++;
127 }
128 } else if (rc < 0) {
129 return -1;
130 }
131 }
132 } while (nc > 0);
133
134 /* make the link */
135 #ifdef DEBUG
136 printf("symlink %s %s\n", device, linkname);
137 #endif
138 if(symlink(device, linkname) < 0) {
139 return -1;
140 }
141
142 return 0;
143 }
144
145
146 static unsigned int hash_partitions()
147 {
148 FILE *parts;
149 char data[256];
150
151 unsigned int hash = 12345;
152
153 if((parts = fopen("/proc/partitions", "r")) == NULL) {
154 perror("hash_partitions: fopen");
155 exit(1);
156 }
157
158 while(fgets(data, 255, parts) != NULL) {
159
160 char *part_dev, *p;
161
162 /* 4th field is device name */
163 if(!(part_dev = strtok(data, " "))) continue;
164 if(!(part_dev = strtok(NULL, " "))) continue;
165 if(!(part_dev = strtok(NULL, " "))) continue;
166 if(!(part_dev = strtok(NULL, " "))) continue;
167
168 p = part_dev;
169 while(*p) hash = hash*129 + (unsigned int)(*p++) + 987654321L;
170 }
171
172 fclose(parts);
173
174 return hash;
175 }
176
177 static unsigned int hash_scsi()
178 {
179 FILE *parts;
180 char data[256];
181
182 unsigned int hash = 12345;
183
184 if((parts = fopen("/proc/scsi/scsi", "r")) == NULL) {
185 perror("hash_scsi: fopen");
186 exit(1);
187 }
188
189 while(fgets(data, 255, parts) != NULL) {
190
191 char *p;
192
193 p = data;
194 while(*p) hash = hash*129 + (unsigned int)(*p++) + 987654321L;
195 }
196
197 fclose(parts);
198
199 return hash;
200 }
201
202
203 static void count_partitions()
204 {
205 scsi_device_t *scsidev = NULL;
206 FILE *parts;
207 char data[256];
208
209 if((parts = fopen("/proc/partitions", "r")) == NULL) {
210 perror("count_partitions: fopen");
211 exit(1);
212 }
213
214 while(fgets(data, 255, parts) != NULL) {
215
216 char *part_dev, *p;
217 int part_num;
218
219 /* 4th field is device name */
220 if(!(part_dev = strtok(data, " "))) continue;
221 if(!(part_dev = strtok(NULL, " "))) continue;
222 if(!(part_dev = strtok(NULL, " "))) continue;
223 if(!(part_dev = strtok(NULL, " "))) continue;
224
225 /* split the field into device name and part no */
226 p = part_dev;
227 part_num = 0;
228 while(*p) {
229 if(isdigit(*p) && sscanf(p, "%d", &part_num) == 1) {
230 *p = '\0';
231 /* set the number of partitions on this device */
232 if(scsidev = find_dev_by_name(part_dev)) {
233 if(part_num > scsidev->num_parts)
234 scsidev->num_parts = part_num;
235 }
236 break;
237 }
238 p++;
239 }
240
241 }
242
243 fclose(parts);
244 }
245
246
247 static scsi_map_t* read_devicemap(const char *filename)
248 {
249 char buf[1024];
250 FILE *devicemap;
251 char *device, *link, *t;
252 scsi_map_t *devmap, *c_devmap;
253
254 devmap = c_devmap = calloc(1, sizeof(scsi_map_t));
255
256 if((devicemap = fopen(filename, "r")) == NULL) {
257 fprintf(stderr, "read_devicemap: cant open '%s': ", devicemap_file);
258 perror("");
259 return devmap;
260 }
261
262 while(fgets(buf, 1023, devicemap) != NULL) {
263 /* Remove trailing \n, if present. */
264 t = buf + strlen(buf) - 1;
265 if(*t == '\n') *t = '\0';
266 if((device = strtok(buf, "\t")) &&
267 (link = strtok(NULL, "\t"))) {
268 #ifdef DEBUG
269 printf("read %s %s\n", device, link);
270 #endif
271 c_devmap->device = strdup(device);
272 c_devmap->link = strdup(link);
273 c_devmap->next = calloc(1, sizeof(scsi_map_t));
274 c_devmap = c_devmap->next;
275 } else {
276 fprintf(stderr, "read_devicemap: invalid format\n");
277 exit(1);
278 }
279 }
280
281 fclose(devicemap);
282
283 return devmap;
284 }
285
286
287 static int write_devicemap(scsi_map_t *devmap, const char *filename)
288 {
289 FILE *devicemap;
290
291 scsi_map_t *c_devmap = devmap;
292
293 if((devicemap = fopen(filename, "w+")) == NULL) {
294 fprintf(stderr, "write_devicemap: cant open '%s': ", filename);
295 perror("");
296 return -1;
297 }
298
299 while(c_devmap->next) {
300 fprintf(devicemap, "%s\t%s\n", c_devmap->device, c_devmap->link);
301 c_devmap = c_devmap->next;
302 }
303
304 fclose(devicemap);
305 }
306
307
308 static int link_devicemap(scsi_map_t *devmap)
309 {
310 scsi_map_t *c_devmap = devmap;
311
312 while(c_devmap->next) {
313 if(make_link(c_devmap->link, c_devmap->device)) return -1;
314 c_devmap = c_devmap->next;
315 }
316 return 0;
317 }
318
319
320 static int free_devicemap(scsi_map_t *devmap)
321 {
322 scsi_map_t *c_devmap = devmap;
323
324 while(c_devmap->next) {
325 scsi_map_t *t = c_devmap;
326 c_devmap = c_devmap->next;
327 if(t->link) free(t->link);
328 if(t->device) free(t->device);
329 free(t);
330 }
331 return 0;
332 }
333
334
335 static int unlink_devicemap(scsi_map_t *devmap)
336 {
337 scsi_map_t *c_devmap = devmap;
338 char pathtemp[PATH_MAX+1];
339
340 while(c_devmap->next) {
341 #ifdef DEBUG
342 printf("unlink %s\n", c_devmap->link);
343 #endif
344 if(unlink(c_devmap->link) < 0) {
345 perror("unlink_devices");
346 return -1;
347 }
348 strcpy(pathtemp, c_devmap->link);
349 /* remove empty parent directories */
350 while(dirname(pathtemp) && strcmp(pathtemp, ".") != 0
351 && strcmp(pathtemp, "/") != 0) unlink(pathtemp);
352
353 c_devmap = c_devmap->next;
354 }
355 return 0;
356 }
357
358
359 static int parse_rule(char *buf, int *line, scsi_map_rule_t **c_rule)
360 {
361 char *k, *v, *t, q;
362 scsi_map_rule_t *c_constraint;
363
364 *line++;
365
366 /* Remove trailing \n, if present. */
367 t = buf + strlen(buf) - 1;
368 if(*t == '\n') *t = '\0';
369
370 k = buf;
371 if(*k == '#') return 0;
372
373 if((*c_rule)->next_constraint) {
374 (*c_rule)->next_rule = calloc(1, sizeof(scsi_map_rule_t));
375 (*c_rule)->next_rule->rule_num = (*c_rule)->rule_num + 1;
376 (*c_rule) = (*c_rule)->next_rule;
377 }
378 c_constraint = (*c_rule);
379
380 while(*k) {
381
382 /* eat whitespace */
383 while(*k && isspace(*k)) k++;
384
385 /* find value after = */
386 v = k;
387 while (*v != '=' && *v != '\0') {
388 if(!isalnum(*v)) {
389 fprintf(stderr, "read_rules: invalid paramater "
390 "character '%c', line %d\n", *v, *line);
391 return -1;
392 }
393 v++;
394 }
395 if( *v == '\0' ) break;
396 *v++ = '\0';
397
398 if(*v == '"' || *v == '\'') {
399 q = *v;
400 v++;
401 } else q = '\0';
402
403 /* terminate value */
404 t = v;
405 while(*t && ((q && *t != q) ||
406 (!q && *t != ' ' && *t != '\t'))) t++;
407 if(q && *t != q) {
408 fprintf(stderr, "read_rules: unterminated quotes on "
409 "parameter '%s', line %d\n", k, *line);
410 return -1;
411 }
412 if(*t) *t++ = '\0';
413
414 c_constraint->key = strdup(k);
415 c_constraint->value = strdup(v);
416 c_constraint->next_constraint = calloc(1, sizeof(scsi_map_rule_t));
417 c_constraint = c_constraint->next_constraint;
418
419 k = t;
420 }
421 return 0;
422 }
423
424
425 static int read_rules()
426 {
427 char buf[1024];
428 FILE *conf;
429 int line;
430 scsi_map_rule_t *c_rule;
431
432 if((conf = fopen(rules_file, "r")) == NULL) return -1;
433
434 c_rule = rules_head = calloc(1, sizeof(scsi_map_rule_t));
435 c_rule->rule_num = 1;
436
437 while(fgets(buf, 1023, conf) != NULL) {
438 if(parse_rule(buf, &line, &c_rule)) exit(1);
439 }
440
441 if(c_rule->next_constraint) {
442 c_rule->next_rule = calloc(1, sizeof(scsi_map_rule_t));
443 c_rule->next_rule->rule_num = c_rule->rule_num + 1;
444 }
445
446 fclose(conf);
447
448 return 0;
449 }
450
451
452 static int default_rules()
453 {
454 rules_head = calloc(1, sizeof(scsi_map_rule_t));
455 rules_head->next_rule = calloc(1, sizeof(scsi_map_rule_t));
456 rules_head->next_constraint = calloc(1, sizeof(scsi_map_rule_t));
457 rules_head->rule_num = 1;
458 rules_head->key = strdup("map");
459 rules_head->value = strdup(device_tmpl);
460 }
461
462
463 static void str_path(char *p)
464 {
465 char *t, *r, *w = p;
466
467 t = r = strdup(p);
468 while(*r) {
469 if(*r != ' ') *w++ = *r++;
470 else r++;
471 }
472 *w = '\0';
473 free(t);
474 while(*p) {
475 if(!isalnum(*p) && *p != '/') *p = '-';
476 p++;
477 }
478 }
479
480
481 static int create_links(scsi_device_t *scsidev,
482 const char* map, const char* partmap)
483 {
484 char dev[PATH_MAX+1];
485 char link[PATH_MAX+1];
486 int p;
487
488 if(map) {
489 if(subst_device(link, PATH_MAX, scsidev, map) == 0) {
490 str_path(link);
491 if(!silent_flag) printf("%s -> %s\n", link, scsidev->device);
492 devmap_last->link = strdup(link);
493 devmap_last->device = strdup(scsidev->device);;
494 devmap_last->next = calloc(1, sizeof(scsi_map_t));
495 devmap_last = devmap_last->next;
496 } else {
497 exit(1);
498 }
499 }
500
501 if(partmap) {
502 for(p=1; p <= scsidev->num_parts; p++) {
503 scsidev->part = p;
504 if(subst_device(link, PATH_MAX, scsidev, partmap) == 0) {
505 str_path(link);
506 sprintf(dev, "%s%d", scsidev->device, p);
507 if(!silent_flag) printf("%s -> %s\n", link, dev);
508 devmap_last->link = strdup(link);
509 devmap_last->device = strdup(dev);;
510 devmap_last->next = calloc(1, sizeof(scsi_map_t));
511 devmap_last = devmap_last->next;
512 } else {
513 exit(1);
514 }
515 }
516 }
517 }
518
519
520 int match_rules(scsi_device_t *scsidev)
521 {
522 char buf[256];
523 scsi_map_rule_t *c_rule = rules_head;
524
525 /* loop through the rules */
526 while(c_rule->next_rule) {
527 scsi_map_rule_t *c_constraint = c_rule;
528 int rules = 0, matches = 0;
529 char *map = NULL, *partmap = NULL;
530
531 /* see if we can match this rule */
532 while(c_constraint->next_constraint) {
533
534 if(strcmp(c_constraint->key, "map") == 0) {
535 map = c_constraint->value;
536 } else if(strcmp(c_constraint->key, "partmap") == 0) {
537 partmap = c_constraint->value;
538 } else {
539 scsi_device_param_t *param = params;
540 while(param->substchar) {
541 if(strcmp(param->name, c_constraint->key) == 0) break;
542 param++;
543 }
544 /* okay found param, see if values match */
545 if(param->substchar) {
546 rules++;
547 if(param->enc(buf, ((void*)scsidev)+param->offset, 255) >= 0 && strcmp(buf, c_constraint->value) == 0) {
548 matches++;
549 }
550 }
551 }
552 c_constraint = c_constraint->next_constraint;
553 }
554
555 if(rules == matches) {
556 if(map && !partmap) {
557 partmap = (char*)malloc(strlen(map)+4);
558 strcpy(partmap, map);
559 strcat(partmap, "p%p");
560 create_links(scsidev, map, partmap);
561 free(partmap);
562 } else if(!map && !partmap) {
563 create_links(scsidev, device_tmpl, partition_tmpl);
564 } else {
565 create_links(scsidev, map, partmap);
566 }
567 }
568
569 c_rule = c_rule->next_rule;
570 }
571 }
572
573
574 static void do_mapscsi()
575 {
576 if(scsidev_head) free_scsidev(scsidev_head);
577 scsidev_head = calloc(1, sizeof(scsi_device_t));
578 if(devmap_head) free_devicemap(devmap_head);
579 devmap_head = devmap_last = calloc(1, sizeof(scsi_map_t));
580 scan_scsi_devices(sg_numeric);
581 map_sg_devices(TYPE_DISK, "sd", 0);
582 map_sg_devices(TYPE_MOD, "sd", 0); /* this can block ?? */
583 map_sg_devices(TYPE_TAPE, "st", 1);
584 map_sg_devices(TYPE_WORM, "scd", 1);
585 map_sg_devices(TYPE_ROM, "scd", 1);
586 map_sg_devices(TYPE_SCANNER, "sg", 1); /* need to optimize */
587 map_sg_devices(TYPE_PROCESSOR, "sg", 1); /* need to optimize */
588 qlogic_map_wwn_to_sd();
589 qlogic_free();
590 count_partitions();
591 }
592
593
594 static void parse_command_line(int argc, char *argv[])
595 {
596 int c;
597 int error_flag = 0, help_flag = 0;
598
599 while ((c = getopt(argc, argv, "hpanxbsRSc:d:")) != EOF)
600 switch (c)
601 {
602 case 'p':
603 print_flag++;
604 break;
605 case 'h':
606 help_flag++;
607 break;
608 case 'a':
609 sg_numeric = 0;
610 break;
611 case 'n':
612 sg_numeric = 1;
613 break;
614 case 'x':
615 execute_flag = 1;
616 break;
617 case 'b':
618 bkgnd_flag = 1;
619 silent_flag = 1;
620 break;
621 case 's':
622 silent_flag = 1;
623 break;
624 case 'c':
625 rules_file = optarg;
626 break;
627 case 'd':
628 devicemap_file = optarg;
629 break;
630 case 'R':
631 rm_links_flag = 0;
632 break;
633 case 'S':
634 save_state_flag = 0;
635 break;
636 case '?':
637 error_flag++;
638 }
639
640 /* read rules from the command line */
641 if (argc - optind > 0) {
642 int k, line=0;
643 scsi_map_rule_t *c_rule;
644
645 c_rule = rules_head = calloc(1, sizeof(scsi_map_rule_t));
646 c_rule->rule_num = 1;
647 for(k=optind; k < argc; k++) {
648 if(parse_rule(argv[k], &line, &c_rule)) exit(1);
649 }
650 if(c_rule->next_constraint) {
651 c_rule->next_rule = calloc(1, sizeof(scsi_map_rule_t));
652 c_rule->next_rule->rule_num = c_rule->rule_num + 1;
653 }
654 }
655
656 if(print_flag + execute_flag + bkgnd_flag > 1) {
657 fprintf(stderr, "must choose only one of -x -b or -p\n");
658 error_flag++;
659 }
660
661 if (error_flag || help_flag)
662 {
663 scsi_device_param_t *param = params;
664
665 fprintf(stderr, "usage:\t%s [-h] [-x] [-s] [-n] [-a] [-R] [-S]\\\n"
666 "\t[-c <config file>] [-d <devicemap file>] \\\n"
667 "\t[attrib=value [attrib=value]...]\n\n", argv[0]);
668 fprintf(stderr,
669 "-h show this help message\n"
670 "-p print - print device scan information\n"
671 "-x execute - actually make the links\n"
672 "-b background - poll for changes in the background\n"
673 "-s silent - don't show mappings on stdout\n"
674 "-n numeric sg device names eg. /dev/sg0 (default)\n"
675 "-a alpha sg device names eg. /dev/sga\n"
676 "-R don't remove previous links\n"
677 "-S don't save state in /var/state/mapscsi/devicemap\n"
678 "-c <f> mapscsi rules file (default /etc/mapscsi.rules)\n"
679 "-d <f> mapscsi state file (default /var/state/mapscsi/devicemap)\n\n"
680 "example /etc/mapscsi.rules\n\n");
681 fprintf(stderr, "type=disk map='%s' partmap='%s'\n",
682 device_tmpl, partition_tmpl);
683 fprintf(stderr, "type=cdrom map='%s'\n", "/dev/scsi/cdrom-%V-%P");
684 fprintf(stderr, "%s", "\nTemplate codes:\n");
685 while(param->substchar) {
686 fprintf(stderr, "%c\t%s\n", param->substchar, param->description);
687 param++;
688 }
689 exit(1);
690 }
691 }
692
693
694 static void sighandler(int signal)
695 {
696 switch(signal) {
697 case SIGQUIT:
698 case SIGTERM:
699 syslog(LOG_INFO, "exiting on SIGTERM");
700 running = 0;
701 break;
702 default:
703 break;
704 }
705 }
706
707
708 int main(int argc, char **argv)
709 {
710 int k;
711 scsi_device_t *scsidev;
712 scsi_map_t *devmap_old = NULL;
713
714 parse_command_line(argc, argv);
715
716 if(bkgnd_flag) {
717 unsigned int last_part_hash = 0, last_scsi_hash = 0;
718 int pid;
719
720 if ((pid = fork()) == -1)
721 {
722 perror("Unable to fork:");
723 exit(1);
724 }
725
726 if (pid) exit(0);
727 close(0);
728 close(1);
729 close(2);
730 open("/dev/null", O_RDONLY);
731 open("/dev/null", O_WRONLY);
732 open("/dev/null", O_WRONLY);
733 chdir("/");
734 setsid();
735 signal(SIGTERM, &sighandler);
736 running = 1;
737
738 openlog("mapscsi", LOG_PID, LOG_DAEMON);
739 if(!rules_head && read_rules()) {
740 syslog(LOG_ERR, "%s reading rules file %s\n"
741 "Using default rules", strerror(errno), rules_file);
742 default_rules();
743 }
744
745 while(running) {
746 unsigned int part_hash, scsi_hash;
747
748 part_hash = hash_partitions();
749 scsi_hash = hash_scsi();
750
751 if(part_hash != last_part_hash ||
752 scsi_hash != last_scsi_hash) {
753
754 if(part_hash && last_part_hash)
755 syslog(LOG_INFO, "device change detected. rescanning...");
756 do_mapscsi();
757 scsidev = scsidev_head;
758 while(scsidev->next) {
759 if(scsidev->device) match_rules(scsidev);
760 scsidev = scsidev->next;
761 }
762 if(rm_links_flag) {
763 if(!devmap_old)
764 devmap_old = read_devicemap(devicemap_file);
765 if(unlink_devicemap(devmap_old)) {
766 syslog(LOG_ERR, "error unlinking old devices");
767 }
768 free_devicemap(devmap_old);
769 }
770 if(link_devicemap(devmap_head)) {
771 syslog(LOG_ERR, "error linking new devices");
772 exit(1);
773 }
774 if(save_state_flag &&
775 write_devicemap(devmap_head, devicemap_file)) {
776 syslog(LOG_ERR, "error writing device map");
777 exit(1);
778 }
779 devmap_old = devmap_head;
780 devmap_head = NULL; /* prevent freeing of devmap */
781 }
782
783 last_part_hash = part_hash;
784 last_scsi_hash = scsi_hash;
785 if(running) sleep(5);
786 }
787 closelog();
788
789 }
790
791 do_mapscsi();
792
793 if(print_flag) {
794 scsidev = scsidev_head;
795 while(scsidev->next) {
796 if(scsidev->device) print_scsi_dev_info(scsidev);
797 scsidev = scsidev->next;
798 }
799 } else {
800 if(!rules_head && read_rules()) {
801 if(!silent_flag)
802 fprintf(stderr, "%s reading rules file %s:"
803 " using default rules\n",
804 strerror(errno), rules_file);
805 default_rules();
806 }
807 scsidev = scsidev_head;
808 while(scsidev->next) {
809 if(scsidev->device) match_rules(scsidev);
810 scsidev = scsidev->next;
811 }
812 if(execute_flag) {
813 if(rm_links_flag) {
814 devmap_old = read_devicemap(devicemap_file);
815 if(unlink_devicemap(devmap_old)) {
816 fprintf(stderr,"error unlinking old devices\n");
817 }
818 free_devicemap(devmap_old);
819 }
820 if(link_devicemap(devmap_head)) {
821 fprintf(stderr,"error linking new devices\n");
822 exit(1);
823 }
824 if(save_state_flag &&
825 write_devicemap(devmap_head, devicemap_file)) {
826 fprintf(stderr,"error writing device map\n");
827 exit(1);
828 }
829 }
830 }
831
832 return 0;
833 }
834