예제 #1
0
파일: __init__.py 프로젝트: pombreda/smbfs
    def makedir(self, path, recursive=False, allow_recreate=False):
        path = normpath(path)
        if path in ('', '/'):
            return

        if recursive:
            created = False
            for path_part in recursepath(path):
                if not self.isdir(path_part):
                    self.conn.mkdir(self.smb_path(path_part))
                    created = True
                else:
                    if self.isfile(path_part):
                        raise ResourceInvalidError(path_part)

            if not created and not allow_recreate:
                raise DestinationExistsError(path)
        else:
            base = dirname(path)
            if not self.exists(base):
                raise ParentDirectoryMissingError(path)

            if not allow_recreate:
                if self.exists(path):
                    if self.isfile(path):
                        raise ResourceInvalidError(path)
                    raise DestinationExistsError(path)
                self.conn.mkdir(self.smb_path(path))
            else:
                if not self.isdir(path):
                    self.conn.mkdir(self.smb_path(path))
예제 #2
0
def copyfile_non_atomic(src_fs,
                        src_path,
                        dst_fs,
                        dst_path,
                        overwrite=True,
                        chunk_size=64 * 1024):
    """A non atomic version of copyfile (will not block other threads using src_fs or dst_fst)

    :param src_fs: Source filesystem object
    :param src_path: -- Source path
    :param dst_fs: Destination filesystem object
    :param dst_path: Destination filesystem object
    :param chunk_size: Size of chunks to move if system copyfile is not available (default 64K)

    """

    if not overwrite and dst_fs.exists(dst_path):
        raise DestinationExistsError(dst_path)

    src = None
    dst = None
    try:
        src = src_fs.open(src_path, 'rb')
        dst = dst_fs.open(dst_path, 'wb')
        write = dst.write
        read = src.read
        chunk = read(chunk_size)
        while chunk:
            write(chunk)
            chunk = read(chunk_size)
    finally:
        if src is not None:
            src.close()
        if dst is not None:
            dst.close()
예제 #3
0
파일: __init__.py 프로젝트: pombreda/smbfs
    def copy(self, src, dst, overwrite=False, chunk_size=1024 * 1024):
        src = normpath(src)

        if not self.isfile(src):
            if self.isdir(src):
                raise ResourceInvalidError(
                    src, msg="Source is not a file: %(path)s")
            raise ResourceNotFoundError(src)

        dst = normpath(dst)

        if not overwrite and self.exists(dst):
            raise DestinationExistsError(dst)

        src_file = None
        dst_file = None

        try:
            src_file = self.open(src, 'r')
            dst_file = self.open(dst, 'w')

            while 1:
                copy_buffer = src_file.read(chunk_size)
                if copy_buffer:
                    dst_file.write(copy_buffer)
                else:
                    break
        finally:
            if src_file is not None:
                src_file.close()
            if dst_file is not None:
                dst_file.close()
예제 #4
0
    def copy(self, src, dst, overwrite=False, chunk_size=65536):
        if self.isdir(src):
            raise ResourceInvalidError(src)
        if not self.isfile(src):
            if not self.isdir(dirname(src)):
                raise ParentDirectoryMissingError(src)
            raise ResourceNotFoundError(src)

        if self.isdir(dst):
            raise ResourceInvalidError(dst)
        if self.isfile(dst):
            if overwrite:
                self.remove(dst)
            else:
                raise DestinationExistsError(dst)
        else:
            if not self.isdir(dirname(dst)):
                raise ParentDirectoryMissingError(dst)

        parent_path = self._ids[dirname(dst)]
        copy_fh = {'title': basename(dst), 'parents': [{'id': parent_path}]}
        copy_fh = self.client.auth.service.files() \
                                  .copy(fileId=self._ids[src], body=copy_fh) \
                                  .execute()
        self._ids[dst] = copy_fh['id']
예제 #5
0
    def makedir(self, path, recursive=False, allow_recreate=False):
        """Creates a file with mimeType _folder_mimetype
        which acts as a folder in GoogleDrive."""
        if self.isdir(path):
            if allow_recreate:
                return
            else:
                raise DestinationExistsError(path)
        if self.isfile(path):
            raise ResourceInvalidError(path)
        if not recursive and not self.isdir(dirname(path)):
            raise ParentDirectoryMissingError(path)

        if recursive:
            self.makedir(dirname(path),
                         recursive=recursive,
                         allow_recreate=True)

        parent_id = self._ids[dirname(path)]
        fh = self.client.CreateFile({
            'title': basename(path),
            'mimeType': self._folder_mimetype,
            'parents': [{
                'id': parent_id
            }]
        })
        fh.Upload()
        self._ids[path] = fh['id']
