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