示例#1
0
def chmod(files, mod, tn=""):
    '''val = 0x00
    c = 0
    logger.logVV(tn, logger.I, utilities.utf8all(
        _("Calculating permissions of"), " ", files))
    # In case the user of this function used UGO instead of SUGO, we'll cover up for that
    if len(mod) < 4:
        c = 1
    # OR all of the chmod options
    for i in mod:
        # OR this option to val
        val = val | _chmod(c, int(i))
        c = c + 1'''
    val = mod
    if isinstance(mod, str):
        val = int(mod, 8)
    else:
        mod_ = str(oct(mod))[1:]
        mod = mod_
    # Chmod it
    logger.logVV(
        tn, logger.I,
        utilities.utf8all(_("Setting permissions of"), " ", files, " ",
                          _("to"), " ", mod))
    os.chmod(files, val)
示例#2
0
 def runthread(self):
     # Generate the package manifest
     logger.logV(self.tn, logger.I, _("Generating package manifests"))
     logger.logVV(self.tn, logger.I, _(
         "Generating filesystem.manifest and filesystem.manifest-desktop"))
     writer = open(isotreel + "casper/filesystem.manifest", "w")
     writer_desktop = open(
         isotreel + "casper/filesystem.manifest-desktop", "w")
     for i in config.AptCache:
         if i.installedVersion is None or len(i.installedVersion) <= 0:
             continue
         name = i.fullname.strip()
         ver = i.installedVersion.strip()
         strs = name + " " + ver + "\n"
         writer.write(strs)
         if (not name in
                 configutils.getValue(configs[configutils.remafterinst])):
             writer_desktop.write(strs)
     writer.close()
     writer_desktop.close()
     logger.logVV(
         self.tn, logger.I, _("Generating filesytem.manifest-remove"))
     writer = open(isotreel + "casper/filesystem.manifest-remove", "w")
     for i in configutils.parseMultipleValues(configutils.getValue(configs[configutils.remafterinst])):
         writer.write(i.strip() + "\n")
     writer.close()
示例#3
0
def touch(files, tn=""):
    if os.path.exists(files):
        logger.logVV(tn, logger.I, _("Touching file") + " " + str(files))
        os.utime(files, None)
    else:
        logger.logVV(tn, logger.I, _("Creating file") + " " + str(files))
        open(files, "w").close()
示例#4
0
 def onWrite(msg):
     logger.logVV(tn, logger.D, "Updating terminal (from thread " + threading.current_thread().name + ")")
     #return
     ui.terminal.moveCursor(QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor)
     QtCore.QMetaObject.invokeMethod(ui.terminal, "insertPlainText",
                                     QtCore.Qt.QueuedConnection,
                         QtCore.Q_ARG("QString", msg.rstrip() + "\n"))
示例#5
0
 def run(self):
     logger.logI(tn, _("Generating compressed filesystem"))
     # Generate the SquashFS file
     # Options:
     # -b 1M                    Use a 1M blocksize (maximum)
     # -no-recovery             No recovery files
     # -always-use-fragments    Fragment blocks for files larger than the blocksize (1M)
     # -comp                    Compression type
     logger.logVV(tn, _("Generating options"))
     opts = "-b 1M -no-recovery -no-duplicates -always-use-fragments"
     opts = opts + " -comp " + configutils.getValue(configs[configutils.sfscomp])
     opts = opts + " " + configutils.getValue(configs[configutils.sfsopts])
     sfsex = "dev etc home media mnt proc sys var usr/lib/ubiquity/apt-setup/generators/40cdrom"
     sfspath = isotreel + "casper/filesystem.squashfs"
     logger.logI(tn, _("Adding the edited /etc and /var to the filesystem"))
     os.system("mksquashfs " + tmpsys + " " + sfspath + " " + opts)
     logger.logI(tn, _("Adding the rest of the system"))
     os.system("mksquashfs / " + sfspath + " " + opts + " -e " + sfsex)
     # Make sure the SquashFS file is OK
     doSFSChecks(sfspath, int(configutils.getValue(configs[configutils.isolevel])))
     # Find the size after it is uncompressed
     logger.logV(tn, _("Writing the size"))
     files = open(isotreel + "casper/filesystem.size", "w")
     files.write(fsutil.getSFSInstSize(sfspath) + "\n")
     files.close()
示例#6
0
 def runthread(self):
     logger.logV(self.tn, logger.I, _("Copying ISOLINUX to the ISO tree"))
     copyFile("/usr/lib/syslinux/isolinux.bin", isotreel +
              "isolinux/", self.tn, True)
     self.setProgress(self.tn, 20)
     copyFile("/usr/lib/syslinux/vesamenu.c32", isotreel +
              "isolinux/", self.tn, True)
     self.setProgress(self.tn, 40)
     logger.logVV(
         self.tn, logger.I, _("Copying isolinux.cfg to the ISO tree"))
     copyFile(configutils.getValue(configs[configutils.isolinuxfile]), isotreel +
              "isolinux/isolinux.cfg", self.tn, True)
     self.setProgress(self.tn, 50)
     # Edit the isolinux.cfg file to replace the variables
     logger.logV(self.tn, logger.I, _("Editing isolinux.cfg"))
     splash = os.path.basename(
         configutils.getValue(configs[configutils.splash]))
     shutil.copy2(configutils.getValue(configs[configutils.splash]),
                  isotreel + "isolinux/" + splash)
     self.setProgress(self.tn, 70)
     for i in [["LABEL", configutils.getValue(configs[configutils.label])],
               ["SPLASH", splash],
               ["TIMEOUT", configutils.getValue(configs[configutils.timeout])]]:
         fsutil.ife(
             fsutil.ife_getbuffers(isotreel + "isolinux/isolinux.cfg"),
             lambda line: [True, re.sub("\$" + i[0], i[1], line)])
