1. Daniel Poelzleithner
  2. vaultfs-main

Commits

poelzi  committed 6e0c595

implemented symlinks and cleanups

  • Participants
  • Parent commits 3bc3ea5
  • Branches default

Comments (0)

Files changed (3)

File vaultdb/models.py

View file
 from django.db import models
+from django.contrib.contenttypes import generic
+import django.contrib.contenttypes.models as genmodels
+
 
 import os
 
 
 class BaseOperations(object):
 
-    def update_absolute(self):
+    def get_absolute_path(self):
         na = []
         st = self
         while st:
             st = st.parent
         #na.append("/")
         na.reverse()
-        self.absolute_path = os.path.join(*na)[:255]
+        return os.path.join(*na)
+
+    def update_absolute(self):
+        self.absolute_path = self.get_absolute_path()[:255]
+
+    def _get_name(self):
+        return self._name
+
+    def _set_name(self, value):
+        self._name = value
+        self.update_absolute()
+    name = property(_get_name, _set_name)
+
 
     def rename(self, newname):
         par = self.parent
             raise VaultNameAlreadyExists, "Name already exists"
         self.name = newname
 
+    is_dir = False
+    is_file = False
+    is_symlink = False
+
 class BaseDirectory(BaseOperations):
+    is_dir = True
 
     def get_child(self, name):
         if name == ".":
             try:
                 return self.directory_set.get(_name__exact=name)
             except:
-                raise VaultDoesNotExist, "Child does not exist"
+                try:
+                    return self.symlink_set.get(_name__exact=name)
+                except:
+                    raise VaultDoesNotExist, "Child does not exist"
 
         raise VaultDoesNotExist, "Child does not exist"
 
             return False
 
     def _get_children(self):
-        for i in self.directory_set.all():
+        for i in self.directory_set:
             yield i
 
-        for i in self.file_set.all():
+        for i in self.file_set:
+            yield i
+
+        for i in self.symlink_set:
             yield i
 
     children = property(_get_children)
             child.name = name
 
         if self.directory_set.filter(_name=child.name).count() or \
-           self.file_set.filter(_name=child.name).count():
+           self.file_set.filter(_name=child.name).count() or \
+           self.symlink_set.filter(_name=child.name).count():
            raise VaultNameAlreadyExists, "Object with name already exist"
 
         #if isinstance(child, File):
     absolute_path = None
     id = None
 
-    def __init__(self):
-        self.directory_set = Directory.objects.filter(parent__isnull=True)
-        self.file_set = Directory.objects.filter(parent__isnull=True)
+    def _dirset(self):
+        return Directory.objects.filter(parent__isnull=True)
+    directory_set = property(_dirset)
+
+    def _fileset(self):
+        return File.objects.filter(parent__isnull=True)
+    file_set = property(_fileset)
+
+    def _symset(self):
+        return Symlink.objects.filter(parent__isnull=True)
+    symlink_set = property(_symset)
 
     def get_as_parent(self):
         return None
             kwargs['_name'] = kwargs.pop('name')
         models.Model.__init__(self, *args, **kwargs)
 
-    def _get_name(self):
-        return self._name
-
-    def _set_name(self, value):
-        self._name = value
-        self.update_absolute()
-
-    name = property(_get_name, _set_name)
-
     class Admin:
         pass
 
 
         self.hash = hi.hexdigest()
 
-    
-
 
 class File(BaseOperations, models.Model):
     """Represents a Link in the filesystem to a real media file"""
     _name = models.CharField("Relative Name", max_length=255, db_index=True)
     parent = models.ForeignKey(Directory, null=True, db_index=True)
     real_file = models.ForeignKey(RealFile, null=True)
+    is_file = True
 
     def __init__(self, *args, **kwargs):
         if kwargs.has_key('name'):
             self.parent = self.parent.get_as_parent()
         super(File, self).save(*args, **kwargs)
 
-    def _get_name(self):
-        return self._name
-
-    def _set_name(self, value):
-        self._name = value
-        self.update_absolute()
-    name = property(_get_name, _set_name)
-
     def __repr__(self):
         return "<File %s (parent: %s)>" %(self.name, self.parent_id)
 
     def __unicode__(self):
         return unicode(self.name)
 
+
+class Symlink(BaseOperations, models.Model):
+    absolute_path = models.CharField("Absolut pathname", max_length=255, editable=False, null=True)
+    _name = models.CharField("Relative Name", max_length=255, db_index=True)
+    parent = models.ForeignKey(Directory, null=True, db_index=True)
+
+    target = models.TextField(null=False)
+    #target_type = models.ForeignKey(genmodels.ContentType)
+    #target_id = models.PositiveIntegerField()
+    #target = generic.GenericForeignKey()
+    #models.ForeignKey(RealFile, null=True)
+
+    is_symlink = True
+
+    def __init__(self, *args, **kwargs):
+        if kwargs.has_key('name'):
+            kwargs['_name'] = kwargs.pop('name')
+
+        super(Symlink, self).__init__(*args, **kwargs)
+
+    def save(self, *args, **kwargs):
+        self.update_absolute()
+        if self.parent:
+            self.parent = self.parent.get_as_parent()
+        super(Symlink, self).save(*args, **kwargs)
+
+    def __repr__(self):
+        return "<Symlink %s -> %s>" %(self.name, self.target)
+
+    def __str__(self):
+        return self.name.encode('utf-8')
+
+    def __unicode__(self):
+        return self.name
+    
+
+
 ACCESS_TYPES = (
     (0, 'Read'),
     (1, 'Write'),

File vaultfuse/tests/fusetests.py

View file
                 )
 
             for d in dirs:
