find.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License version 2.1
  6. * as published by the Free Software Foundation
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <errno.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <sys/stat.h>
  17. #include <sys/sysmacros.h>
  18. #include "libfstools.h"
  19. int
  20. find_overlay_mount(char *overlay)
  21. {
  22. FILE *fp = fopen("/proc/mounts", "r");
  23. static char line[256];
  24. int ret = -1;
  25. if(!fp)
  26. return ret;
  27. while (ret && fgets(line, sizeof(line), fp))
  28. if (!strncmp(line, overlay, strlen(overlay)))
  29. ret = 0;
  30. fclose(fp);
  31. return ret;
  32. }
  33. /*
  34. * Find path of a device mounted to the given point.
  35. */
  36. char*
  37. find_mount(char *mp)
  38. {
  39. FILE *fp = fopen("/proc/mounts", "r");
  40. static char line[256];
  41. char *point = NULL;
  42. if(!fp)
  43. return NULL;
  44. while (fgets(line, sizeof(line), fp)) {
  45. char *s, *t = strstr(line, " ");
  46. if (!t) {
  47. fclose(fp);
  48. return NULL;
  49. }
  50. *t = '\0';
  51. t++;
  52. s = strstr(t, " ");
  53. if (!s) {
  54. fclose(fp);
  55. return NULL;
  56. }
  57. *s = '\0';
  58. if (!strcmp(t, mp)) {
  59. fclose(fp);
  60. return line;
  61. }
  62. }
  63. fclose(fp);
  64. return point;
  65. }
  66. /*
  67. * Match filesystem type against a bunch of valid types
  68. *
  69. * jffs2reset may ask if the filesystem type is actually ready for use
  70. * with overlayfs before wiping it...
  71. */
  72. static int fs_rootfs_only(char *fstype)
  73. {
  74. if (strncmp(fstype, "ext4", 4) &&
  75. strncmp(fstype, "f2fs", 4) &&
  76. strncmp(fstype, "jffs2", 5) &&
  77. strncmp(fstype, "ubifs", 5)) {
  78. ULOG_ERR("block is mounted with wrong fs\n");
  79. return 1;
  80. }
  81. return 0;
  82. }
  83. /*
  84. * Check if a given device is mounted and return its mountpoint
  85. */
  86. char*
  87. find_mount_point(char *block, int root_only)
  88. {
  89. FILE *fp = fopen("/proc/self/mountinfo", "r");
  90. static char line[256];
  91. int len = strlen(block);
  92. char *point = NULL, *pos, *tmp, *cpoint, *devname, *fstype;
  93. struct stat s;
  94. int rstat;
  95. unsigned int minor, major;
  96. if (!fp)
  97. return NULL;
  98. rstat = stat(block, &s);
  99. while (fgets(line, sizeof(line), fp)) {
  100. /* skip first two columns */
  101. pos = strchr(line, ' ');
  102. if (!pos)
  103. continue;
  104. pos = strchr(pos + 1, ' ');
  105. if (!pos)
  106. continue;
  107. /* extract block device major:minor */
  108. tmp = ++pos;
  109. pos = strchr(pos, ':');
  110. if (!pos)
  111. continue;
  112. *pos = '\0';
  113. major = atoi(tmp);
  114. tmp = ++pos;
  115. pos = strchr(pos, ' ');
  116. if (!pos)
  117. continue;
  118. *pos = '\0';
  119. minor = atoi(tmp);
  120. /* skip another column */
  121. pos = strchr(pos + 1, ' ');
  122. if (!pos)
  123. continue;
  124. /* get mountpoint */
  125. tmp = ++pos;
  126. pos = strchr(pos, ' ');
  127. if (!pos)
  128. continue;
  129. *pos = '\0';
  130. cpoint = tmp;
  131. /* skip another two columns */
  132. pos = strchr(pos + 1, ' ');
  133. if (!pos)
  134. continue;
  135. pos = strchr(pos + 1, ' ');
  136. if (!pos)
  137. continue;
  138. /* get fstype */
  139. tmp = ++pos;
  140. pos = strchr(pos, ' ');
  141. if (!pos)
  142. continue;
  143. *pos = '\0';
  144. fstype = tmp;
  145. /* get device name */
  146. tmp = ++pos;
  147. pos = strchr(pos, ' ');
  148. if (!pos)
  149. continue;
  150. *pos = '\0';
  151. devname = tmp;
  152. /* if device name matches */
  153. if (!strncmp(block, devname, len)) {
  154. if (root_only && fs_rootfs_only(fstype))
  155. break;
  156. /* found, return mountpoint */
  157. point = strdup(cpoint);
  158. break;
  159. }
  160. /* last chance: check if major:minor of block device match */
  161. if (rstat)
  162. continue;
  163. if (!S_ISBLK(s.st_mode))
  164. continue;
  165. if (major == major(s.st_rdev) &&
  166. minor == minor(s.st_rdev)) {
  167. if (root_only && fs_rootfs_only(fstype))
  168. break;
  169. /* found, return mountpoint */
  170. point = strdup(cpoint);
  171. break;
  172. }
  173. }
  174. fclose(fp);
  175. return point;
  176. }
  177. int
  178. find_filesystem(char *fs)
  179. {
  180. FILE *fp = fopen("/proc/filesystems", "r");
  181. static char line[256];
  182. int ret = -1;
  183. if (!fp) {
  184. ULOG_ERR("opening /proc/filesystems failed: %s\n", strerror(errno));
  185. goto out;
  186. }
  187. while (ret && fgets(line, sizeof(line), fp))
  188. if (strstr(line, fs))
  189. ret = 0;
  190. fclose(fp);
  191. out:
  192. return ret;
  193. }