Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux
[cascardo/linux.git] / tools / hv / hv_vss_daemon.c
index 921c1be..fea03a3 100644 (file)
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/poll.h>
+#include <sys/ioctl.h>
 #include <linux/types.h>
+#include <fcntl.h>
 #include <stdio.h>
+#include <mntent.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
 #include <arpa/inet.h>
+#include <linux/fs.h>
 #include <linux/connector.h>
 #include <linux/hyperv.h>
 #include <linux/netlink.h>
@@ -43,46 +47,60 @@ static struct sockaddr_nl addr;
 #endif
 
 
+static int vss_do_freeze(char *dir, unsigned int cmd, char *fs_op)
+{
+       int ret, fd = open(dir, O_RDONLY);
+
+       if (fd < 0)
+               return 1;
+       ret = ioctl(fd, cmd, 0);
+       syslog(LOG_INFO, "VSS: %s of %s: %s\n", fs_op, dir, strerror(errno));
+       close(fd);
+       return !!ret;
+}
+
 static int vss_operate(int operation)
 {
        char *fs_op;
-       char cmd[512];
-       char buf[512];
-       FILE *file;
-       char *p;
-       char *x;
-       int error = 0;
+       char match[] = "/dev/";
+       FILE *mounts;
+       struct mntent *ent;
+       unsigned int cmd;
+       int error = 0, root_seen = 0;
 
        switch (operation) {
        case VSS_OP_FREEZE:
-               fs_op = "-f ";
+               cmd = FIFREEZE;
+               fs_op = "freeze";
                break;
        case VSS_OP_THAW:
-               fs_op = "-u ";
+               cmd = FITHAW;
+               fs_op = "thaw";
                break;
        default:
                return -1;
        }
 
-       file = popen("mount | awk '/^\\/dev\\// { print $3}'", "r");
-       if (file == NULL)
+       mounts = setmntent("/proc/mounts", "r");
+       if (mounts == NULL)
                return -1;
 
-       while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
-               x = strchr(p, '\n');
-               *x = '\0';
-               if (!strncmp(p, "/", sizeof("/")))
+       while ((ent = getmntent(mounts))) {
+               if (strncmp(ent->mnt_fsname, match, strlen(match)))
                        continue;
-
-               sprintf(cmd, "%s %s %s", "fsfreeze ", fs_op, p);
-               syslog(LOG_INFO, "VSS cmd is %s\n", cmd);
-               error = system(cmd);
+               if (strcmp(ent->mnt_type, "iso9660") == 0)
+                       continue;
+               if (strcmp(ent->mnt_dir, "/") == 0) {
+                       root_seen = 1;
+                       continue;
+               }
+               error |= vss_do_freeze(ent->mnt_dir, cmd, fs_op);
        }
-       pclose(file);
+       endmntent(mounts);
 
-       sprintf(cmd, "%s %s %s", "fsfreeze ", fs_op, "/");
-       syslog(LOG_INFO, "VSS cmd is %s\n", cmd);
-       error = system(cmd);
+       if (root_seen) {
+               error |= vss_do_freeze("/", cmd, fs_op);
+       }
 
        return error;
 }