loading of subjectPublicKeyInfo wrapped keys using KEY_ANY (openssl format)
[strongswan.git] / src / dumm / cowfs.c
index f3b169b..4c16c7c 100644 (file)
@@ -55,23 +55,29 @@ struct private_cowfs_t {
        char *master;
        /** host filesystem path */
        char *host;
-       /** scenario filesystem path */
-       char *scen;
+       /** overlay filesystem path */
+       char *over;
        /** fd of read only master filesystem */
        int master_fd;
        /** copy on write overlay to master */
        int host_fd;
-       /** optional scenario COW overlay */
-       int scen_fd;
+       /** optional COW overlay */
+       int over_fd;
        /** thread processing FUSE */
        pthread_t thread;
 };
 
+/**
+ * get this pointer stored in fuse context
+ */
 static private_cowfs_t *get_this()
 {
        return (fuse_get_context())->private_data;
 }
 
+/**
+ * make a path relative
+ */
 static void rel(const char **path)
 {
        if (**path == '/')
@@ -85,15 +91,15 @@ static void rel(const char **path)
 }
 
 /**
- * get the filesystem to read something from
+ * get the highest overlay in which path exists
  */
 static int get_rd(const char *path)
 {
        private_cowfs_t *this = get_this();
 
-       if (this->scen_fd > 0 && faccessat(this->scen_fd, path, F_OK, 0) == 0)
+       if (this->over_fd > 0 && faccessat(this->over_fd, path, F_OK, 0) == 0)
        {
-               return this->scen_fd;
+               return this->over_fd;
        }
        if (faccessat(this->host_fd, path, F_OK, 0) == 0)
        {
@@ -103,20 +109,20 @@ static int get_rd(const char *path)
 }
 
 /**
- * get the filesystem to write something to
+ * get the highest overlay available, to write something
  */
 static int get_wr(const char *path)
 {
        private_cowfs_t *this = get_this();
-       if (this->scen_fd > 0)
+       if (this->over_fd > 0)
        {
-               return this->scen_fd;
+               return this->over_fd;
        }
        return this->host_fd;
 }
 
 /**
- * create all directories need to create the file "path"
+ * create full "path" at "wr" the same way they exist at "rd"
  */
 static bool clone_path(int rd, int wr, const char *path)
 {
@@ -130,7 +136,7 @@ static bool clone_path(int rd, int wr, const char *path)
                *pos = '\0';
                if (fstatat(wr, full, &st, 0) < 0)
                {
-                       /* TODO: handle symlinks! */
+                       /* TODO: handle symlinks!? */
                        if (fstatat(rd, full, &st, 0) < 0)
                        {
                                return FALSE;
@@ -147,7 +153,7 @@ static bool clone_path(int rd, int wr, const char *path)
 }
 
 /**
- * copy a file from a readonly to a read-write overlay
+ * copy a (special) file from a readonly to a read-write overlay
  */
 static int copy(const char *path)
 {
@@ -169,35 +175,44 @@ static int copy(const char *path)
        {
                return -1;
        }
-       from = openat(rd, path, O_RDONLY, st.st_mode);
-       if (from < 0)
-       {
-               return -1;
-       }
        if (!clone_path(rd, wr, path))
        {
                return -1;
        }
-       to = openat(wr, path, O_WRONLY | O_CREAT, st.st_mode);
-       if (to < 0)
+       if (mknodat(wr, path, st.st_mode, st.st_rdev) < 0)
        {
-               close(from);
                return -1;
        }
-       while ((len = read(from, buf, sizeof(buf))) > 0)
+       /* copy if no special file */
+       if (st.st_size)
        {
-               if (write(to, buf, len) < len)
+               from = openat(rd, path, O_RDONLY, st.st_mode);
+               if (from < 0)
+               {
+                       return -1;
+               }
+               to = openat(wr, path, O_WRONLY , st.st_mode);
+               if (to < 0)
                {
                        close(from);
-                       close(to);
                        return -1;
                }
-       }
-       close(from);
-       close(to);
-       if (len < 0)
-       {
-               return -1;
+               while ((len = read(from, buf, sizeof(buf))) > 0)
+               {
+                       if (write(to, buf, len) < len)
+                       {
+                               /* TODO: only on len < 0 ? */
+                               close(from);
+                               close(to);
+                               return -1;
+                       }
+               }
+               close(from);
+               close(to);
+               if (len < 0)
+               {
+                       return -1;
+               }
        }
        return wr;
 }
@@ -303,7 +318,7 @@ static int cowfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
        
        d1 = get_dir(this->master, path);
        d2 = get_dir(this->host, path);
-       d3 = get_dir(this->scen, path);
+       d3 = get_dir(this->over, path);
        
        if (d1)
        {
@@ -423,10 +438,18 @@ static int cowfs_rmdir(const char *path)
  */
 static int cowfs_symlink(const char *from, const char *to)
 {
+       int fd;
+       const char *fromrel = from;
+
        rel(&to);
+       rel(&fromrel);
 
-       /* TODO: relative from? */
-       if (symlinkat(from, get_wr(to), to) < 0)
+       fd = get_wr(to);
+       if (!clone_path(get_rd(fromrel), fd, fromrel))
+       {
+               return -errno;
+       }
+       if (symlinkat(from, fd, to) < 0)
        {
                return -errno;
        }
@@ -466,11 +489,22 @@ static int cowfs_rename(const char *from, const char *to)
  */
 static int cowfs_link(const char *from, const char *to)
 {
+       int rd, wr;
+
        rel(&from);
        rel(&to);
-
-    if (linkat(get_rd(from), from, get_wr(to), to, 0) < 0)
+       
+       rd = get_rd(from);
+       wr = get_wr(to);
+       
+       if (!clone_path(rd, wr, to))
+       {
+               DBG1("cloning path '%s' failed", to);
+               return -errno;
+       }
+    if (linkat(rd, from, wr, to, 0) < 0)
     {
+               DBG1("linking '%s' to '%s' failed", from, to);
        return -errno;
        }
     return 0;
@@ -551,6 +585,7 @@ static int cowfs_truncate(const char *path, off_t size)
 {
        int fd;
        struct stat st;
+       
        private_cowfs_t *this = get_this();
 
        rel(&path);
@@ -653,6 +688,7 @@ static int cowfs_read(const char *path, char *buf, size_t size, off_t offset,
        {
                return -errno;
        }
+       
        res = pread(file, buf, size, offset);
        if (res < 0)
        {
@@ -705,9 +741,9 @@ static int cowfs_statfs(const char *path, struct statvfs *stbuf)
        int fd;
        
        fd = this->host_fd;
-       if (this->scen_fd > 0)
+       if (this->over_fd > 0)
        {
-               fd = this->scen_fd;
+               fd = this->over_fd;
        }
 
        if (fstatvfs(fd, stbuf) < 0)
@@ -757,20 +793,31 @@ static struct fuse_operations cowfs_operations = {
 };
 
 /**
- * Implementation of cowfs_t.set_scenario.
+ * Implementation of cowfs_t.set_overlay.
  */
-static void set_scenario(private_cowfs_t *this, char *path)
+static bool set_overlay(private_cowfs_t *this, char *path)
 {
-       if (this->scen)
+       if (this->over)
        {
-               free(this->scen);
+               free(this->over);
+               this->over = NULL;
        }
-       if (this->scen_fd > 0)
+       if (this->over_fd > 0)
        {
-               close(this->scen_fd);
+               close(this->over_fd);
+               this->over_fd = -1;
        }
-       this->scen = strdup(path);
-       this->scen_fd = open(path, O_RDONLY | O_DIRECTORY);
+       if (path)
+       {
+               this->over_fd = open(path, O_RDONLY | O_DIRECTORY);
+               if (this->over_fd < 0)
+               {
+                       DBG1("failed to open overlay directory '%s': %m", path);
+                       return FALSE;
+               }
+               this->over = strdup(path);
+       }
+       return TRUE;
 }
 
 /**
@@ -779,18 +826,18 @@ static void set_scenario(private_cowfs_t *this, char *path)
 static void destroy(private_cowfs_t *this)
 {
        fuse_exit(this->fuse);
-       pthread_join(this->thread, NULL);
        fuse_unmount(this->mount, this->chan);
+       pthread_join(this->thread, NULL);
        fuse_destroy(this->fuse);
        free(this->mount);
        free(this->master);
        free(this->host);
-       free(this->scen);
+       free(this->over);
        close(this->master_fd);
        close(this->host_fd);
-       if (this->scen_fd > 0)
+       if (this->over_fd > 0)
        {
-               close(this->scen_fd);
+               close(this->over_fd);
        }
        free(this);
 }
@@ -803,7 +850,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
        struct fuse_args args = {0, NULL, 0};
        private_cowfs_t *this = malloc_thing(private_cowfs_t);
        
-       this->public.set_scenario = (void(*)(cowfs_t*, char *path))set_scenario;
+       this->public.set_overlay = (bool(*)(cowfs_t*, char *path))set_overlay;
        this->public.destroy = (void(*)(cowfs_t*))destroy;
        
     this->master_fd = open(master, O_RDONLY | O_DIRECTORY);
@@ -819,7 +866,7 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
        close(this->master_fd);
        free(this);
     }
-       this->scen_fd = -1;
+       this->over_fd = -1;
        
     this->chan = fuse_mount(mount, &args);
     if (this->chan == NULL)
@@ -846,9 +893,9 @@ cowfs_t *cowfs_create(char *master, char *host, char *mount)
     this->mount = strdup(mount);
     this->master = strdup(master);
     this->host = strdup(host);
-    this->scen = NULL;
+    this->over = NULL;
        
-       if (pthread_create(&this->thread, NULL, (void*)fuse_loop_mt, this->fuse) != 0)
+       if (pthread_create(&this->thread, NULL, (void*)fuse_loop, this->fuse) != 0)
        {
        DBG1("creating thread to handle FUSE failed");
        fuse_unmount(mount, this->chan);