示例#7
0
    def runthread(self):
        # Generate the package manifest
        logger.logV(self.tn, logger.I, _("Generating package manifests"))
        logger.logVV(self.tn, logger.I, _(
            "Generating filesystem.manifest and filesystem.manifest-desktop"))
        writer = open(isotreel + "casper/filesystem.manifest", "w")
        writer_desktop = open(
            isotreel + "casper/filesystem.manifest-desktop", "w")

        # installedVersion throws an error when it doesn't exist in 'Package'
        # TODO: figure out why, but for now.. check for attribute as well
        for i in config.AptCache:
            if not hasattr(i,'installedVersion') or i.installedVersion is None or len(i.installedVersion) <= 0:
                continue
            name = i.fullname.strip()
            ver = i.installedVersion.strip()
            strs = name + " " + ver + "\n"
            writer.write(strs)
            if (not name in
                    configutils.getValue(configs[configutils.remafterinst])):
                writer_desktop.write(strs)
        writer.close()
        writer_desktop.close()
        logger.logVV(
            self.tn, logger.I, _("Generating filesytem.manifest-remove"))
        writer = open(isotreel + "casper/filesystem.manifest-remove", "w")
        for i in configutils.parseMultipleValues(configutils.getValue(configs[configutils.remafterinst])):
            writer.write(i.strip() + "\n")
        writer.close()
示例#8
0
def addOptional(threads):
    for i in range(len(threads)):
        if not "threadspan" in threads[i]:
            threads[i]["threadspan"] = 1
        if not "enabled" in threads[i]:
            threads[i]["enabled"] = True
    logger.logVV(tn, logger.D, "Check addoptional")
示例#9
0
def touch(files, tn=""):
    if os.path.exists(files):
        logger.logVV(tn, logger.I, _("Touching file") + " " + str(files))
        os.utime(files, None)
    else:
        logger.logVV(tn, logger.I, _("Creating file") + " " + str(files))
        open(files, "w").close()
示例#10
0
 def runthread(self):
     logger.logV(
         self.tn, logger.I, _("Copying preseed files to the ISO tree"))
     for i in fsutil.listdir(configutils.getValue(configs[configutils.preseed])):
         logger.logVV(self.tn, logger.I, _("Copying") +
                      " " + i + " " + _("to the ISO tree"))
         copyFile(i, isotreel + "preseed/", self.tn)
示例#11
0
 def runthread(self):
     # Create the logs
     logger.logV(self.tn, logger.I, _("Creating empty logs"))
     for i in [
         "dpkg.log",
         "lastlog",
         "mail.log",
         "syslog",
         "auth.log",
         "daemon.log",
         "faillog",
         "lpr.log",
         "mail.warn",
         "user.log",
         "boot",
         "debug",
         "mail.err",
         "messages",
         "wtmp",
         "bootstrap.log",
         "dmesg",
         "kern.log",
         "mail.info",
     ]:
         logger.logVV(self.tn, logger.I, logger.MTab + _("Creating") + " " + i)
         fsutil.touch(tmpsys + "var/log/" + i)
示例#12
0
def makedir(dirs1, tn=""):
    dirs = dirs1
    mode = 0o777
    if isinstance(dirs1, list):
        dirs = dirs1[0]
        mode = dirs1[1]
    if not os.path.exists(dirs):
        logger.logVV(tn, logger.I, _("Creating directory") + " " + str(dirs))
        os.makedirs(dirs, mode)
示例#13
0
def makedir(dirs1, tn=""):
    dirs = dirs1
    mode = 0o777
    if isinstance(dirs1, list):
        dirs = dirs1[0]
        mode = dirs1[1]
    if not os.path.exists(dirs):
        logger.logVV(tn, logger.I, _("Creating directory") + " " + str(dirs))
        os.makedirs(dirs, mode)
示例#14
0
def fscopy(src, dst, excludes1, tn=""):
    src1 = re.sub(r"/+$", "", src)
    src = src1
    # Get a list of all files
    files = listdir(src, {
        "recurse": True,
        "dirs": True,
        "symlinks": False
    }, tn)
    # Exclude the files that are not wanted
    excludes = []
    if len(excludes1) > 0:
        excludes = exclude(files, excludes1)
    makedir(dst)
    # Copy the files
    for file__ in files:
        file_ = utilities.utf8(os.path.basename(utilities.utf8(file__)))
        # Make sure we don't copy files that are supposed to be excluded
        if file_ in excludes:
            #logger.logVV(tn, logger.W, utilities.utf8all(file_, " ", _("is to be excluded. Skipping a CPU cycle")))
            continue
        fullpath = utilities.utf8(file__)
        #print(dst + " " + file__[len(src):])
        temp = re.sub(r"^/+", "", file__[len(src):])
        newpath = utilities.utf8(os.path.join(dst, temp))
        # Save some valuable time
        if os.path.exists(newpath):
            fpmd5 = genMD5(fullpath)
            npmd5 = genMD5(newpath)
            if fpmd5 == npmd5:
                continue
        dfile = delink(fullpath)
        if dfile is not None:
            logger.logVV(
                tn, logger.I,
                utilities.utf8all(
                    file_, " ",
                    _("is a symlink. Creating an identical symlink at"), " ",
                    newpath))
            symlink(dfile, newpath)
        elif os.path.isdir(fullpath):
            logger.logVV(
                tn, logger.I,
                utilities.utf8all(_("Creating directory"), " ", file_))
            makedir(newpath)
            logger.logVV(tn, logger.I, _("Setting permissions"))
            copystat(fullpath, newpath)
        else:
            logger.logVV(
                tn, logger.I,
                utilities.utf8all(_("Copying"), " ", fullpath, " ", _("to"),
                                  " ", newpath))
            shutil.copy2(fullpath, newpath)
    logger.logVV(tn, logger.I, _("Setting permissions"))
    copystat(src, dst)
示例#15
0
 def onWrite(msg):
     logger.logVV(
         tn, logger.D, "Updating terminal (from thread " +
         threading.current_thread().name + ")")
     #return
     ui.terminal.moveCursor(QtGui.QTextCursor.End,
                            QtGui.QTextCursor.MoveAnchor)
     QtCore.QMetaObject.invokeMethod(
         ui.terminal, "insertPlainText", QtCore.Qt.QueuedConnection,
         QtCore.Q_ARG("QString",
                      msg.rstrip() + "\n"))
示例#16
0
 def runthread(self):
     # Create the logs
     logger.logV(self.tn, logger.I, _("Creating empty logs"))
     for i in [
             "dpkg.log", "lastlog", "mail.log", "syslog", "auth.log",
             "daemon.log", "faillog", "lpr.log", "mail.warn", "user.log",
             "boot", "debug", "mail.err", "messages", "wtmp",
             "bootstrap.log", "dmesg", "kern.log", "mail.info"
     ]:
         logger.logVV(self.tn, logger.I,
                      logger.MTab + _("Creating") + " " + i)
         fsutil.touch(tmpsys + "var/log/" + i)
