mount.c 18 KB

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