You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1523 regels
50 KiB

  1. #-*- coding: utf-8 -*-
  2. # Copyright 2008-2010 Calculate Ltd. http://www.calculate-linux.org
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import string
  16. from random import choice
  17. import os
  18. from os import path
  19. import types
  20. import subprocess
  21. from subprocess import Popen,PIPE,STDOUT
  22. import stat
  23. from shutil import copytree, rmtree
  24. import cl_overriding
  25. import re
  26. import sys
  27. import getpass
  28. from types import StringType
  29. import tarfile
  30. try:
  31. from magic import (open as type_file, MAGIC_NONE as MAGIC_NONE,
  32. MAGIC_CONTINUE)
  33. except ImportError:
  34. try:
  35. from magic import (open as type_file, NONE as MAGIC_NONE,
  36. CONTINUE as MAGIC_CONTINUE)
  37. except:
  38. type_file = None
  39. MAGIC_NONE = None
  40. MAGIC_CONTINUE = None
  41. import cl_lang
  42. tr = cl_lang.lang()
  43. tr.setLocalDomain('cl_lib')
  44. tr.setLanguage(sys.modules[__name__])
  45. class _error:
  46. # Здесь ошибки, если они есть
  47. error = []
  48. def getError(self):
  49. """Выдать ошибки"""
  50. if not self.error:
  51. return False
  52. error = ""
  53. for e in self.error:
  54. error += e + "\n"
  55. return error
  56. def setError(self, error):
  57. """Установка ошибки"""
  58. self.error.append(error)
  59. return True
  60. class _warning:
  61. # Здесь предупреждения
  62. warning = []
  63. def getWarning(self):
  64. """Выдать ошибки"""
  65. if not self.warning:
  66. return False
  67. warning = ""
  68. for w in self.warning:
  69. warning += w + "\n"
  70. return warning
  71. def setWarning(self, warning):
  72. """Установка ошибки"""
  73. self.warning.append(warning)
  74. return True
  75. class proxy_type_file:
  76. def __init__(self,flags):
  77. self.flags = flags
  78. def load(self):
  79. pass
  80. def setflags(self,flags):
  81. self.flags = flags
  82. def close(self):
  83. pass
  84. def file(self,filename):
  85. if path.exists(filename):
  86. if self.flags == 0x410:
  87. processFile = process("file","-bi",filename)
  88. if processFile.success():
  89. return processFile.read().rstrip()
  90. else:
  91. processFile = process("file","-bkz",filename)
  92. if processFile.success():
  93. return processFile.read().rstrip()
  94. return None
  95. class typeFile:
  96. """Получение типа файла"""
  97. def __init__(self, magic=0x410):
  98. if type_file is None:
  99. self.magicObject = proxy_type_file(MAGIC_NONE)
  100. else:
  101. self.magicObject = type_file(MAGIC_NONE)
  102. self.magicObject.load()
  103. self.magicObject.setflags(magic)
  104. def __del__(self):
  105. """Закрываем magic"""
  106. self.magicObject.close()
  107. def getMType(self, filename):
  108. """Информация о типе файла"""
  109. try:
  110. ret = self.magicObject.file(filename)
  111. except UnicodeDecodeError:
  112. try:
  113. ret = self.magicObject.file(filename.decode('utf-8'))
  114. except UnicodeDecodeError:
  115. return None
  116. # fix for kernel 3.7.7 (bad work samba with big files)
  117. if ret is None and self.magicObject.errno() == 5:
  118. r,w = os.pipe()
  119. devnull = os.open(os.devnull,os.O_WRONLY)
  120. cat = subprocess.Popen(['/bin/cat',filename],stdout=w,
  121. stderr=devnull,close_fds=True)
  122. ret = self.magicObject.descriptor(r)
  123. os.close(w)
  124. os.close(devnull)
  125. cat.wait()
  126. return ret
  127. def isBinary(self, filename):
  128. """является ли файл бинарным"""
  129. mime = self.getMType(filename)
  130. # В случае ошибки
  131. if mime.count("`"):
  132. return mime
  133. elif mime.count("binary"):
  134. return True
  135. return False
  136. class scanDirectory:
  137. """Класс для cканирования директории"""
  138. def processingFile(self, pathname, prefix):
  139. """Обработка в случае файла"""
  140. return True
  141. def processingDirectory(self, pathname, prefix):
  142. """Обработка в случае директории если возвращаем None то пропуск дир."""
  143. return True
  144. def scanningDirectory(self, scanDir, skipFile=[], skipDir=[],
  145. prefix=None, flagDir=False):
  146. """Сканирование и обработка шаблонов в директории scanDir"""
  147. ret = True
  148. if not prefix:
  149. prefix = path.join(scanDir,"")[:-1]
  150. if not flagDir:
  151. # проверка корневой директории
  152. retDir = self.processingDirectory(scanDir, scanDir)
  153. if retDir is None:
  154. return None
  155. elif retDir is False:
  156. return False
  157. if flagDir or stat.S_ISDIR(os.lstat(scanDir)[stat.ST_MODE]):
  158. for absPath in sorted(listDirectory(scanDir,fullPath=True)):
  159. relPath = absPath.split(prefix)[1]
  160. stInfo = os.lstat(absPath)
  161. statInfo = stInfo[stat.ST_MODE]
  162. if stat.S_ISREG(statInfo):
  163. # Обработка файла
  164. if relPath in skipFile:
  165. continue
  166. if not self.processingFile(absPath, prefix):
  167. return False
  168. elif stat.S_ISDIR(statInfo):
  169. # Обработка директории
  170. if relPath in skipDir:
  171. continue
  172. retDir = self.processingDirectory(absPath, prefix)
  173. if retDir is None:
  174. continue
  175. elif retDir is False:
  176. return False
  177. ret = self.scanningDirectory(absPath, skipFile,
  178. skipDir, prefix, True)
  179. if ret is False:
  180. return False
  181. return ret
  182. class process:
  183. """Execute system command by Popen
  184. Examples:
  185. execute program and get result:
  186. if process("/bin/gzip","/boot/somefile").success():
  187. print "Gzip success"
  188. unzip and process unzip data by cpio (list files):
  189. processGzip = process("/bin/gzip","-dc","/boot/initrd")
  190. processCpio = process("/bin/cpio","-tf",stdin=processGzip)
  191. filelist = processCpio.readlines()
  192. execute command and send data:
  193. processGrub = process("/sbin/grub")
  194. processGrub.write("root (hd0,0)\n")
  195. processGrub.write("setup (hd0)\n")
  196. processGrub.write("quit\n")
  197. isok = processGrub.success()
  198. union stdout and stderr:
  199. process("/bin/ls","/",stderr=STDOUT)
  200. result to stdout:
  201. process("/bin/ls",stdout=None)
  202. get data from keyboard:
  203. process("/bin/cat",stdin=None)
  204. """
  205. def __init__(self,command,*params,**kwarg):
  206. if not "stdin" in kwarg:
  207. stdin=self._defaultStdin
  208. else:
  209. if kwarg["stdin"] == None:
  210. stdin = self._keyboardStdin
  211. else:
  212. stdin=kwarg["stdin"].getStdout
  213. self.stdout = kwarg.get("stdout",PIPE)
  214. self.envdict = kwarg.get("envdict",{})
  215. if "lang" in kwarg:
  216. self.envdict["LANG"] = kwarg.get('lang')
  217. self.langc = "langc" in kwarg
  218. self.stderr = kwarg.get("stderr",PIPE)
  219. self.command = [command] + list(params)
  220. self.stdin = stdin
  221. self.iter = None
  222. self.pipe = None
  223. self.cacheresult = None
  224. self.communicated = False
  225. def _open(self):
  226. """Open pipe if it not open"""
  227. if not self.pipe:
  228. self.pipe = Popen(self.command,
  229. stdout=self.stdout,
  230. stdin=self.stdin(),
  231. stderr=self.stderr,
  232. env=self.envdict)
  233. def _defaultStdin(self):
  234. """Return default stdin"""
  235. return PIPE
  236. def _keyboardStdin(self):
  237. """Return keyboard stdin"""
  238. return None
  239. def getStdout(self):
  240. """Get current stdout"""
  241. self.close()
  242. self._open()
  243. return self.pipe.stdout
  244. def write(self,data):
  245. """Write to process stdin"""
  246. self._open()
  247. self.pipe.stdin.write(data)
  248. self.pipe.stdin.flush()
  249. def close(self):
  250. """Close stdin"""
  251. if self.pipe:
  252. self.pipe.stdin.close()
  253. def read(self):
  254. """Read all data"""
  255. try:
  256. self._open()
  257. if self.cacheresult is None:
  258. self.cacheresult = self.pipe.communicate()[0]
  259. return self.cacheresult
  260. except KeyboardInterrupt:
  261. self.kill()
  262. raise KeyboardInterrupt
  263. def readlines(self):
  264. """Read lines"""
  265. return self.read().split('\n')
  266. def __iter__(self):
  267. """Get iterator"""
  268. if not self.iter:
  269. self.iter = iter(self.readlines())
  270. return self.iter
  271. def kill(self):
  272. """Kill this process"""
  273. if self.pipe:
  274. self.pipe.kill()
  275. def next(self):
  276. """Next string from stdout"""
  277. return self.__iter__().next()
  278. def returncode(self):
  279. """Get return code"""
  280. self.read()
  281. return self.pipe.returncode
  282. def success(self):
  283. """Success or not"""
  284. return self.returncode() == 0
  285. def failed(self):
  286. """Failed or not"""
  287. return self.returncode() != 0
  288. class processProgress(process):
  289. """Execute system command by Popen for parse stdout."""
  290. def __init__(self,command,*params,**kwarg):
  291. process.__init__(self,command,*params,**kwarg)
  292. self.readsize = kwarg.get("readsize",10)
  293. self.init(**kwarg)
  294. def init(self,**kwarg):
  295. pass
  296. def read(self):
  297. """Read data with parsing ability"""
  298. try:
  299. self.processInit()
  300. self._open()
  301. if self.cacheresult is None:
  302. self.cacheresult = []
  303. self.buf = ""
  304. part = self.pipe.stdout.read(1)
  305. while part:
  306. if self.buf:
  307. self.buf += part
  308. else:
  309. self.buf = part
  310. if self.processStdout():
  311. self.processDraw()
  312. self.cacheresult.append(part)
  313. part = self.pipe.stdout.read(self.readsize)
  314. self.pipe.poll()
  315. self.processEnd(self.success())
  316. except KeyboardInterrupt:
  317. self.cacheresult = "".join(self.cacheresult)
  318. self.pipe.kill()
  319. self.processEnd(False)
  320. raise KeyboardInterrupt()
  321. self.cacheresult = "".join(self.cacheresult)
  322. return self.cacheresult
  323. def processInit(self):
  324. """Called when read first byte"""
  325. pass
  326. def processDraw(self):
  327. """Called when processStdout return True"""
  328. pass
  329. def processStdout(self):
  330. """Called when read readsize byte from stdout"""
  331. return True
  332. def processEnd(self,res=True):
  333. """Called when process end"""
  334. pass
  335. def runOsCommand(cmd,in_str=None, env_dict=None):
  336. """Run system command
  337. Параметры:
  338. cmd внешняя программа
  339. in_str данные передаваемые программе на страндартный вход.
  340. env_dict словарь переменных окружения
  341. Возвращает (код возврата, список stdout+stderr)
  342. """
  343. pipe = subprocess.Popen(cmd, stdin=subprocess.PIPE,
  344. stdout=subprocess.PIPE,
  345. stderr=subprocess.PIPE,
  346. env=env_dict,
  347. close_fds=True,
  348. shell=True)
  349. fout, fin, ferr = (pipe.stdout, pipe.stdin, pipe.stderr)
  350. # если есть данные на вход, передать их
  351. if in_str:
  352. fin.write(in_str)
  353. fin.close()
  354. res = map(lambda x: x.rstrip(), fout.readlines())
  355. fout.close()
  356. res += map(lambda x: x.rstrip(), ferr.readlines())
  357. ferr.close()
  358. # Код возврата
  359. retcode = pipe.wait()
  360. return retcode, res
  361. def genpassword(passlen=9):
  362. """Return random charset specified lenght (passlen)"""
  363. return ''.join(map(lambda x:choice(string.ascii_letters+string.digits),
  364. xrange(0,passlen)))
  365. def getpathenv():
  366. """Return path for run utilities"""
  367. bindir=set(filter(path.exists,
  368. ['/sbin','/bin','/usr/sbin','/usr/bin']))
  369. env=os.environ
  370. envPath = set(env.get('PATH','').split(":")) | bindir
  371. return ":".join(envPath)
  372. class MultiReplace:
  373. """MultiReplace function object
  374. Usage:
  375. replacer = MultiReplace({'str':'efg','in':'asd'})
  376. s = replacer("string")
  377. """
  378. def __init__(self, repl_dict):
  379. # string to string mapping; use a regular expression
  380. keys = repl_dict.keys()
  381. keys.sort(reverse=True) # lexical order
  382. pattern = u"|".join([re.escape(key) for key in keys])
  383. self.pattern = re.compile(pattern)
  384. self.dict = repl_dict
  385. def replace(self, s):
  386. # apply replacement dictionary to string
  387. def repl(match, get=self.dict.get):
  388. item = match.group(0)
  389. return get(item, item)
  390. return self.pattern.sub(repl, s)
  391. __call__ = replace
  392. def str2dict(s):
  393. """Convert string to dictionary:
  394. String format:
  395. {'key1':'value1','key2':'val\'ue2'}
  396. """
  397. value = r'(?:\\\\|\\\'|[^\'])'
  398. pair = r"""
  399. \s*' # begin key
  400. (%(v)s*)
  401. ' # end key
  402. \s*:\s* # delimeter key/value
  403. ' # begin value
  404. (%(v)s*)
  405. '\s* # end value
  406. """ % {"v":value}
  407. reDict = re.compile(pair, re.X)
  408. reMatchDict = re.compile("""
  409. ^{ # begin dict
  410. ((%(v)s,)* # many pair with comma at end
  411. %(v)s)? # pair without comma
  412. }$ # end dict
  413. """ % {'v':pair}, re.X)
  414. if reMatchDict.match(s.strip()):
  415. d = dict(reDict.findall(s))
  416. replaceSlash = MultiReplace({'\\\\':'\\','\\\'':'\''})
  417. for i in d.keys():
  418. d[i] = replaceSlash(d[i])
  419. return d
  420. else:
  421. cl_overriding.printERROR(_("wrong dictionary value: %s"%s))
  422. cl_overriding.exit(1)
  423. def str2list(s):
  424. """Convert string to list:
  425. String format:
  426. ['value1','val\'ue2']
  427. """
  428. value = r'(?:\\\\|\\\'|[^\'])'
  429. element = r"""
  430. \s*' # begin value
  431. (%(v)s*)
  432. '\s* # end value
  433. """ % {"v":value}
  434. reList = re.compile(element, re.X)
  435. reMatchList = re.compile("""
  436. ^\[ # begin dict
  437. ((%(v)s,)* # many elements with comma at end
  438. %(v)s)? # element without comma
  439. \]$ # end dict
  440. """ % {'v':element}, re.X)
  441. if reMatchList.match(s.strip()):
  442. replaceSlash = MultiReplace({'\\\\':'\\','\\\'':'\''})
  443. return [replaceSlash(i) for i in reList.findall(s)]
  444. else:
  445. cl_overriding.printERROR(_("wrong list value: %s"%s))
  446. cl_overriding.exit(1)
  447. def list2str(list):
  448. """Convert list to string
  449. Return string with escaped \ and '.
  450. """
  451. replaceSlash = MultiReplace({'\\':'\\\\','\'':'\\\''})
  452. return "[%s]" % ','.join(["'%s'"%replaceSlash(str(i))
  453. for i in list ])
  454. def dict2str(dict):
  455. """Convert dictionry to string
  456. Return string with escaped \ and '.
  457. """
  458. replaceSlash = MultiReplace({'\\':'\\\\','\'':'\\\''})
  459. return '{%s}' % ','.join(["'%s':'%s'" % (str(k),replaceSlash(str(v))) \
  460. for (k,v) in dict.items()])
  461. def convertStrListDict(val):
  462. """Convert data between string, list, dict"""
  463. # if val is list
  464. if type(val) == types.ListType:
  465. return list2str(val)
  466. # if val is dictionary
  467. elif type(val) == types.DictType:
  468. return dict2str(val)
  469. # else it is string
  470. else:
  471. # detect dictionary
  472. if re.match("^{.*}$",val):
  473. return str2dict(val)
  474. # detect list
  475. elif re.match("^\[.*\]$",val):
  476. return str2list(val)
  477. # else is simple string
  478. else:
  479. return val
  480. def _toUNICODE(val):
  481. """Convert text to unicode"""
  482. if type(val) == types.UnicodeType:
  483. return val
  484. else:
  485. return str(val).decode('UTF-8')
  486. def getModeFile(nameFile, mode="all"):
  487. """Выдает информацию о файле
  488. mode=="all"
  489. права файла, владелец, группа файла
  490. mode=="mode"
  491. права файла
  492. mode=="owner"
  493. владелец, группа файла
  494. """
  495. fst = os.lstat(nameFile)
  496. if mode == "all":
  497. return (stat.S_IMODE(fst.st_mode), fst.st_uid, fst.st_gid)
  498. if mode == "mode":
  499. return stat.S_IMODE(fst.st_mode)
  500. if mode == "owner":
  501. return fst.st_uid, fst.st_gid
  502. def chownR(directory, uid, gid):
  503. """Recusive chown"""
  504. def chownPaths(rootPath, listPath, uid, gid):
  505. for chPath in listPath:
  506. chownPath = path.join(rootPath, chPath)
  507. statInfo = os.lstat(chownPath)[stat.ST_MODE]
  508. if stat.S_ISLNK(statInfo):
  509. os.lchown(chownPath, uid, gid)
  510. else:
  511. os.chown(chownPath, uid, gid)
  512. for root, dirs, files in os.walk(directory):
  513. # меняем владельца директории
  514. os.chown(root, uid, gid)
  515. # Меняем владельца директорий
  516. chownPaths(root, dirs, uid, gid)
  517. # Меняем владельца файлов
  518. chownPaths(root, files, uid, gid)
  519. return True
  520. def copyDir(srcDir, destDir):
  521. """Копируем директорию srcDir в destDir
  522. При копировании сохраняются владелец, группа, права
  523. """
  524. def ignoreFile(pathname, names):
  525. """Игнорирование сокетов при копировании"""
  526. ignore = []
  527. for name in names:
  528. if stat.S_ISSOCK(os.lstat(path.join(pathname, name))[stat.ST_MODE]):
  529. ignore.append(name)
  530. return ignore
  531. copytree(srcDir, destDir, ignore=ignoreFile)
  532. return True
  533. def removeDir(rmDir):
  534. """Рекурсивное удаление директории"""
  535. rmtree(rmDir)
  536. return True
  537. def getRunCommands():
  538. """List run program"""
  539. def getCmd(procNum):
  540. cmdLineFile = '/proc/%s/cmdline'%procNum
  541. try:
  542. if path.exists(cmdLineFile):
  543. return open(cmdLineFile,'r').read().strip()
  544. except:
  545. pass
  546. return ""
  547. if not os.access('/proc',os.R_OK):
  548. return []
  549. return map(getCmd,
  550. filter(lambda x:x.isdigit(),
  551. listDirectory('/proc')))
  552. def isFstabMount(pathname,mapDevUuid={},listFstab=[]):
  553. """Get mount point or device from fstab"""
  554. def removeQuotes(s):
  555. return s.replace('"','').replace("'","")
  556. if pathname == "swap":
  557. absPath = "swap"
  558. else:
  559. absPath = path.abspath(pathname)
  560. if not mapDevUuid:
  561. mapDevUuid.update(getUUIDDict())
  562. # convert fstab to
  563. # [['/dev/sda3', '/', '', 'reiserfs', 'noatime', '', '', '0', '2\n'],
  564. # ['/dev/sda5', '/var/calculate', 'reiserfs', 'noatime', '0', '0\n']]
  565. #if not listFstab:
  566. if not listFstab:
  567. listFstab.extend(
  568. map(lambda x: [mapDevUuid.get(removeQuotes(x[0]),x[0]),
  569. x[1] if x[2] != "swap" else "swap"],
  570. filter(lambda x: len(x) >= 4,
  571. map(lambda x: filter(lambda x: x,
  572. x.replace('\t',' ').split(' ')),
  573. filter(lambda x: not x.startswith('#') and x.strip(),
  574. open("/etc/fstab"))))))
  575. # get mount point or device or dir
  576. return filter(lambda x: x!=absPath,
  577. reduce(lambda x,y: y,
  578. filter(lambda x: absPath in x and x[1] != "none",
  579. listFstab),[""]))[0]
  580. class SingletonParam(type):
  581. def __init__(cls, name, bases, dict):
  582. super(SingletonParam, cls).__init__(name, bases, dict)
  583. cls.instance = {}
  584. def __call__(cls,*args,**kw):
  585. keyarg = args[0] if args else ""
  586. if not keyarg in cls.instance:
  587. cls.instance[keyarg] = \
  588. super(SingletonParam, cls).__call__(*args, **kw)
  589. return cls.instance[keyarg]
  590. class FStab(object):
  591. """Data reader for fstab"""
  592. __metaclass__ = SingletonParam
  593. fstab_file = '/etc/fstab'
  594. NAME, DIR, TYPE, OPTS, FREQ, PASSNO = range(0,6)
  595. def __init__(self,fstab_file=None):
  596. if fstab_file:
  597. self.fstab_file = fstab_file
  598. self.cache = []
  599. self.rotateCache = []
  600. self.dictUUID = getUUIDDict()
  601. self.rebuildCache()
  602. def rebuildCache(self):
  603. """Rebuild cache from fstab file"""
  604. self.cache = \
  605. map(lambda x:map(lambda y:y.strip(),x.split()),
  606. filter(lambda x:x and not x.lstrip().startswith("#"),
  607. open(self.fstab_file,'r').read().split('\n')))
  608. for data in self.cache:
  609. convertDev = lambda x: path.realpath(x) if x.startswith('/') else x
  610. data[0] = getUdevDeviceInfo(
  611. name=convertDev(self.dictUUID.get(data[0],data[0]))
  612. ).get('DEVNAME','')
  613. data[1] = data[1] if data[2] != "swap" else "swap"
  614. self.rotateCache = zip(*self.cache)
  615. def getBy(self,what=DIR,where=NAME,eq=None,noteq=None,allentry=False):
  616. """Get data from fstab"""
  617. if not eq is None:
  618. filterfunc = lambda x: x[where] == eq
  619. else:
  620. filterfunc = lambda x: x[where] != noteq
  621. res = map(lambda x:x[what],filter(filterfunc,self.cache))
  622. if allentry:
  623. return res
  624. else:
  625. return "" if not res else res[-1]
  626. def getFields(self,*fields):
  627. """Get all data by specifie fields"""
  628. return zip(*reduce(lambda x,y:x+[self.rotateCache[y]],fields,[]))
  629. def isExists(self,what=DIR,eq=None,noteq=None):
  630. """Field with condition exist in fstab"""
  631. if not eq is None:
  632. filterfunc = lambda x: x[what] == eq
  633. else:
  634. filterfunc = lambda x: x[what] != noteq
  635. return bool(filter(filterfunc,self.cache))
  636. def isMount(pathname):
  637. """В случае монтирования директории выдает другой примонтированный путь"""
  638. absPath = path.abspath(pathname)
  639. mtabFile = '/etc/mtab'
  640. if not os.access(mtabFile,os.R_OK):
  641. return ""
  642. return filter(lambda x: x!=absPath,
  643. reduce(lambda x,y: y,
  644. filter(lambda x: absPath in x,
  645. map(lambda x: [x[0], x[1]],
  646. map(lambda x: x.split(" "),
  647. open(mtabFile)))), [""]))[0]
  648. def commonPath(*paths):
  649. """Return common path from list of paths"""
  650. paths = map(lambda x:path.normpath(x).split('/'),paths)
  651. res = map(lambda x:x[0],
  652. filter(lambda x:filter(lambda y:x[0]==y,x[1:]),zip(*paths)))
  653. return "/".join(res)
  654. def childMounts(pathname):
  655. """Get all mount points which contain path"""
  656. if pathname != "none":
  657. absPath = path.abspath(pathname)
  658. else:
  659. absPath = pathname
  660. mtabFile = '/etc/mtab'
  661. if not os.access(mtabFile,os.R_OK):
  662. return ""
  663. return reduce(lambda x,y: x + [y],
  664. filter(lambda x: commonPath(absPath,x[0])==absPath or \
  665. commonPath(absPath,x[1])==absPath,
  666. map(lambda x: [x[0], x[1]],
  667. map(lambda x: x.split(" "),
  668. open(mtabFile)))),
  669. [])
  670. def pathJoin(*paths):
  671. """Складывает пути, в отличии от os.path.join, складывает абсолютные пути"""
  672. if len(paths)==1:
  673. return paths[0]
  674. return reduce(path.join,
  675. filter(lambda x:x and x != "/",
  676. map(lambda x: x.startswith("/") and x[1:] or x,
  677. paths[1:])),paths[0])
  678. def getUserPassword(flag="dialog", pwDialog=False):
  679. """Получить пароль у пользователя
  680. flag - опция "dalog" или "stdin" - откуда получаем пароль
  681. pwDialog - структура для вывода приглашения в режиме диалога
  682. """
  683. userPwd = ""
  684. if flag == "dialog":
  685. if not pwDialog:
  686. pwDialog = [_("New password"),
  687. _("Retype the new password")]
  688. pwdA = getpass.getpass(pwDialog[0]+":")
  689. pwdB = getpass.getpass(pwDialog[1]+":")
  690. elif flag == "stdin":
  691. pwdA = sys.stdin.readline().rstrip()
  692. pwdB = sys.stdin.readline().rstrip()
  693. else:
  694. cl_overriding.printERROR(_("ERROR in function getUserPassword, \
  695. incorrect option 'flag=%s'")%flag)
  696. return False
  697. if not pwdA or not (pwdA == pwdB):
  698. cl_overriding.printERROR(_("ERROR") + ": " +\
  699. _("wrong password")+ ": " + _("try again"))
  700. return False
  701. userPwd = pwdA
  702. return userPwd
  703. def cmpVersion(v1,v2):
  704. """Compare versions specified by tuple or string"""
  705. if isinstance(v1,StringType):
  706. v1 = getTupleVersion(v1)
  707. if isinstance(v2,StringType):
  708. v2 = getTupleVersion(v2)
  709. return cmp((v1[0]+[0,]*(len(v2[0])-len(v1[0])),v1[1]),
  710. (v2[0]+[0,]*(len(v1[0])-len(v2[0])),v2[1]))
  711. def getTupleVersion(ver):
  712. """Get version specified by string as list:
  713. Example:
  714. 2.6.30 [(2,6,30),('r',0)]
  715. 2.6.31-r1 [(2,6,31),('r',1)]
  716. """
  717. suffix_value = {"pre": -2, "p": 0, "alpha": -4, "beta": -3,
  718. "rc": -1}
  719. def toTuple(v):
  720. return map(lambda x: suffix_value[x] if x in suffix_value else x,
  721. map(lambda x: int(x) if x.isdigit() else x,
  722. re.findall("r\d+$|\d+|[a-zA-Z+]+",
  723. v.replace('-SNAPSHOT',''))))
  724. vers, revision = re.search("(^.*?)(-r\d+)?$",ver,re.S).groups()
  725. vers = toTuple(vers)
  726. revision = toTuple(revision or "r0")
  727. return [vers,revision]
  728. def appendProgramToEnvFile(nameProg, objVar):
  729. """Append name program to variable cl-merges and
  730. save /etc/calculate/calculate.env """
  731. if not objVar.AppendToList("cl_merges", nameProg, force=True):
  732. return False
  733. if not objVar.WriteList("cl_merges", force=True):
  734. return False
  735. return True
  736. def removeProgramToEnvFile(nameProg, objVar):
  737. """Remove name program from variable cl-merges and save
  738. /etc/calculate/calculate.env"""
  739. if not objVar.RemoveToList("cl_merges", nameProg, force=True):
  740. return False
  741. if not objVar.WriteList("cl_merges", force=True):
  742. return False
  743. return True
  744. def checkDigestFile(digestfile):
  745. """Check digest by digestfile"""
  746. reEntry = re.compile(r"# (\S+) HASH\n(\S+) (\S+)",re.S)
  747. result = []
  748. for alg,hashdata,filename in \
  749. reEntry.findall(open(digestfile,'r').read()):
  750. if hasattr(hashlib,alg.lower()):
  751. hashobj = getattr(hashlib,alg.lower())
  752. filename = path.join(path.dirname(digestfile),filename)
  753. if os.path.exists(filename):
  754. digest = hashobj(open(filename,'r').read())
  755. result.append((alg,
  756. digest.hexdigest().upper() == hashdata.upper()))
  757. return result
  758. def getFilesCount(directory):
  759. """Get files count from directory"""
  760. if path.exists(directory):
  761. return reduce(lambda x,y:x+len(y[1])+len(y[2]),
  762. os.walk(directory),0)
  763. return 0
  764. def listDirectory(directory,fullPath=False):
  765. """Get files from directory, if it exists"""
  766. if not path.exists(directory):
  767. return []
  768. try:
  769. if fullPath:
  770. return map(lambda x:path.join(directory,x),
  771. os.listdir(directory))
  772. else:
  773. return os.listdir(directory)
  774. except OSError:
  775. pass
  776. return []
  777. def getInstalledVideo(prefix="/"):
  778. """Get installed video drivers"""
  779. x11Drivers = path.join(prefix,"usr/lib/xorg/modules/drivers")
  780. return map(lambda x:x[:-7],
  781. filter(lambda x:x.endswith('_drv.so'),
  782. listDirectory(x11Drivers)))
  783. def getDistfilesVideo(prefix="/"):
  784. """Get video drivers from distfiles"""
  785. distFiles = path.join(prefix,"usr/portage/distfiles")
  786. return list(set(
  787. map(lambda x:'fglrx' if "amd" in x else "nvidia",
  788. filter(lambda x:"amd" in x or
  789. x.startswith('NVIDIA-Linux'),
  790. listDirectory(distFiles)))))
  791. def getAvailableVideo(prefix="/"):
  792. """Get available video drivers (installed and maybe installed)"""
  793. return list(set(getInstalledVideo(prefix=prefix) + \
  794. getDistfilesVideo(prefix=prefix)))
  795. def readLinesFile(filename):
  796. """Read file by line"""
  797. try:
  798. if path.exists(filename):
  799. for line in open(filename,'r'):
  800. yield line.rstrip('\n')
  801. except (OSError,IOError):
  802. pass
  803. finally:
  804. raise StopIteration
  805. def readFile(filename):
  806. """Read whole file or return empty string"""
  807. try:
  808. if path.exists(filename):
  809. return open(filename,'r').read()
  810. except (OSError,IOError):
  811. pass
  812. return ""
  813. def getUUIDDict(revers=False):
  814. """Get dict UUID -> dev"""
  815. blkidProcess = process("/sbin/blkid","-s","UUID","-c","/dev/null")
  816. if revers:
  817. datafunc = lambda x,y: (y,x)
  818. else:
  819. datafunc = lambda x,y: (x,y)
  820. DEV,UUID = 0,1
  821. reSplit = re.compile('^([^:]+):.*UUID="([^"]+)"',re.S)
  822. return dict(
  823. map(lambda x:datafunc("UUID=%s"%x[UUID],
  824. getUdevDeviceInfo(name=x[DEV]).get('DEVNAME',x[DEV])),
  825. map(lambda x:x.groups(),
  826. filter(lambda x:x,
  827. map(reSplit.search,
  828. blkidProcess)))))
  829. def detectDeviceForPartition(dev):
  830. """Detect parent device for partition by udev and return property"""
  831. prop = getUdevDeviceInfo(name=dev)
  832. if prop.get('DEVTYPE','') != 'partition':
  833. return ''
  834. parentpath = path.dirname(prop.get('DEVPATH',''))
  835. if parentpath:
  836. devProp = getUdevDeviceInfo(path=parentpath)
  837. return devProp.get('DEVNAME','')
  838. return None
  839. def getProgPath(progname):
  840. """Get full path of program or False"""
  841. baseprogname = path.basename(progname)
  842. env = {"LANG":"C"}
  843. env.update(os.environ.items() + [("PATH",getpathenv())] +\
  844. env.items())
  845. res = runOsCommand("which %s"%baseprogname,env_dict=env)
  846. if res[0] == 0:
  847. return res[1][0].strip()
  848. elif path.isabs(progname) and path.exists(progname):
  849. return progname
  850. else:
  851. return False
  852. def checkUtils(*utils):
  853. """Check utils, exit if it not found and return fullpath"""
  854. retval = []
  855. for util in utils:
  856. utilPath = getProgPath(util)
  857. if not utilPath:
  858. cl_overriding.printERROR(_("Command not found '%s'")%
  859. path.basename(util))
  860. cl_overriding.exit(1)
  861. retval.append(utilPath)
  862. if len(retval) == 1:
  863. return retval[0]
  864. else:
  865. return retval
  866. reVerSplit = re.compile(r"^(.*?)-(([^-]+?)(?:-(r\d+))?)(?:.(tbz2))?$",re.S)
  867. def reVerSplitToPV(x):
  868. """Convert match from reVerSplit to PV hash"""
  869. if type(x) == str:
  870. x = reVerSplit.search(x)
  871. if x:
  872. match = x.groups()
  873. return {'PN':match[0],
  874. 'PF':"%s-%s"%(match[0],match[1]),
  875. 'P':"%s-%s"%(match[0],match[2]),
  876. 'PV':match[2],
  877. 'PR':match[3] or "r0",
  878. 'PVR':match[1]}
  879. return {'PN':"",
  880. 'PF':"",
  881. 'P':"",
  882. 'PV':"",
  883. 'PR':"",
  884. 'PVR':""}.copy()
  885. def getPkgUses(fullpkg):
  886. """Get USE and IUSE from package"""
  887. category,slash,pkg = fullpkg.partition('/')
  888. pkgCategory = '/var/db/pkg/{0}'.format(category)
  889. packages = filter(lambda x:x['PN'] == pkg,
  890. map(reVerSplitToPV,
  891. filter(lambda x:x,
  892. map(lambda x:reVerSplit.search(x),
  893. listDirectory(pkgCategory)))))
  894. if not packages:
  895. return None
  896. usePath = path.join(pkgCategory,packages[-1]['PF'],"USE")
  897. iusePath = path.join(pkgCategory,packages[-1]['PF'],"IUSE")
  898. iuse = open(iusePath,'r').read().strip().split() \
  899. if path.exists(iusePath) else \
  900. []
  901. use = open(usePath,'r').read().strip().split() \
  902. if path.exists(usePath) else \
  903. []
  904. return (map(lambda x:x[1:] if x.startswith("+") else x,
  905. filter(lambda x:x,
  906. use)),
  907. map(lambda x:x[1:] if x.startswith("+") else x,
  908. filter(lambda x:x,
  909. iuse)))
  910. def isPkgInstalled(pkg,prefix='/'):
  911. """Check is package installed"""
  912. pkgDir = path.join(prefix,'var/db/pkg')
  913. if "/" in pkg:
  914. category,op,pkg = pkg.partition('/')
  915. return bool(
  916. filter(lambda x:x['PN'] == pkg,
  917. map(reVerSplitToPV,
  918. listDirectory(path.join(pkgDir,category)))))
  919. else:
  920. return bool(
  921. filter(lambda x: filter(lambda y:y['PN'] == pkg,
  922. map(reVerSplitToPV,
  923. listDirectory(x))),
  924. listDirectory(pkgDir,fullPath=True)))
  925. def getPkgInstalled(pkg,prefix='/'):
  926. """Check is package installed"""
  927. pkgDir = path.join(prefix,'var/db/pkg')
  928. if "/" in pkg:
  929. category,op,pkg = pkg.partition('/')
  930. return filter(lambda x:x['PN'] == pkg,
  931. map(reVerSplitToPV,
  932. listDirectory(path.join(pkgDir,category))))
  933. else:
  934. return filter(lambda x: filter(lambda y:y['PN'] == pkg,
  935. map(reVerSplitToPV,
  936. listDirectory(x))),
  937. listDirectory(pkgDir,fullPath=True))
  938. def getPkgActiveUses(fullpkg):
  939. """Get active uses from package"""
  940. res = getPkgUses(fullpkg)
  941. if not res:
  942. return None
  943. return list(set(res[0]) & set(res[1]))
  944. def getSquashList():
  945. """Get supprted squashfs compressions method"""
  946. wantMethod = set(["lzo","lzma","xz","gzip"])
  947. usesSquashFs = getPkgActiveUses("sys-fs/squashfs-tools")
  948. if not usesSquashFs:
  949. return ["gzip"]
  950. else:
  951. pkgInfo = getPkgInstalled('sys-fs/squashfs-tools')
  952. if pkgInfo and pkgInfo[0]['PV']:
  953. pkgVer = getTupleVersion(pkgInfo[0]['PV'])
  954. gzipVer = getTupleVersion('4.2')
  955. if pkgVer >= gzipVer:
  956. usesSquashFs.append('gzip')
  957. return map(lambda x:{"lzma":"xz"}.get(x,x),
  958. list(set(usesSquashFs) & wantMethod))
  959. def countPartitions(devname):
  960. """Count partition for specified device"""
  961. syspath = getUdevDeviceInfo(name=devname).get('DEVPATH','')
  962. if not syspath:
  963. return 0
  964. deviceName = path.basename(syspath)
  965. if not syspath.startswith("/sys"):
  966. syspath = pathJoin("/sys",syspath)
  967. return len(filter(lambda x:x.startswith(deviceName),
  968. listDirectory(syspath)))
  969. def getLvmGroups():
  970. """Get LVM groups"""
  971. pvdisplayCmd = getProgPath('/sbin/pvdisplay')
  972. pvdata = process(pvdisplayCmd,"-C","-o", "vg_name","--noh")
  973. return filter(lambda x:x,pvdata.read().split())
  974. def getLvmPartitions(vg_name,lv_name,cache=[]):
  975. """Get lvm partitions"""
  976. if not cache:
  977. pvdisplayCmd = getProgPath('/sbin/pvdisplay')
  978. pvdata = process(pvdisplayCmd,"-C","-o",
  979. "vg_name,lv_name,pv_name","--noh")
  980. if pvdata.success():
  981. cache.extend(
  982. filter(lambda x:x and len(x)==3,
  983. map(lambda x:x.split(),
  984. pvdata.read().split('\n'))))
  985. if cache:
  986. res = map(lambda x:x[2],
  987. filter(lambda x:x[0]==vg_name and x[1]==lv_name,cache))
  988. if res:
  989. return res
  990. return []
  991. def getPartitionDevice(syspath):
  992. """Get real parent device by partition,lvm,mdraid"""
  993. prop = getUdevDeviceInfo(path=syspath)
  994. # real device
  995. if prop.get('ID_TYPE',"") == "disk" and \
  996. prop.get('DEVTYPE',"") == "disk":
  997. return prop.get('DEVNAME',"")
  998. # partition
  999. if prop.get('DEVTYPE') == "partition":
  1000. return getPartitionDevice(path.dirname(syspath))
  1001. # md raid
  1002. if prop.get('MD_LEVEL',"").startswith("raid"):
  1003. if not syspath.startswith('/sys'):
  1004. syspath = pathJoin('/sys',syspath)
  1005. syspath = pathJoin(syspath,"md")
  1006. for rd in filter(lambda x:path.basename(x).startswith('rd'),
  1007. listDirectory(syspath,fullPath=True)):
  1008. rdBlockPath = path.join(rd,"block")
  1009. if path.exists(rdBlockPath):
  1010. return getPartitionDevice(path.realpath(rdBlockPath))
  1011. else:
  1012. return ""
  1013. # lvm
  1014. if prop.get('DM_LV_NAME',"") != "":
  1015. parts = getLvmPartitions(prop.get('DM_VG_NAME',''),
  1016. prop.get('DM_LV_NAME',''))
  1017. if parts:
  1018. propPartLvm = getUdevDeviceInfo(name=parts[0])
  1019. if 'DEVPATH' in propPartLvm:
  1020. return getPartitionDevice(propPartLvm['DEVPATH'])
  1021. return ""
  1022. def getAvailableX11Drivers(prefix="/"):
  1023. """Get available x11 drivers (Depricated Function)"""
  1024. xorg_modules_dir = path.join(prefix,'usr/lib/xorg/modules/drivers')
  1025. return map(lambda x: x[:-7],
  1026. filter(lambda x:x.endswith('_drv.so'),
  1027. listDirectory(xorg_modules_dir)))
  1028. def lspci(filtername=None,shortInfo=False):
  1029. """Get hash of lspci, filtred by filtername. If shortInfo, then
  1030. type,vendor and name get only first word
  1031. pcidata(domain,bus,slot,func)
  1032. 'type'
  1033. 'vendor'
  1034. 'name'"""
  1035. reData = re.compile(r'(\S+)\s"([^"]+)"\s+"([^"]+)"\s+"([^"]+)"',re.S)
  1036. if filtername:
  1037. filterfunc = lambda x: filtername in x
  1038. else:
  1039. filterfunc = lambda x:x
  1040. if shortInfo:
  1041. sfunc = lambda x:x.partition(" ")[0]
  1042. else:
  1043. sfunc = lambda x:x
  1044. lspciProg = checkUtils('/usr/sbin/lspci')
  1045. processLsPci = process(lspciProg,"-m")
  1046. retData = {}
  1047. for device in map(lambda x:x.groups(),
  1048. filter(lambda x:x,
  1049. map(reData.search,
  1050. filter(filterfunc,
  1051. processLsPci)))):
  1052. retData[device[0]] = {'type':sfunc(device[1]),\
  1053. 'vendor':sfunc(device[2]),\
  1054. 'name':sfunc(device[3])}
  1055. return retData
  1056. def getUdevDeviceInfo(path="",name=""):
  1057. """Get device info by syspath of name"""
  1058. udevadmCmd = getProgPath('/sbin/udevadm')
  1059. typeQuery = "--path" if path else "--name"
  1060. value = path if path else name
  1061. return dict(
  1062. filter(lambda x:x[0],
  1063. map(lambda x:x.partition("=")[0::2],
  1064. process(udevadmCmd,"info","--query","property",
  1065. typeQuery,value).read().split("\n"))))
  1066. def getPartitionSize(dev):
  1067. """Get partition size"""
  1068. SECTORSIZE=512
  1069. sizeFile = pathJoin(dev,"size")
  1070. if path.exists(sizeFile):
  1071. size = int(open(sizeFile,'r').read().strip())*SECTORSIZE
  1072. suffix = (((1024**0),"",False),
  1073. ((1024**1),"K",False),
  1074. ((1024**2),"M",False),
  1075. ((1024**3),"G",True),
  1076. ((1024**4),"T",True),
  1077. ((1024**5),"P",True))
  1078. suffix = filter(lambda x:size >x[0],suffix)
  1079. if suffix:
  1080. suffix = suffix[-1]
  1081. printSize = int(size / (float(suffix[0])/10))
  1082. printSizeTail = printSize % 10
  1083. printSize = printSize / 10
  1084. if suffix[2] and printSizeTail:
  1085. return "%d.%d%s"%(printSize,printSizeTail,suffix[1])
  1086. else:
  1087. return "%d%s"%(printSize,suffix[1])
  1088. return ""
  1089. def getDeviceType(syspath):
  1090. """Get device type (disk,partition,lvm,raid)"""
  1091. prop = getUdevDeviceInfo(path=syspath)
  1092. # real device
  1093. if prop.get('ID_CDROM',""):
  1094. return "cdrom"
  1095. if prop.get('ID_TYPE',"") == "disk" and \
  1096. prop.get('DEVTYPE',"") == "disk":
  1097. return "disk"
  1098. # partition
  1099. if prop.get('DEVTYPE') == "partition":
  1100. return getDeviceType(path.dirname(syspath))+"-partition"
  1101. # md raid
  1102. if prop.get('MD_LEVEL',"").startswith("raid"):
  1103. if not syspath.startswith('/sys'):
  1104. syspath = pathJoin('/sys',syspath)
  1105. syspath = pathJoin(syspath,"md")
  1106. for rd in filter(lambda x:path.basename(x).startswith('rd'),
  1107. listDirectory(syspath,fullPath=True)):
  1108. rdBlockPath = path.join(rd,"block")
  1109. if path.exists(rdBlockPath):
  1110. return getDeviceType(path.realpath(rdBlockPath))+"-raid"
  1111. else:
  1112. return "loop"
  1113. # lvm
  1114. if prop.get('DM_LV_NAME',"") != "":
  1115. parts = getLvmPartitions(prop.get('DM_VG_NAME',''),
  1116. prop.get('DM_LV_NAME',''))
  1117. if parts:
  1118. propPartLvm = getUdevDeviceInfo(name=parts[0])
  1119. if 'DEVPATH' in propPartLvm:
  1120. return getDeviceType(propPartLvm['DEVPATH'])+"-lvm"
  1121. return "loop"
  1122. def getRaidPartitions(raidpath):
  1123. """Get raid partitions"""
  1124. prop = getUdevDeviceInfo(path=raidpath)
  1125. raidParts = []
  1126. if prop.get('MD_LEVEL',"").startswith("raid"):
  1127. if not raidpath.startswith('/sys'):
  1128. raidpath = pathJoin('/sys',raidpath)
  1129. raidpath = pathJoin(raidpath,"md")
  1130. for rd in filter(lambda x:path.basename(x).startswith('rd'),
  1131. listDirectory(raidpath,fullPath=True)):
  1132. rdpath = path.join(raidpath,rd,"block")
  1133. if path.exists(rdpath):
  1134. raidParts.append(
  1135. getUdevDeviceInfo(path=path.realpath(rdpath)).get(
  1136. "DEVNAME",''))
  1137. return filter(lambda x:x,raidParts)
  1138. def getPartitionType(prop):
  1139. """Get type of dos part table (primary,extended or logical)"""
  1140. if prop.get('ID_PART_ENTRY_SCHEME') == 'dos':
  1141. partId = prop.get('ID_PART_ENTRY_TYPE','')
  1142. partNumber = prop.get('ID_PART_ENTRY_NUMBER','')
  1143. if partId and partNumber:
  1144. if partId == "0x5":
  1145. return "extended"
  1146. elif int(partNumber)>4:
  1147. return "logical"
  1148. else:
  1149. return "primary"
  1150. return prop.get('ID_PART_TABLE_TYPE','')
  1151. def detectBuild(pathname,dictInfo):
  1152. """Detect build by root passwd 'root'"""
  1153. shadowPath = pathJoin(pathname,'/etc/shadow')
  1154. if r"root:$1$JMvNh5xg$VnV1DyJdTcwuZ0hp5YiJG0:14349:0:::::" in \
  1155. readFile(shadowPath):
  1156. dictInfo['type'] = ' assemble'
  1157. elif path.exists(pathJoin(pathname,"delta")) and \
  1158. path.exists(pathJoin(pathname,"workspace")):
  1159. dictInfo['type'] = " builder"
  1160. issue = readFile(pathJoin(pathname,'etc/gentoo-release'))
  1161. if "Server" in issue:
  1162. if "Scratch" in issue:
  1163. dictInfo['name'] = "CSS"
  1164. else:
  1165. dictInfo['name'] = "CDS"
  1166. elif "Desktop" in issue:
  1167. if "XFCE" in issue:
  1168. dictInfo['name'] = "CLDX"
  1169. elif "KDE" in issue:
  1170. dictInfo['name'] = "CLD"
  1171. elif "GNOME" in issue:
  1172. dictInfo['name'] = "CLDG"
  1173. elif "Scratch" in issue:
  1174. dictInfo['name'] = "CLS"
  1175. else:
  1176. dictInfo['type'] = ''
  1177. return dictInfo
  1178. def getOsProberHash(getContentFunc=None):
  1179. """Get partition content by os-prober"""
  1180. os_prober = getProgPath('/usr/bin/os-prober')
  1181. if os_prober:
  1182. DEV,LONG,SHORT,TYPE = 0,1,2,3
  1183. osProberList = \
  1184. map(lambda x:[getUdevDeviceInfo(name=x[DEV]).get('DEVNAME',''),
  1185. x[LONG],x[SHORT],x[TYPE]],
  1186. filter(lambda x:len(x)>=4,
  1187. map(lambda x:x.split(":"),
  1188. process(os_prober))))
  1189. for osRecord in osProberList:
  1190. if "Gentoo" in osRecord[SHORT] and getContentFunc:
  1191. osDescr = getContentFunc(osRecord[DEV],addFunc=detectBuild)
  1192. if "name" in osDescr and "march" in osDescr and \
  1193. "build" in osDescr and "ver" in osDescr and \
  1194. (osDescr["ver"] != "0" or osDescr["build"]):
  1195. if osDescr['build']:
  1196. osDescr['build'] = "-%s"%osDescr['build']
  1197. else:
  1198. osDescr['build'] = "-%s"%osDescr['ver']
  1199. osRecord[SHORT] = \
  1200. "{name}-{march}{build}{type}".format(**osDescr)
  1201. else:
  1202. osRecord[SHORT] = "Gentoo"
  1203. elif "Gentoo" in osRecord[SHORT] and "Calculate" in osRecord[LONG]:
  1204. osRecord[SHORT] = "Calculate"
  1205. osProberHash = \
  1206. dict(
  1207. map(lambda x:(x[DEV],x[SHORT]),
  1208. osProberList))
  1209. else:
  1210. osProberHash = {}
  1211. return osProberHash
  1212. def refreshLVM():
  1213. """Run command which refresh information about LVM"""
  1214. vgscan = getProgPath('/sbin/vgscan')
  1215. vgchange = getProgPath('/sbin/vgchange')
  1216. lvchange = getProgPath('/sbin/lvchange')
  1217. if vgscan and vgchange and lvchange:
  1218. process(vgscan).success()
  1219. process(vgchange,'-ay','--refresh').success()
  1220. for group in getLvmGroups():
  1221. process(lvchange,'-ay','--refresh',group).success()
  1222. def refreshUdev():
  1223. """Run command which refresh information about device in udev"""
  1224. udevadm = getProgPath('/sbin/udevadm')
  1225. if udevadm:
  1226. blkidFile = '/etc/blkid.tab'
  1227. if path.exists(blkidFile):
  1228. try:
  1229. os.unlink(blkidFile)
  1230. except OSError:
  1231. pass
  1232. process(udevadm,"trigger","--subsystem-match","block").success()
  1233. def getPasswdUsers(minId=1000,maxId=65000):
  1234. """
  1235. Get users from passwd from minId to maxId
  1236. """
  1237. retList = []
  1238. fileName = "/etc/passwd"
  1239. if os.access(fileName, os.R_OK):
  1240. reNumb = re.compile("^\d+$")
  1241. lenData=7
  1242. userData = filter(lambda x: len(x)==lenData,
  1243. map(lambda x: x.rstrip().split(":"),
  1244. open(fileName)))
  1245. userData = filter(lambda x:\
  1246. reNumb.match(x[2]) and minId<=int(x[2])<=maxId,
  1247. userData)
  1248. sortUsers = map(lambda x: x[0], userData)
  1249. sortUsers.sort()
  1250. retList = ["root"] + sortUsers
  1251. return retList
  1252. def getCmdLineParam(paramName):
  1253. """Get value of param /proc/cmdline. If param not found then empty.
  1254. """
  1255. cmdLine = '/proc/cmdline'
  1256. paramName = "%s="%paramName
  1257. params = \
  1258. map(lambda x:x.partition('=')[2],
  1259. filter(lambda x:x.startswith(paramName),
  1260. readFile(cmdLine).split(' ')))
  1261. if params:
  1262. return params[-1]
  1263. else:
  1264. return ""
  1265. def getSupportArch():
  1266. """Get supported architectures by processor.
  1267. Is support processor x86_64 else only i686.
  1268. """
  1269. if filter(lambda x:x.startswith('flags') and " lm " in x,
  1270. readLinesFile('/proc/cpuinfo')):
  1271. return ['i686','x86_64']
  1272. else:
  1273. return ['i686']
  1274. def makeDirectory(pathname):
  1275. """Make directory and parent.
  1276. If directory exists then return False else True"""
  1277. try:
  1278. parent = path.split(path.normpath(pathname))[0]
  1279. if not path.exists(parent):
  1280. makeDirectory(parent)
  1281. else:
  1282. if path.exists(pathname):
  1283. return False
  1284. os.mkdir(pathname)
  1285. return True
  1286. except Exception, e:
  1287. return False
  1288. def tarLinks(rootpath,archpath,skip=[]):
  1289. """Add symbolic links to archive file"""
  1290. links = []
  1291. if skip:
  1292. reSkip = re.compile("|".join(map(lambda x:x.replace("*",".*"),
  1293. skip))).search
  1294. else:
  1295. reSkip = lambda x:False
  1296. lenprefix = len(path.normpath(rootpath))+1
  1297. if path.exists(archpath):
  1298. os.unlink(archpath)
  1299. # create arch
  1300. tar = tarfile.open(archpath,"w:bz2")
  1301. # find links
  1302. for root, dirs, files in os.walk(rootpath):
  1303. for link in filter(os.path.islink,
  1304. map(lambda x:path.join(root,x),
  1305. dirs+files)):
  1306. # try add link
  1307. try:
  1308. if not reSkip(link):
  1309. ti = tar.gettarinfo(link)
  1310. ti.name = link[lenprefix:]
  1311. tar.addfile(ti)
  1312. links.append(link)
  1313. except OSError:
  1314. pass
  1315. # discard mounted paths
  1316. removeDirs = map(lambda x:x[0],
  1317. filter(lambda x:path.islink(x[1]) or path.ismount(x[1]),
  1318. map(lambda x:(x,path.join(root,x)),
  1319. dirs)))
  1320. map(lambda x:dirs.remove(x),
  1321. removeDirs)
  1322. tar.close()
  1323. return links
  1324. def countFiles(dirpath,onefilesystem=True):
  1325. """
  1326. Count files in dirpath
  1327. """
  1328. num = 1
  1329. for dirpath,dirnames,filenames in os.walk(dirpath):
  1330. num += len(set(dirnames) | set(filenames))
  1331. if onefilesystem:
  1332. mountDirs = filter(lambda x:path.ismount(path.join(dirpath,x)),
  1333. dirnames)
  1334. for dirname in mountDirs:
  1335. dirnames.remove(dirname)
  1336. return num
  1337. class InitrdFile(object):
  1338. re_kver_path = re.compile("/modules/([^/]+)/kernel")
  1339. def __init__(self, _file):
  1340. self._file = _file
  1341. def get_kernel_version(self):
  1342. for fn in self.get_names():
  1343. if "/modules/" in fn and "/kernel" in fn:
  1344. m = self.re_kver_path.search(fn)
  1345. if m:
  1346. return m.group(1)
  1347. else:
  1348. break
  1349. return ""
  1350. def get_names(self):
  1351. if not path.exists(self._file):
  1352. # raise IOError
  1353. open(self._file)
  1354. ftype = typeFile(magic=0x4).getMType
  1355. rdtype = ftype(self._file)
  1356. if "LZ4" in rdtype:
  1357. arch_cmd = '/usr/bin/lz4'
  1358. elif "XZ" in rdtype:
  1359. arch_cmd = '/usr/bin/xz'
  1360. else:
  1361. arch_cmd = '/bin/gzip'
  1362. gz = Popen([arch_cmd, "-dc", self._file], stdout=PIPE, stderr=PIPE,
  1363. close_fds=True)
  1364. cpio = Popen(["/bin/cpio","-tf"], stdout=PIPE, stdin=gz.stdout,
  1365. stderr=PIPE, close_fds=True)
  1366. try:
  1367. for fn in cpio.stdout.xreadlines():
  1368. yield fn.rstrip()
  1369. finally:
  1370. cpio.terminate()
  1371. gz.terminate()
  1372. def __iter__(self):
  1373. return iter(self.get_names())