-                l("DIR %s" %d)
+                ab = os.path.join(root, d)
+                if os.path.islink(ab):
+                    l("SYMLINK %s -> %s" %(d, os.path.realpath(ab)))
+                else:
+                    l("DIR %s" %d)
 
             l("%s files %s dirs" %(len(files), len(dirs)))
             l('')
         self.assertEqual(os.path.exists(P(('test2','sub3'))), False)
         
 
+    def test_symlink(self):
+        self.test_mkdir()
+        os.symlink(P('test2'), P('sym1'))
+        self.assertEqual(os.path.exists(P('test2')), True)
+        self.assertEqual(os.path.exists(P('sym1')), True)
+        os.unlink(P('sym1'))
+        self.assertEqual(os.path.exists(P('sym1')), False)
+        self.assertEqual(os.path.exists(P('test2')), True)
+        os.symlink(P('test2'), P('sym1'))
+        os.symlink(P('sym1'), P('sym2'))
+        self.assertEqual(os.path.exists(P('sym1')), True)
+        self.assertEqual(os.path.exists(P('sym2')), True)
+        os.symlink('/tmp', P('symtmp'))
+        self.assertEqual(os.path.exists(P('symtmp')), True)
+        os.rename(P('symtmp'),P('symtmp2') )
+        self.assertEqual(os.path.exists(P('symtmp2')), True)
+        self.assertEqual(os.path.exists(P('symtmp')), False)
+
+
+
+        #os.rename(P('test2.new'), P('test2'))

File vaultfuse/vault_fuse.py

View file
             return self.build_stat_file(obj)
         elif isinstance(obj, models.Directory):
             return self.build_stat_dir(obj)
+        elif isinstance(obj, models.Symlink):
+            return self.build_stat_sym(obj)
         else:
             return self.build_stat_meta()
 
             #dobj.real_file.file_ctime))
         return rv
 
+    def build_stat_sym(self, dobj):
+        """returns a os.stat compatible object from directory"""
+        #print "build sysm stat"
+        # fixme: handle uid/guid better ???
+        #if dobj.target:
+        #
+        #return posix.stat_result((33188, 1, 1, 1, 1000, 1000, 0, 0, 0, 0))
+        #return S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO
+        return posix.stat_result((S_IFLNK|S_IRWXU|S_IRWXG|S_IRWXO, 1, 1, 1, 1000, 1000, 0L, 1204582032, 1204582032, 1204582032))
+
+        rv = posix.stat_result(
+            (33188,
+            1, # inode
+            1, # dev
+            1, # fobj.file_links + count_duplicates,
+            os.geteuid(), # uid
+            os.getegid(), # gid
+            0,
+            #dobj.real_file.file_size,
+            0,
+            #dobj.real_file.file_atime,
+            0,
+            #dobj.real_file.file_mtime,
+            0))
+            #dobj.real_file.file_ctime))
+        return rv
 
 
     def build_stat_meta(self):
     def getattr_meta(self, rpath, mpath):
         pass
 
+    #def lookup(self, path):
+    #    print "!!!LOOKUP", path
+
+
     def getattr(self, path):
         pchunks = parse_path(path)
         #print "getattr ", pchunks
+        #print path
 
         mt = None
         rpart = []
 
     def readlink(self, path):
         #return os.readlink("." + path)
-        raise OSError(ENOENT, "Not implemented")
+        #raise OSError(ENOENT, "Not implemented")
+        #print "readlink", path
+        try:
+            d = models.Directory.objects.resolve_complete(path)
+            #print d
+        except VaultDoesNotExist:
+            raise OSError(2,"Does not exist")
+        if d.is_symlink:
+            return d.target.encode('utf-8')
+        raise OSError(2,"Does not exist")
 
 
     @staticmethod
             for i in TOP_METAS + ALL_METAS:
                 yield fuse.Direntry(META_PREFIX + i)
 
-            for de in models.Directory.objects.filter(parent__isnull=True):
+            for de in models.ROOTDIRECTORY.children:#models.Directory.objects.filter(parent__isnull=True):
                 if de.name:
                     yield fuse.Direntry(de.name.encode("utf-8"))
 
                 d = models.Directory.objects.resolve_complete(pchunks)
             except VaultDoesNotExist:
                 raise OSError(2,"Does not exist")
-                
+
+            if not isinstance(d, models.Symlink):
+                for i in os.listdir(d.target):
+                    yield fuse.Direntry(i)
+                return
+
             if not isinstance(d, models.Directory):
                 return
             for i in ALL_METAS:
 
     def unlink(self, path):
         d = models.Directory.objects.resolve_complete(path)
-        if isinstance(d, models.File):
+        if isinstance(d, (models.File, models.Symlink)):
             d.delete()
-        raise OSError(ENOFILE, "Not a file")
+            return
+        raise OSError(ENOLINK, "Not a file")
 
     def rmdir(self, path):
         d = models.Directory.objects.resolve_complete(path)
             d.delete()
 
     def symlink(self, path, path1):
-        os.symlink(path, "." + path1)
+        (par, left) = models.Directory.objects.resolve_parent(path1)
+        if par.has_child(left[0]):
+            raise OSError(EEXIST, "Target exists")
+        n = models.Symlink(_name=left[0], parent=par.get_as_parent(),
+                            target=path)
+
+        n.save()
+        return 0
+        # try to resolve its internal
+        #print self.__dict__
+        #print self.fuse_args.__dict__
+        #if path[:len(self.fuse_args.mountpoint)] == self.fuse_args.mountpoint:
+        #    ipath = path[len(self.fuse_args.mountpoint):]
+        #    print ipath
+
+        #n.target(path)
+
+        #if
+        #os.symlink(path, "." + path1)
 
     def rename(self, path, path1):
         #os.rename("." + path, "." + path1)