예제 #1
0
def init_client_mmap(token,
                     mmap_group=None,
                     socket_filename=None,
                     size=128 * 1024 * 1024):
    """
        Initializes an mmap area, writes the token in it and returns:
            (success flag, mmap_area, mmap_size, temp_file, mmap_filename)
        The caller must keep hold of temp_file to ensure it does not get deleted!
        This is used by the client.
    """
    if not can_use_mmap():
        log.error("cannot use mmap: python version is too old?")
        return False, None, 0, None, None
    log("init_mmap(%s, %s, %s)", token, mmap_group, socket_filename)
    try:
        import mmap
        import tempfile
        from stat import S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP
        mmap_dir = os.getenv("TMPDIR", "/tmp")
        if not os.path.exists(mmap_dir):
            raise Exception("TMPDIR %s does not exist!" % mmap_dir)
        #create the mmap file, the mkstemp that is called via NamedTemporaryFile ensures
        #that the file is readable and writable only by the creating user ID
        try:
            temp = tempfile.NamedTemporaryFile(prefix="xpra.",
                                               suffix=".mmap",
                                               dir=mmap_dir)
        except OSError as e:
            log.error("Error: cannot create mmap file:")
            log.error(" %s", e)
            return False, None, 0, None, None
        #keep a reference to it so it does not disappear!
        mmap_temp_file = temp
        mmap_filename = temp.name
        fd = temp.file.fileno()
        #set the group permissions and gid if the mmap-group option is specified
        if mmap_group and type(socket_filename) == str and os.path.exists(
                socket_filename):
            s = os.stat(socket_filename)
            os.fchown(fd, -1, s.st_gid)
            os.fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
        assert size >= 1024 * 1024, "mmap size is too small: %s (minimum is 1MB)" % to_std_unit(
            size)
        assert size <= 1024 * 1024 * 1024, "mmap is too big: %s (maximum is 1GB)" % to_std_unit(
            size)
        unit = max(4096, mmap.PAGESIZE)
        #add 8 bytes for the mmap area control header zone:
        mmap_size = roundup(size + 8, unit)
        log("using mmap file %s, fd=%s, size=%s", mmap_filename, fd, mmap_size)
        os.lseek(fd, mmap_size - 1, os.SEEK_SET)
        assert os.write(fd, b'\x00')
        os.lseek(fd, 0, os.SEEK_SET)
        mmap_area = mmap.mmap(fd, length=mmap_size)
        write_mmap_token(mmap_area, token)
        return True, mmap_area, mmap_size, mmap_temp_file, mmap_filename
    except Exception as e:
        log.error("failed to setup mmap: %s", e, exc_info=True)
        clean_mmap(mmap_filename)
        return False, None, 0, None, None
예제 #2
0
def init_client_mmap(token, mmap_group=None, socket_filename=None, size=128*1024*1024):
    """
        Initializes an mmap area, writes the token in it and returns:
            (success flag, mmap_area, mmap_size, temp_file, mmap_filename)
        The caller must keep hold of temp_file to ensure it does not get deleted!
        This is used by the client.
    """
    if not can_use_mmap():
        log.error("cannot use mmap: python version is too old?")
        return False, None, 0, None, None
    log("init_mmap(%s, %s, %s)", token, mmap_group, socket_filename)
    try:
        import mmap
        import tempfile
        from stat import S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP
        mmap_dir = os.getenv("TMPDIR", "/tmp")
        if not os.path.exists(mmap_dir):
            raise Exception("TMPDIR %s does not exist!" % mmap_dir)
        #create the mmap file, the mkstemp that is called via NamedTemporaryFile ensures
        #that the file is readable and writable only by the creating user ID
        try:
            temp = tempfile.NamedTemporaryFile(prefix="xpra.", suffix=".mmap", dir=mmap_dir)
        except OSError as e:
            log.error("Error: cannot create mmap file:")
            log.error(" %s", e)
            return False, None, 0, None, None
        #keep a reference to it so it does not disappear!
        mmap_temp_file = temp
        mmap_filename = temp.name
        fd = temp.file.fileno()
        #set the group permissions and gid if the mmap-group option is specified
        if mmap_group and type(socket_filename)==str and os.path.exists(socket_filename):
            s = os.stat(socket_filename)
            os.fchown(fd, -1, s.st_gid)
            os.fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
        assert size>=1024*1024, "mmap size is too small: %s (minimum is 1MB)" % to_std_unit(size)
        assert size<=1024*1024*1024, "mmap is too big: %s (maximum is 1GB)" % to_std_unit(size)
        unit = max(4096, mmap.PAGESIZE)
        #add 8 bytes for the mmap area control header zone:
        mmap_size = roundup(size + 8, unit)
        log("using mmap file %s, fd=%s, size=%s", mmap_filename, fd, mmap_size)
        os.lseek(fd, mmap_size-1, os.SEEK_SET)
        assert os.write(fd, b'\x00')
        os.lseek(fd, 0, os.SEEK_SET)
        mmap_area = mmap.mmap(fd, length=mmap_size)
        write_mmap_token(mmap_area, token)
        return True, mmap_area, mmap_size, mmap_temp_file, mmap_filename
    except Exception as e:
        log.error("failed to setup mmap: %s", e, exc_info=True)
        clean_mmap(mmap_filename)
        return False, None, 0, None, None