예제 #6
0
    def _move(self, src, dst, overwrite=False):
        """Move source to destination with support for overwriting destination.

        Used by ``XRootDPyFS.move()``, ``XRootDPyFS.movedir()`` and
        ``XRootDPyFS.rename()``.

        .. warning::

           It is the responsibility of the caller of this method to check that
           the source exists.

           If ``overwrite`` is ``True``, this method will first remove any
           destination directory/file if it exists, and then try to move the
           source. Hence, if the source doesn't exists, it will remove the
           destination and then fail.
        """
        if self.exists(dst):
            if not overwrite:
                raise DestinationExistsError(dst)

            if self.isfile(dst):
                self.remove(dst)
            elif self.isdir(dst):
                self.removedir(dst, force=True)

        status, dummy = self._client.mv(src, dst)

        if not status.ok:
            self._raise_status(dst, status)

        return True
예제 #7
0
    def copydir(self, src, dst, overwrite=False, parallel=True):
        """Copy a directory from source to destination.

        By default the copy is done by recreating the source directory
        structure at the destination, and then copy files in parallel from
        source to destination.

        :param src: Source directory path.
        :type src: str
        :param dst: Destination directory path.
        :type dst: str
        :param overwrite: If True then any existing files in the destination
            directory will be overwritten.
        :type overwrite: bool
        :param parallel: If True (default), the copy will be done in parallel.
        :type parallel: bool
        """
        if not self.isdir(src):
            if self.isfile(src):
                raise ResourceInvalidError(
                    src, msg="Source is not a directory: %(path)s")
            raise ResourceNotFoundError(src)

        if self.exists(dst):
            if overwrite:
                if self.isdir(dst):
                    self.removedir(dst, force=True)
                elif self.isfile(dst):
                    self.remove(dst)
            else:
                raise DestinationExistsError(dst)

        if parallel:
            process = CopyProcess()

            def process_copy(src, dst, overwrite=False):
                process.add_job(src, dst)

            copyfile = process_copy
        else:
            copyfile = self.copy

        self.makedir(dst, allow_recreate=True)

        for src_dirpath, filenames in self.walk(src):
            dst_dirpath = pathcombine(dst, frombase(src, src_dirpath))
            self.makedir(dst_dirpath, allow_recreate=True, recursive=True)
            for filename in filenames:
                src_filename = pathjoin(src_dirpath, filename)
                dst_filename = pathjoin(dst_dirpath, filename)
                copyfile(src_filename, dst_filename, overwrite=overwrite)

        if parallel:
            process.prepare()
            process.run()

        return True
예제 #8
0
 def _raise_status(self, path, status):
     """Raise error based on status."""
     if status.errno == 3006:
         raise DestinationExistsError(path=path, details=status)
     elif status.errno == 3005:
         raise DirectoryNotEmptyError(path=path, details=status)
     elif status.errno == 3011:
         raise ResourceInvalidError(path=path, details=status)
     else:
         raise FSError(details=status)
예제 #9
0
def movefile(src_fs,
             src_path,
             dst_fs,
             dst_path,
             overwrite=True,
             chunk_size=64 * 1024):
    """Move a file from one filesystem to another. Will use system copyfile, if both files have a syspath.
    Otherwise file will be copied a chunk at a time.

    :param src_fs: Source filesystem object
    :param src_path: Source path
    :param dst_fs: Destination filesystem object
    :param dst_path: Destination filesystem object
    :param chunk_size: Size of chunks to move if system copyfile is not available (default 64K)

    """
    src_syspath = src_fs.getsyspath(src_path, allow_none=True)
    dst_syspath = dst_fs.getsyspath(dst_path, allow_none=True)

    if not overwrite and dst_fs.exists(dst_path):
        raise DestinationExistsError(dst_path)

    if src_fs is dst_fs:
        src_fs.move(src_path, dst_path, overwrite=overwrite)
        return

    # System copy if there are two sys paths
    if src_syspath is not None and dst_syspath is not None:
        FS._shutil_movefile(src_syspath, dst_syspath)
        return

    src_lock = getattr(src_fs, '_lock', None)

    if src_lock is not None:
        src_lock.acquire()

    try:
        src = None
        try:
            # Chunk copy
            src = src_fs.open(src_path, 'rb')
            dst_fs.setcontents(dst_path, src, chunk_size=chunk_size)
        except:
            raise
        else:
            src_fs.remove(src_path)
        finally:
            if src is not None:
                src.close()
    finally:
        if src_lock is not None:
            src_lock.release()