示例#17
0
 def runthread(self):
     # Create the logs
     logger.logV(self.tn, logger.I, _("Creating empty logs"))
     a = ["dpkg.log", "lastlog", "mail.log", "syslog", "auth.log", "daemon.log", "faillog",
          "lpr.log", "mail.warn", "user.log", "boot", "debug", "mail.err", "messages", "wtmp",
          "bootstrap.log", "dmesg", "kern.log", "mail.info"]
     la = len(a)
     inc = 100 / la
     for i in range(la):
         logger.logVV(
             self.tn, logger.I, logger.MTab + _("Creating") + " " + a[i])
         fsutil.touch(tmpsys + "var/log/" + a[i])
         self.setProgress(self.tn, (i + 1) * inc)
示例#18
0
def adrm(dirs, options, excludes1 = [], tn = ""):
    # Get a list of all files inside the directory
    files = listdir(dirs, {"recurse": True, "dirs": True, "symlinks": False}, tn)
    excludes = []
    # Exclude the files listed to exclude
    if options["excludes"] and len(excludes1) > 0:
        excludes = exclude(files, excludes1)
    # Remove the wanted files
    for file_ in files:
        file__ = utilities.utf8(file_)
        file_ = utilities.utf8(os.path.basename(file__))
        # Make sure we don't remove files that are listed to exclude from removal
        if file__ in excludes:
            logger.logVV(tn, logger.I, utilities.utf8all(file_, " ",
                                                         _("is to be excluded. Skipping a CPU cycle")))
            continue
        fullpath = file__
        dfile = delink(fullpath)
        if dfile == None:
            if os.path.isfile(fullpath):
                rm(fullpath)
            elif os.path.isdir(fullpath) and options["remdirs"]:
                rm(fullpath)
        else:
            if options["remsymlink"]:
                logger.logVV(tn, logger.I, utilities.utf8all(_("Removing symlink"), " ", fullpath))
                rm(fullpath)
            if options["remfullpath"]:
                logger.logVV(tn, logger.I, utilities.utf8all(_("Removing"), " ", dfile, " (",
                                                   _("directed by symlink"), fullpath, ")"))
                rm(dfile)
    if options["remdirs"] is True:
        logger.logVV(tn, logger.I, utilities.utf8all(_("Removing source directory"), " ", dirs))
        rm(dirs)
