Beispiel #1
0
    def release(self, path, fuse_file_info):
        """
        Save file to database and launch replication to remote Cozy.
            path {string}: file path
            fuse_file_info {struct}: information about open file

            Release is called when there are no more references
            to an open file: all file descriptors are closed and
            all memory mappings are unmapped.
        """
        try:
            path = _normalize_path(path)
            logger.info('release file %s' % path)
            file_doc = dbutils.get_file(self.db, path)
            binary_id = file_doc["binary"]["file"]["id"]

            if path in self.writeBuffers:
                data = self.writeBuffers[path]
                self.db.put_attachment(self.db[binary_id],
                                       data,
                                       filename="file")
                file_doc['size'] = len(data)
                file_doc['lastModification'] = get_current_date()
                self.writeBuffers.pop(path, None)

                binary = self.db[binary_id]
                file_doc['binary']['file']['rev'] = binary['_rev']
                self.db.save(file_doc)

            logger.info("release is done")
            return 0

        except Exception as e:
            logger.exception(e)
            return -errno.ENOENT
Beispiel #2
0
    def unlink(self, path):
        """
        Remove file from database.
        """

        try:
            path = _normalize_path(path)
            logger.info('unlink %s' % path)
            parts = path.rsplit(u'/', 1)
            if len(parts) == 1:
                dirname, filename = u'', parts[0]
            else:
                dirname, filename = parts

            file_doc = dbutils.get_file(self.db, path)
            if file_doc is not None:
                binary_id = file_doc["binary"]["file"]["id"]
                logger.info(self.db[file_doc["_id"]])

                try:
                    self.db.delete(self.db[binary_id])
                except ResourceNotFound:
                    pass
                self.db.delete(self.db[file_doc["_id"]])
                logger.info('file %s removed' % path)
                self._update_parent_folder(file_doc['path'])
                return 0
            else:
                logger.warn('Cannot delete file, no entry found')
                return -errno.ENOENT

        except Exception as e:
            logger.exception(e)
            return -errno.ENOENT
Beispiel #3
0
 def _is_found(self, path):
     '''
     Returns true if the path exists in the database, false either.
     '''
     path = fusepath.normalize_path(path)
     file_doc = dbutils.get_file(self.db, path)
     return file_doc is not None
Beispiel #4
0
 def _create_new_file(self, path):
     '''
     Create empty binary cache and load file metadata from database.
     '''
     file_doc = dbutils.get_file(self.db, path)
     file_doc['size'] = 0
     file_doc['lastModification'] = fusepath.get_current_date()
     dbutils.update_file(self.db, file_doc)
Beispiel #5
0
    def get_st(self, path):
        self.receive()
        if path in self.cache['st']:
            logger.info('st : cache')
            return self.cache['st'][path]
        else:
            try:
                st = CouchStat()

                # Path is root
                if path is "/":
                    st.st_mode = stat.S_IFDIR | 0o775
                    st.st_nlink = 2
                    self.cache['st'][path] = st
                    return st

                else:
                    # Or path is a folder
                    folder = dbutils.get_folder(self.db, path)
                    if folder is not None:
                        st.st_mode = stat.S_IFDIR | 0o775
                        st.st_nlink = 2
                        if 'lastModification' in folder:
                            st.st_atime = get_date(folder['lastModification'])
                            st.st_ctime = st.st_atime
                            st.st_mtime = st.st_atime
                        self.cache['st'][path] = st
                        return st

                    else:
                        # Or path is a file
                        file_doc = dbutils.get_file(self.db, path)

                        if file_doc is not None:
                            st.st_mode = stat.S_IFREG | 0o664
                            st.st_nlink = 1
                            # TODO: if size is not set, get the binary
                            # and save the information.
                            st.st_size = file_doc.get('size', 4096)
                            if 'lastModification' in file_doc:
                                st.st_atime = \
                                    get_date(file_doc['lastModification'])
                                st.st_ctime = st.st_atime
                                st.st_mtime = st.st_atime
                            self.cache['st'][path] = st
                            return st

                        else:
                            print 'File does not exist: %s' % path
                            logger.info('file_not_fount')
                            return st
                self.send()

            except Exception as e:
                logger.exception(e)
                return e
