示例#1
0
    def on_rmdir(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_RMDIR is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        _error = None
        _err = None
        try:
            os.rmdir(path)

        except FileNotFoundError as e:
            logging.error("{} not found".format(path))
            err = errno.ENOENT
            _error = e
        except OSError as e:
            err = e.errno
            _error = e
        except Exception as e:
            err = errno.EIO
            _error = e

        if _error != None:
            logging.error("Error during rmdir request: {}".format(_error))
            response_obj.set_err_no(_err)
            response_obj.set_data({"message": str(_error)})

        self.send_json_response(200, response_obj.as_dict())
示例#2
0
    def on_readdir(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_READDIR is requested
        :param httpfs_request_args: The client request args dict
        """
        path = self.get_abs_path(httpfs_request_args["path"])
        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        file_stats = os.stat(path)
        is_owner = file_stats.st_uid == uid
        is_group = file_stats.st_gid == gid

        response_obj = HttpFsResponse()

        if uid == 0:
            access_ok = True
        elif is_owner:
            access_ok = file_stats.st_mode & stat.S_IRUSR
        elif is_group:
            access_ok = file_stats.st_mode & stat.S_IRGRP
        else:
            access_ok = file_stats.st_mode & stat.S_IROTH

        if access_ok:
            dir_listing = os.listdir(path)
            dir_listing = [".", ".."] + dir_listing
            response_obj.set_data({"dir_listing": dir_listing})
        else:
            logging.warning("Error during readdir request: Access denied")
            response_obj.set_err_no(errno.EACCES)
            response_obj.set_data({"message": "Access denied"})

        self.send_json_response(200, response_obj.as_dict())
示例#3
0
    def on_release(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_RELEASE is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()

        try:
            os.close(httpfs_request_args["file_descriptor"])
        except Exception as e:
            logging.error("Error during release request: {}".format(e))
            response_obj.set_err_no(errno.EIO)

        self.send_json_response(200, response_obj.as_dict())
示例#4
0
    def on_flush(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_FLUSH is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()

        try:
            os.fsync(httpfs_request_args["file_descriptor"])
        except Exception as e:
            logging.error("Error during flush request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#5
0
    def on_symlink(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_SYMLINK is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        source = self.get_abs_path(httpfs_request_args["source"])
        target = self.get_abs_path(httpfs_request_args["target"])

        try:
            os.symlink(source, target)
        except Exception as e:
            logging.error("Error during symlink request: {}".format(e))
            response_obj.set_err_no(errno.EIO)

        self.send_json_response(200, response_obj.as_dict())
示例#6
0
    def on_mkdir(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_MKDIR is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])

        try:
            os.mkdir(path, mode=httpfs_request_args["mode"])
        except Exception as e:
            logging.error("Error during mkdir request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#7
0
    def on_read(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_READ is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        file_descriptor = httpfs_request_args["file_descriptor"]
        offset = httpfs_request_args["offset"]
        size = httpfs_request_args["size"]

        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        file_stats = os.stat(file_descriptor)
        is_owner = file_stats.st_uid == uid
        is_group = file_stats.st_gid == gid

        if uid == 0:
            access_ok = True
        elif is_owner:
            access_ok = file_stats.st_mode & stat.S_IRUSR
        elif is_group:
            access_ok = file_stats.st_mode & stat.S_IRGRP
        else:
            access_ok = file_stats.st_mode & stat.S_IROTH

        try:
            if access_ok:
                with self.server.get_fs_lock():
                    os.lseek(file_descriptor, offset, os.SEEK_SET)
                    bytes_read = os.read(file_descriptor, size)
                response_obj.set_data({
                    "bytes_read":
                    base64.standard_b64encode(bytes_read).decode("utf-8")
                })
            else:
                logging.warning("Error during read request: Access denied")
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})

        except Exception as e:
            logging.error("Error during read request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#8
0
    def on_link(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_LINK is requested
        :param httpfs_request_args: The client request args dict
        """
        target_path = self.get_abs_path(httpfs_request_args["target"])
        source_path = self.get_abs_path(httpfs_request_args["source"])

        response_obj = HttpFsResponse()

        try:
            os.link(source_path, target_path)
        except Exception as e:
            logging.error("Error during link request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#9
0
    def on_truncate(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_TRUNCATE is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        length = httpfs_request_args["length"]

        try:
            with open(path, 'r+') as f:
                f.truncate(length)
        except Exception as e:
            logging.error("Error during truncate request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(200, response_obj.as_dict())
示例#10
0
    def on_readlink(self, httpfs_request_args):
        # TODO: This doesn't work
        """
        Called when HttpFsRequest.OP_RELEASE is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        link_path = self.get_abs_path(httpfs_request_args["link_path"])

        try:
            target = os.readlink(link_path)
            if target.startswith("/"):
                target = os.path.relpath(target, self.server.get_fs_root())
            response_obj.set_data({"target": target})
        except Exception as e:
            logging.error("Error during readlink request: {}".format(e))
            response_obj.set_err_no(errno.EIO)

        self.send_json_response(200, response_obj.as_dict())
示例#11
0
    def on_create(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_ACCESS is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        dir_stats = os.stat(os.path.dirname(path))
        is_dir_owner = dir_stats.st_uid == uid
        is_dir_group = dir_stats.st_gid == gid

        if uid == 0:
            access_ok = True
        elif is_dir_owner:
            access_ok = dir_stats.st_mode & stat.S_IWUSR
        elif is_dir_group:
            access_ok = dir_stats.st_mode & stat.S_IWGRP
        else:
            access_ok = dir_stats.st_mode & stat.S_IWOTH

        try:
            if access_ok:
                fd = os.open(path,
                             flags=os.O_WRONLY | os.O_CREAT | os.O_TRUNC
                             | os.O_ASYNC | os.O_NOATIME,
                             mode=httpfs_request_args["mode"])
                os.chown(path, uid, gid)
                response_obj.set_data({"file_descriptor": fd})
            else:
                logging.warning("Error during create request: Access denied")
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})

        except Exception as e:
            logging.error("Error during create request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#12
0
    def on_chown(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_FLUSH is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        client = self.client_address[0]
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]
        caller_uid = httpfs_request_args["caller_uid"]
        caller_gid = httpfs_request_args["caller_gid"]

        file_stats = os.stat(path)
        is_owner = file_stats.st_uid == caller_uid
        is_group = file_stats.st_gid == caller_gid

        if caller_uid == 0:
            access_ok = True
        elif is_owner:
            access_ok = file_stats.st_mode & stat.S_IWUSR
        elif is_group:
            access_ok = file_stats.st_mode & stat.S_IWGRP
        else:
            access_ok = file_stats.st_mode & stat.S_IWOTH

        # TODO: Don't let me if it isn't mine
        try:
            if access_ok:
                os.chown(path, uid, gid)
                logging.debug("Successful chown for {}".format(client))
            else:
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})
                logging.warning("Error during chown request: Access denied")
        except Exception as e:
            logging.error("Error during chown request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#13
0
    def on_utimens(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_UTIMENS is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        times = httpfs_request_args["times"]
        if isinstance(times, list):
            times = tuple(times)

        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        file_stats = os.stat(path)
        is_owner = file_stats.st_uid == uid
        is_group = file_stats.st_gid == gid

        if uid == 0:
            access_ok = True
        elif is_owner:
            access_ok = file_stats.st_mode & stat.S_IWUSR
        elif is_group:
            access_ok = file_stats.st_mode & stat.S_IWGRP
        else:
            access_ok = file_stats.st_mode & stat.S_IWOTH

        try:
            if access_ok:
                os.utime(path, times)
            else:
                logging.warning("Error during write request: Access denied")
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})

        except Exception as e:
            logging.error("Error during utimens request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#14
0
    def on_getattr(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_GET_ATTR is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])

        try:
            os_attrs = os.lstat(path)
            attrs = dict()

            for k in _HttpFsRequestHandler.GETATTR_KEYS:
                attrs[k] = getattr(os_attrs, k)

            response_obj.set_data(attrs)

        except FileNotFoundError:
            logging.warning("{} not found".format(path))
            response_obj.set_err_no(errno.ENOENT)

        self.send_json_response(200, response_obj.as_dict())
示例#15
0
    def on_rename(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_RENAME is requested
        :param httpfs_request_args: The client request args dict
        """
        old_path = self.get_abs_path(httpfs_request_args["old_path"])
        new_path = self.get_abs_path(httpfs_request_args["new_path"])

        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        file_stats = os.stat(old_path)
        is_owner = file_stats.st_uid == uid
        is_group = file_stats.st_gid == gid

        response_obj = HttpFsResponse()

        if uid == 0:
            access_ok = True
        elif is_owner:
            access_ok = file_stats.st_mode & stat.S_IWUSR
        elif is_group:
            access_ok = file_stats.st_mode & stat.S_IWGRP
        else:
            access_ok = file_stats.st_mode & stat.S_IWOTH

        try:
            if access_ok:
                os.rename(old_path, new_path)
            else:
                logging.warning("Error during rename request: Access denied")
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})
        except Exception as e:
            logging.error("Error during rename request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#16
0
    def on_unlink(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_UNLINK is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        try:
            file_stats = os.stat(path)
            is_owner = file_stats.st_uid == uid
            is_group = file_stats.st_gid == gid

            if uid == 0:
                access_ok = True
            elif is_owner:
                access_ok = file_stats.st_mode & stat.S_IWUSR
            elif is_group:
                access_ok = file_stats.st_mode & stat.S_IWGRP
            else:
                access_ok = file_stats.st_mode & stat.S_IWOTH

            if access_ok:
                os.unlink(path)
            else:
                logging.warning("Error during unlink request: Access denied")
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})
        except OSError as e:
            logging.error("Error during unlink request: {}".format(e))
            response_obj.set_err_no(e.errno)
            response_obj.set_data({"message": str(e)})
        except Exception as e:
            logging.error("Error during unlink request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(200, response_obj.as_dict())
示例#17
0
    def on_open(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_OPEN is requested
        :param httpfs_request_args: The client request args dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])

        # Hardcode async and noatime
        flags = httpfs_request_args["flags"] | os.O_ASYNC | os.O_NOATIME

        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        dir_stats = os.stat(os.path.dirname(path))
        is_dir_owner = dir_stats.st_uid == uid
        is_dir_group = dir_stats.st_gid == gid

        if uid == 0:
            access_ok = True
        elif is_dir_owner:
            access_ok = dir_stats.st_mode & stat.S_IXUSR
        elif is_dir_group:
            access_ok = dir_stats.st_mode & stat.S_IXGRP
        else:
            access_ok = dir_stats.st_mode & stat.S_IXOTH

        if access_ok and os.path.exists(path):
            file_stats = os.stat(path)
            is_owner = file_stats.st_uid == uid
            is_group = file_stats.st_gid == gid

            read_requested = (flags & os.O_RDONLY or flags & os.O_RDWR
                              or flags & os.O_EXCL)
            write_requested = (flags & os.O_WRONLY or flags & os.O_RDWR
                               or flags & os.O_APPEND)

            if uid == 0:
                access_ok = True
            elif is_owner:
                if read_requested:
                    access_ok = file_stats.st_mode & stat.S_IRUSR
                elif write_requested:
                    access_ok = file_stats.st_mode & stat.S_IWUSR
            elif is_group:
                if read_requested:
                    access_ok = file_stats.st_mode & stat.S_IRGRP
                elif write_requested:
                    access_ok = file_stats.st_mode & stat.S_IWGRP
            else:
                if read_requested:
                    access_ok = file_stats.st_mode & stat.S_IROTH
                elif write_requested:
                    access_ok = file_stats.st_mode & stat.S_IROTH

        try:
            if access_ok:
                fd = os.open(self.get_abs_path(httpfs_request_args["path"]),
                             flags)
                response_obj.set_data({"file_descriptor": fd})
            else:
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})
                logging.warning("Error during open request: Access denied")

        except Exception as e:
            logging.error("Error during open request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
示例#18
0
    def on_write(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_UTIMENS is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        start_time = time.time()

        response_obj = HttpFsResponse()

        file_descriptor = httpfs_request_args["file_descriptor"]
        data = base64.standard_b64decode(httpfs_request_args["data"])
        offset = httpfs_request_args["offset"]

        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]

        file_stats = os.stat(file_descriptor)
        is_owner = file_stats.st_uid == uid
        is_group = file_stats.st_gid == gid

        if uid == 0:
            access_ok = True
        elif is_owner:
            access_ok = file_stats.st_mode & stat.S_IWUSR
        elif is_group:
            access_ok = file_stats.st_mode & stat.S_IWGRP
        else:
            access_ok = file_stats.st_mode & stat.S_IWOTH

        try:
            if access_ok:
                write_start_time = time.time()
                with self.server.get_fs_lock():
                    os.lseek(file_descriptor, offset, os.SEEK_SET)
                    bytes_written = os.write(file_descriptor, data)
                    logging.debug("{} wrote {} bytes".format(
                        self.client_address[0], bytes_written))
                    response_obj.set_data({"bytes_written": bytes_written})
                write_elapsed = time.time() - write_start_time
                logging.debug(
                    "Took {:.2f}s to write {} bytes ({:.2f} MB/s)".format(
                        write_elapsed, bytes_written,
                        bytes_written / 1024**2 / write_elapsed))
            else:
                logging.warning("Error during write request: Access denied")
                response_obj.set_err_no(errno.EACCES)
                response_obj.set_data({"message": "Access denied"})

        except Exception as e:
            logging.error("Error during write request: {}".format(e))
            response_obj.set_err_no(errno.EIO)
            response_obj.set_data({"message": str(e)})

        # Send response
        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())
        response_elapsed = time.time() - start_time

        # Print 1/10 of the time
        logging.debug(
            "Took {:.2f}s to complete write response ({:.2f} MB/s)".format(
                response_elapsed, bytes_written / 1024**2 / response_elapsed))
示例#19
0
    def on_access(self, httpfs_request_args):
        """
        Called when HttpFsRequest.OP_ACCESS is received from the client
        :param httpfs_request_args: The client request arg dict
        """
        response_obj = HttpFsResponse()
        path = self.get_abs_path(httpfs_request_args["path"])
        mode = httpfs_request_args["mode"]
        uid = httpfs_request_args["uid"]
        gid = httpfs_request_args["gid"]
        file_stats = os.stat(path)

        is_owner = file_stats.st_uid == uid
        is_group = file_stats.st_gid == gid
        read_requested = bool(mode & os.R_OK)
        write_requested = bool(mode & os.W_OK)
        execute_requested = bool(mode & os.X_OK)
        exists_requested = mode == os.F_OK

        access_ok = True

        # Exists requested
        if exists_requested:
            access_ok = os.path.exists(path)

        # Owner access
        if is_owner:
            owner_readable = bool(file_stats.st_mode & stat.S_IRUSR)
            owner_writeable = bool(file_stats.st_mode & stat.S_IWUSR)
            owner_executable = bool(file_stats.st_mode & stat.S_IXUSR)
            if read_requested:
                access_ok = access_ok and owner_readable
            if write_requested:
                access_ok = access_ok and owner_writeable
            if execute_requested:
                access_ok = access_ok and owner_executable
        # Group access
        elif is_group:
            group_readable = bool(file_stats.st_mode & stat.S_IRGRP)
            group_writeable = bool(file_stats.st_mode & stat.S_IWGRP)
            group_executable = bool(file_stats.st_mode & stat.S_IXGRP)
            if read_requested:
                access_ok = access_ok and group_readable
            if write_requested:
                access_ok = access_ok and group_writeable
            if execute_requested:
                access_ok = access_ok and group_executable
        # World access
        else:
            world_readable = bool(file_stats.st_mode & stat.S_IROTH)
            world_writeable = bool(file_stats.st_mode & stat.S_IWOTH)
            world_executable = bool(file_stats.st_mode & stat.S_IXGRP)
            if read_requested:
                access_ok = access_ok and world_readable
            if write_requested:
                access_ok = access_ok and world_writeable
            if execute_requested:
                access_ok = access_ok and world_executable

        if not access_ok:
            logging.warning("Error during access request: Access denied")
            response_obj.set_err_no(errno.EACCES)

        self.send_json_response(http.HTTPStatus.OK, response_obj.as_dict())