示例#19
0
def rm(files, followlink=False, tn=""):
    rfile = files
    dfile = delink(files)
    rmstring = "Removing "
    if os.path.isdir(files):
        rmstring += "directory "
    if dfile != None:
        files = dfile
        if os.path.isfile(files):
            logger.logVV(tn, logger.I,
                         utilities.utf8all(_("Removing symlink"), " ", rfile))
        elif os.path.isdir(files):
            logger.logVV(
                tn, logger.I,
                utilities.utf8all(_("Removing directory symlink"), " ", rfile))
        os.remove(rfile)
        if followlink:
            files = rfile
        else:
            return
    if os.path.isfile(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        os.remove(rfile)
    elif os.path.isdir(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        shutil.rmtree(rfile)
示例#20
0
 def run(self):
     logger.logV(self.tn, _("Copying ISOLINUX to the ISO tree"))
     copyFile("/usr/lib/syslinux/isolinux.bin", isotreel + "isolinux/", True)
     copyFile("/usr/lib/syslinux/vesamenu.c32", isotreel + "isolinux/", True)
     logger.logVV(self.tn, _("Copying isolinux.cfg to the ISO tree"))
     copyFile(configutils.getValue(configs[configutils.isolinuxfile], isotreel + 
                                   "isolinux/isolinux.cfg", True))
     # Edit the isolinux.cfg file to replace the variables
     logger.logV(_("Editing isolinux.cfg"))
     for i in [["LABEL", configutils.getValue(configs[configutils.label])],
               ["SPLASH", configutils.getValue(configs[configutils.splash])],
               ["TIMEOUT", configutils.getValue(configs[configutils.timeout])]]:
         fsutil.ife(fsutil.ife_getbuffers(isotreel + "isolinux/isolinux.cfg"),
                    lambda line: re.sub("\$" + i[0], i[1], line))
示例#21
0
 def runthread(self):
     logger.logI(self.tn, logger.I, _("Starting generation of the ISO image"))
     # Make a last verification on the SquashFS
     squashfs.doSFSChecks(isotreel + "casper/filesystem.squashfs",
                          configutils.getValue(configs[configutils.isolevel]))
     self.setProgress(self.tn, 5)
     # Generate MD5 checksums
     logger.logV(self.tn, logger.I, _("Generating MD5 sums"))
     files = open(isotreel + "md5sum.txt", "w")
     for x in fsutil.listdir(isotreel, {"recurse": True}):
         i = re.sub(r"^ *" + isotreel + "/*", "./", x)
         if not "isolinux" in i and not "md5sum" in i:
             logger.logVV(self.tn, logger.I, _("Writing MD5 sum of") + " " + i)
             fmd5 = fsutil.genFinalMD5(i, x)
             if fmd5 != "" and fmd5 != None:
                 files.write(fmd5)
     files.close()
     self.setProgress(self.tn, 15)
     logger.logI(self.tn, logger.I, _("Generating the ISO"))
     location = (configutils.getValue(configs[configutils.isodir]) + "/" +
                 configutils.getValue(configs[configutils.isolocation]))
     patt = re.compile("^ *([0-9]+)\.?[0-9]*%.*$")
     appnd = "32"
     if sys.maxsize > 2 ** 32:
         appnd = "64"
     os.environ["LD_PRELOAD"] = os.path.split(os.path.realpath(__file__))[0] + "/isatty" + appnd + ".so"
     isocmd = subprocess.Popen(shlex.split(configutils.getValue(configs[configutils.isogenerator]) + " -o " +
                                           location + " " + isogenopts + " -V \"" +
                                           configutils.getValue(configs[configutils.label]) + "\" " + isotreel),
                               stderr=subprocess.PIPE, universal_newlines=True)
     oldprogress = 0
     while isocmd.poll() is None:
         output = isocmd.stderr.readline()
         match = patt.match(output)
         if match != None:
             progress = int(match.group(1))
             if progress > oldprogress:
                 # 1.4285714285714286 is just 100 / 70
                 self.setProgress(self.tn, 15 + int(utilities.floatDivision(progress, 1.4285714285714286)))
                 oldprogress = progress
         sys.stdout.write(output)
         sys.stdout.flush()
     os.environ["LD_PRELOAD"] = ""
     self.setProgress(self.tn, 85)
     # Generate the MD5 sum
     logger.logV(self.tn, logger.I, _("Generating MD5 sum for the ISO"))
     files = open(location + ".md5", "w")
     files.write(fsutil.genFinalMD5("./" + configutils.getValue(configs[configutils.isolocation]),
                                    location))
     files.close()
示例#22
0
def rm(files, followlink=False, tn=""):
    if not os.path.exists(files):
        # If there isn't anything to remove, why bother with this function?
        return
    rfile = files
    dfile = delink(files)
    rmstring = "Removing "
    if os.path.isdir(files):
        rmstring += "directory "
    if dfile is not None:
        files = dfile
        if os.path.isfile(files):
            logger.logVV(tn, logger.I,
                         utilities.utf8all(_("Removing symlink"), " ", rfile))
        elif os.path.isdir(files):
            logger.logVV(
                tn, logger.I,
                utilities.utf8all(_("Removing directory symlink"), " ", rfile))
        os.remove(rfile)
        if followlink:
            files = rfile
        else:
            return
    if os.path.isfile(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        os.remove(rfile)
    elif os.path.isdir(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        shutil.rmtree(rfile)
示例#23
0
def rm(files, followlink=False, tn=""):
    if not os.path.exists(files):
        # If there isn't anything to remove, why bother with this function?
        return
    rfile = files
    dfile = delink(files)
    rmstring = "Removing "
    if os.path.isdir(files):
        rmstring += "directory "
    if dfile is not None:
        files = dfile
        if os.path.isfile(files):
            logger.logVV(tn, logger.I, utilities.utf8all(_("Removing symlink"), " ", rfile))
        elif os.path.isdir(files):
            logger.logVV(tn, logger.I, utilities.utf8all(_("Removing directory symlink"), " ", rfile))
        os.remove(rfile)
        if followlink:
            files = rfile
        else:
            return
    if os.path.isfile(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        os.remove(rfile)
    elif os.path.isdir(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        shutil.rmtree(rfile)
示例#24
0
def adrm(dirs, options, excludes1=[], tn=""):
    # Get a list of all files inside the directory
    files = listdir(dirs, {"recurse": True, "dirs": True, "symlinks": True}, tn)
    excludes = []
    # Exclude the files listed to exclude
    if options.excludes is True and len(excludes1) > 0:
        excludes = exclude(files, excludes1)
    # Remove the wanted files
    for file in files:
        # Make sure we don't remove files that are listed to exclude from removal
        if file in excludes:
            logger.logVV(tn, file + " " + _("is to be excluded. Skipping a CPU cycle"))
            continue
        fullpath = os.path.join(dirs, file)
        dfile = delink(fullpath)
        if dfile is not None:
            if os.path.isfile(dfile):
                rm(fullpath)
                continue
            elif os.path.isdir(fullpath):
                adrm(fullpath, options, excludes1, tn)
        else:
            if options.remsymlink is True:
                logger.logVV(tn, _("Removing symlink") + " " + fullpath)
                rm(fullpath)
            if options.remfullpath is True:
                logger.logVV(tn, _("Removing") + " " + dfile + " (" + _("directed by symlink")
                              + fullpath + ")")
    if options.remdirs is True:
        logger.logVV(tn, _("Removing source directory") + " " + dirs)
        rm(dirs)
示例#25
0
 def runthread(self):
     logger.logI(self.tn, logger.I, _(
         "Making the ISO compatible with a USB burner"))
     logger.logVV(self.tn, logger.I, _("Writing .disk/info"))
     files = open(isotreel + ".disk/info", "w")
     files.write(getDiskName() + "\n")
     files.close()
     self.setProgress(self.tn, 20)
     logger.logV(self.tn, logger.I, _(
         "Making symlink pointing to the ISO root dir"))
     if os.path.lexists(isotreel + "ubuntu"):
         fsutil.rm(isotreel + "ubuntu", False, self.tn)
     os.symlink(isotreel, isotreel + "ubuntu")
     self.setProgress(self.tn, 40)
     logger.logVV(self.tn, logger.I, _("Writing release notes URL"))
     files = open(isotreel + ".disk/release_notes_url", "w")
     files.write(configutils.getValue(configs[configutils.url]) + "\n")
     files.close()
     self.setProgress(self.tn, 60)
     logger.logVV(self.tn, logger.I, _("Writing .disk/base_installable"))
     fsutil.touch(isotreel + ".disk/base_installable")
     self.setProgress(self.tn, 80)
     logger.logVV(self.tn, logger.I, _("Writing CD Type"))
     files = open(isotreel + ".disk/cd_type", "w")
     files.write("full_cd/single\n")
     files.close()
示例#26
0
def fscopy(src, dst, excludes1, tn=""):
    # Get a list of all files
    files = listdir(src, {"recurse": True, "dirs": True, "symlinks": True}, tn)
    # Exclude the files that are not wanted
    excludes = []
    if len(excludes1) > 0:
        excludes = exclude(files, excludes1)
    makedir(dst)
    # Copy the files
    for file in files:
        # Make sure we don't copy files that are supposed to be excluded
        if file in excludes:
            logger.logVV(tn, file + " " + _("is to be excluded. Skipping a CPU cycle"))
            continue
        fullpath = os.path.join(src, file)
        newpath = os.path.join(dst, file)
        dfile = delink(fullpath)
        if dfile is not None:
            logger.logVV(tn, file + " " + _("is a symlink. Creating an identical symlink at") + " " + 
                         newpath)
            os.symlink(dfile, newpath)
        elif os.path.isdir(fullpath):
            logger.logVV(tn, _("Recursing into") + " " + file)
            fscopy(fullpath, newpath, excludes, tn)
        else:
            logger.logVV(tn, _("Copying") + " " + fullpath + " " + _("to") + " " + newpath)
            shutil.copy2(fullpath, newpath)
    logger.logV(tn, _("Setting permissions"))
    shutil.copystat(src, dst)
示例#27
0
 def setProgress(tn, progress):
     logger.logVV(tn, logger.D, "Setting progress to " + str(progress) + " (from thread " + threading.current_thread().name + ")")
     #return
     # Do something here
     if progress > 100:
         progress = 100
     elif progress < 0:
         progress = 0
     page["progress"][tn] = progress
     totprogress = 0
     for i in page["progress"]:
         totprogress += utilities.floatDivision(float(page["progress"][i]), 100)
     QtCore.QMetaObject.invokeMethod(ui.progress, "setValue",
                                     QtCore.Qt.QueuedConnection,
                         QtCore.Q_ARG("int", utilities.calcPercent(totprogress, numthreads2)))
示例#28
0
 def _ActualLoop(threads, threadsdone, threadsrunning, threadids):
     logger.logVV(tn, logger.D, "Check ActualLoop")
     #global threads, threadsdone, threadsrunning, threadids
     while config.ThreadStop is False:
         # Clear old threads
         for x in threadsrunning:
             checkThread(x, threadsdone, threadsrunning, threads, pelock, **options)
         # End if all threads are done
         if len(threadsdone) >= len(threads):
             logger.logVV(tn, logger.D, "Ending ActualLoop")
             break
         # Run runnable threads
         for x in findRunnableThreads(threadids, threadsdone, threadsrunning, threads, **options):
             runThread(x, threadsdone, threadsrunning, threads, pslock, **options)
         time.sleep(float(1.0 / config.ThreadRPS))
示例#29
0
def chmod(file, mod, tn=""):
    val = 0x00
    c = 0
    logger.logVV(tn, _("Calculating permissions of") + " " + file)
    # In case the user of this function used UGO instead of SUGO, we'll cover up for that
    if len(mod) < 4:
        c = 1
    # OR all of the chmod options
    for i in mod:
        # OR this option to val
        val = val | _chmod(c, int(i))
        c = c + 1
    # Chmod it
    logger.logVV(tn, _("Setting permissions of") + " " + file + " " + _("to") + " " + mod)
    os.chmod(file, val)
示例#30
0
 def runthread(self):
     # Create the logs
     logger.logV(self.tn, logger.I, _("Creating empty logs"))
     a = [
         "dpkg.log", "lastlog", "mail.log", "syslog", "auth.log",
         "daemon.log", "faillog", "lpr.log", "mail.warn", "user.log",
         "boot", "debug", "mail.err", "messages", "wtmp", "bootstrap.log",
         "dmesg", "kern.log", "mail.info"
     ]
     la = len(a)
     inc = 100 / la
     for i in range(la):
         logger.logVV(self.tn, logger.I,
                      logger.MTab + _("Creating") + " " + a[i])
         fsutil.touch(tmpsys + "var/log/" + a[i])
         self.setProgress(self.tn, (i + 1) * inc)
示例#31
0
def fscopy(src, dst, excludes1, tn = ""):
    src1 = re.sub(r"/+$", "", src)
    src = src1
    # Get a list of all files
    files = listdir(src, {"recurse": True, "dirs": True, "symlinks": False}, tn)
    # Exclude the files that are not wanted
    excludes = []
    if len(excludes1) > 0:
        excludes = exclude(files, excludes1)
    makedir(dst)
    # Copy the files
    for file__ in files:
        file_ = utilities.utf8(os.path.basename(utilities.utf8(file__)))
        # Make sure we don't copy files that are supposed to be excluded
        if file_ in excludes:
            #logger.logVV(tn, logger.W, utilities.utf8all(file_, " ", _("is to be excluded. Skipping a CPU cycle")))
            continue
        fullpath = utilities.utf8(file__)
        #print(dst + " " + file__[len(src):])
        temp = re.sub(r"^/+", "", file__[len(src):])
        newpath = utilities.utf8(os.path.join(dst, temp))
        # Save some valuable time
        if os.path.exists(newpath):
            fpmd5 = genMD5(fullpath)
            npmd5 = genMD5(newpath)
            if fpmd5 == npmd5:
                continue
        dfile = delink(fullpath)
        if dfile is not None:
            logger.logVV(tn, logger.I, utilities.utf8all(file_, " ",
                                            _("is a symlink. Creating an identical symlink at"), " ",
                                            newpath))
            symlink(dfile, newpath)
        elif os.path.isdir(fullpath):
            logger.logVV(tn, logger.I, utilities.utf8all(_("Creating directory"), " ", file_))
            makedir(newpath)
            logger.logVV(tn, logger.I, _("Setting permissions"))
            copystat(fullpath, newpath)
        else:
            logger.logVV(tn, logger.I, utilities.utf8all(_("Copying"), " ", fullpath, " ", _("to"), " ", newpath))
            shutil.copy2(fullpath, newpath)
    logger.logVV(tn, logger.I, _("Setting permissions"))
    copystat(src, dst)
示例#32
0
 def setProgress(tn, progress):
     logger.logVV(
         tn, logger.D, "Setting progress to " + str(progress) +
         " (from thread " + threading.current_thread().name + ")")
     #return
     # Do something here
     if progress > 100:
         progress = 100
     elif progress < 0:
         progress = 0
     page["progress"][tn] = progress
     totprogress = 0
     for i in page["progress"]:
         totprogress += utilities.floatDivision(
             float(page["progress"][i]), 100)
     QtCore.QMetaObject.invokeMethod(
         ui.progress, "setValue", QtCore.Qt.QueuedConnection,
         QtCore.Q_ARG("int",
                      utilities.calcPercent(totprogress, numthreads2)))
示例#33
0
def chmod(files, mod, tn = ""):
    '''val = 0x00
    c = 0
    logger.logVV(tn, logger.I, utilities.utf8all(_("Calculating permissions of"), " ", files))
    # In case the user of this function used UGO instead of SUGO, we'll cover up for that
    if len(mod) < 4:
        c = 1
    # OR all of the chmod options
    for i in mod:
        # OR this option to val
        val = val | _chmod(c, int(i))
        c = c + 1'''
    val = mod
    if isinstance(mod, str):
        val = int(mod, 8)
    else:
        mod_ = str(oct(mod))[1:]
        mod = mod_
    # Chmod it
    logger.logVV(tn, logger.I, utilities.utf8all(_("Setting permissions of"), " ", files, " ", _("to"), " ", mod))
    os.chmod(files, val)
示例#34
0
 def run(self):
     logger.logI(self.tn, _("Starting generation of the ISO image"))
     # Make a last verification on the SquashFS
     squashfs.doSFSChecks(isotreel + "casper/filesystem.squashfs",
                          configutils.getValue(configs[configutils.isolevel]))
     # Generate MD5 checksums
     logger.logV(self.tn, _("Generating MD5 sums"))
     files = open(isotreel + "md5sum.txt")
     for x in fsutil.listdir(isotreel, {"recurse": True}):
         i = re.sub(r"^ *" + isotreel + ".*", ".", x)
         if i.find("isotree") == -1 and i.find("md5sum") == -1:
             logger.logVV(self.tn, _("Writing MD5 sum of") + " " + i)
             files.write(fsutil.genFinalMD5(i))
     files.close()
     logger.logI(self.tn, _("Generating the ISO"))
     os.system(configutils.getValue(configs[configutils.isogenerator]) + " " + isogenopts + " -V " + 
               configutils.getValue(configs[configutils.label]) + " -o " + 
               configutils.getValue(configs[configutils.isolocation]))
     # Generate the MD5 sum
     logger.logV(self.tn, _("Generating MD5 sum for the ISO"))
     files = open(configs[configutils.isolocation] + ".md5", "w")
     files.write(fsutil.genFinalMD5(i))
     files.close()
示例#35
0
def adrm(dirs, options, excludes1=[], tn=""):
    # Get a list of all files inside the directory
    files = listdir(dirs, {
        "recurse": True,
        "dirs": True,
        "symlinks": False
    }, tn)
    excludes = []
    # Exclude the files listed to exclude
    if options["excludes"] and len(excludes1) > 0:
        excludes = exclude(files, excludes1)
    # Remove the wanted files
    for file_ in files:
        file__ = utilities.utf8(file_)
        file_ = utilities.utf8(os.path.basename(file__))
        # Make sure we don't remove files that are listed to exclude from removal
        if file__ in excludes:
            logger.logVV(
                tn, logger.I,
                utilities.utf8all(
                    file_, " ", _("is to be excluded. Skipping a CPU cycle")))
            continue
        fullpath = file__
        dfile = delink(fullpath)
        if dfile == None:
            if os.path.isfile(fullpath):
                rm(fullpath)
            elif os.path.isdir(fullpath) and options["remdirs"]:
                rm(fullpath)
        else:
            if options["remsymlink"]:
                logger.logVV(
                    tn, logger.I,
                    utilities.utf8all(_("Removing symlink"), " ", fullpath))
                rm(fullpath)
            if options["remfullpath"]:
                logger.logVV(
                    tn, logger.I,
                    utilities.utf8all(_("Removing"), " ", dfile, " (",
                                      _("directed by symlink"), fullpath, ")"))
                rm(dfile)
    if options["remdirs"] is True:
        logger.logVV(
            tn, logger.I,
            utilities.utf8all(_("Removing source directory"), " ", dirs))
        rm(dirs)
示例#36
0
 def runthread(self):
     # Generate the package manifest
     logger.logV(self.tn, logger.I, _("Generating package manifests"))
     logger.logVV(self.tn, logger.I, _("Generating filesystem.manifest and filesystem.manifest-desktop"))
     pkglistu = config.AptCache.packages
     writer = open(isotreel + "casper/filesystem.manifest", "w")
     writer_desktop = open(isotreel + "casper/filesystem.manifest-desktop", "w")
     for i in pkglistu:
         if i.current_ver == None:
             continue
         name = i.get_fullname(True).strip()
         ver = i.current_ver.ver_str.strip()
         strs = name + " " + ver + "\n"
         writer.write(strs)
         if (not name in
             configutils.parseMultipleValues(configutils.getValue(configs[configutils.remafterinst]))):
             writer_desktop.write(strs)
     writer.close()
     writer_desktop.close()
     logger.logVV(self.tn, logger.I, _("Generating filesytem.manifest-remove"))
     writer = open(isotreel + "casper/filesystem.manifest-remove", "w")
     for i in configutils.parseMultipleValues(configutils.getValue(configs[configutils.remafterinst])):
         writer.write(i.strip() + "\n")
     writer.close()
示例#37
0
 def run(self):
     logger.logI(self.tn, _("Making the ISO compatible with a USB burner"))
     logger.logVV(self.tn, _("Writing .disk/info"))
     files = open(isotreel + ".disk/info", "w")
     files.write(getDiskName())
     files.close()
     logger.logV(self.tn, _("Making symlink pointing to the ISO root dir"))
     os.symlink(isotreel + "ubuntu", isotreel)
     logger.logVV(self.tn, _("Writing release notes URL"))
     files = open(isotreel + ".disk/release_notes_url", "w")
     files.write(configutils.getValue(configs[configutils.url]) + "\n")
     files.close()
     logger.logVV(self.tn, _("Writing .disk/base_installable"))
     fsutil.touch(isotreel + ".disk/base_installable")
     logger.logVV(self.tn, _("Writing CD Type"))
     files = open(isotreel + ".disk/cd_type", "w")
     files.write("full_cd/single\n")
     files.close()
示例#38
0
def rm(files, followlink=False, tn=""):
    rfile = files
    dfile = delink(files)
    rmstring = "Removing "
    if os.path.isdir(files):
        rmstring += "directory "
    if dfile is not None:
        files = dfile
        rmstring += "symlink "
    if os.path.isfile(files):
        logger.logVV(tn, _(rmstring) + files)
        os.remove(rfile)
        if followlink is True and dfile is not None:
            logger.logVV(tn, _("Removing") + " " + files)
            os.remove(files)
    elif os.path.isdir(files):
        logger.logVV(tn, _(rmstring + files))
        shutil.rmtree(rfile)
        if followlink is True and dfile is not None:
            logger.logVV(tn, _("Removing directory") + " " + files)
            os.remove(files)
示例#39
0
def rm(files, followlink = False, tn = ""):
    rfile = files
    dfile = delink(files)
    rmstring = "Removing "
    if os.path.isdir(files):
        rmstring += "directory "
    if dfile != None:
        files = dfile
        if os.path.isfile(files):
            logger.logVV(tn, logger.I, utilities.utf8all(_("Removing symlink"), " ", rfile))
        elif os.path.isdir(files):
            logger.logVV(tn, logger.I, utilities.utf8all(_("Removing directory symlink"), " ", rfile))
        os.remove(rfile)
        if followlink:
            files = rfile
        else:
            return
    if os.path.isfile(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        os.remove(rfile)
    elif os.path.isdir(files):
        logger.logVV(tn, logger.I, utilities.utf8all(_(rmstring), files))
        shutil.rmtree(rfile)
示例#40
0
 def run(self):
     # Generate the package manifest
     logger.logV(self.tn, _("Generating package manifests"))
     logger.logVV(self.tn, _("Generating filesystem.manifest"))
     pkglistu = os.popen("dpkg -l")
     writer = open(isotreel + "casper/filesystem.manifest", "w")
     for i in pkglistu:
         splitted = i.split()
         if not splitted[1].strip() in config[configutils.remafterinst]:
             writer.write(splitted[1].strip() + " " + splitted[2].strip() + "\n")
     writer.close()
     logger.logVV(self.tn, _("Generating filesytem.manifest-remove"))
     writer = open(isotreel + "casper/filesystem.manifest-remove", "w")
     for i in config[configutils.remafterinst]:
         writer.write(i.strip() + "\n")
     writer.close()
     # We don't want any differences, so we'll just copy filesystem.manifest to filesystem.manifest-desktop
     logger.logVV(self.tn, _("Generating filesystem.manifest-desktop"))
     copyFile(isotreel + "casper/filesystem.manifest", isotreel + "casper/filesystem.manifest-desktop")
示例#41
0
 def runthread(self):
     # Setup the password and group stuff
     logger.logI(self.tn, logger.I, _("Removing conflicting users"))
     passwdf = tmpsys + "etc/passwd"
     #passwdfile = open(passwdf, "r")
     #passwdstat = fsutil.getStat(passwdf)
     #passwdbuffer = configutils.getBuffer(passwdfile)
     #passwdfile.close()
     #passwdfile = open(passwdf, "w")
     buffers = fsutil.ife_getbuffers(passwdf)
     pe = pwdmanip.parsePasswdEntries(buffers[3])
     buffers[3] = pe
     # Users to "delete" on the live system
     logger.logV(self.tn, logger.I, _("Gathering users to remove"))
     nobody = ""
     for x in pe:
         if x["user"] == "nobody":
             nobody = x
     max_uid = 1999
     sysrange = 500
     if not isinstance(nobody, dict):
         logger.logV(self.tn, logger.E,
                     _("User 'nobody' could not be found!"))
     else:
         nuid = int(nobody["uid"])
         if nuid <= 100:
             # nobody has been assigned to the conventional system UID range
             max_uid = 1999
             sysrange = 100
         elif nuid < 500:
             # nobody has been assigned to the RHEL system UID range
             max_uid = 1999
             sysrange = 500
         elif nuid >= 65530 and nuid <= 65535:
             # nobody has been assigned to the highest possible unsigned short integer (16 bit) range
             max_uid = nuid - 1
             sysrange = 555
         elif nuid >= 32766:
             # nobody has been assigned to the highest possible signed short integer (16 bit) range
             max_uid = nuid - 1
             sysrange = 500
         else:
             max_uid = 1999
             sysrange = 555
     usrs = pwdmanip.getPPByUID(numrange.gen_num_range(sysrange, max_uid),
                                pe)
     print(usrs)
     if config.VVStatus is False:
         logger.logV(self.tn, logger.I, _("Removing them"))
     logger.logVV(self.tn, logger.I, _("Removing users in /etc/passwd"))
     fsutil.ife(
         buffers, lambda line: [True, pwdmanip.PPtoEntry(line)]
         if not line in usrs else [False, ""])
     # Rewrite the password file
     #for i in ppe:
     #    if not i in usrs:
     #        passwdfile.write(pwdmanip.PPtoEntry(i))
     #fsutil.copystat(passwdstat, passwdf)
     #passwdfile.close()
     # Now for the group file
     logger.logVV(self.tn, logger.I, _("Removing users in /etc/group"))
     groupf = tmpsys + "etc/group"
     buffers = fsutil.ife_getbuffers(groupf)
     pe = pwdmanip.parseGroupEntries(buffers[3])
     buffers[3] = pe
     fsutil.ife(buffers, lambda line: self._parseGroup(line, usrs))
     # Work on both shadow files
     shadowf = tmpsys + "etc/shadow"
     gshadowf = tmpsys + "etc/gshadow"
     buffers = fsutil.ife_getbuffers(shadowf)
     gbuffers = fsutil.ife_getbuffers(gshadowf)
     pe = pwdmanip.parseShadowEntries(buffers[3])
     buffers[3] = pe
     # If you look carefully (or just do a quick google search :P), you will notice that gshadow files
     # are very similar to group files, so we can just parse them as if they were group files
     pe = pwdmanip.parseGroupEntries(gbuffers[3])
     gbuffers[3] = pe
     logger.logVV(self.tn, logger.I, _("Removing users in /etc/shadow"))
     fsutil.ife(buffers, lambda line: self._parseShadow(line, usrs))
     logger.logVV(self.tn, logger.I, _("Removing users in /etc/gshadow"))
     fsutil.ife(gbuffers, lambda line: self._parseGroup(line, usrs))
     logger.logV(self.tn, logger.I, _("Creating backups"))
     shutil.copy2(tmpsys + "etc/passwd", tmpsys + "etc/passwd-")
     shutil.copy2(tmpsys + "etc/group", tmpsys + "etc/group-")
     shutil.copy2(tmpsys + "etc/shadow", tmpsys + "etc/shadow-")
     shutil.copy2(tmpsys + "etc/gshadow", tmpsys + "etc/gshadow-")
示例#42
0
def symlink(files, dst, tn=""):
    if not os.path.lexists(dst) and not os.path.exists(dst):
        logger.logVV(tn, logger.I, utilities.utf8all(_("Creating symlink"), " ", dst))
        os.symlink(files, dst)
示例#43
0
def symlink(files, dst, tn=""):
    if not os.path.lexists(dst) and not os.path.exists(dst):
        logger.logVV(tn, logger.I,
                     utilities.utf8all(_("Creating symlink"), " ", dst))
        os.symlink(files, dst)
示例#44
0
 def runthread(self):
     logger.logI(tn, logger.I, _("Generating compressed filesystem"))
     # Generate the SquashFS file
     # Options:
     # -b 1M                    Use a 1M blocksize (maximum)
     # -no-recovery             No recovery files
     # -always-use-fragments    Fragment blocks for files larger than the blocksize (1M)
     # -comp                    Compression type
     logger.logVV(tn, logger.I, _("Generating options"))
     opts = "-b 1M -no-recovery -no-duplicates -always-use-fragments"
     opts = opts + " -comp " + configutils.getValue(
         configs[configutils.sfscomp])
     opts = opts + " " + configutils.getValue(configs[configutils.sfsopts])
     sfsex = "dev etc home media mnt proc sys var run usr/lib/ubiquity/apt-setup/generators/40cdrom tmp"
     sfspath = isotreel + "casper/filesystem.squashfs"
     if os.path.exists(sfspath):
         fsutil.rm(sfspath)
     # This line would match the pattern below: [==========/              ]  70/300  20%
     patt = re.compile("^ *\[=*. *\] *[0-9]*/[0-9]* *([0-9]*)% *$")
     appnd = "32"
     if sys.maxsize > 2**32:
         appnd = "64"
     # Hack to make sure all output is given
     os.environ["LD_PRELOAD"] = os.path.split(
         os.path.realpath(__file__))[0] + "/isatty" + appnd + ".so"
     logger.logI(tn, logger.I,
                 _("Adding the edited /etc and /var to the filesystem"))
     logger.logI(tn, logger.I,
                 logger.MTab + _("This might take a couple of minutes"))
     sfscmd = subprocess.Popen(shlex.split("mksquashfs " + tmpsys + " " +
                                           sfspath + " " + opts),
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               universal_newlines=True)
     oldprogress = 0
     while sfscmd.poll() is None:
         output = sfscmd.stdout.readline()
         match = patt.match(output)
         if match is not None:
             sys.stdout.write("\r" + match.group(0))
             sys.stdout.flush()
             progress = int(match.group(1))
             if progress > oldprogress:
                 self.setProgress(tn,
                                  int(utilities.floatDivision(progress, 2)))
                 oldprogress = progress
         elif len(output.strip()) > 0:
             logger.logI(tn,
                         logger.I,
                         output.rstrip(),
                         noterm=True,
                         nogui=True)
     sys.stdout.write("\n")
     logger.logI(tn, logger.I,
                 _("Adding the rest of the system (this can take a while)"))
     sfscmd = subprocess.Popen(shlex.split("mksquashfs / " + sfspath + " " +
                                           opts + " -e " + sfsex),
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               universal_newlines=True)
     oldprogress = 0
     while sfscmd.poll() is None:
         output = sfscmd.stdout.readline()
         match = patt.match(output)
         if match is not None:
             sys.stdout.write("\r" + match.group(0))
             sys.stdout.flush()
             progress = int(match.group(1))
             if progress > oldprogress:
                 self.setProgress(
                     tn, 50 + int(utilities.floatDivision(progress, 2)))
                 oldprogress = progress
         elif len(output.strip()) > 0:
             logger.logI(tn,
                         logger.I,
                         output.rstrip(),
                         noterm=True,
                         nogui=True)
     sys.stdout.write("\n")
     os.environ["LD_PRELOAD"] = ""
     # Make sure the SquashFS file is OK
     doSFSChecks(sfspath,
                 int(configutils.getValue(configs[configutils.isolevel])))
     # Find the size after it is uncompressed
     logger.logV(tn, logger.I, _("Writing the size"))
     files = open(isotreel + "casper/filesystem.size", "w")
     files.write(str(fsutil.getSFSInstSize(sfspath)) + "\n")
     files.close()
示例#45
0
def threadLoop(threads1_, **options):
    logger.logV(tn, logger.D, "Running thread loop")
    # Remove pointers
    threads1 = copy.deepcopy(threads1_)
    # Initialization
    threadsdone = []
    threadsrunning = []
    threadids = []
    threads = []
    pslock = None
    pelock = None
    if "poststart" in options:
        pslock = threading.RLock()
        if "postend" in options and options["postend"] == options["poststart"]:
            pelock = pslock
    logger.logVV(tn, logger.D, "Check poststart")
    if "postend" in options and pelock == None:
        pelock = threading.RLock()
    logger.logVV(tn, logger.D, "Check postend")
    # Remove duplicates
    for i in threads1:
        if not i in threads:
            threads.append(i)
    logger.logVV(tn, logger.D, "Check remduplicates")
    addOptional(threads)
    # Generate the threads
    for i in range(len(threads)):
        temp_ = threads[i]["thread"]
        kw = {"tn": logger.genTN(threads[i]["tn"])}
        if "threadargs" in options:
            for x in options["threadargs"].keys():
                kw[x] = options["threadargs"][x]
        temp = temp_(**kw)
        threads[i]["thread"] = temp
    logger.logVV(tn, logger.D, "Check genthreads")
    # Generate the thread IDS
    for i in range(len(threads)):
        threadids.append(i)
    logger.logVV(tn, logger.D, "Check genthreadids")
    # Make sure thread dependencies are made as IDs, and not actual thread dictionaries
    for i in range(len(threads)):
        for x in range(len(threads[i]["deps"])):
            if threads[i]["deps"][x] in threads:
                for y in range(len(threads)):
                    if threads[i]["deps"][x] == threads[y]:
                        threads[i]["deps"][x] = y
                        break
    logger.logVV(tn, logger.D, "Check threaddeps")
    # Actual loop
    def _ActualLoop(threads, threadsdone, threadsrunning, threadids):
        logger.logVV(tn, logger.D, "Check ActualLoop")
        #global threads, threadsdone, threadsrunning, threadids
        while config.ThreadStop is False:
            # Clear old threads
            for x in threadsrunning:
                checkThread(x, threadsdone, threadsrunning, threads, pelock, **options)
            # End if all threads are done
            if len(threadsdone) >= len(threads):
                logger.logVV(tn, logger.D, "Ending ActualLoop")
                break
            # Run runnable threads
            for x in findRunnableThreads(threadids, threadsdone, threadsrunning, threads, **options):
                runThread(x, threadsdone, threadsrunning, threads, pslock, **options)
            time.sleep(float(1.0 / config.ThreadRPS))
    # Make a new thread (so that the user can continue on using relinux)
    t = threading.Thread(target = _ActualLoop, args = (threads, threadsdone, threadsrunning, threadids))
    t.start()