예제 #3
0
 def unit(scale):
     if scale==1:
         return ""
     else:
         unit, value = to_std_unit(scale)
         if value==1:
             return str(unit)
         return "x%s%s" % (int(value), unit)
예제 #4
0
 def unit(scale):
     if scale==1:
         return ""
     else:
         unit, value = to_std_unit(scale)
         if value==1:
             return str(unit)
         return "x%s%s" % (int(value), unit)
예제 #5
0
    def _process_print(self, _proto, packet):
        #ie: from the xpraforwarder we call this command:
        #command = ["xpra", "print", "socket:/path/tosocket",
        #           filename, mimetype, source, title, printer, no_copies, print_options]
        assert self.file_transfer.printing
        #printlog("_process_print(%s, %s)", proto, packet)
        if len(packet) < 3:
            printlog.error("Error: invalid print packet, only %i arguments",
                           len(packet))
            printlog.error(" %s", [repr_ellipsized(x) for x in packet])
            return

        def s(b):
            try:
                return b.decode("utf-8")
            except Exception:
                return bytestostr(b)

        filename = s(packet[1])
        file_data = packet[2]
        mimetype, source_uuid, title, printer, no_copies, print_options = "", "*", "unnamed document", "", 1, ""
        if len(packet) >= 4:
            mimetype = bytestostr(packet[3])
        if len(packet) >= 5:
            source_uuid = bytestostr(packet[4])
        if len(packet) >= 6:
            title = s(packet[5])
        if len(packet) >= 7:
            printer = bytestostr(packet[6])
        if len(packet) >= 8:
            no_copies = int(packet[7])
        if len(packet) >= 9:
            print_options = packet[8]
        #parse and validate:
        if len(mimetype) >= 128:
            printlog.error("Error: invalid mimetype in print packet:")
            printlog.error(" %s", repr_ellipsized(mimetype))
            return
        if not isinstance(print_options, dict):
            s = bytestostr(print_options)
            print_options = {}
            for x in s.split(" "):
                parts = x.split("=", 1)
                if len(parts) == 2:
                    print_options[parts[0]] = parts[1]
        printlog("process_print: %s",
                 (filename, mimetype, "%s bytes" % len(file_data), source_uuid,
                  title, printer, no_copies, print_options))
        printlog("process_print: got %s bytes for file %s", len(file_data),
                 filename)
        #parse the print options:
        u = hashlib.sha1()
        u.update(file_data)
        printlog("sha1 digest: %s", u.hexdigest())
        options = {
            "printer": printer,
            "title": title,
            "copies": no_copies,
            "options": print_options,
            "sha1": u.hexdigest(),
        }
        printlog("parsed printer options: %s", options)
        if SAVE_PRINT_JOBS:
            self._save_print_job(filename, file_data)

        sent = 0
        sources = tuple(self._server_sources.values())
        printlog("will try to send to %i clients: %s", len(sources), sources)
        for ss in sources:
            if source_uuid not in ("*", ss.uuid):
                printlog("not sending to %s (uuid=%s, wanted uuid=%s)", ss,
                         ss.uuid, source_uuid)
                continue
            if not ss.printing:
                if source_uuid != '*':
                    printlog.warn("Warning: printing is not enabled for:")
                    printlog.warn(" %s", ss)
                else:
                    printlog("printing is not enabled for %s", ss)
                continue
            if not ss.printers:
                printlog.warn("Warning: client %s does not have any printers",
                              ss.uuid)
                continue
            if printer not in ss.printers:
                printlog.warn(
                    "Warning: client %s does not have a '%s' printer", ss.uuid,
                    printer)
                continue
            printlog("'%s' sent to %s for printing on '%s'",
                     bytestostr(title or filename), ss, printer)
            if ss.send_file(filename, mimetype, file_data, len(file_data),
                            True, True, options):
                sent += 1
        #warn if not sent:
        if sent == 0:
            l = printlog.warn
        else:
            l = printlog.info
        unit_str, v = to_std_unit(len(file_data), unit=1024)
        l("'%s' (%i%sB) sent to %i client%s for printing", title or filename,
          v, unit_str, sent, engs(sent))
