find.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. size_t len = strlen(overlay);
  24. static char line[256];
  25. int ret = -1;
  26. if(!fp)
  27. return ret;
  28. while (ret && fgets(line, sizeof(line), fp))
  29. if (len < sizeof(line) && !strncmp(line, overlay, len) && line[len] == ' ')
  30. ret = 0;
  31. fclose(fp);
  32. return ret;
  33. }
  34. /*
  35. * Find path of a device mounted to the given point.
  36. */
  37. char*
  38. find_mount(char *mp)
  39. {
  40. FILE *fp = fopen("/proc/mounts", "r");
  41. static char line[256];
  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 NULL;
  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. char *point = NULL, *pos, *tmp, *cpoint, *devname, *fstype;
  92. struct stat s;
  93. int rstat;
  94. unsigned int minor, major;
  95. if (!block)
  96. return NULL;
  97. if (!fp)
  98. return NULL;
  99. rstat = stat(block, &s);
  100. while (fgets(line, sizeof(line), fp)) {
  101. /* skip first two columns */
  102. pos = strchr(line, ' ');
  103. if (!pos)
  104. continue;
  105. pos = strchr(pos + 1, ' ');
  106. if (!pos)
  107. continue;
  108. /* extract block device major:minor */
  109. tmp = ++pos;
  110. pos = strchr(pos, ':');
  111. if (!pos)
  112. continue;
  113. *pos = '\0';
  114. major = atoi(tmp);
  115. tmp = ++pos;
  116. pos = strchr(pos, ' ');
  117. if (!pos)
  118. continue;
  119. *pos = '\0';
  120. minor = atoi(tmp);
  121. /* skip another column */
  122. pos = strchr(pos + 1, ' ');
  123. if (!pos)
  124. continue;
  125. /* get mountpoint */
  126. tmp = ++pos;
  127. pos = strchr(pos, ' ');
  128. if (!pos)
  129. continue;
  130. *pos = '\0';
  131. cpoint = tmp;
  132. /* skip another two columns */
  133. pos = strchr(pos + 1, ' ');
  134. if (!pos)
  135. continue;
  136. pos = strchr(pos + 1, ' ');
  137. if (!pos)
  138. continue;
  139. /* get fstype */
  140. tmp = ++pos;
  141. pos = strchr(pos, ' ');
  142. if (!pos)
  143. continue;
  144. *pos = '\0';
  145. fstype = tmp;
  146. /* get device name */
  147. tmp = ++pos;
  148. pos = strchr(pos, ' ');
  149. if (!pos)
  150. continue;
  151. *pos = '\0';
  152. devname = tmp;
  153. /* if device name matches */
  154. if (!strcmp(block, devname)) {
  155. if (root_only && fs_rootfs_only(fstype))
  156. break;
  157. /* found, return mountpoint */
  158. point = strdup(cpoint);
  159. break;
  160. }
  161. /* last chance: check if major:minor of block device match */
  162. if (rstat)
  163. continue;
  164. if (!S_ISBLK(s.st_mode))
  165. continue;
  166. if (major == major(s.st_rdev) &&
  167. minor == minor(s.st_rdev)) {
  168. if (root_only && fs_rootfs_only(fstype))
  169. break;
  170. /* found, return mountpoint */
  171. point = strdup(cpoint);
  172. break;
  173. }
  174. }
  175. fclose(fp);
  176. return point;
  177. }
  178. int
  179. find_filesystem(char *fs)
  180. {
  181. FILE *fp = fopen("/proc/filesystems", "r");
  182. static char line[256];
  183. int ret = -1;
  184. if (!fp) {
  185. ULOG_ERR("opening /proc/filesystems failed: %m\n");
  186. goto out;
  187. }
  188. while (ret && fgets(line, sizeof(line), fp))
  189. if (strstr(line, fs))
  190. ret = 0;
  191. fclose(fp);
  192. out:
  193. return ret;
  194. }