mtab.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright (C) 2005-2009 Junjiro Okajima
  3. *
  4. * This program, aufs is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. /* cf. fstab.c or the locking for /etc/mtab in util-linux */
  19. /*
  20. * we need to extract a part of util-linux and create a simple and generic
  21. * library for locking /etc/mtab.
  22. */
  23. /* #include <linux/proc_fs.h> */
  24. #define PROC_SUPER_MAGIC 0x9fa0
  25. #include <sys/stat.h>
  26. #include <sys/statfs.h>
  27. #include <sys/types.h>
  28. #include <sys/wait.h>
  29. #include <fcntl.h>
  30. #include <mntent.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <unistd.h>
  34. #include "au_util.h"
  35. void au_print_ent(struct mntent *ent)
  36. {
  37. printf("%s on %s type %s (%s)\n",
  38. ent->mnt_fsname, ent->mnt_dir, ent->mnt_type, ent->mnt_opts);
  39. }
  40. /* ---------------------------------------------------------------------- */
  41. static void lock_mtab(char *pid_file)
  42. {
  43. int err, i;
  44. for (i = 0; i < 5; i++) {
  45. err = link(pid_file, MTab "~");
  46. if (!err)
  47. break;
  48. sleep(1);
  49. }
  50. if (err)
  51. AuFin(MTab "~");
  52. }
  53. static void unlock_mtab(void)
  54. {
  55. int err;
  56. err = rename(MTab "~", MTab);
  57. if (err)
  58. AuFin(MTab);
  59. }
  60. static void append_mtab(FILE *fp, FILE *ofp, struct mntent *ent)
  61. {
  62. int err;
  63. struct mntent *p;
  64. while ((p = getmntent(ofp))) {
  65. err = addmntent(fp, p);
  66. if (err)
  67. AuFin("addmntent");
  68. }
  69. err = addmntent(fp, ent);
  70. if (err)
  71. AuFin("addmntent");
  72. }
  73. /* todo: there are some cases which options are not changed */
  74. static void update_mtab(FILE *fp, char *mntpnt, int do_remount, int do_verbose)
  75. {
  76. int err;
  77. long pos;
  78. FILE *ofp;
  79. struct mntent ent, *p;
  80. /* prohibit updating mount options for this mntpnt */
  81. au_plink_maint(mntpnt);
  82. err = au_proc_getmntent(mntpnt, &ent);
  83. if (err)
  84. AuFin("no such mount point");
  85. ofp = setmntent(MTab, "r");
  86. if (!ofp)
  87. AuFin(MTab);
  88. if (do_remount) {
  89. /* find the last one */
  90. pos = -1;
  91. while ((p = getmntent(ofp))) {
  92. if (!strcmp(p->mnt_dir, mntpnt))
  93. pos = ftell(ofp);
  94. }
  95. rewind(ofp);
  96. if (pos > 0) {
  97. while ((p = getmntent(ofp))) {
  98. if (ftell(ofp) == pos) {
  99. /* replace the line */
  100. p = &ent;
  101. pos = -1;
  102. }
  103. err = addmntent(fp, p);
  104. if (err)
  105. AuFin("addmntent");
  106. }
  107. if (pos > 0)
  108. AuFin("internal error");
  109. } else
  110. append_mtab(fp, ofp, &ent);
  111. } else
  112. append_mtab(fp, ofp, &ent);
  113. endmntent(ofp); /* ignore */
  114. au_plink_maint(NULL);
  115. if (do_verbose)
  116. au_print_ent(&ent);
  117. }
  118. /* ---------------------------------------------------------------------- */
  119. int au_update_mtab(char *mntpnt, int do_remount, int do_verbose)
  120. {
  121. int err, fd, status, e2;
  122. pid_t pid;
  123. ino_t ino;
  124. struct stat st;
  125. struct statfs stfs;
  126. struct flock flock = {
  127. .l_type = F_WRLCK,
  128. .l_whence = SEEK_SET,
  129. .l_start = 0,
  130. .l_len = 0
  131. };
  132. char pid_file[sizeof(MTab "~.") + 20];
  133. FILE *fp;
  134. err = statfs(MTab, &stfs);
  135. if (stfs.f_type == PROC_SUPER_MAGIC)
  136. return 0;
  137. snprintf(pid_file, sizeof(pid_file), MTab "~.%d", getpid());
  138. fd = open(pid_file, O_RDWR | O_CREAT | O_EXCL,
  139. S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  140. if (fd < 0)
  141. AuFin("%s", pid_file);
  142. err = fcntl(fd, F_SETLK, &flock);
  143. if (err)
  144. AuFin("%s", pid_file);
  145. fp = fdopen(fd, "r+");
  146. if (!fp)
  147. AuFin("%s", pid_file);
  148. pid = fork();
  149. if (!pid) {
  150. lock_mtab(pid_file);
  151. update_mtab(fp, mntpnt, do_remount, do_verbose);
  152. unlock_mtab();
  153. return 0;
  154. } else if (pid < 0)
  155. AuFin("fork");
  156. err = fstat(fd, &st);
  157. if (err)
  158. perror(pid_file);
  159. ino = st.st_ino;
  160. err = waitpid(pid, &status, 0);
  161. if (err < 0) {
  162. perror(pid_file);
  163. goto out;
  164. }
  165. err = !WIFEXITED(status);
  166. if (!err)
  167. err = WEXITSTATUS(status);
  168. e2 = unlink(pid_file);
  169. if (e2 && errno != ENOENT)
  170. perror(pid_file);
  171. e2 = stat(MTab "~", &st);
  172. if (!e2) {
  173. if (st.st_ino == ino) {
  174. /*
  175. * The inode number is same,
  176. * it means it is we who made the file.
  177. * If someone else removed our file between stat(2) and
  178. * unlink(2), it is a breakage of the rule.
  179. */
  180. e2 = unlink(MTab "~");
  181. if (e2)
  182. perror(MTab);
  183. }
  184. } else if (errno != ENOENT)
  185. perror(MTab "~");
  186. fclose(fp);
  187. out:
  188. return err;
  189. }