예제 #6
0
def init_client_mmap(mmap_group=None, socket_filename=None, size=128*1024*1024, filename=None):
    """
        Initializes an mmap area, writes the token in it and returns:
            (success flag, mmap_area, mmap_size, temp_file, mmap_filename)
        The caller must keep hold of temp_file to ensure it does not get deleted!
        This is used by the client.
    """
    def rerr():
        return False, False, None, 0, None, None
    log("init_mmap%s", (mmap_group, socket_filename, size, filename))
    mmap_filename = filename
    mmap_temp_file = None
    delete = True
    try:
        import mmap
        unit = max(4096, mmap.PAGESIZE)
        #add 8 bytes for the mmap area control header zone:
        mmap_size = roundup(size + 8, unit)
        if WIN32:
            if not filename:
                from xpra.net.crypto import get_hex_uuid
                filename = "xpra-%s" % get_hex_uuid()
            mmap_filename = filename
            mmap_area = mmap.mmap(0, mmap_size, filename)
            #not a real file:
            delete = False
            mmap_temp_file = None
        else:
            assert POSIX
            if filename:
                if os.path.exists(filename):
                    fd = os.open(filename, os.O_EXCL | os.O_RDWR)
                    mmap_size = os.path.getsize(mmap_filename)
                    #mmap_size = 4*1024*1024    #size restriction needed with ivshmem
                    delete = False
                    log.info("Using existing mmap file '%s': %sMB", mmap_filename, mmap_size//1024//1024)
                else:
                    import errno
                    flags = os.O_CREAT | os.O_EXCL | os.O_RDWR
                    try:
                        fd = os.open(filename, flags)
                        mmap_temp_file = None   #os.fdopen(fd, 'w')
                        mmap_filename = filename
                    except OSError as e:
                        if e.errno == errno.EEXIST:
                            log.error("Error: the mmap file '%s' already exists", filename)
                            return rerr()
                        raise
            else:
                import tempfile
                mmap_dir = os.getenv("TMPDIR", "/tmp")
                if not os.path.exists(mmap_dir):
                    raise Exception("TMPDIR %s does not exist!" % mmap_dir)
                #create the mmap file, the mkstemp that is called via NamedTemporaryFile ensures
                #that the file is readable and writable only by the creating user ID
                try:
                    temp = tempfile.NamedTemporaryFile(prefix="xpra.", suffix=".mmap", dir=mmap_dir)
                except OSError as e:
                    log.error("Error: cannot create mmap file:")
                    log.error(" %s", e)
                    return rerr()
                #keep a reference to it so it does not disappear!
                mmap_temp_file = temp
                mmap_filename = temp.name
                fd = temp.file.fileno()
            #set the group permissions and gid if the mmap-group option is specified
            if mmap_group and type(socket_filename)==str and os.path.exists(socket_filename):
                from stat import S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP
                s = os.stat(socket_filename)
                os.fchown(fd, -1, s.st_gid)
                os.fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
            assert mmap_size>=1024*1024, "mmap size is too small: %s (minimum is 1MB)" % to_std_unit(mmap_size)
            assert mmap_size<=1024*1024*1024, "mmap is too big: %s (maximum is 1GB)" % to_std_unit(mmap_size)
            log("using mmap file %s, fd=%s, size=%s", mmap_filename, fd, mmap_size)
            os.lseek(fd, mmap_size-1, os.SEEK_SET)
            assert os.write(fd, b'\x00')
            os.lseek(fd, 0, os.SEEK_SET)
            mmap_area = mmap.mmap(fd, length=mmap_size)
        return True, delete, mmap_area, mmap_size, mmap_temp_file, mmap_filename
    except Exception as e:
        log("failed to setup mmap: %s", e, exc_info=True)
        log.error("Error: mmap setup failed:")
        log.error(" %s", e)
        clean_mmap(mmap_filename)
        return rerr()