|
|
@@ -0,0 +1,142 @@
|
|
|
+#include <stdlib.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <limits.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <getopt.h>
|
|
|
+#include <locale.h>
|
|
|
+#include <err.h>
|
|
|
+#include <string.h>
|
|
|
+#include <errno.h>
|
|
|
+#include <getopt.h>
|
|
|
+#include <signal.h>
|
|
|
+
|
|
|
+static struct stat parent, current;
|
|
|
+
|
|
|
+static int period;
|
|
|
+const char *path;
|
|
|
+
|
|
|
+static void __attribute__((__noreturn__)) usage(void)
|
|
|
+{
|
|
|
+ fputs("\nUsage:\n", stderr);
|
|
|
+ fputs("ismounted [-w timeout] folder\n", stderr);
|
|
|
+ fputs(" -w: 1s periodic check until the process ran out of time.\n", stderr);
|
|
|
+
|
|
|
+ exit(EXIT_SUCCESS);
|
|
|
+}
|
|
|
+
|
|
|
+static void sigHandler(int signo,
|
|
|
+ siginfo_t *si __attribute__((unused)), void /* ucontext_t */ *uap __attribute__((unused)))
|
|
|
+{
|
|
|
+ switch (signo) {
|
|
|
+ case SIGINFO:
|
|
|
+ printf("Waiting for %s mount. %d seconds remaining.\n", path, period);
|
|
|
+ break;
|
|
|
+ case SIGALRM:
|
|
|
+ /* Timer */
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char *argv[])
|
|
|
+{
|
|
|
+ int r;
|
|
|
+ char *p_folder = NULL, *a_folder = NULL;
|
|
|
+ /* timer: optional */
|
|
|
+ struct itimerspec its;
|
|
|
+ timer_t timerid;
|
|
|
+ int ismounted = 0;
|
|
|
+
|
|
|
+ /* handle options */
|
|
|
+ int ch;
|
|
|
+ struct option longopts[] = {
|
|
|
+ { "wait", required_argument, &period, 'w' },
|
|
|
+ { NULL, 0, NULL, 0 }
|
|
|
+ };
|
|
|
+
|
|
|
+ opterr = 0;
|
|
|
+ while ((ch = getopt_long(argc, argv, "w:", longopts, NULL)) != -1) {
|
|
|
+ switch (ch) {
|
|
|
+ case 'w':
|
|
|
+ period = atoi(optarg);
|
|
|
+ break;
|
|
|
+ case 0:
|
|
|
+ /* long option */
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (optind == (argc - 1))
|
|
|
+ path = argv[optind];
|
|
|
+ else
|
|
|
+ usage();
|
|
|
+
|
|
|
+ /* get real path name */
|
|
|
+ a_folder = realpath(path, NULL);
|
|
|
+ if (a_folder == NULL)
|
|
|
+ err(EXIT_FAILURE, "Path <%s> unreachable.", path);
|
|
|
+
|
|
|
+ if (!strcmp("/", a_folder)) {
|
|
|
+ printf("That's the root filesystem dude.");
|
|
|
+ return EXIT_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* move to parent */
|
|
|
+ strncat(a_folder, "/../", PATH_MAX - 1);
|
|
|
+ p_folder = realpath(a_folder, NULL);
|
|
|
+
|
|
|
+ r = stat(p_folder, &parent);
|
|
|
+ if (r)
|
|
|
+ err(EXIT_FAILURE, "Parent folder of <%s> is unreachable.", path);
|
|
|
+
|
|
|
+ /* signal */
|
|
|
+ struct sigaction sa;
|
|
|
+ sa.sa_handler = NULL;
|
|
|
+ sa.sa_sigaction = &sigHandler;
|
|
|
+ sa.sa_flags = SA_SIGINFO;
|
|
|
+ sigemptyset(&sa.sa_mask);
|
|
|
+ sigfillset(&sa.sa_mask);
|
|
|
+ if (sigaction(SIGINFO, &sa, NULL)) {
|
|
|
+ warn("SIGNFO not caught.");
|
|
|
+ }
|
|
|
+ if (sigaction(SIGALRM, &sa, NULL)) {
|
|
|
+ err(EXIT_FAILURE, "sigaction:ALARM");
|
|
|
+ }
|
|
|
+
|
|
|
+ /* timer, if set */
|
|
|
+ if ((period > 0) ) {
|
|
|
+ its.it_interval.tv_sec = 1;
|
|
|
+ its.it_interval.tv_nsec = 0;
|
|
|
+ its.it_value.tv_sec = its.it_interval.tv_sec;
|
|
|
+ its.it_value.tv_nsec = 0;
|
|
|
+ if (timer_create(CLOCK_REALTIME, NULL, &timerid)) {
|
|
|
+ err(EXIT_FAILURE,"timer_create failed.");
|
|
|
+ }
|
|
|
+ if (timer_settime(timerid, 0, &its, NULL)) {
|
|
|
+ err(EXIT_FAILURE, "timer_settime failed.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* proceed */
|
|
|
+ printf("Waiting for folder %s to be mounted ...\n", path);
|
|
|
+ while (1) {
|
|
|
+ r = stat(path, ¤t);
|
|
|
+ if (r)
|
|
|
+ err(EXIT_FAILURE, "Current folder <%s> is unreachable.", path);
|
|
|
+
|
|
|
+ ismounted = (current.st_dev != parent.st_dev);
|
|
|
+ if (ismounted || (period == 0))
|
|
|
+ break;
|
|
|
+
|
|
|
+ /* timer */
|
|
|
+ pause();
|
|
|
+ --period;
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("Folder path %s is %sa mount point.\n", path, (ismounted) ? "" : "*not* " );
|
|
|
+
|
|
|
+ return EXIT_SUCCESS;
|
|
|
+}
|
|
|
+
|