|
|
#-*- coding: utf-8 -*-
|
|
|
|
|
|
# Copyright 2008-2010 Calculate Ltd. http://www.calculate-linux.org
|
|
|
#
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
# You may obtain a copy of the License at
|
|
|
#
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
#
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
# See the License for the specific language governing permissions and
|
|
|
# limitations under the License.
|
|
|
|
|
|
|
|
|
import string
|
|
|
from random import choice
|
|
|
import os
|
|
|
import types
|
|
|
import subprocess
|
|
|
from subprocess import Popen,PIPE,STDOUT
|
|
|
import stat
|
|
|
from shutil import copytree, rmtree
|
|
|
import cl_overriding
|
|
|
import re
|
|
|
import sys
|
|
|
import getpass
|
|
|
from types import StringType
|
|
|
import magic as type_file
|
|
|
|
|
|
import cl_lang
|
|
|
tr = cl_lang.lang()
|
|
|
tr.setLocalDomain('cl_lib')
|
|
|
tr.setLanguage(sys.modules[__name__])
|
|
|
|
|
|
class _error:
|
|
|
# Здесь ошибки, если они есть
|
|
|
error = []
|
|
|
def getError(self):
|
|
|
"""Выдать ошибки"""
|
|
|
if not self.error:
|
|
|
return False
|
|
|
error = ""
|
|
|
for e in self.error:
|
|
|
error += e + "\n"
|
|
|
return error
|
|
|
|
|
|
def setError(self, error):
|
|
|
"""Установка ошибки"""
|
|
|
self.error.append(error)
|
|
|
return True
|
|
|
|
|
|
class _warning:
|
|
|
# Здесь предупреждения
|
|
|
warning = []
|
|
|
def getWarning(self):
|
|
|
"""Выдать ошибки"""
|
|
|
if not self.warning:
|
|
|
return False
|
|
|
warning = ""
|
|
|
for w in self.warning:
|
|
|
warning += w + "\n"
|
|
|
return warning
|
|
|
|
|
|
def setWarning(self, warning):
|
|
|
"""Установка ошибки"""
|
|
|
self.warning.append(warning)
|
|
|
return True
|
|
|
|
|
|
class typeFile:
|
|
|
"""Получение типа файла"""
|
|
|
|
|
|
def __init__(self, magic=0x410):
|
|
|
self.magicObject = type_file.open(type_file.MAGIC_NONE)
|
|
|
self.magicObject.load()
|
|
|
self.magicObject.setflags(magic)
|
|
|
|
|
|
def __del__(self):
|
|
|
"""Закрываем magic"""
|
|
|
self.magicObject.close()
|
|
|
|
|
|
def getMType(self, filename):
|
|
|
"""Информация о типе файла"""
|
|
|
return self.magicObject.file(filename)
|
|
|
|
|
|
def isBinary(self, filename):
|
|
|
"""является ли файл бинарным"""
|
|
|
mime = self.getMType(filename)
|
|
|
# В случае ошибки
|
|
|
if mime.count("`"):
|
|
|
return mime
|
|
|
elif mime.count("binary"):
|
|
|
return True
|
|
|
return False
|
|
|
|
|
|
class scanDirectory:
|
|
|
"""Класс для cканирования директории"""
|
|
|
|
|
|
def processingFile(self, path, prefix):
|
|
|
"""Обработка в случае файла"""
|
|
|
return True
|
|
|
|
|
|
def processingDirectory(self, path, prefix):
|
|
|
"""Обработка в случае директории если возвращаем None то пропуск дир."""
|
|
|
return True
|
|
|
|
|
|
def scanningDirectory(self, scanDir, skipFile=[], skipDir=[],
|
|
|
prefix=None, flagDir=False):
|
|
|
"""Сканирование и обработка шаблонов в директории scanDir"""
|
|
|
ret = True
|
|
|
if not prefix:
|
|
|
prefix = os.path.join(scanDir,"")[:-1]
|
|
|
if not flagDir:
|
|
|
# проверка корневой директории
|
|
|
retDir = self.processingDirectory(scanDir, scanDir)
|
|
|
if retDir is None:
|
|
|
return None
|
|
|
elif retDir is False:
|
|
|
return False
|
|
|
if flagDir or stat.S_ISDIR(os.lstat(scanDir)[stat.ST_MODE]):
|
|
|
for fileOrDir in sorted(os.listdir(scanDir)):
|
|
|
absPath = os.path.join(scanDir,fileOrDir)
|
|
|
relPath = absPath.split(prefix)[1]
|
|
|
stInfo = os.lstat(absPath)
|
|
|
statInfo = stInfo[stat.ST_MODE]
|
|
|
if stat.S_ISREG(statInfo):
|
|
|
# Обработка файла
|
|
|
if relPath in skipFile:
|
|
|
continue
|
|
|
if not self.processingFile(absPath, prefix):
|
|
|
ret = False
|
|
|
break
|
|
|
elif stat.S_ISDIR(statInfo):
|
|
|
# Обработка директории
|
|
|
if relPath in skipDir:
|
|
|
continue
|
|
|
retDir = self.processingDirectory(absPath, prefix)
|
|
|
if retDir is None:
|
|
|
continue
|
|
|
elif retDir is False:
|
|
|
ret = False
|
|
|
break
|
|
|
ret = self.scanningDirectory(absPath, skipFile,
|
|
|
skipDir, prefix, True)
|
|
|
if ret is False:
|
|
|
break
|
|
|
return ret
|
|
|
|
|
|
class process:
|
|
|
"""Execute system command by Popen
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
execute program and get result:
|
|
|
if process("/bin/gzip","/boot/somefile").success():
|
|
|
print "Gzip success"
|
|
|
|
|
|
unzip and process unzip data by cpio (list files):
|
|
|
processGzip = process("/bin/gzip","-dc","/boot/initrd")
|
|
|
processCpio = process("/bin/cpio","-tf",stdin=processGzip)
|
|
|
filelist = processCpio.readlines()
|
|
|
|
|
|
execute command and send data:
|
|
|
processGrub = process("/sbin/grub")
|
|
|
processGrub.write("root (hd0,0)\n")
|
|
|
processGrub.write("setup (hd0)\n")
|
|
|
processGrub.write("quit\n")
|
|
|
isok = processGrub.success()
|
|
|
|
|
|
union stdout and stderr:
|
|
|
process("/bin/ls","/",stderr=STDOUT)
|
|
|
|
|
|
result to stdout:
|
|
|
process("/bin/ls",stdout=None)
|
|
|
|
|
|
get data from keyboard:
|
|
|
process("/bin/cat",stdin=None)
|
|
|
"""
|
|
|
def __init__(self,command,*params,**kwarg):
|
|
|
if not "stdin" in kwarg:
|
|
|
stdin=self._defaultStdin
|
|
|
else:
|
|
|
if kwarg["stdin"] == None:
|
|
|
stdin = self._keyboardStdin
|
|
|
else:
|
|
|
stdin=kwarg["stdin"].getStdout
|
|
|
self.stdout = kwarg.get("stdout",PIPE)
|
|
|
self.envdict = kwarg.get("envdict",None)
|
|
|
|
|
|
self.stderr = kwarg.get("stderr",PIPE)
|
|
|
self.command = [command] + list(params)
|
|
|
self.stdin = stdin
|
|
|
self.iter = None
|
|
|
self.pipe = None
|
|
|
self.cacheresult = None
|
|
|
self.communicated = False
|
|
|
|
|
|
def _open(self):
|
|
|
"""Open pipe if it not open"""
|
|
|
if not self.pipe:
|
|
|
self.pipe = Popen(self.command,
|
|
|
stdout=self.stdout,
|
|
|
stdin=self.stdin(),
|
|
|
stderr=self.stderr,
|
|
|
env=self.envdict)
|
|
|
|
|
|
def _defaultStdin(self):
|
|
|
"""Return default stdin"""
|
|
|
return PIPE
|
|
|
|
|
|
def _keyboardStdin(self):
|
|
|
"""Return keyboard stdin"""
|
|
|
return None
|
|
|
|
|
|
def getStdout(self):
|
|
|
"""Get current stdout"""
|
|
|
self.close()
|
|
|
return self.pipe.stdout
|
|
|
|
|
|
def write(self,data):
|
|
|
"""Write to process stdin"""
|
|
|
self._open()
|
|
|
self.pipe.stdin.write(data)
|
|
|
self.pipe.stdin.flush()
|
|
|
|
|
|
def close(self):
|
|
|
"""Close stdin"""
|
|
|
if self.pipe:
|
|
|
self.pipe.stdin.close()
|
|
|
|
|
|
def read(self):
|
|
|
"""Read all data"""
|
|
|
try:
|
|
|
self._open()
|
|
|
if self.cacheresult is None:
|
|
|
self.cacheresult = self.pipe.communicate()[0]
|
|
|
return self.cacheresult
|
|
|
except KeyboardInterrupt:
|
|
|
self.kill()
|
|
|
raise KeyboardInterrupt
|
|
|
|
|
|
def readlines(self):
|
|
|
"""Read lines"""
|
|
|
return self.read().split('\n')
|
|
|
|
|
|
def __iter__(self):
|
|
|
"""Get iterator"""
|
|
|
if not self.iter:
|
|
|
self.iter = iter(self.readlines())
|
|
|
return self.iter
|
|
|
|
|
|
def kill(self):
|
|
|
"""Kill this process"""
|
|
|
if self.pipe:
|
|
|
self.pipe.kill()
|
|
|
|
|
|
def next(self):
|
|
|
"""Next string from stdout"""
|
|
|
return self.__iter__().next()
|
|
|
|
|
|
def returncode(self):
|
|
|
"""Get return code"""
|
|
|
self.read()
|
|
|
return self.pipe.returncode
|
|
|
|
|
|
def success(self):
|
|
|
"""Success or not"""
|
|
|
return self.returncode() == 0
|
|
|
|
|
|
def failed(self):
|
|
|
"""Failed or not"""
|
|
|
return self.returncode() != 0
|
|
|
|
|
|
class processProgress(process):
|
|
|
"""Execute system command by Popen for parse stdout."""
|
|
|
|
|
|
def __init__(self,command,*params,**kwarg):
|
|
|
process.__init__(self,command,*params,**kwarg)
|
|
|
self.readsize = kwarg.get("readsize",10)
|
|
|
self.init(**kwarg)
|
|
|
|
|
|
def init(self,**kwarg):
|
|
|
pass
|
|
|
|
|
|
def read(self):
|
|
|
"""Read data with parsing ability"""
|
|
|
try:
|
|
|
self.processInit()
|
|
|
self._open()
|
|
|
if self.cacheresult is None:
|
|
|
self.cacheresult = []
|
|
|
self.buf = ""
|
|
|
part = self.pipe.stdout.read(1)
|
|
|
while part:
|
|
|
if self.buf:
|
|
|
self.buf += part
|
|
|
else:
|
|
|
self.buf = part
|
|
|
if self.processStdout():
|
|
|
self.processDraw()
|
|
|
self.cacheresult.append(part)
|
|
|
part = self.pipe.stdout.read(self.readsize)
|
|
|
self.pipe.poll()
|
|
|
self.processEnd(self.success())
|
|
|
except KeyboardInterrupt:
|
|
|
self.cacheresult = "".join(self.cacheresult)
|
|
|
self.pipe.kill()
|
|
|
self.processEnd(False)
|
|
|
raise KeyboardInterrupt()
|
|
|
self.cacheresult = "".join(self.cacheresult)
|
|
|
return self.cacheresult
|
|
|
|
|
|
def processInit(self):
|
|
|
"""Called when read first byte"""
|
|
|
pass
|
|
|
|
|
|
def processDraw(self):
|
|
|
"""Called when processStdout return True"""
|
|
|
pass
|
|
|
|
|
|
def processStdout(self):
|
|
|
"""Called when read readsize byte from stdout"""
|
|
|
return True
|
|
|
|
|
|
def processEnd(self,res=True):
|
|
|
"""Called when process end"""
|
|
|
pass
|
|
|
|
|
|
def runOsCommand(cmd,in_str=None, env_dict=None):
|
|
|
"""Выполняет внешнюю программу
|
|
|
|
|
|
Параметры:
|
|
|
cmd внешняя программа
|
|
|
in_str данные передаваемые программе на страндартный вход.
|
|
|
env_dict словарь переменных окружения
|
|
|
Возвращает (код возврата, список stdout+stderr)
|
|
|
"""
|
|
|
pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE,
|
|
|
stdout=subprocess.PIPE,
|
|
|
stderr=subprocess.PIPE,
|
|
|
env=env_dict,
|
|
|
close_fds=True,
|
|
|
shell=True)
|
|
|
fout, fin, ferr = (pipe.stdout, pipe.stdin, pipe.stderr)
|
|
|
# если есть данные на вход, передать их
|
|
|
if in_str:
|
|
|
fin.write(in_str)
|
|
|
fin.close()
|
|
|
res = map(lambda x: x.rstrip(), fout.readlines())
|
|
|
fout.close()
|
|
|
res += map(lambda x: x.rstrip(), ferr.readlines())
|
|
|
ferr.close()
|
|
|
# Код возврата
|
|
|
retcode = pipe.wait()
|
|
|
return retcode, res
|
|
|
|
|
|
def genpassword(passlen=9):
|
|
|
'''Вернуть случайный набор символов указанной длины
|
|
|
|
|
|
Параметры:
|
|
|
passlen длина пароля который нужно сгенерировать
|
|
|
|
|
|
Возвращаемые параметры:
|
|
|
Сгенерированный пароль указанной длины
|
|
|
'''
|
|
|
res=''.join([choice(string.ascii_letters+string.digits)\
|
|
|
for i in xrange(passlen)])
|
|
|
return res
|
|
|
|
|
|
def fillstr(char, width):
|
|
|
'''Заполнить строку указанным числом символов. Псеводоним символ*кол-во'''
|
|
|
return str(char) * width
|
|
|
|
|
|
def getpathenv():
|
|
|
"""Вернуть пути для запуска утилит"""
|
|
|
bindir=['/sbin','/bin','/usr/sbin','/usr/bin']
|
|
|
env=os.environ
|
|
|
if env and env.has_key('PATH'):
|
|
|
lpath=env['PATH'].split(":")
|
|
|
npath=[]
|
|
|
for dirname in bindir:
|
|
|
if os.path.exists(dirname) and dirname not in lpath:
|
|
|
npath.append(dirname)
|
|
|
lpath=npath+lpath
|
|
|
return ":".join(lpath)
|
|
|
|
|
|
class MultiReplace:
|
|
|
"""MultiReplace function object
|
|
|
|
|
|
Usage:
|
|
|
replacer = MultiReplace({'str':'efg','in':'asd'})
|
|
|
s = replacer("string")
|
|
|
"""
|
|
|
def __init__(self, repl_dict):
|
|
|
# string to string mapping; use a regular expression
|
|
|
keys = repl_dict.keys()
|
|
|
keys.sort(reverse=True) # lexical order
|
|
|
pattern = u"|".join([re.escape(key) for key in keys])
|
|
|
self.pattern = re.compile(pattern)
|
|
|
self.dict = repl_dict
|
|
|
|
|
|
def replace(self, s):
|
|
|
# apply replacement dictionary to string
|
|
|
def repl(match, get=self.dict.get):
|
|
|
item = match.group(0)
|
|
|
return get(item, item)
|
|
|
return self.pattern.sub(repl, s)
|
|
|
__call__ = replace
|
|
|
|
|
|
def str2dict(s):
|
|
|
"""Convert string to dictionary:
|
|
|
|
|
|
String format:
|
|
|
{'key1':'value1','key2':'val\'ue2'}
|
|
|
"""
|
|
|
value = r'(?:\\\\|\\\'|[^\'])'
|
|
|
pair = r"""
|
|
|
\s*' # begin key
|
|
|
(%(v)s*)
|
|
|
' # end key
|
|
|
\s*:\s* # delimeter key/value
|
|
|
' # begin value
|
|
|
(%(v)s*)
|
|
|
'\s* # end value
|
|
|
""" % {"v":value}
|
|
|
reDict = re.compile(pair, re.X)
|
|
|
reMatchDict = re.compile("""
|
|
|
^{ # begin dict
|
|
|
((%(v)s,)* # many pair with comma at end
|
|
|
%(v)s)? # pair without comma
|
|
|
}$ # end dict
|
|
|
""" % {'v':pair}, re.X)
|
|
|
if reMatchDict.match(s.strip()):
|
|
|
d = dict(reDict.findall(s))
|
|
|
replaceSlash = MultiReplace({'\\\\':'\\','\\\'':'\''})
|
|
|
for i in d.keys():
|
|
|
d[i] = replaceSlash(d[i])
|
|
|
return d
|
|
|
else:
|
|
|
cl_overriding.printERROR(_("wrong dict value: %s"%s))
|
|
|
cl_overriding.exit(1)
|
|
|
|
|
|
def str2list(s):
|
|
|
"""Convert string to list:
|
|
|
|
|
|
String format:
|
|
|
['value1','val\'ue2']
|
|
|
"""
|
|
|
value = r'(?:\\\\|\\\'|[^\'])'
|
|
|
element = r"""
|
|
|
\s*' # begin value
|
|
|
(%(v)s*)
|
|
|
'\s* # end value
|
|
|
""" % {"v":value}
|
|
|
reList = re.compile(element, re.X)
|
|
|
reMatchList = re.compile("""
|
|
|
^\[ # begin dict
|
|
|
((%(v)s,)* # many elements with comma at end
|
|
|
%(v)s)? # element without comma
|
|
|
\]$ # end dict
|
|
|
""" % {'v':element}, re.X)
|
|
|
if reMatchList.match(s.strip()):
|
|
|
replaceSlash = MultiReplace({'\\\\':'\\','\\\'':'\''})
|
|
|
return [replaceSlash(i) for i in reList.findall(s)]
|
|
|
else:
|
|
|
cl_overriding.printERROR(_("wrong list value: %s"%s))
|
|
|
cl_overriding.exit(1)
|
|
|
|
|
|
def list2str(list):
|
|
|
"""Convert list to string
|
|
|
|
|
|
Return string with escaped \ and '.
|
|
|
"""
|
|
|
replaceSlash = MultiReplace({'\\':'\\\\','\'':'\\\''})
|
|
|
return "[%s]" % ','.join(["'%s'"%replaceSlash(str(i))
|
|
|
for i in list ])
|
|
|
|
|
|
def dict2str(dict):
|
|
|
"""Convert dictionry to string
|
|
|
|
|
|
Return string with escaped \ and '.
|
|
|
"""
|
|
|
replaceSlash = MultiReplace({'\\':'\\\\','\'':'\\\''})
|
|
|
return '{%s}' % ','.join(["'%s':'%s'" % (str(k),replaceSlash(str(v))) \
|
|
|
for (k,v) in dict.items()])
|
|
|
|
|
|
def convertStrListDict(val):
|
|
|
"""Convert data between string, list, dict"""
|
|
|
# if val is list
|
|
|
if type(val) == types.ListType:
|
|
|
return list2str(val)
|
|
|
# if val is dictionary
|
|
|
elif type(val) == types.DictType:
|
|
|
return dict2str(val)
|
|
|
# else it is string
|
|
|
else:
|
|
|
# detect dictionary
|
|
|
if re.match("^{.*}$",val):
|
|
|
return str2dict(val)
|
|
|
# detect list
|
|
|
elif re.match("^\[.*\]$",val):
|
|
|
return str2list(val)
|
|
|
# else is simple string
|
|
|
else:
|
|
|
return val
|
|
|
|
|
|
def _toUNICODE(val):
|
|
|
"""Convert text to unicode"""
|
|
|
if type(val) == types.UnicodeType:
|
|
|
return val
|
|
|
else:
|
|
|
return str(val).decode('UTF-8')
|
|
|
|
|
|
|
|
|
def getModeFile(nameFile, mode="all"):
|
|
|
"""Выдает информацию о файле
|
|
|
mode=="all"
|
|
|
права файла, владелец, группа файла
|
|
|
mode=="mode"
|
|
|
права файла
|
|
|
mode=="owner"
|
|
|
владелец, группа файла
|
|
|
"""
|
|
|
fst = os.lstat(nameFile)
|
|
|
if mode == "all":
|
|
|
return (stat.S_IMODE(fst.st_mode), fst.st_uid, fst.st_gid)
|
|
|
if mode == "mode":
|
|
|
return stat.S_IMODE(fst.st_mode)
|
|
|
if mode == "owner":
|
|
|
return fst.st_uid, fst.st_gid
|
|
|
|
|
|
|
|
|
def chownR(directory, uid, gid):
|
|
|
"""изменяет владельца и группу
|
|
|
|
|
|
для всех файлов и директорий внутри directory
|
|
|
"""
|
|
|
def chownPaths(rootPath, listPath, uid, gid):
|
|
|
for chPath in listPath:
|
|
|
chownPath = os.path.join(rootPath, chPath)
|
|
|
statInfo = os.lstat(chownPath)[stat.ST_MODE]
|
|
|
if stat.S_ISLNK(statInfo):
|
|
|
os.lchown(chownPath, uid, gid)
|
|
|
else:
|
|
|
os.chown(chownPath, uid, gid)
|
|
|
|
|
|
for root, dirs, files in os.walk(directory):
|
|
|
# меняем владельца директории
|
|
|
os.chown(root, uid, gid)
|
|
|
# Меняем владельца директорий
|
|
|
chownPaths(root, dirs, uid, gid)
|
|
|
# Меняем владельца файлов
|
|
|
chownPaths(root, files, uid, gid)
|
|
|
return True
|
|
|
|
|
|
def copyDir(srcDir, destDir):
|
|
|
"""Копируем директорию srcDir в destDir
|
|
|
|
|
|
При копировании сохраняются владелец, группа, права
|
|
|
"""
|
|
|
def ignoreFile(path, names):
|
|
|
"""Игнорирование сокетов при копировании"""
|
|
|
ignore = []
|
|
|
for name in names:
|
|
|
if stat.S_ISSOCK(os.lstat(os.path.join(path, name))[stat.ST_MODE]):
|
|
|
ignore.append(name)
|
|
|
return ignore
|
|
|
|
|
|
copytree(srcDir, destDir, ignore=ignoreFile)
|
|
|
return True
|
|
|
|
|
|
def removeDir(rmDir):
|
|
|
"""Рекурсивное удаление директории"""
|
|
|
rmtree(rmDir)
|
|
|
return True
|
|
|
|
|
|
def getRunCommands():
|
|
|
"""List run program"""
|
|
|
def getCmd(procNum):
|
|
|
cmdLineFile = '/proc/%s/cmdline'%procNum
|
|
|
try:
|
|
|
if os.path.exists(cmdLineFile):
|
|
|
return open(cmdLineFile,'r').read().strip()
|
|
|
except:
|
|
|
pass
|
|
|
return ""
|
|
|
if not os.access('/proc',os.R_OK):
|
|
|
return []
|
|
|
return map(getCmd,filter(lambda x:x.isdigit(),
|
|
|
os.listdir('/proc')))
|
|
|
|
|
|
def isFstabMount(pathname,mapDevUuid={}):
|
|
|
"""Get mount point or device from fstab"""
|
|
|
def removeQuotes(s):
|
|
|
return s.replace('"','').replace("'","")
|
|
|
if pathname == "swap":
|
|
|
absPath = "swap"
|
|
|
else:
|
|
|
absPath = os.path.abspath(pathname)
|
|
|
if not mapDevUuid:
|
|
|
devuuid = '/dev/disk/by-uuid'
|
|
|
mapDevUuid.update(
|
|
|
map(lambda x:("UUID=%s"%os.path.basename(x),
|
|
|
os.path.normpath(os.path.join(devuuid,os.readlink(x)))),
|
|
|
filter(os.path.islink,
|
|
|
map(lambda x:os.path.join(devuuid,x),
|
|
|
os.listdir(devuuid)))))
|
|
|
# convert fstab to
|
|
|
# [['/dev/sda3', '/', '', 'reiserfs', 'noatime', '', '', '0', '2\n'],
|
|
|
# ['/dev/sda5', '/var/calculate', 'reiserfs', 'noatime', '0', '0\n']]
|
|
|
listFstab = filter(lambda x: len(x) >= 4,
|
|
|
map(lambda x: filter(lambda x: x,
|
|
|
x.replace('\t',' ').split(' ')),
|
|
|
filter(lambda x: not x.startswith('#') and x.strip(),
|
|
|
open("/etc/fstab"))))
|
|
|
# get mount point or device or dir
|
|
|
return filter(lambda x: x!=absPath,
|
|
|
reduce(lambda x,y: y,
|
|
|
filter(lambda x: absPath in x and x[1] != "none",
|
|
|
map(lambda x: [mapDevUuid.get(removeQuotes(x[0]),x[0]),
|
|
|
x[1] if x[2] != "swap" else "swap"],
|
|
|
listFstab)),[""]))[0]
|
|
|
|
|
|
def isMount(path):
|
|
|
"""В случае монтирования директории выдает другой примонтированный путь"""
|
|
|
absPath = os.path.abspath(path)
|
|
|
mtabFile = '/etc/mtab'
|
|
|
if not os.access(mtabFile,os.R_OK):
|
|
|
return ""
|
|
|
return filter(lambda x: x!=absPath,
|
|
|
reduce(lambda x,y: y, filter(lambda x: absPath in x,
|
|
|
map(lambda x: [x[0], x[1]], map(lambda x: x.split(" "),
|
|
|
open(mtabFile)))),[""]))[0]
|
|
|
|
|
|
def commonPath(*paths):
|
|
|
"""Return common path from list of paths"""
|
|
|
paths = map(lambda x:os.path.normpath(x).split('/'),paths)
|
|
|
res = map(lambda x:x[0],
|
|
|
filter(lambda x:filter(lambda y:x[0]==y,x[1:]),zip(*paths)))
|
|
|
return "/".join(res)
|
|
|
|
|
|
def childMounts(path):
|
|
|
"""Get all mount points which contain path"""
|
|
|
if path != "none":
|
|
|
absPath = os.path.abspath(path)
|
|
|
else:
|
|
|
absPath = path
|
|
|
mtabFile = '/etc/mtab'
|
|
|
if not os.access(mtabFile,os.R_OK):
|
|
|
return ""
|
|
|
return reduce(lambda x,y: x + [y],
|
|
|
filter(lambda x: commonPath(absPath,x[0])==absPath or \
|
|
|
commonPath(absPath,x[1])==absPath,
|
|
|
map(lambda x: [x[0], x[1]],
|
|
|
map(lambda x: x.split(" "),
|
|
|
open(mtabFile)))),
|
|
|
[])
|
|
|
|
|
|
def pathJoin(*paths):
|
|
|
"""Складывает пути, в отличии от os.path.join, складывает абсолютные пути"""
|
|
|
if len(paths)==1:
|
|
|
return paths[0]
|
|
|
return reduce(os.path.join,
|
|
|
filter(lambda x:x and x != "/",
|
|
|
map(lambda x: x.startswith("/") and x[1:] or x,
|
|
|
paths[1:])),paths[0])
|
|
|
|
|
|
def getUserPassword(flag="dialog", pwDialog=False):
|
|
|
"""Получить пароль у пользователя
|
|
|
|
|
|
flag - опция "dalog" или "stdin" - откуда получаем пароль
|
|
|
pwDialog - структура для вывода приглашения в режиме диалога
|
|
|
"""
|
|
|
userPwd = ""
|
|
|
if flag == "dialog":
|
|
|
if not pwDialog:
|
|
|
pwDialog = [_("New password"),
|
|
|
_("Retype new password")]
|
|
|
pwdA = getpass.getpass(pwDialog[0]+":")
|
|
|
pwdB = getpass.getpass(pwDialog[1]+":")
|
|
|
elif flag == "stdin":
|
|
|
pwdA = sys.stdin.readline().rstrip()
|
|
|
pwdB = sys.stdin.readline().rstrip()
|
|
|
else:
|
|
|
cl_overriding.printERROR(_("ERROR in function getUserPassword, \
|
|
|
incorrect option 'flag=%s'")%flag)
|
|
|
return False
|
|
|
if not pwdA or not (pwdA == pwdB):
|
|
|
cl_overriding.printERROR(_("ERROR") + ": " +\
|
|
|
_("password incorrect")+ ": " + _("try again"))
|
|
|
return False
|
|
|
userPwd = pwdA
|
|
|
return userPwd
|
|
|
|
|
|
def cmpVersion(v1,v2):
|
|
|
"""Compare versions specified by tuple or string"""
|
|
|
if isinstance(v1,StringType):
|
|
|
v1 = getTupleVersion(v1)
|
|
|
if isinstance(v2,StringType):
|
|
|
v2 = getTupleVersion(v2)
|
|
|
return cmp((v1[0]+[0,]*(len(v2[0])-len(v1[0])),v1[1]),
|
|
|
(v2[0]+[0,]*(len(v1[0])-len(v2[0])),v2[1]))
|
|
|
|
|
|
def getTupleVersion(ver):
|
|
|
"""Get version specified by string as list:
|
|
|
Example:
|
|
|
2.6.30 [(2,6,30),('r',0)]
|
|
|
2.6.31-r1 [(2,6,31),('r',1)]
|
|
|
"""
|
|
|
suffix_value = {"pre": -2, "p": 0, "alpha": -4, "beta": -3,
|
|
|
"rc": -1}
|
|
|
def toTuple(v):
|
|
|
return map(lambda x: suffix_value[x] if x in suffix_value else x,
|
|
|
map(lambda x: int(x) if x.isdigit() else x,
|
|
|
re.findall("r\d+$|\d+|[a-zA-Z+]+",
|
|
|
v.replace('-SNAPSHOT',''))))
|
|
|
vers, revision = re.search("(^.*?)(-r\d+)?$",ver,re.S).groups()
|
|
|
vers = toTuple(vers)
|
|
|
revision = toTuple(revision or "r0")
|
|
|
return [vers,revision]
|
|
|
|
|
|
def appendProgramToEnvFile(nameProg, objVar):
|
|
|
"""Append name program to variable cl-merges and
|
|
|
|
|
|
save /etc/calculate/calculate.env """
|
|
|
if not objVar.AppendToList("cl_merges", nameProg, force=True):
|
|
|
return False
|
|
|
if not objVar.WriteList("cl_merges", force=True):
|
|
|
return False
|
|
|
return True
|
|
|
|
|
|
def removeProgramToEnvFile(nameProg, objVar):
|
|
|
"""Remove name program from variable cl-merges and save
|
|
|
|
|
|
/etc/calculate/calculate.env"""
|
|
|
if not objVar.RemoveToList("cl_merges", nameProg, force=True):
|
|
|
return False
|
|
|
if not objVar.WriteList("cl_merges", force=True):
|
|
|
return False
|
|
|
return True
|
|
|
|
|
|
def checkDigestFile(digestfile):
|
|
|
"""Check digest by digestfile"""
|
|
|
reEntry = re.compile(r"# (\S+) HASH\n(\S+) (\S+)",re.S)
|
|
|
result = []
|
|
|
for alg,hashdata,filename in \
|
|
|
reEntry.findall(open(digestfile,'r').read()):
|
|
|
if hasattr(hashlib,alg.lower()):
|
|
|
hashobj = getattr(hashlib,alg.lower())
|
|
|
filename = os.path.join(os.path.dirname(digestfile),filename)
|
|
|
if os.path.exists(filename):
|
|
|
digest = hashobj(open(filename,'r').read())
|
|
|
result.append((alg,
|
|
|
digest.hexdigest().upper() == hashdata.upper()))
|
|
|
return result
|
|
|
|
|
|
def getFilesCount(directory):
|
|
|
"""Get files count from directory"""
|
|
|
if os.path.exists(directory):
|
|
|
return len(reduce(lambda x,y:x+y,map(lambda x:x[1]+x[2],
|
|
|
os.walk(directory)),[]))
|
|
|
return 0
|