예제 #10
0
    def rename(self, src, dst):
        if not self.exists(src):
            raise ResourceNotFoundError(src)
        if self.exists(dst):
            raise DestinationExistsError(dst)
        if isprefix(src, dst):
            raise ResourceInvalidError(dst)

        fh = self.client.CreateFile({
            'id': self._ids[src],
            'title': basename(dst)
        })
        fh.Upload()
        self._ids[dst] = self._ids.pop(src)
예제 #11
0
파일: __init__.py 프로젝트: pombreda/smbfs
    def move(self, src, dst, overwrite=False, chunk_size=16384):
        if self.isfile(src):
            src = self._prepare_normpath(src)
            dst = self._prepare_normpath(dst)

            if self.isdir(dst):
                dst = '/'.join([dst, basename(src)])
            if not overwrite and self.exists(dst):
                raise DestinationExistsError(dst)

            self.rename(src, dst)
        else:
            raise ResourceInvalidError(src,
                                       msg="Source is not a file: %(path)s")
예제 #12
0
 def _raise_status(self, path, status):
     """Raise error based on status."""
     if status.errno in [3006, 17]:
         raise DestinationExistsError(path=path, details=status)
     elif status.errno == 3005:
         # Unfortunately only way to determine if the error is due to a
         # directory not being empty, or that a resource is not a directory:
         if status.message.strip().endswith("not a directory"):
             raise ResourceInvalidError(path=path, details=status)
         else:
             raise DirectoryNotEmptyError(path=path, details=status)
     elif status.errno == 3011:
         raise ResourceNotFoundError(path=path, details=status)
     else:
         raise ResourceError(path=path, details=status)
예제 #13
0
    def makedir(self, path, recursive=False, allow_recreate=False):
        if not path and not allow_recreate:
            raise PathError(path)

        path = normpath(path)
        if path in ('', '/'):
            if allow_recreate:
                return
            raise DestinationExistsError(path)

        parent_path, dirname = pathsplit(path)
        parent_box_id = self._root_id
        for name in iteratepath(parent_path):
            children_items = self._get_children_items(parent_box_id)
            child_item = children_items.get(name)
            if not child_item:
                if recursive:
                    child_item = self._makedir(parent_box_id, name)
                else:
                    raise ParentDirectoryMissingError(path)

            if child_item['type'] != _ITEM_TYPE_FOLDER:
                raise ResourceInvalidError(path)

            parent_box_id = child_item['id']

        # Check if an item with required name already exists.
        children_items = self._get_children_items(parent_box_id)
        child_item = children_items.get(dirname)
        if child_item:
            if allow_recreate and child_item['type'] == _ITEM_TYPE_FOLDER:
                return
            else:
                raise DestinationExistsError(path)

        self._makedir(parent_box_id, dirname)
예제 #14
0
 def file_create_folder(self, path):
     """Add newly created directory to cache."""
     try:
         metadata = super(DropboxClient, self).file_create_folder(path)
     except rest.ErrorResponse as e:
         if e.status == 403:
             raise DestinationExistsError(path)
         if e.status == 400:
             raise OperationFailedError(opname='file_create_folder',
                                        msg=str(e))
     except:
         raise RemoteConnectionError(
             "Most probable reasons: access token has expired or user"
             " credentials are invalid.")
     self.cache.set(path, metadata)
     return metadata['path']
예제 #15
0
파일: __init__.py 프로젝트: pombreda/fs-smb
 def inner(*args, **kwargs):
     try:
         return outer(*args, **kwargs)
     except DestinationExistsError:
         raise DestinationExistsError(args[2])
     except ResourceNotFoundError:
         # Parent directory does not exist or is not a directory.
         src, dst = args[1:3]
         fs = args[0]
         for p in (src, dst):
             if not fs.exists(p):
                 root = dirname(p)
                 if not fs.isdir(root):
                     if fs.isfile(root):
                         raise ResourceInvalidError(p)
                     else:
                         raise ParentDirectoryMissingError(p)
                 else:
                     raise ResourceNotFoundError(p)
