ismounted.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include <stdlib.h>
  2. #include <sys/stat.h>
  3. #include <stdio.h>
  4. #include <limits.h>
  5. #include <unistd.h>
  6. #include <getopt.h>
  7. #include <locale.h>
  8. #include <err.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <getopt.h>
  12. #include <signal.h>
  13. static struct stat parent, current;
  14. static int period;
  15. static const char *path;
  16. static void __attribute__((__noreturn__)) usage(void)
  17. {
  18. fputs("\nUsage:\n", stderr);
  19. fputs("ismounted [-w timeout] folder\n", stderr);
  20. fputs(" -w: 1s periodic check until the process ran out of time.\n", stderr);
  21. exit(EXIT_SUCCESS);
  22. }
  23. static void sigHandler(int signo,
  24. siginfo_t *si __attribute__((unused)), void /* ucontext_t */ *uap __attribute__((unused)))
  25. {
  26. switch (signo) {
  27. case SIGINFO:
  28. printf("Waiting for %s mount. %d seconds remaining.\n", path, period);
  29. break;
  30. case SIGALRM:
  31. /* Timer */
  32. --period;
  33. break;
  34. default:
  35. break;
  36. }
  37. }
  38. int main(int argc, char *argv[])
  39. {
  40. int r;
  41. char *p_folder = NULL, *a_folder = NULL;
  42. /* timer: optional */
  43. struct itimerspec its;
  44. timer_t timerid = 0;
  45. int ismounted = 0;
  46. /* signals */
  47. struct sigaction sa;
  48. /* handle options */
  49. int ch;
  50. struct option longopts[] = {
  51. { "wait", required_argument, &period, 'w' },
  52. { NULL, 0, NULL, 0 }
  53. };
  54. opterr = 0;
  55. while ((ch = getopt_long(argc, argv, "w:", longopts, NULL)) != -1) {
  56. switch (ch) {
  57. case 'w':
  58. period = atoi(optarg);
  59. break;
  60. case 0:
  61. /* long option */
  62. break;
  63. }
  64. }
  65. if (optind == (argc - 1))
  66. path = argv[optind];
  67. else
  68. usage();
  69. /* get real path name */
  70. a_folder = realpath(path, NULL);
  71. if (a_folder == NULL)
  72. err(EXIT_FAILURE, "Path <%s> unreachable.", path);
  73. if (!strcmp("/", a_folder)) {
  74. printf("That's the root filesystem dude.");
  75. return EXIT_SUCCESS;
  76. }
  77. /* move to parent */
  78. strncat(a_folder, "/../", PATH_MAX - 1);
  79. p_folder = realpath(a_folder, NULL);
  80. r = stat(p_folder, &parent);
  81. if (r)
  82. err(EXIT_FAILURE, "Parent folder of <%s> is unreachable.", path);
  83. /* signal */
  84. sa.sa_handler = NULL;
  85. sa.sa_sigaction = &sigHandler;
  86. sa.sa_flags = SA_SIGINFO;
  87. sigemptyset(&sa.sa_mask);
  88. sigfillset(&sa.sa_mask);
  89. if (sigaction(SIGINFO, &sa, NULL))
  90. warn("SIGNFO not caught.");
  91. if (sigaction(SIGALRM, &sa, NULL))
  92. err(EXIT_FAILURE, "sigaction:ALARM");
  93. /* timer, if set */
  94. if ((period > 0) ) {
  95. its.it_interval.tv_sec = 1;
  96. its.it_interval.tv_nsec = 0;
  97. its.it_value.tv_sec = its.it_interval.tv_sec;
  98. its.it_value.tv_nsec = 0;
  99. if (timer_create(CLOCK_REALTIME, NULL, &timerid))
  100. err(EXIT_FAILURE,"timer_create failed.");
  101. if (timer_settime(timerid, 0, &its, NULL))
  102. err(EXIT_FAILURE, "timer_settime failed.");
  103. }
  104. /* proceed */
  105. printf("Waiting for folder %s to be mounted ...\n", path);
  106. while (1) {
  107. r = stat(path, &current);
  108. if (r)
  109. err(EXIT_FAILURE, "Current folder <%s> is unreachable.", path);
  110. ismounted = (current.st_dev != parent.st_dev);
  111. if (ismounted || (period == 0))
  112. break;
  113. pause();
  114. }
  115. printf("Folder path %s is %sa mount point.\n", path, (ismounted) ? "" : "*not* " );
  116. if (timerid)
  117. timer_delete(timerid);
  118. return EXIT_SUCCESS;
  119. }