1 #include <errno.h> 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 #include <sys/stat.h> 7 #include <sys/types.h> 8 #include <fcntl.h> 9 #include <sys/ioctl.h> 10 #include <linux/hdreg.h> 11 #include <scsi/sg.h> 12 #include <dirent.h> 13 #include <sys/wait.h> 14 #include <sys/inotify.h> 15 #include <sys/mount.h> 16 #include <glob.h> 17 #include <libgen.h> 18 #include <poll.h> 19 #include <syslog.h> 20 21 #include "include/log.h" 22 #include "include/list.h" 23 #include "include/sys.h" 24 #include "include/signal.h" 25 #include "include/timer.h" 26 #include "include/autofs.h" 27 #include "include/ucix.h" 28 #include "include/fs.h" 29 #include "include/mount.h" 30 31 int mount_new(char *path, char *dev); 32 33 static struct list_head mounts; 34 35 /** 36 * enum status - status of mount entry 37 * 38 * @STATUS_UNMOUNTED: currently not mounted 39 * @STATUS_MOUNTED: mounted & ready for usage 40 * @STATUS_EXPIRED: mount expired & *temporary* unmounted 41 * @STATUS_IGNORE: entry should be ignored and never mounted 42 */ 43 enum status { 44 STATUS_UNMOUNTED = 0, 45 STATUS_MOUNTED, 46 STATUS_EXPIRED, 47 STATUS_IGNORE, 48 }; 49 50 struct mount { 51 struct list_head list; 52 char name[64]; 53 char dev[64]; 54 char serial[64]; 55 char vendor[64]; 56 char model[64]; 57 char rev[64]; 58 enum status status; 59 char size[64]; 60 char sector_size[64]; 61 int fs; 62 }; 63 64 static char *fs_names[] = { 65 "", 66 "", 67 "mbr", 68 "ext2", 69 "ext3", 70 "fat", 71 "hfsplus", 72 "", 73 "ntfs", 74 "", 75 "exfat", 76 "ext4", 77 "hfsplusjournal" 78 }; 79 80 #define MAX_MOUNTED 32 81 #define MAX_MOUNT_NAME 32 82 83 static char mounted[MAX_MOUNTED][3][MAX_MOUNT_NAME]; 84 static int mounted_count = 0; 85 extern char uci_path[32]; 86 87 static void mount_dump_uci_state(void) 88 { 89 struct uci_context *ctx; 90 struct list_head *p; 91 char mountd[] = {"mountd"}; 92 char type[] = {"mountd_disc"}; 93 int mounted = 0; 94 unsigned long long int size = 0; 95 unlink("/var/state/mountd"); 96 ctx = ucix_init("mountd"); 97 uci_set_savedir(ctx, "/var/state/"); 98 ucix_add_option_int(ctx, mountd, mountd, "count", list_count(&mounts)); 99 list_for_each(p, &mounts) 100 { 101 struct mount *q = container_of(p, struct mount, list); 102 char t[64]; 103 if(q->fs == EXTENDED) 104 continue; 105 ucix_add_section(ctx, mountd, q->serial, type); 106 strcpy(t, q->dev); 107 t[3] = '\0'; 108 ucix_add_option(ctx, mountd, q->serial, "disc", t); 109 ucix_add_option(ctx, mountd, q->serial, "sector_size", q->sector_size); 110 snprintf(t, 64, "part%dmounted", atoi(&q->dev[3])); 111 ucix_add_option(ctx, mountd, q->serial, t, q->status == STATUS_MOUNTED ? "1" : ""); 112 ucix_add_option(ctx, mountd, q->serial, "vendor", q->vendor); 113 ucix_add_option(ctx, mountd, q->serial, "model", q->model); 114 ucix_add_option(ctx, mountd, q->serial, "rev", q->rev); 115 snprintf(t, 64, "size%d", atoi(&q->dev[3])); 116 ucix_add_option(ctx, mountd, q->serial, t, q->size); 117 if(q->fs > MBR && q->fs <= LASTFS) 118 { 119 snprintf(t, 64, "fs%d", atoi(&q->dev[3])); 120 ucix_add_option(ctx, mountd, q->serial, t, fs_names[q->fs]); 121 } 122 if (q->status == STATUS_MOUNTED) 123 mounted++; 124 if ((q->status != STATUS_IGNORE) && q->size && q->sector_size) 125 size = size + (((unsigned long long int)atoi(q->size)) * ((unsigned long long int)atoi(q->sector_size))); 126 } 127 ucix_add_option_int(ctx, mountd, mountd, "mounted", mounted); 128 ucix_add_option_int(ctx, mountd, mountd, "total", size); 129 system_printf("echo -n %llu > /tmp/run/mountd_size", size); 130 ucix_save_state(ctx, "mountd"); 131 ucix_cleanup(ctx); 132 } 133 134 static struct mount* mount_find(char *name, char *dev) 135 { 136 struct list_head *p; 137 list_for_each(p, &mounts) 138 { 139 struct mount *q = container_of(p, struct mount, list); 140 if(name) 141 if(!strcmp(q->name, name)) 142 return q; 143 if(dev) 144 if(!strcmp(q->dev, dev)) 145 return q; 146 } 147 return 0; 148 } 149 150 static void mount_add_list(char *name, char *dev, char *serial, 151 char *vendor, char *model, char *rev, int ignore, char *size, char *sector_size, int fs) 152 { 153 struct mount *mount; 154 char dev_path[64], dev_link[64], tmp[64]; 155 156 mount = malloc(sizeof(struct mount)); 157 INIT_LIST_HEAD(&mount->list); 158 strncpy(mount->vendor, vendor, 64); 159 strncpy(mount->model, model, 64); 160 strncpy(mount->rev, rev, 64); 161 strncpy(mount->name, name, 64); 162 strncpy(mount->dev, dev, 64); 163 strncpy(mount->serial, serial, 64); 164 strncpy(mount->size, size, 64); 165 strncpy(mount->sector_size, sector_size, 64); 166 mount->status = STATUS_UNMOUNTED; 167 mount->fs = fs; 168 list_add(&mount->list, &mounts); 169 170 if (ignore) { 171 mount->status = STATUS_IGNORE; 172 } else { 173 struct stat st; 174 175 log_printf("new mount : %s -> %s (%s)\n", name, dev, fs_names[mount->fs]); 176 177 snprintf(dev_link, sizeof(dev_link), "%s%s", uci_path, name); 178 snprintf(dev_path, sizeof(dev_path), "%s%s", "/tmp/run/mountd/", dev); 179 /* If link aleady exists - replace it */ 180 if (lstat(dev_link, &st) == 0 && S_ISLNK(st.st_mode)) { 181 snprintf(tmp, sizeof(tmp), "%s%s", uci_path, "tmp"); 182 symlink(dev_path, tmp); 183 rename(tmp, dev_link); 184 } else { 185 symlink(dev_path, dev_link); 186 } 187 if (!mount_new("/tmp/run/mountd/", dev)) 188 system_printf("ACTION=add DEVICE=%s NAME=%s /sbin/hotplug-call mount", dev, name); 189 } 190 } 191 192 static int mount_check_disc(char *disc) 193 { 194 FILE *fp = fopen("/proc/mounts", "r"); 195 char tmp[256]; 196 int avail = -1; 197 if(!fp) 198 { 199 log_printf("error reading /proc/mounts"); 200 return avail; 201 } 202 while((fgets(tmp, 256, fp) != NULL) && (avail == -1)) 203 { 204 char *t; 205 char tmp2[32]; 206 t = strstr(tmp, " "); 207 if(t) 208 { 209 int l; 210 *t = '\0'; 211 l = snprintf(tmp2, 31, "/dev/%s", disc); 212 213 if(!strncmp(tmp, tmp2, l)) 214 avail = 0; 215 } 216 } 217 fclose(fp); 218 return avail; 219 } 220 221 static int mount_wait_for_disc(char *disc) 222 { 223 int i = 10; 224 while(i--) 225 { 226 int ret = mount_check_disc(disc); 227 if(!ret) 228 return ret; 229 poll(0, 0, 100); 230 } 231 return -1; 232 } 233 234 int mount_new(char *path, char *dev) 235 { 236 struct mount *mount; 237 char tmp[256]; 238 int ret = 1; 239 pid_t pid; 240 mount = mount_find(0, dev); 241 if(!mount) 242 { 243 log_printf("request for invalid path %s%s\n", path, dev); 244 return -1; 245 } 246 if (mount->status == STATUS_IGNORE || mount->status == STATUS_MOUNTED || mount->fs == EXTENDED) 247 return -1; 248 snprintf(tmp, 256, "%s%s", path, mount->dev); 249 log_printf("mounting %s\n", tmp); 250 mkdir(tmp, 777); 251 252 pid = autofs_safe_fork(); 253 if(!pid) 254 { 255 char *options, *fstype; 256 if(mount->fs == EXFAT) 257 { 258 options = "rw,uid=1000,gid=1000"; 259 fstype = "exfat"; 260 } 261 if(mount->fs == FAT) 262 { 263 options = "rw,uid=1000,gid=1000"; 264 fstype = "vfat"; 265 } 266 if(mount->fs == EXT4) 267 { 268 options = "rw,defaults"; 269 fstype = "ext4"; 270 } 271 if(mount->fs == EXT3) 272 { 273 options = "rw,defaults"; 274 fstype = "ext3"; 275 } 276 if(mount->fs == EXT2) 277 { 278 options = "rw,defaults"; 279 fstype = "ext2"; 280 } 281 if(mount->fs == HFSPLUS) 282 { 283 options = "rw,defaults,uid=1000,gid=1000"; 284 fstype = "hfsplus"; 285 } 286 if(mount->fs == HFSPLUSJOURNAL) 287 { 288 options = "ro,defaults,uid=1000,gid=1000"; 289 fstype = "hfsplus"; 290 } 291 if(mount->fs == NTFS) 292 { 293 options = "force"; 294 fstype = "ntfs-3g"; 295 } 296 if(mount->fs > MBR && mount->fs <= LASTFS) 297 { 298 struct uci_context *ctx; 299 char *uci_options, *uci_fstype; 300 ctx = ucix_init("mountd"); 301 if(fs_names[mount->fs]) 302 { 303 uci_options = ucix_get_option(ctx, "mountd", fs_names[mount->fs], "options"); 304 uci_fstype = ucix_get_option(ctx, "mountd", fs_names[mount->fs], "fstype"); 305 if(uci_options) 306 options = uci_options; 307 if(uci_fstype) 308 fstype = uci_fstype; 309 log_printf("mount -t %s -o %s /dev/%s %s", fstype, options, mount->dev, tmp); 310 ret = system_printf("mount -t %s -o %s /dev/%s %s", fstype, options, mount->dev, tmp); 311 } 312 ucix_cleanup(ctx); 313 } 314 exit(WEXITSTATUS(ret)); 315 } 316 pid = waitpid(pid, &ret, 0); 317 ret = WEXITSTATUS(ret); 318 log_printf("----------> mount ret = %d\n", ret); 319 if (ret && ret != 0xff) { 320 rmdir(tmp); 321 return -1; 322 } 323 if(mount_wait_for_disc(mount->dev) == 0) 324 { 325 mount->status = STATUS_MOUNTED; 326 mount_dump_uci_state(); 327 } else return -1; 328 return 0; 329 } 330 331 int mount_remove(char *path, char *dev) 332 { 333 struct mount *mount; 334 char tmp[256]; 335 int ret; 336 snprintf(tmp, 256, "%s%s", path, dev); 337 log_printf("device %s has expired... unmounting %s\n", dev, tmp); 338 ret = system_printf("/bin/umount %s", tmp); 339 if(ret != 0) 340 return 0; 341 rmdir(tmp); 342 mount = mount_find(0, dev); 343 if(mount) 344 mount->status = STATUS_EXPIRED; 345 log_printf("finished unmounting\n"); 346 mount_dump_uci_state(); 347 return 0; 348 } 349 350 static int dir_sort(const struct dirent **a, const struct dirent **b) 351 { 352 return 0; 353 } 354 355 static int dir_filter(const struct dirent *a) 356 { 357 if(strstr(a->d_name, ":")) 358 return 1; 359 return 0; 360 } 361 362 static char* mount_get_serial(char *dev) 363 { 364 static char tmp[64]; 365 static char tmp2[64]; 366 int disc; 367 static struct hd_driveid hd; 368 int i; 369 static char *serial; 370 static char disc_id[13]; 371 snprintf(tmp, 64, "/dev/%s", dev); 372 disc = open(tmp, O_RDONLY); 373 if(!disc) 374 { 375 log_printf("Trying to open unknown disc\n"); 376 return 0; 377 } 378 i = ioctl(disc, HDIO_GET_IDENTITY, &hd); 379 close(disc); 380 if(!i) 381 serial = (char*)hd.serial_no; 382 /* if we failed, it probably a usb storage device */ 383 /* there must be a better way for this */ 384 if(i) 385 { 386 struct dirent **namelist; 387 int n = scandir("/sys/bus/scsi/devices/", &namelist, dir_filter, dir_sort); 388 if(n > 0) 389 { 390 while(n--) 391 { 392 char *t = strstr(namelist[n]->d_name, ":"); 393 if(t) 394 { 395 int id; 396 struct stat buf; 397 char tmp3[strlen(namelist[n]->d_name) + strlen(dev) + 31]; 398 int ret; 399 *t = 0; 400 id = atoi(namelist[n]->d_name); 401 *t = ':'; 402 403 sprintf(tmp3, "/sys/bus/scsi/devices/%s/block:%s/", namelist[n]->d_name, dev); 404 ret = stat(tmp3, &buf); 405 if(ret) 406 { 407 sprintf(tmp3, "/sys/bus/scsi/devices/%s/block/%s/", namelist[n]->d_name, dev); 408 ret = stat(tmp3, &buf); 409 } 410 if(!ret) 411 { 412 FILE *fp; 413 snprintf(tmp2, 64, "/proc/scsi/usb-storage/%d", id); 414 fp = fopen(tmp2, "r"); 415 if(fp) 416 { 417 while(fgets(tmp2, 64, fp) != NULL) 418 { 419 serial = strstr(tmp2, "Serial Number:"); 420 if(serial) 421 { 422 serial += strlen("Serial Number: "); 423 serial[strlen(serial) - 1] = '\0'; 424 i = 0; 425 break; 426 } 427 } 428 fclose(fp); 429 } 430 } 431 } 432 free(namelist[n]); 433 } 434 free(namelist); 435 } 436 } 437 if(i) 438 { 439 log_printf("could not find a serial number for the device %s\n", dev); 440 } else { 441 /* serial string id is cheap, but makes the discs anonymous */ 442 unsigned char uniq[6]; 443 unsigned int *u = (unsigned int*) uniq; 444 int l = strlen(serial); 445 int i; 446 memset(disc_id, 0, 13); 447 memset(uniq, 0, 6); 448 for(i = 0; i < l; i++) 449 { 450 uniq[i%6] += serial[i]; 451 } 452 sprintf(disc_id, "%08X%02X%02X", *u, uniq[4], uniq[5]); 453 //log_printf("Serial number - %s %s\n", serial, disc_id); 454 return disc_id; 455 } 456 sprintf(disc_id, "000000000000"); 457 return disc_id; 458 } 459 460 static void mount_dev_add(char *dev) 461 { 462 struct mount *mount = mount_find(0, dev); 463 if(!mount) 464 { 465 char node[64]; 466 char name[64]; 467 int ignore = 0; 468 char *s; 469 char tmp[64]; 470 char tmp2[64]; 471 char *p; 472 struct uci_context *ctx; 473 char vendor[64]; 474 char model[64]; 475 char rev[64]; 476 char size[64]; 477 char sector_size[64]; 478 FILE *fp; 479 int offset = 3; 480 int fs; 481 482 strcpy(name, dev); 483 if (!strncmp(name, "mmcblk", 6)) 484 offset = 7; 485 name[offset] = '\0'; 486 s = mount_get_serial(name); 487 if(!s) { 488 return; 489 } 490 if (!strncmp(name, "mmcblk", 6)) { 491 snprintf(tmp, 64, "part%s", &dev[8]); 492 snprintf(node, 64, "SD-P%s", &dev[8]); 493 494 } else { 495 snprintf(tmp, 64, "part%s", &dev[3]); 496 snprintf(node, 64, "USB-%s", &dev[2]); 497 } 498 if(node[4] >= 'a' && node[4] <= 'z') 499 { 500 node[4] -= 'a'; 501 node[4] += 'A'; 502 } 503 ctx = ucix_init("mountd"); 504 p = ucix_get_option(ctx, "mountd", s, tmp); 505 ucix_cleanup(ctx); 506 if(p) 507 { 508 if(strlen(p) == 1) 509 { 510 if(*p == '') 511 ignore = 1; 512 } else { 513 snprintf(node, 64, "%s", p); 514 } 515 } 516 strcpy(name, dev); 517 name[3] = '\0'; 518 snprintf(tmp, 64, "/sys/class/block/%s/device/model", name); 519 fp = fopen(tmp, "r"); 520 if(!fp) 521 { 522 snprintf(tmp, 64, "/sys/block/%s/device/model", name); 523 fp = fopen(tmp, "r"); 524 } 525 if(!fp) 526 snprintf(model, 64, "unknown"); 527 else { 528 fgets(model, 64, fp); 529 model[strlen(model) - 1] = '\0';; 530 fclose(fp); 531 } 532 snprintf(tmp, 64, "/sys/class/block/%s/device/vendor", name); 533 fp = fopen(tmp, "r"); 534 if(!fp) 535 { 536 snprintf(tmp, 64, "/sys/block/%s/device/vendor", name); 537 fp = fopen(tmp, "r"); 538 } 539 if(!fp) 540 snprintf(vendor, 64, "unknown"); 541 else { 542 fgets(vendor, 64, fp); 543 vendor[strlen(vendor) - 1] = '\0'; 544 fclose(fp); 545 } 546 snprintf(tmp, 64, "/sys/class/block/%s/device/rev", name); 547 fp = fopen(tmp, "r"); 548 if(!fp) 549 { 550 snprintf(tmp, 64, "/sys/block/%s/device/rev", name); 551 fp = fopen(tmp, "r"); 552 } 553 if(!fp) 554 snprintf(rev, 64, "unknown"); 555 else { 556 fgets(rev, 64, fp); 557 rev[strlen(rev) - 1] = '\0'; 558 fclose(fp); 559 } 560 snprintf(tmp, 64, "/sys/class/block/%s/size", dev); 561 fp = fopen(tmp, "r"); 562 if(!fp) 563 { 564 snprintf(tmp, 64, "/sys/block/%s/%s/size", name, dev); 565 fp = fopen(tmp, "r"); 566 } 567 if(!fp) 568 snprintf(size, 64, "unknown"); 569 else { 570 fgets(size, 64, fp); 571 size[strlen(size) - 1] = '\0'; 572 fclose(fp); 573 } 574 strcpy(tmp2, dev); 575 tmp2[3] = '\0'; 576 snprintf(tmp, 64, "/sys/block/%s/queue/hw_sector_size", tmp2); 577 fp = fopen(tmp, "r"); 578 if(!fp) 579 snprintf(sector_size, 64, "unknown"); 580 else { 581 fgets(sector_size, 64, fp); 582 sector_size[strlen(sector_size) - 1] = '\0'; 583 fclose(fp); 584 } 585 snprintf(tmp, 64, "/dev/%s", dev); 586 fs = detect_fs(tmp); 587 if (fs <= MBR || fs > LASTFS) { 588 ignore = 1; 589 } 590 mount_add_list(node, dev, s, vendor, model, rev, ignore, size, sector_size, fs); 591 mount_dump_uci_state(); 592 } 593 } 594 595 static int mount_dev_del(struct mount *mount) 596 { 597 char tmp[256]; 598 int err = 0; 599 600 if (mount->status == STATUS_MOUNTED) { 601 snprintf(tmp, 256, "%s%s", "/tmp/run/mountd/", mount->dev); 602 log_printf("device %s has disappeared ... unmounting %s\n", mount->dev, tmp); 603 if (umount(tmp)) { 604 err = -errno; 605 umount2(tmp, MNT_DETACH); 606 } 607 rmdir(tmp); 608 mount_dump_uci_state(); 609 } 610 611 return err; 612 } 613 614 void mount_dump_list(void) 615 { 616 struct list_head *p; 617 list_for_each(p, &mounts) 618 { 619 struct mount *q = container_of(p, struct mount, list); 620 log_printf("* %s %s %d\n", q->name, q->dev, q->status == STATUS_MOUNTED); 621 } 622 } 623 624 char* is_mounted(char *block, char *path) 625 { 626 int i; 627 for(i = 0; i < mounted_count; i++) 628 { 629 if(block) 630 if(!strncmp(&mounted[i][0][0], block, strlen(&mounted[i][0][0]))) 631 return &mounted[i][0][0]; 632 if(path) 633 if(!strncmp(&mounted[i][1][1], &path[1], strlen(&mounted[i][1][0]))) 634 return &mounted[i][0][0]; 635 } 636 return 0; 637 } 638 639 static void mount_update_mount_list(void) 640 { 641 FILE *fp = fopen("/proc/mounts", "r"); 642 char tmp[256]; 643 644 if(!fp) 645 { 646 log_printf("error reading /proc/mounts"); 647 return; 648 } 649 mounted_count = 0; 650 while(fgets(tmp, 256, fp) != NULL) 651 { 652 char *t, *t2; 653 654 if (mounted_count + 1 > MAX_MOUNTED) { 655 log_printf("found more than %d mounts \n", MAX_MOUNTED); 656 break; 657 } 658 659 t = strstr(tmp, " "); 660 if(t) 661 { 662 *t = '\0'; 663 t++; 664 } else t = tmp; 665 strncpy(&mounted[mounted_count][0][0], tmp, MAX_MOUNT_NAME); 666 t2 = strstr(t, " "); 667 if(t2) 668 { 669 *t2 = '\0'; 670 t2++; 671 } else t2 = t; 672 strncpy(&mounted[mounted_count][1][0], t, MAX_MOUNT_NAME); 673 t = strstr(t2, " "); 674 if(t) 675 { 676 *t = '\0'; 677 t++; 678 } else t = tmp; 679 strncpy(&mounted[mounted_count][2][0], t2, MAX_MOUNT_NAME); 680 /* printf("%s %s %s\n", 681 mounted[mounted_count][0], 682 mounted[mounted_count][1], 683 mounted[mounted_count][2]);*/ 684 685 mounted_count++; 686 } 687 fclose(fp); 688 } 689 690 /* FIXME: we need more intelligence here */ 691 static int dir_filter2(const struct dirent *a) 692 { 693 if(!strncmp(a->d_name, "mmcblk", 6) || !strncmp(a->d_name, "sd", 2)) 694 return 1; 695 return 0; 696 } 697 #define MAX_BLOCK 64 698 static char block[MAX_BLOCK][MAX_BLOCK]; 699 static int blk_cnt = 0; 700 701 static int check_block(char *b) 702 { 703 int i; 704 for(i = 0; i < blk_cnt; i++) 705 { 706 if(!strcmp(block[i], b)) 707 return 1; 708 } 709 return 0; 710 } 711 712 static void mount_enum_drives(void) 713 { 714 struct dirent **namelist, **namelist2; 715 int i, n = scandir("/sys/block/", &namelist, dir_filter2, dir_sort); 716 struct list_head *p; 717 blk_cnt = 0; 718 if(n > 0) 719 { 720 while(n--) 721 { 722 if(blk_cnt < MAX_BLOCK) 723 { 724 int m; 725 char tmp[64]; 726 snprintf(tmp, 64, "/sys/block/%s/", namelist[n]->d_name); 727 m = scandir(tmp, &namelist2, dir_filter2, dir_sort); 728 if(m > 0) 729 { 730 while(m--) 731 { 732 strncpy(&block[blk_cnt][0], namelist2[m]->d_name, MAX_BLOCK); 733 blk_cnt++; 734 free(namelist2[m]); 735 } 736 free(namelist2); 737 } else { 738 strncpy(&block[blk_cnt][0], namelist[n]->d_name, MAX_BLOCK); 739 blk_cnt++; 740 } 741 } 742 free(namelist[n]); 743 } 744 free(namelist); 745 } 746 p = mounts.next; 747 while(p != &mounts) 748 { 749 struct mount *q = container_of(p, struct mount, list); 750 char tmp[64]; 751 struct uci_context *ctx; 752 int del = 0; 753 char *t; 754 snprintf(tmp, 64, "part%s", &q->dev[3]); 755 ctx = ucix_init("mountd"); 756 t = ucix_get_option(ctx, "mountd", q->serial, tmp); 757 ucix_cleanup(ctx); 758 if (t && q->status != STATUS_MOUNTED) 759 { 760 if(!strcmp(t, "")) 761 { 762 if (q->status != STATUS_IGNORE) 763 del = 1; 764 } else if(!strcmp(t, "1")) 765 { 766 if(strncmp(q->name, "Disc-", 5)) 767 del = 1; 768 } else if(strcmp(q->name, t)) 769 { 770 del = 1; 771 } 772 } 773 if(!check_block(q->dev)||del) 774 { 775 if (q->status == STATUS_MOUNTED || q->status == STATUS_EXPIRED) { 776 char dev_link[64]; 777 int err; 778 779 system_printf("ACTION=remove DEVICE=%s NAME=%s /sbin/hotplug-call mount", q->dev, q->name); 780 781 err = mount_dev_del(q); 782 783 snprintf(dev_link, sizeof(dev_link), "%s%s", uci_path, q->name); 784 if (err == -EBUSY) { 785 /* Create "tmp" symlink to non-existing path */ 786 snprintf(tmp, sizeof(tmp), "%s%s", uci_path, "tmp"); 787 symlink("## DEVICE MISSING ##", tmp); 788 789 /* Replace old symlink with the not working one */ 790 rename(tmp, dev_link); 791 } else { 792 log_printf("unlinking %s\n", dev_link); 793 unlink(dev_link); 794 } 795 } 796 797 p->prev->next = p->next; 798 p->next->prev = p->prev; 799 p = p->next; 800 free(q); 801 802 mount_dump_uci_state(); 803 system_printf("/etc/fonstated/ReloadSamba"); 804 } else p = p->next; 805 } 806 807 for(i = 0; i < blk_cnt; i++) 808 mount_dev_add(block[i]); 809 } 810 811 static void mount_check_enum(void) 812 { 813 waitpid(-1, 0, WNOHANG); 814 mount_enum_drives(); 815 } 816 817 void mount_init(void) 818 { 819 INIT_LIST_HEAD(&mounts); 820 timer_add(mount_update_mount_list, 2); 821 timer_add(mount_check_enum, 1); 822 mount_update_mount_list(); 823 } 824
This page was automatically generated by LXR 0.3.1. • OpenWrt