def select_log_file(log_dir, log_file, display_name): """ returns the log file path we should be using given the parameters, this may return a temporary logpath if display_name is not available. """ if log_file: if os.path.isabs(log_file): logpath = log_file else: logpath = os.path.join(log_dir, log_file) v = shellsub(logpath, {"DISPLAY" : display_name}) if display_name or v==logpath: #we have 'display_name', or we just don't need it: return v if display_name: logpath = norm_makepath(log_dir, display_name) + ".log" else: logpath = os.path.join(log_dir, "tmp_%d.log" % os.getpid()) return logpath
def start_Xvfb(xvfb_str, pixel_depth, display_name, cwd, uid, gid, username, xauth_data, uinput_uuid=None): if not POSIX: raise InitException("starting an Xvfb is not supported on %s" % os.name) if OSX: raise InitException("starting an Xvfb is not supported on MacOS") if not xvfb_str: raise InitException("the 'xvfb' command is not defined") cleanups = [] log = get_vfb_logger() log("start_Xvfb%s", (xvfb_str, pixel_depth, display_name, cwd, uid, gid, username, xauth_data, uinput_uuid)) xauthority = get_xauthority_path(display_name, username, uid, gid) os.environ["XAUTHORITY"] = xauthority if not os.path.exists(xauthority): log("creating XAUTHORITY=%s with data=%s", xauthority, xauth_data) try: with open(xauthority, 'wa') as f: if getuid() == 0 and (uid != 0 or gid != 0): os.fchown(f.fileno(), uid, gid) except Exception as e: #trying to continue anyway! log.error("Error trying to create XAUTHORITY file %s:", xauthority) log.error(" %s", e) else: log("found existing XAUTHORITY file '%s'", xauthority) use_display_fd = display_name[0] == 'S' subs = {} def pathexpand(s): return osexpand(s, actual_username=username, uid=uid, gid=gid, subs=subs) subs.update({ "DISPLAY": display_name, "XPRA_LOG_DIR": pathexpand(os.environ.get("XPRA_LOG_DIR")), }) #identify logfile argument if it exists, #as we may have to rename it, or create the directory for it: import shlex xvfb_cmd = shlex.split(xvfb_str) if not xvfb_cmd: raise InitException( "cannot start Xvfb, the command definition is missing!") #make sure all path values are expanded: xvfb_cmd = [pathexpand(s) for s in xvfb_cmd] try: logfile_argindex = xvfb_cmd.index('-logfile') assert logfile_argindex + 1 < len( xvfb_cmd ), "invalid xvfb command string: -logfile should not be last (found at index %i)" % logfile_argindex xorg_log_file = xvfb_cmd[logfile_argindex + 1] except ValueError: xorg_log_file = None tmp_xorg_log_file = None if xorg_log_file: if use_display_fd: #keep track of it so we can rename it later: tmp_xorg_log_file = xorg_log_file #make sure the Xorg log directory exists: xorg_log_dir = os.path.dirname(xorg_log_file) if not os.path.exists(xorg_log_dir): try: log("creating Xorg log dir '%s'", xorg_log_dir) os.mkdir(xorg_log_dir, 0o700) if POSIX and uid != getuid() or gid != getgid(): try: os.lchown(xorg_log_dir, uid, gid) except: pass except OSError as e: raise InitException( "failed to create the Xorg log directory '%s': %s" % (xorg_log_dir, e)) if uinput_uuid: #use uinput: #identify -config xorg.conf argument and replace it with the uinput one: try: config_argindex = xvfb_cmd.index("-config") except ValueError as e: log.warn("Warning: cannot use uinput") log.warn(" '-config' argument not found in the xvfb command") else: assert config_argindex + 1 < len( xvfb_cmd ), "invalid xvfb command string: -config should not be last (found at index %i)" % config_argindex xorg_conf = xvfb_cmd[config_argindex + 1] if xorg_conf.endswith("xorg.conf"): xorg_conf = xorg_conf.replace("xorg.conf", "xorg-uinput.conf") if os.path.exists(xorg_conf): xvfb_cmd[config_argindex + 1] = xorg_conf #create uinput device definition files: #(we have to assume that Xorg is configured to use this path..) xorg_conf_dir = pathexpand(get_Xdummy_confdir()) cleanups = create_xorg_device_configs(xorg_conf_dir, uinput_uuid, uid, gid) xvfb_executable = xvfb_cmd[0] if (xvfb_executable.endswith("Xorg") or xvfb_executable.endswith("Xdummy")) and pixel_depth > 0: xvfb_cmd.append("-depth") xvfb_cmd.append(str(pixel_depth)) xvfb = None try: if use_display_fd: def displayfd_err(msg): raise InitException("%s: %s" % (xvfb_executable, msg)) r_pipe, w_pipe = os.pipe() try: if PYTHON3: os.set_inheritable(w_pipe, True) #@UndefinedVariable xvfb_cmd += ["-displayfd", str(w_pipe)] xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, display_name) def preexec(): setsid() if getuid() == 0 and uid: setuidgid(uid, gid) close_fds([0, 1, 2, r_pipe, w_pipe]) try: xvfb = subprocess.Popen(xvfb_cmd, executable=xvfb_executable, close_fds=False, stdin=subprocess.PIPE, preexec_fn=preexec, cwd=cwd) except OSError as e: log("Popen%s", (xvfb_cmd, xvfb_executable, cwd), exc_info=True) raise InitException( "failed to execute xvfb command %s: %s" % (xvfb_cmd, e)) assert xvfb.poll() is None, "xvfb command failed" # Read the display number from the pipe we gave to Xvfb try: buf = read_displayfd(r_pipe) except Exception as e: log("read_displayfd(%s)", r_pipe, exc_info=True) displayfd_err("failed to read displayfd pipe %s: %s" % (r_pipe, e)) finally: osclose(r_pipe) osclose(w_pipe) n = parse_displayfd(buf, displayfd_err) new_display_name = ":%s" % n log("Using display number provided by %s: %s", xvfb_executable, new_display_name) if tmp_xorg_log_file != None: #ie: ${HOME}/.xpra/Xorg.${DISPLAY}.log -> /home/antoine/.xpra/Xorg.S14700.log f0 = shellsub(tmp_xorg_log_file, subs) subs["DISPLAY"] = new_display_name #ie: ${HOME}/.xpra/Xorg.${DISPLAY}.log -> /home/antoine/.xpra/Xorg.:1.log f1 = shellsub(tmp_xorg_log_file, subs) if f0 != f1: try: os.rename(f0, f1) except Exception as e: log.warn("Warning: failed to rename Xorg log file,") log.warn(" from '%s' to '%s'" % (f0, f1)) log.warn(" %s" % e) display_name = new_display_name else: # use display specified xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, display_name) xvfb_cmd.append(display_name) def preexec(): if getuid() == 0 and (uid != 0 or gid != 0): setuidgid(uid, gid) else: setsid() log("xvfb_cmd=%s", xvfb_cmd) xvfb = subprocess.Popen(xvfb_cmd, executable=xvfb_executable, close_fds=True, stdin=subprocess.PIPE, preexec_fn=preexec) xauth_add(xauthority, display_name, xauth_data, uid, gid) except Exception as e: if xvfb and xvfb.poll() is None: log.error(" stopping vfb process with pid %i", xvfb.pid) xvfb.terminate() raise log("xvfb process=%s", xvfb) log("display_name=%s", display_name) return xvfb, display_name, cleanups
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 def validate_size(size): assert size >= 64 * 1024 * 1024, "mmap size is too small: %sB (minimum is 64MB)" % std_unit( size) assert size <= 4 * 1024 * 1024 * 1024, "mmap is too big: %sB (maximum is 4GB)" % std_unit( size) 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: validate_size(mmap_size) 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) validate_size(mmap_size) #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: validate_size(mmap_size) 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: validate_size(mmap_size) import tempfile from xpra.platform.paths import get_mmap_dir mmap_dir = get_mmap_dir() subs = os.environ.copy() subs.update({ "UID": os.getuid(), "GID": os.getgid(), "PID": os.getpid(), }) mmap_dir = shellsub(mmap_dir, subs) if mmap_dir and not os.path.exists(mmap_dir): os.mkdir(mmap_dir, 0o700) if not mmap_dir or not os.path.exists(mmap_dir): raise Exception("mmap directory %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) 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()
def start_Xvfb(xvfb_str, vfb_geom, pixel_depth, display_name, cwd, uid, gid, username, uinput_uuid=None): if not POSIX: raise InitException("starting an Xvfb is not supported on %s" % os.name) if OSX: raise InitException("starting an Xvfb is not supported on MacOS") if not xvfb_str: raise InitException("the 'xvfb' command is not defined") log = get_vfb_logger() log("start_Xvfb%s", (xvfb_str, vfb_geom, pixel_depth, display_name, cwd, uid, gid, username, uinput_uuid)) use_display_fd = display_name[0]=='S' subs = {} def pathexpand(s): return osexpand(s, actual_username=username, uid=uid, gid=gid, subs=subs) etc_prefix = os.environ.get("XPRA_INSTALL_PREFIX", "") if etc_prefix.endswith("/usr"): etc_prefix = etc_prefix[:-4] subs.update({ "DISPLAY" : display_name, "XPRA_LOG_DIR" : pathexpand(os.environ.get("XPRA_LOG_DIR")), "XORG_CONFIG_PREFIX" : os.environ.get("XORG_CONFIG_PREFIX", etc_prefix), }) #identify logfile argument if it exists, #as we may have to rename it, or create the directory for it: xvfb_cmd = shlex.split(xvfb_str) if not xvfb_cmd: raise InitException("cannot start Xvfb, the command definition is missing!") #make sure all path values are expanded: xvfb_cmd = [pathexpand(s) for s in xvfb_cmd] #try to honour initial geometries if specified: if vfb_geom and xvfb_cmd[0].endswith("Xvfb"): #find the '-screen' arguments: #"-screen 0 8192x4096x24+32" try: no_arg = xvfb_cmd.index("0") except ValueError: no_arg = -1 geom_str = "%sx%s" % ("x".join(str(x) for x in vfb_geom), pixel_depth) if no_arg>0 and xvfb_cmd[no_arg-1]=="-screen" and len(xvfb_cmd)>(no_arg+1): #found an existing "-screen" argument for this screen number, #replace it: xvfb_cmd[no_arg+1] = geom_str else: #append: xvfb_cmd += ["-screen", "0", geom_str] try: logfile_argindex = xvfb_cmd.index('-logfile') if logfile_argindex+1>=len(xvfb_cmd): raise InitException("invalid xvfb command string: -logfile should not be last") xorg_log_file = xvfb_cmd[logfile_argindex+1] except ValueError: xorg_log_file = None tmp_xorg_log_file = None if xorg_log_file: if use_display_fd: #keep track of it so we can rename it later: tmp_xorg_log_file = xorg_log_file #make sure the Xorg log directory exists: xorg_log_dir = os.path.dirname(xorg_log_file) if not os.path.exists(xorg_log_dir): try: log("creating Xorg log dir '%s'", xorg_log_dir) os.mkdir(xorg_log_dir, 0o700) if POSIX and uid!=getuid() or gid!=getgid(): try: os.lchown(xorg_log_dir, uid, gid) except OSError: log("lchown(%s, %i, %i)", xorg_log_dir, uid, gid, exc_info=True) except OSError as e: raise InitException("failed to create the Xorg log directory '%s': %s" % (xorg_log_dir, e)) from None if uinput_uuid: #use uinput: #identify -config xorg.conf argument and replace it with the uinput one: try: config_argindex = xvfb_cmd.index("-config") except ValueError as e: log.warn("Warning: cannot use uinput") log.warn(" '-config' argument not found in the xvfb command") else: if config_argindex+1>=len(xvfb_cmd): raise InitException("invalid xvfb command string: -config should not be last") xorg_conf = xvfb_cmd[config_argindex+1] if xorg_conf.endswith("xorg.conf"): xorg_conf = xorg_conf.replace("xorg.conf", "xorg-uinput.conf") if os.path.exists(xorg_conf): xvfb_cmd[config_argindex+1] = xorg_conf #create uinput device definition files: #(we have to assume that Xorg is configured to use this path..) xorg_conf_dir = pathexpand(get_Xdummy_confdir()) create_xorg_device_configs(xorg_conf_dir, uinput_uuid, uid, gid) xvfb_executable = xvfb_cmd[0] if (xvfb_executable.endswith("Xorg") or xvfb_executable.endswith("Xdummy")) and pixel_depth>0: xvfb_cmd.append("-depth") xvfb_cmd.append(str(pixel_depth)) xvfb = None try: if use_display_fd: def displayfd_err(msg): raise InitException("%s: %s" % (xvfb_executable, msg)) r_pipe, w_pipe = os.pipe() try: os.set_inheritable(w_pipe, True) #@UndefinedVariable xvfb_cmd += ["-displayfd", str(w_pipe)] xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, display_name.lstrip(":")) def preexec(): os.setpgrp() if getuid()==0 and uid: setuidgid(uid, gid) try: xvfb = Popen(xvfb_cmd, executable=xvfb_executable, preexec_fn=preexec, cwd=cwd, pass_fds=(w_pipe,)) except OSError as e: log("Popen%s", (xvfb_cmd, xvfb_executable, cwd), exc_info=True) raise InitException("failed to execute xvfb command %s: %s" % (xvfb_cmd, e)) from None assert xvfb.poll() is None, "xvfb command failed" # Read the display number from the pipe we gave to Xvfb try: buf = read_displayfd(r_pipe) except Exception as e: log("read_displayfd(%s)", r_pipe, exc_info=True) displayfd_err("failed to read displayfd pipe %s: %s" % (r_pipe, e)) finally: osclose(r_pipe) osclose(w_pipe) n = parse_displayfd(buf, displayfd_err) new_display_name = ":%s" % n log("Using display number provided by %s: %s", xvfb_executable, new_display_name) if tmp_xorg_log_file: #ie: ${HOME}/.xpra/Xorg.${DISPLAY}.log -> /home/antoine/.xpra/Xorg.S14700.log f0 = shellsub(tmp_xorg_log_file, subs) subs["DISPLAY"] = new_display_name #ie: ${HOME}/.xpra/Xorg.${DISPLAY}.log -> /home/antoine/.xpra/Xorg.:1.log f1 = shellsub(tmp_xorg_log_file, subs) if f0 != f1: try: os.rename(f0, f1) except Exception as e: log.warn("Warning: failed to rename Xorg log file,") log.warn(" from '%s' to '%s'" % (f0, f1)) log.warn(" %s" % e) display_name = new_display_name else: # use display specified xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, display_name) xvfb_cmd.append(display_name) def preexec(): if getuid()==0 and (uid!=0 or gid!=0): setuidgid(uid, gid) else: os.setsid() log("xvfb_cmd=%s", xvfb_cmd) xvfb = Popen(xvfb_cmd, executable=xvfb_executable, stdin=PIPE, preexec_fn=preexec) except Exception as e: if xvfb and xvfb.poll() is None: log.error(" stopping vfb process with pid %i", xvfb.pid) xvfb.terminate() raise log("xvfb process=%s", xvfb) log("display_name=%s", display_name) return xvfb, display_name
def start_Xvfb(xvfb_str, pixel_depth, display_name, cwd, uid, gid, xauth_data): if not POSIX: raise InitException("starting an Xvfb is not supported on %s" % os.name) if not xvfb_str: raise InitException("the 'xvfb' command is not defined") from xpra.log import Logger log = Logger("server", "x11") # We need to set up a new server environment xauthority = os.environ.get("XAUTHORITY", os.path.expanduser("~/.Xauthority")) if not os.path.exists(xauthority): log("creating XAUTHORITY=%s with data=%s", xauthority, xauth_data) try: with open(xauthority, 'wa') as f: if getuid() == 0 and (uid != 0 or gid != 0): os.fchown(f.fileno(), uid, gid) except Exception as e: #trying to continue anyway! log.error("Error trying to create XAUTHORITY file %s:", xauthority) log.error(" %s", e) use_display_fd = display_name[0] == 'S' #identify logfile argument if it exists, #as we may have to rename it, or create the directory for it: import shlex xvfb_cmd = shlex.split(xvfb_str) try: logfile_argindex = xvfb_cmd.index('-logfile') except ValueError: logfile_argindex = -1 assert logfile_argindex + 1 < len( xvfb_cmd ), "invalid xvfb command string: -logfile should not be last (found at index %i)" % logfile_argindex tmp_xorg_log_file = None if logfile_argindex > 0: if use_display_fd: #keep track of it so we can rename it later: tmp_xorg_log_file = xvfb_cmd[logfile_argindex + 1] #make sure the Xorg log directory exists: xorg_log_dir = osexpand(os.path.dirname(xvfb_cmd[logfile_argindex + 1])) if not os.path.exists(xorg_log_dir): try: log("creating Xorg log dir '%s'", xorg_log_dir) os.mkdir(xorg_log_dir, 0o700) if POSIX and uid != getuid() or gid != getgid(): try: os.lchown(xorg_log_dir, uid, gid) except: pass except OSError as e: raise InitException( "failed to create the Xorg log directory '%s': %s" % (xorg_log_dir, e)) #apply string substitutions: subs = { "XAUTHORITY": xauthority, "USER": os.environ.get("USER", "unknown-user"), "UID": os.getuid(), "GID": os.getgid(), "HOME": os.environ.get("HOME", cwd), "DISPLAY": display_name, "XPRA_LOG_DIR": os.environ.get("XPRA_LOG_DIR"), } xvfb_cmd = shellsub(xvfb_str, subs).split() log("shellsub(%s, %s)=%s", xvfb_str, subs, xvfb_cmd) if not xvfb_cmd: raise InitException( "cannot start Xvfb, the command definition is missing!") xvfb_executable = xvfb_cmd[0] if (xvfb_executable.endswith("Xorg") or xvfb_executable.endswith("Xdummy")) and pixel_depth > 0: xvfb_cmd.append("-depth") xvfb_cmd.append(str(pixel_depth)) if use_display_fd: # 'S' means that we allocate the display automatically r_pipe, w_pipe = os.pipe() xvfb_cmd += ["-displayfd", str(w_pipe)] xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, display_name) def preexec(): setsid() if POSIX and getuid() == 0 and uid: setuidgid(uid, gid) close_fds([0, 1, 2, r_pipe, w_pipe]) log("xvfb_cmd=%s", xvfb_cmd) xvfb = subprocess.Popen(xvfb_cmd, executable=xvfb_executable, close_fds=False, stdin=subprocess.PIPE, preexec_fn=preexec, cwd=cwd) # Read the display number from the pipe we gave to Xvfb # waiting up to 10 seconds for it to show up limit = monotonic_time() + 10 buf = "" import select #@UnresolvedImport while monotonic_time() < limit and len(buf) < 8: r, _, _ = select.select([r_pipe], [], [], max(0, limit - monotonic_time())) if r_pipe in r: buf += os.read(r_pipe, 8) if buf[-1] == '\n': break os.close(r_pipe) os.close(w_pipe) if len(buf) == 0: raise InitException( "%s did not provide a display number using -displayfd" % xvfb_executable) if buf[-1] != '\n': raise InitException("%s output not terminated by newline: %s" % (xvfb_executable, buf)) try: n = int(buf[:-1]) except: raise InitException("%s display number is not a valid number: %s" % (xvfb_executable, buf[:-1])) if n < 0 or n >= 2**16: raise InitException("%s provided an invalid display number: %s" % (xvfb_executable, n)) new_display_name = ":%s" % n log("Using display number provided by %s: %s", xvfb_executable, new_display_name) if tmp_xorg_log_file != None: #ie: ${HOME}/.xpra/Xorg.${DISPLAY}.log -> /home/antoine/.xpra/Xorg.S14700.log f0 = shellsub(tmp_xorg_log_file, subs) subs["DISPLAY"] = new_display_name #ie: ${HOME}/.xpra/Xorg.${DISPLAY}.log -> /home/antoine/.xpra/Xorg.:1.log f1 = shellsub(tmp_xorg_log_file, subs) if f0 != f1: try: os.rename(f0, f1) except Exception as e: sys.stderr.write( "failed to rename Xorg log file from '%s' to '%s'\n" % (f0, f1)) sys.stderr.write(" %s\n" % e) display_name = new_display_name else: # use display specified xvfb_cmd[0] = "%s-for-Xpra-%s" % (xvfb_executable, display_name) xvfb_cmd.append(display_name) def preexec(): if getuid() == 0 and (uid != 0 or gid != 0): setuidgid(uid, gid) else: setsid() log("xvfb_cmd=%s", xvfb_cmd) xvfb = subprocess.Popen(xvfb_cmd, executable=xvfb_executable, close_fds=True, stdin=subprocess.PIPE, preexec_fn=preexec) xauth_add(display_name, xauth_data) log("xvfb process=%s", xvfb) log("display_name=%s", display_name) return xvfb, display_name
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 def validate_size(size : int): assert size>=64*1024*1024, "mmap size is too small: %sB (minimum is 64MB)" % std_unit(size) assert size<=4*1024*1024*1024, "mmap is too big: %sB (maximum is 4GB)" % std_unit(size) 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: validate_size(mmap_size) if not filename: from xpra.os_util 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 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) validate_size(mmap_size) #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: validate_size(mmap_size) 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 FileExistsError: log.error("Error: the mmap file '%s' already exists", filename) return rerr() else: validate_size(mmap_size) import tempfile from xpra.platform.paths import get_mmap_dir mmap_dir = get_mmap_dir() subs = os.environ.copy() subs.update({ "UID" : os.getuid(), "GID" : os.getgid(), "PID" : os.getpid(), }) mmap_dir = shellsub(mmap_dir, subs) if mmap_dir and not os.path.exists(mmap_dir): os.mkdir(mmap_dir, 0o700) if not mmap_dir or not os.path.exists(mmap_dir): raise Exception("mmap directory %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 mmap_group = (mmap_group or "") if POSIX and mmap_group and mmap_group not in FALSE_OPTIONS: group_id = None if mmap_group=="SOCKET": group_id = get_socket_group(socket_filename) elif mmap_group.lower()=="auto": group_id = xpra_group() if not group_id and socket_filename: group_id = get_socket_group(socket_filename) elif mmap_group.lower() in TRUE_OPTIONS: log.info("parsing legacy mmap-group value '%s' as 'auto'", mmap_group) log.info(" please update your configuration") group_id = xpra_group() or get_socket_group(socket_filename) else: group_id = get_group_id(mmap_group) if group_id>0: log("setting mmap file %s to group id=%i", mmap_filename, group_id) try: os.fchown(fd, -1, group_id) except OSError as e: log("fchown(%i, %i, %i) on %s", fd, -1, group_id, mmap_filename, exc_info=True) log.error("Error: failed to change group ownership of mmap file to '%s':", mmap_group) log.error(" %s", e) from stat import S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP os.fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) 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) if delete: if mmap_temp_file: try: mmap_temp_file.close() except OSError: log("%s()", mmap_temp_file.close, exc_info=True) log.error(" failed to remove the mmap temp file: %s", e) else: clean_mmap(mmap_filename) return rerr()