Beispiel #6
0
    def getattr(self, path):
        """
        Return file descriptor for given_path. Useful for 'ls -la' command like.
        """
        try:
            logger.debug('getattr %s' % path)

            st = CouchStat()

            # Path is root
            if path is "/":
                st.st_mode = stat.S_IFDIR | 0o775
                st.st_nlink = 2
                return st

            else:
                # Or path is a folder
                folder = dbutils.get_folder(self.db, path)

                if folder is not None:
                    st.st_mode = stat.S_IFDIR | 0o775
                    st.st_nlink = 2
                    if 'lastModification' in folder:
                        st.st_atime = get_date(folder['lastModification'])
                        st.st_ctime = st.st_atime
                        st.st_mtime = st.st_atime
                    return st

                else:
                    # Or path is a file
                    file_doc = dbutils.get_file(self.db, path)

                    if file_doc is not None:
                        st.st_mode = stat.S_IFREG | 0o664
                        st.st_nlink = 1
                        # TODO: if size is not set, get the binary
                        # and save the information.
                        st.st_size = file_doc.get('size', 4096)
                        if 'lastModification' in file_doc:
                            st.st_atime = \
                                get_date(file_doc['lastModification'])
                            st.st_ctime = st.st_atime
                            st.st_mtime = st.st_atime
                        return st

                    else:
                        print 'File does not exist: %s' % path
                        return -errno.ENOENT
                        return st

        except Exception as e:
            logger.exception(e)
            return -errno.ENOENT
Beispiel #7
0
 def get_binary(self, path):
     self.receive()
     if path in self.cache['binaries']:
         return self.cache['binaries'][path]
     else:            
         file_doc = dbutils.get_file(self.db, path)
         if file_doc is not None:
             binary_id = file_doc["binary"]["file"]["id"]
             self.cache['binaries'][path] = binary_id
             return binary_id
         else:
             return False
Beispiel #8
0
 def _remove_file_from_db(self, path):
     '''
     Remove binary document if it exists, then remove file document.
     '''
     file_doc = dbutils.get_file(self.db, path)
     if file_doc["binary"] is not None and 'file' in file_doc["binary"]:
         binary_id = file_doc["binary"]["file"]["id"]
         try:
             self.db.delete(self.db[binary_id])
         except ResourceNotFound:
             pass
     dbutils.delete_file(self.db, file_doc)
Beispiel #9
0
    def _get_attr_from_db(self, path, isfile=None):
        '''
        Build fuse file attribute from data located in database. Check if path
        corresponds to a folder first.
        '''
        st = CouchStat()
        path = fusepath.normalize_path(path)

        if isfile is None:
            folder = dbutils.get_folder(self.db, path)
            if folder is not None:
                st.set_folder(folder)
                self.attr_cache.add(path, st)
                return st
            else:
                file_doc = dbutils.get_file(self.db, path)
                if file_doc is not None:
                    st.set_file(file_doc)
                    self.attr_cache.add(path, st)
                    return st
                else:
                    return None
        elif isfile:
            file_doc = dbutils.get_file(self.db, path)
            if file_doc is not None:
                st.set_file(file_doc)
                self.attr_cache.add(path, st)
                return st
            else:
                return None
        else:
            folder = dbutils.get_folder(self.db, path)
            if folder is not None:
                st.set_folder(folder)
                self.attr_cache.add(path, st)
                return st
            else:
                return None
Beispiel #10
0
    def get_file_metadata(self, path):
        '''
        Return file metadata based on given path. The corresponding file doc is
        returned with the linked binary ID and the cached file path.
        '''
        res = self.metadata_cache.get(path)
        if res is None:
            file_doc = dbutils.get_file(self.db, path)
            binary_id = file_doc["binary"]["file"]["id"]
            cache_file_folder = os.path.join(self.cache_path, binary_id)
            cache_file_name = os.path.join(cache_file_folder, 'file')

            res = (file_doc, binary_id, cache_file_name)
            self.metadata_cache.add(path, res)
        return res