예제 #16
0
 def file_copy(self, src, dst):
     """Copy a file to another location."""
     try:
         metadata = super(DropboxClient, self).file_copy(src, dst)
     except rest.ErrorResponse as e:
         if e.status == 404:
             raise ResourceNotFoundError(src)
         if e.status == 403:
             raise DestinationExistsError(dst)
         if e.status == 503:
             raise OperationFailedError(opname='file_copy',
                                        msg="User over storage quota")
         raise OperationFailedError(opname='file_copy', msg=str(e))
     except:
         raise RemoteConnectionError(
             "Most probable reasons: access token has expired or user"
             " credentials are invalid.")
     self.cache.set(dst, metadata)
     return metadata['path']
예제 #17
0
파일: __init__.py 프로젝트: pombreda/fs-smb
    def makedir(self, path, recursive=False, allow_recreate=False):
        # Create a directory from the top downwards depending upon the flags.
        paths = recursepath(path) if recursive else (path, )
        for p in paths:
            if p == '/':
                continue

            # Try to create a directory first then ask for forgiveness.
            try:
                self._create_dir(p)
            except DestinationExistsError as e:
                if self.isfile(p):
                    raise ResourceInvalidError(path)
                elif self.isdir(p):
                    if not recursive and not allow_recreate:
                        raise DestinationExistsError(path)
            except ResourceNotFoundError as e:
                if not recursive and not self.isdir(dirname(p)):
                    raise ParentDirectoryMissingError(path)
                e.path = path
                raise
            except FSError as e:
                e.path = path
                raise
예제 #18
0
파일: __init__.py 프로젝트: pombreda/fs-smb
    def inner(*args, **kwargs):
        try:
            return outer(*args, **kwargs)
        except socket.gaierror as e:
            if e.errno == socket.EAI_NONAME:
                raise RemoteConnectionError(str(e), details=e)
            raise
        except socket.error as e:
            if e.errno in (errno.ECONNREFUSED, errno.EPIPE, errno.ETIMEDOUT):
                raise RemoteConnectionError(str(e), details=e)
            raise
        except OperationFailure as e:
            # Cycle through each message and map the first one to PyFilesystem
            # that is not a successful status (0x00000000).
            share = args[0]
            path = args[1]
            for msg in e.smb_messages:
                # Protocol versions expose the error values differently.
                if msg.protocol == 1:
                    msg_status = msg.status.internal_value
                else:
                    msg_status = msg.status

                if msg_status == 0x0:
                    continue
                elif msg_status == 0x103:
                    # Unknown error, but message says it is not found.
                    raise ResourceNotFoundError(path=path)
                elif msg_status == 0xc000000f:
                    raise ResourceNotFoundError(path=path)
                elif msg_status == 0xc0000022:
                    raise PermissionDeniedError('access', path=path)
                elif msg_status == 0xc0000033:
                    raise ResourceInvalidError(path=path)
                elif msg_status == 0xc0000034:
                    raise ResourceNotFoundError(path=path)
                elif msg_status == 0xc0000035:
                    raise DestinationExistsError(path=path)
                elif msg_status == 0xc000003a:
                    raise ResourceNotFoundError(path=path)
                elif msg_status == 0xc0000056:
                    raise DeletePendingError(path=path)
                elif msg_status == 0xc000006f:
                    raise AccountTimeRestrictedError(path=path)
                elif msg_status == 0xc0000071:
                    raise PasswordExpiredError(path=path)
                elif msg_status == 0xc00000ba:
                    raise ResourceInvalidError(path=path)
                elif msg_status == 0xc00000cc:
                    # Share does not exist.
                    raise ResourceInvalidError(path=share)
                elif msg_status == 0xc00000d0:
                    raise ResourceInvalidError(path=path)
                elif msg_status == 0xc0000101:
                    raise DirectoryNotEmptyError(path=path)
                elif msg_status == 0xc0000103:
                    raise ResourceInvalidError(path=path)
                elif msg_status == 0xc0000193:
                    raise AccountExpiredError(path=path)
                elif msg_status == 0xc0000224:
                    raise PasswordChangeRequiredError(path=path)
                elif msg_status == 0xc0000234:
                    raise AccountLockedError(path=path)
                else:
                    raise Exception('Unhandled SMB error:  {0}'.format(
                        hex(msg_status)))
            raise
        except NotConnectedError as e:
            # Connection does not exist or was disconnected.  Using the wrong
            # NetBIOS name can cause this against a Windows server while Samba
            # will ignore it.
            raise RemoteConnectionError(details=e)
        except NotReadyError as e:
            # Connection has not been successfully authenticated.
            raise RemoteConnectionError(details=e)