ismounted.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. 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. break;
  33. default:
  34. break;
  35. }
  36. }
  37. int main(int argc, char *argv[])
  38. {
  39. int r;
  40. char *p_folder = NULL, *a_folder = NULL;
  41. /* timer: optional */
  42. struct itimerspec its;
  43. timer_t timerid = 0;
  44. int ismounted = 0;
  45. /* handle options */
  46. int ch;
  47. struct option longopts[] = {
  48. { "wait", required_argument, &period, 'w' },
  49. { NULL, 0, NULL, 0 }
  50. };
  51. opterr = 0;
  52. while ((ch = getopt_long(argc, argv, "w:", longopts, NULL)) != -1) {
  53. switch (ch) {
  54. case 'w':
  55. period = atoi(optarg);
  56. break;
  57. case 0:
  58. /* long option */
  59. break;
  60. }
  61. }
  62. if (optind == (argc - 1))
  63. path = argv[optind];
  64. else
  65. usage();
  66. /* get real path name */
  67. a_folder = realpath(path, NULL);
  68. if (a_folder == NULL)
  69. err(EXIT_FAILURE, "Path <%s> unreachable.", path);
  70. if (!strcmp("/", a_folder)) {
  71. printf("That's the root filesystem dude.");
  72. return EXIT_SUCCESS;
  73. }
  74. /* move to parent */
  75. strncat(a_folder, "/../", PATH_MAX - 1);
  76. p_folder = realpath(a_folder, NULL);
  77. r = stat(p_folder, &parent);
  78. if (r)
  79. err(EXIT_FAILURE, "Parent folder of <%s> is unreachable.", path);
  80. /* signal */
  81. struct sigaction sa;
  82. sa.sa_handler = NULL;
  83. sa.sa_sigaction = &sigHandler;
  84. sa.sa_flags = SA_SIGINFO;
  85. sigemptyset(&sa.sa_mask);
  86. sigfillset(&sa.sa_mask);
  87. if (sigaction(SIGINFO, &sa, NULL)) {
  88. warn("SIGNFO not caught.");
  89. }
  90. if (sigaction(SIGALRM, &sa, NULL)) {
  91. err(EXIT_FAILURE, "sigaction:ALARM");
  92. }
  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. }
  102. if (timer_settime(timerid, 0, &its, NULL)) {
  103. err(EXIT_FAILURE, "timer_settime failed.");
  104. }
  105. }
  106. /* proceed */
  107. printf("Waiting for folder %s to be mounted ...\n", path);
  108. while (1) {
  109. r = stat(path, &current);
  110. if (r)
  111. err(EXIT_FAILURE, "Current folder <%s> is unreachable.", path);
  112. ismounted = (current.st_dev != parent.st_dev);
  113. if (ismounted || (period == 0))
  114. break;
  115. /* timer */
  116. pause();
  117. --period;
  118. }
  119. printf("Folder path %s is %sa mount point.\n", path, (ismounted) ? "" : "*not* " );
  120. if (timerid)
  121. timer_delete(timerid);
  122. return EXIT_SUCCESS;
  123. }