Beispiel #11
0
    def unlink(self, path):
        """
        Remove file from current FS. Update cache accordingly.
        """
        try:
            logger.info('unlink %s' % path)
            path = fusepath.normalize_path(path)

            if dbutils.get_file(self.db, path) is not None:
                self.binary_cache.remove(path)
                self._clean_cache(path, True)
                self._remove_file_from_db(path)
                self._update_parent_folder(path)
                return 0
            else:
                logger.info('Cannot delete file, no entry found')
                return -errno.ENOENT

        except Exception as e:
            logger.exception(e)
            return -errno.ENOENT
Beispiel #12
0
    def read(self, path, size, offset):
        """
        Return content of file located at given path.
            path {string}: file path
            size {integer}: size of file part to read
            offset {integer}: beginning of file part to read
        """
        # TODO: do not load the file for each chunk.
        # Save it in a cache file maybe?.
        try:
            path = _normalize_path(path)
            logger.info('read %s' % path)
            file_doc = dbutils.get_file(self.db, path)
            binary_id = file_doc["binary"]["file"]["id"]
            binary_attachment = self.db.get_attachment(binary_id, "file")

            if binary_attachment is None:
                logger.info('No attachment for this binary')
                return ''

            else:
                content = binary_attachment.read()
                content_length = len(content)
                logger.info('Return file content')

                if offset < content_length:
                    if offset + size > content_length:
                        size = content_length - offset
                    buf = content[offset:offset+size]

                else:
                    buf = ''
                    logger.info('Empty file content')

                return buf

        except Exception, e:
            logger.exception(e)
            return -errno.ENOENT
Beispiel #13
0
    def rename(self, pathfrom, pathto, root=True):
        """
        Rename file and subfiles (if it's a folder) in device.
        """
        logger.info("rename %s -> %s: " % (pathfrom, pathto))
        try:
            pathfrom = fusepath.normalize_path(pathfrom)
            pathto = fusepath.normalize_path(pathto)

            file_doc = dbutils.get_file(self.db, pathfrom)
            if file_doc is not None:
                file_path, name = fusepath.split(pathto)

                file_doc.update({
                    "name": name,
                    "path": file_path,
                    "lastModification": fusepath.get_current_date()
                })
                dbutils.update_file(self.db, file_doc)

            folder_doc = dbutils.get_folder(self.db, pathfrom)
            if folder_doc is not None:
                folder_path, name = fusepath.split(pathto)
                folder_doc.update({
                    "name": name,
                    "path": folder_path,
                    "lastModification": fusepath.get_current_date()
                })

                # Rename all subfiles
                for res in self.db.view("file/byFolder", key=pathfrom):
                    child_pathfrom = os.path.join(
                        res.value['path'],
                        res.value['name']
                    )
                    child_pathto = os.path.join(folder_path, name, res.value['name'])
                    self.rename(child_pathfrom, child_pathto, False)

                for res in self.db.view("folder/byFolder", key=pathfrom):
                    child_pathfrom = os.path.join(
                        res.value['path'],
                        res.value['name'])
                    child_pathto = os.path.join(folder_path, name, res.value['name'])
                    self.rename(child_pathfrom, child_pathto, False)

                dbutils.update_folder(self.db, folder_doc)

            parent_path_from, namefrom = fusepath.split(pathfrom)
            parent_path_to, nameto = fusepath.split(pathto)

            if root:
                self._update_parent_folder(parent_path_from)
                self._update_parent_folder(parent_path_to)

            names = dbutils.name_cache.get(parent_path_from)
            if names is not None and namefrom in names:
                names.remove(namefrom)
                names.add(parent_path_from, names)

            names = dbutils.name_cache.get(parent_path_to)
            if names is not None:
                names.append(nameto)
                names.add(parent_path_to, names)

            self._clean_cache(pathfrom)
            self._add_to_cache(pathto)

            if folder_doc is None and file_doc is None:
                return -errno.ENOENT
            else:
                return 0

        except Exception as e:
            logger.exception(e)
            return -errno.ENOENT