Package entropy :: Module tools

Source Code for Module entropy.tools

   1  #!/usr/bin/python 
   2  # -*- coding: iso-8859-1 -*- 
   3  ''' 
   4      # DESCRIPTION: 
   5      # generic tools for all the handlers applications 
   6   
   7      Copyright (C) 2007-2008 Fabio Erculiani 
   8   
   9      This program is free software; you can redistribute it and/or modify 
  10      it under the terms of the GNU General Public License as published by 
  11      the Free Software Foundation; either version 2 of the License, or 
  12      (at your option) any later version. 
  13   
  14      This program is distributed in the hope that it will be useful, 
  15      but WITHOUT ANY WARRANTY; without even the implied warranty of 
  16      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  17      GNU General Public License for more details. 
  18   
  19      You should have received a copy of the GNU General Public License 
  20      along with this program; if not, write to the Free Software 
  21      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  22  ''' 
  23   
  24  from __future__ import with_statement 
  25  import random 
  26  import stat 
  27  import errno 
  28  import re 
  29  import os 
  30  import time 
  31  import shutil 
  32  import tarfile 
  33  import subprocess 
  34  import grp 
  35  import pwd 
  36  import hashlib 
  37  from entropy.output import * # there is also TextInterface 
  38  from entropy.const import * 
  39  from entropy.exceptions import * 
  40   
41 -def is_root():
42 return not etpConst['uid']
43
44 -def is_user_in_entropy_group(uid = None):
45 46 if uid == None: 47 uid = os.getuid() 48 if uid == 0: 49 return True 50 51 try: 52 username = pwd.getpwuid(uid)[0] 53 except KeyError: 54 return False 55 56 try: 57 data = grp.getgrnam(etpConst['sysgroup']) 58 except KeyError: 59 return False 60 61 #etp_gid = data[2] 62 etp_group_users = data[3] 63 64 if not etp_group_users or \ 65 username not in etp_group_users: 66 return False 67 68 return True
69
70 -def get_uid_from_user(username):
71 try: 72 return pwd.getpwnam(username)[2] 73 except (KeyError, IndexError,): 74 return -1
75
76 -def get_gid_from_group(groupname):
77 try: 78 return grp.getgrnam(groupname)[2] 79 except (KeyError, IndexError,): 80 return -1
81
82 -def get_user_from_uid(uid):
83 try: 84 return pwd.getpwuid(uid)[0] 85 except KeyError: 86 return None
87
88 -def get_group_from_gid(gid):
89 try: 90 return grp.getgrgid(gid)[0] 91 except (KeyError, IndexError,): 92 return -1
93
94 -def kill_threads():
95 const_kill_threads()
96 100
101 -def get_traceback():
102 import traceback 103 from cStringIO import StringIO 104 buf = StringIO() 105 traceback.print_exc(file = buf) 106 return buf.getvalue()
107 143 144 # Get the content of an online page 145 # @returns content: if the file exists 146 # @returns False: if the file is not found
147 -def get_remote_data(url):
148 149 import socket 150 import urllib2 151 socket.setdefaulttimeout(60) 152 # now pray the server 153 from entropy.core import SystemSettings 154 sys_settings = SystemSettings() 155 proxy_settings = sys_settings['system']['proxy'] 156 try: 157 mydict = {} 158 if proxy_settings['ftp']: 159 mydict['ftp'] = proxy_settings['ftp'] 160 if proxy_settings['http']: 161 mydict['http'] = proxy_settings['http'] 162 if mydict: 163 mydict['username'] = proxy_settings['username'] 164 mydict['password'] = proxy_settings['password'] 165 add_proxy_opener(urllib2, mydict) 166 else: 167 # unset 168 urllib2._opener = None 169 item = urllib2.urlopen(url) 170 result = item.readlines() 171 item.close() 172 del item 173 if (not result): 174 socket.setdefaulttimeout(2) 175 return False 176 socket.setdefaulttimeout(2) 177 return result 178 except: 179 socket.setdefaulttimeout(2) 180 return False
181
182 -def is_png_file(path):
183 f = open(path,"r") 184 x = f.read(4) 185 if x == '\x89PNG': 186 return True 187 return False
188
189 -def is_jpeg_file(path):
190 f = open(path,"r") 191 x = f.read(10) 192 if x == '\xff\xd8\xff\xe0\x00\x10JFIF': 193 return True 194 return False
195
196 -def is_bmp_file(path):
197 f = open(path,"r") 198 x = f.read(2) 199 if x == 'BM': 200 return True 201 return False
202
203 -def is_gif_file(path):
204 f = open(path,"r") 205 x = f.read(5) 206 if x == 'GIF89': 207 return True 208 return False
209
210 -def is_supported_image_file(path):
211 calls = [is_png_file, is_jpeg_file, is_bmp_file, is_gif_file] 212 for mycall in calls: 213 if mycall(path): return True 214 return False
215
216 -def is_april_first():
217 april_first = "01-04" 218 cur_time = time.strftime("%d-%m") 219 if april_first == cur_time: 220 return True 221 return False
222
223 -def add_proxy_opener(module, data):
224 import types 225 if type(module) != types.ModuleType: # FIXME: check if it's urllib2 226 raise InvalidDataType("InvalidDataType: not a module") 227 if not data: 228 return 229 230 username = None 231 password = None 232 authinfo = None 233 if data.has_key('password'): 234 username = data.pop('username') 235 if data.has_key('password'): 236 username = data.pop('password') 237 if username == None or password == None: 238 username = None 239 password = None 240 else: 241 passmgr = module.HTTPPasswordMgrWithDefaultRealm() 242 if data['http']: 243 passmgr.add_password(None, data['http'], username, password) 244 if data['ftp']: 245 passmgr.add_password(None, data['ftp'], username, password) 246 authinfo = module.ProxyBasicAuthHandler(passmgr) 247 248 proxy_support = module.ProxyHandler(data) 249 if authinfo: 250 opener = module.build_opener(proxy_support, authinfo) 251 else: 252 opener = module.build_opener(proxy_support) 253 module.install_opener(opener)
254
255 -def is_valid_ascii(string):
256 try: 257 mystring = str(string) 258 del mystring 259 except: 260 return False 261 return True
262
263 -def is_valid_unicode(string):
264 try: 265 unicode(string) 266 except: 267 return False 268 return True
269
270 -def is_valid_email(email):
271 monster = "(?:[a-z0-9!#$%&'*+/=?^_{|}~-]+(?:.[a-z0-9!#$%" + \ 272 "&'*+/=?^_{|}~-]+)*|\"(?:" + \ 273 "[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]" + \ 274 "|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9]" + \ 275 "(?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?" + \ 276 "|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.)" + \ 277 "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?" + \ 278 "|[a-z0-9-]*[a-z0-9]:(?:" + \ 279 "[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]" + \ 280 "|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])" 281 evil = re.compile(monster) 282 if evil.match(email): 283 return True 284 return False
285
286 -def islive():
287 return const_islive()
288
289 -def get_file_size(file_path):
290 my = file_path[:] 291 if isinstance(my, unicode): 292 my = my.encode("utf-8") 293 mystat = os.lstat(my) 294 return int(mystat.st_size)
295
296 -def sum_file_sizes(file_list):
297 size = 0 298 for myfile in file_list: 299 try: 300 size += get_file_size(myfile) 301 except (OSError,IOError,): 302 continue 303 return size
304
305 -def check_required_space(mountpoint, bytes_required):
306 import statvfs 307 st = os.statvfs(mountpoint) 308 freeblocks = st[statvfs.F_BFREE] 309 blocksize = st[statvfs.F_BSIZE] 310 freespace = freeblocks*blocksize 311 if bytes_required > freespace: 312 # it's NOT fine 313 return False 314 return True
315
316 -def getstatusoutput(cmd):
317 """Return (status, output) of executing cmd in a shell.""" 318 pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r') 319 text = pipe.read() 320 sts = pipe.close() 321 if sts is None: sts = 0 322 if text[-1:] == '\n': text = text[:-1] 323 return sts, text
324 325 # Copyright 1998-2004 Gentoo Foundation 326 # Copyright 2009 Fabio Erculiani (reducing code complexity) 327 # Distributed under the terms of the GNU General Public License v2 328 # $Id: __init__.py 12159 2008-12-05 00:08:58Z zmedico $ 329 # atomic file move function
330 -def movefile(src, dest, src_basedir = None):
331 332 sstat = os.lstat(src) 333 destexists = 1 334 try: 335 dstat = os.lstat(dest) 336 except (OSError, IOError,): 337 dstat = os.lstat(os.path.dirname(dest)) 338 destexists = 0 339 340 if destexists: 341 if stat.S_ISLNK(dstat[stat.ST_MODE]): 342 try: 343 os.unlink(dest) 344 destexists = 0 345 except (OSError, IOError,): 346 pass 347 348 if stat.S_ISLNK(sstat[stat.ST_MODE]): 349 try: 350 target = os.readlink(src) 351 if src_basedir != None: 352 if target.find(src_basedir) == 0: 353 target = target[len(src_basedir):] 354 if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]): 355 os.unlink(dest) 356 os.symlink(target,dest) 357 os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) 358 return True 359 except SystemExit: 360 raise 361 except Exception, e: 362 print "!!! failed to properly create symlink:" 363 print "!!!",dest,"->",target 364 print "!!!",e 365 return False 366 367 renamefailed = True 368 if sstat.st_dev == dstat.st_dev: 369 try: 370 os.rename(src,dest) 371 renamefailed = False 372 except Exception, e: 373 if e[0] != errno.EXDEV: 374 # Some random error. 375 print "!!! Failed to move",src,"to",dest 376 print "!!!",e 377 return False 378 # Invalid cross-device-link 'bind' mounted or actually Cross-Device 379 380 if renamefailed: 381 didcopy = True 382 if stat.S_ISREG(sstat[stat.ST_MODE]): 383 try: # For safety copy then move it over. 384 while 1: 385 tmp_dest = "%s#entropy_new_%s" % (dest,get_random_number(),) 386 if not os.path.lexists(tmp_dest): break 387 shutil.copyfile(src,tmp_dest) 388 os.rename(tmp_dest,dest) 389 didcopy = True 390 except SystemExit, e: 391 raise 392 except Exception, e: 393 print '!!! copy',src,'->',dest,'failed.' 394 print "!!!",e 395 return False 396 else: 397 #we don't yet handle special, so we need to fall back to /bin/mv 398 a = getstatusoutput("mv -f '%s' '%s'" % (src,dest,)) 399 if a[0]!=0: 400 print "!!! Failed to move special file:" 401 print "!!! '"+src+"' to '"+dest+"'" 402 print "!!!",a 403 return False 404 try: 405 if didcopy: 406 if stat.S_ISLNK(sstat[stat.ST_MODE]): 407 os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) 408 else: 409 os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) 410 os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown 411 os.unlink(src) 412 except SystemExit, e: 413 raise 414 except Exception, e: 415 print "!!! Failed to chown/chmod/unlink in movefile()" 416 print "!!!",dest 417 print "!!!",e 418 return False 419 420 try: 421 os.utime(dest, (sstat.st_atime, sstat.st_mtime)) 422 except OSError: 423 # The utime can fail here with EPERM even though the move succeeded. 424 # Instead of failing, use stat to return the mtime if possible. 425 try: 426 long(os.stat(dest).st_mtime) 427 return True 428 except OSError, e: 429 print "!!! Failed to stat in movefile()\n" 430 print "!!! %s\n" % dest 431 print "!!! %s\n" % str(e) 432 return False 433 434 return True
435
436 -def ebeep(count = 5):
437 mycount = count 438 while mycount > 0: 439 os.system("sleep 0.35; echo -ne \"\a\"; sleep 0.35") 440 mycount -= 1
441
442 -def application_lock_check(option = None, gentle = False):
443 if etpConst['applicationlock']: 444 if not gentle: 445 raise SystemExit(10) 446 return True 447 return False
448
449 -def get_random_number():
450 try: 451 return abs(hash(os.urandom(2)))%99999 452 except NotImplementedError: 453 random.seed() 454 return random.randint(10000,99999)
455
456 -def split_indexable_into_chunks(mystr, chunk_len):
457 chunks = [] 458 my = mystr[:] 459 mylen = len(my) 460 mycount = 0 461 while mylen: 462 chunk = my[:chunk_len] 463 chunks.append(chunk) 464 my_chunk_len = len(chunk) 465 my = my[my_chunk_len:] 466 mylen -= my_chunk_len 467 return chunks
468
469 -def countdown(secs=5, what="Counting...", back = False):
470 if secs: 471 if back: 472 try: 473 print red(">>"), what, 474 except UnicodeEncodeError: 475 print red(">>"),what.encode('utf-8'), 476 else: 477 try: 478 print what 479 except UnicodeEncodeError: 480 print what.encode('utf-8') 481 for i in range(secs)[::-1]: 482 sys.stdout.write(red(str(i+1)+" ")) 483 sys.stdout.flush() 484 time.sleep(1)
485
486 -def md5sum(filepath):
487 m = hashlib.md5() 488 readfile = open(filepath) 489 block = readfile.read(1024) 490 while block: 491 m.update(block) 492 block = readfile.read(1024) 493 readfile.close() 494 return m.hexdigest()
495
496 -def sha512(filepath):
497 m = hashlib.sha512() 498 readfile = open(filepath) 499 block = readfile.read(1024) 500 while block: 501 m.update(block) 502 block = readfile.read(1024) 503 readfile.close() 504 return m.hexdigest()
505
506 -def sha256(filepath):
507 m = hashlib.sha256() 508 readfile = open(filepath) 509 block = readfile.read(1024) 510 while block: 511 m.update(block) 512 block = readfile.read(1024) 513 readfile.close() 514 return m.hexdigest()
515
516 -def sha1(filepath):
517 m = hashlib.sha1() 518 readfile = open(filepath) 519 block = readfile.read(1024) 520 while block: 521 m.update(block) 522 block = readfile.read(1024) 523 readfile.close() 524 return m.hexdigest()
525
526 -def md5sum_directory(directory):
527 if not os.path.isdir(directory): 528 raise DirectoryNotFound("DirectoryNotFound: directory just does not exist.") 529 myfiles = os.listdir(directory) 530 m = hashlib.md5() 531 if not myfiles: 532 return "0" # no files means 0 533 534 for currentdir,subdirs,files in os.walk(directory): 535 for myfile in files: 536 myfile = os.path.join(currentdir,myfile) 537 readfile = open(myfile) 538 block = readfile.read(1024) 539 while block: 540 m.update(block) 541 block = readfile.read(1024) 542 readfile.close() 543 return m.hexdigest()
544
545 -def md5obj_directory(directory):
546 if not os.path.isdir(directory): 547 raise DirectoryNotFound("DirectoryNotFound: directory just does not exist.") 548 myfiles = os.listdir(directory) 549 m = hashlib.md5() 550 if not myfiles: 551 return m 552 553 for currentdir,subdirs,files in os.walk(directory): 554 for myfile in files: 555 myfile = os.path.join(currentdir,myfile) 556 readfile = open(myfile) 557 block = readfile.read(1024) 558 while block: 559 m.update(block) 560 block = readfile.read(1024) 561 readfile.close() 562 return m
563 564 # kindly stolen from Anaconda 565 # Copyright 1999-2008 Red Hat, Inc. <iutil.py>
566 -def getfd(filespec, readOnly = 0):
567 import types 568 if type(filespec) == types.IntType: 569 return filespec 570 if filespec == None: 571 filespec = "/dev/null" 572 573 flags = os.O_RDWR | os.O_CREAT 574 if (readOnly): 575 flags = os.O_RDONLY 576 return os.open(filespec, flags)
577
578 -def uncompress_file(file_path, destination_path, opener):
579 f_out = open(destination_path,"wb") 580 f_in = opener(file_path,"rb") 581 data = f_in.read(8192) 582 while data: 583 f_out.write(data) 584 data = f_in.read(8192) 585 f_out.flush() 586 f_out.close() 587 f_in.close()
588
589 -def compress_file(file_path, destination_path, opener, compress_level = None):
590 f_in = open(file_path,"rb") 591 if compress_level != None: 592 f_out = opener(destination_path,"wb",compresslevel = compress_level) 593 else: 594 f_out = opener(destination_path,"wb") 595 data = f_in.read(8192) 596 while data: 597 f_out.write(data) 598 data = f_in.read(8192) 599 if hasattr(f_out,'flush'): 600 f_out.flush() 601 f_out.close() 602 f_in.close()
603 604 # files_to_compress must be a list of valid file paths
605 -def compress_files(dest_file, files_to_compress, compressor = "bz2"):
606 607 if compressor not in ("bz2","gz",): 608 raise AttributeError("invalid compressor specified") 609 610 id_strings = {} 611 tar = tarfile.open(dest_file,"w:%s" % (compressor,)) 612 try: 613 for path in files_to_compress: 614 exist = os.lstat(path) 615 tarinfo = tar.gettarinfo(path, os.path.basename(path)) 616 tarinfo.uname = id_strings.setdefault(tarinfo.uid, str(tarinfo.uid)) 617 tarinfo.gname = id_strings.setdefault(tarinfo.gid, str(tarinfo.gid)) 618 if not stat.S_ISREG(exist.st_mode): continue 619 tarinfo.type = tarfile.REGTYPE 620 with open(path) as f: 621 tar.addfile(tarinfo, f) 622 finally: 623 tar.close()
624
625 -def universal_uncompress(compressed_file, dest_path, catch_empty = False):
626 627 try: 628 tar = tarfile.open(compressed_file,"r") 629 except tarfile.ReadError: 630 if catch_empty: 631 return True 632 return False 633 except EOFError: 634 return False 635 636 try: 637 638 dest_path = dest_path.encode('utf-8') 639 def mymf(tarinfo): 640 if tarinfo.isdir(): 641 # Extract directory with a safe mode, so that 642 # all files below can be extracted as well. 643 try: 644 os.makedirs(os.path.join(dest_path, tarinfo.name), 0777) 645 except EnvironmentError: 646 pass 647 return tarinfo 648 tar.extract(tarinfo, dest_path) 649 del tar.members[:] 650 return tarinfo
651 652 def mycmp(a,b): 653 return cmp(a.name, b.name) 654 655 directories = sorted(map(mymf, tar), mycmp, reverse = True) 656 657 # Set correct owner, mtime and filemode on directories. 658 def mymf2(tarinfo): 659 epath = os.path.join(dest_path, tarinfo.name) 660 try: 661 tar.chown(tarinfo, epath) 662 663 # this is mandatory on uid/gid that don't exist 664 # and in this strict order !! 665 uname = tarinfo.uname 666 gname = tarinfo.gname 667 ugdata_valid = False 668 try: 669 int(gname) 670 int(uname) 671 except ValueError: 672 ugdata_valid = True 673 674 try: 675 if ugdata_valid: 676 # get uid/gid 677 # if not found, returns -1 that won't change anything 678 uid, gid = get_uid_from_user(uname), \ 679 get_gid_from_group(gname) 680 os.lchown(epath, uid, gid) 681 except OSError: 682 pass 683 684 tar.utime(tarinfo, epath) 685 tar.chmod(tarinfo, epath) 686 except tarfile.ExtractError: 687 if tar.errorlevel > 1: 688 return False 689 done = map(mymf2, directories) 690 del done 691 692 except EOFError: 693 return False 694 695 finally: 696 tar.close() 697 698 return True 699
700 -def unpack_gzip(gzipfilepath):
701 import gzip 702 filepath = gzipfilepath[:-3] # remove .gz 703 item = open(filepath,"wb") 704 filegz = gzip.GzipFile(gzipfilepath,"rb") 705 chunk = filegz.read(8192) 706 while chunk: 707 item.write(chunk) 708 chunk = filegz.read(8192) 709 filegz.close() 710 item.flush() 711 item.close() 712 return filepath
713
714 -def unpack_bzip2(bzip2filepath):
715 import bz2 716 filepath = bzip2filepath[:-4] # remove .bz2 717 item = open(filepath,"wb") 718 filebz2 = bz2.BZ2File(bzip2filepath,"rb") 719 chunk = filebz2.read(8192) 720 while chunk: 721 item.write(chunk) 722 chunk = filebz2.read(8192) 723 filebz2.close() 724 item.flush() 725 item.close() 726 return filepath
727
728 -def backup_client_repository():
729 if os.path.isfile(etpConst['etpdatabaseclientfilepath']): 730 rnd = get_random_number() 731 source = etpConst['etpdatabaseclientfilepath'] 732 dest = etpConst['etpdatabaseclientfilepath']+".backup."+str(rnd) 733 shutil.copy2(source,dest) 734 user = os.stat(source)[4] 735 group = os.stat(source)[5] 736 os.chown(dest,user,group) 737 shutil.copystat(source,dest) 738 return dest 739 return ""
740
741 -def extract_xpak(tbz2file,tmpdir = None):
742 # extract xpak content 743 xpakpath = suck_xpak(tbz2file, etpConst['packagestmpdir']) 744 return unpack_xpak(xpakpath,tmpdir)
745
746 -def read_xpak(tbz2file):
747 xpakpath = suck_xpak(tbz2file, etpConst['entropyunpackdir']) 748 f = open(xpakpath,"rb") 749 data = f.read() 750 f.close() 751 os.remove(xpakpath) 752 return data
753
754 -def unpack_xpak(xpakfile, tmpdir = None):
755 try: 756 import entropy.xpak as xpak 757 if tmpdir is None: 758 tmpdir = etpConst['packagestmpdir']+"/"+os.path.basename(xpakfile)[:-5]+"/" 759 if os.path.isdir(tmpdir): 760 shutil.rmtree(tmpdir,True) 761 os.makedirs(tmpdir) 762 xpakdata = xpak.getboth(xpakfile) 763 xpak.xpand(xpakdata,tmpdir) 764 del xpakdata 765 try: 766 os.remove(xpakfile) 767 except OSError: 768 pass 769 except: 770 return None 771 return tmpdir
772
773 -def suck_xpak(tbz2file, outputpath):
774 775 dest_filename = os.path.basename(tbz2file)[:-5]+".xpak" 776 xpakpath = os.path.join(outputpath, dest_filename) 777 old = open(tbz2file,"rb") 778 779 # position old to the end 780 old.seek(0, os.SEEK_END) 781 # read backward until we find 782 bytes = old.tell() 783 counter = bytes - 1 784 xpak_end = "XPAKSTOP" 785 xpak_start = "XPAKPACK" 786 xpak_entry_point = "X" 787 xpak_tag_len = len(xpak_start) 788 chunk_len = 3 789 data_start_position = None 790 data_end_position = None 791 792 while counter >= (0 - chunk_len): 793 794 old.seek(counter - bytes, os.SEEK_END) 795 if (bytes - (abs(counter - bytes))) < chunk_len: 796 chunk_len = 1 797 read_bytes = old.read(chunk_len) 798 read_len = len(read_bytes) 799 800 entry_idx = read_bytes.rfind(xpak_entry_point) 801 if entry_idx != -1: 802 803 cut_gotten = read_bytes[entry_idx:] 804 offset = xpak_tag_len - len(cut_gotten) 805 chunk = cut_gotten + old.read(offset) 806 807 if (chunk == xpak_end) and (data_start_position is None): 808 data_end_position = old.tell() 809 810 elif (chunk == xpak_start) and (data_end_position is not None): 811 data_start_position = old.tell() - xpak_tag_len 812 break 813 814 counter -= read_len 815 816 if data_start_position is None: 817 return None 818 if data_end_position is None: 819 return None 820 821 # now write to found metadata to file 822 # starting from data_start_position 823 # ending to data_end_position 824 db = open(xpakpath,"wb") 825 old.seek(data_start_position) 826 to_read = data_end_position - data_start_position 827 while to_read > 0: 828 data = old.read(to_read) 829 db.write(data) 830 to_read -= len(data) 831 832 db.flush() 833 db.close() 834 old.close() 835 return xpakpath
836
837 -def append_xpak(tbz2file, atom):
838 import entropy.xpak as xpak 839 from entropy.spm import Spm 840 text = TextInterface() 841 spm_intf = Spm.get_spm_interface() 842 spm = spm_intf(text) 843 dbdir = spm.get_vdb_path()+"/"+atom+"/" 844 if os.path.isdir(dbdir): 845 tbz2 = xpak.tbz2(tbz2file) 846 tbz2.recompose(dbdir) 847 return tbz2file
848
849 -def aggregate_edb(tbz2file,dbfile):
850 f = open(tbz2file,"abw") 851 f.write(etpConst['databasestarttag']) 852 g = open(dbfile,"rb") 853 chunk = g.read(8192) 854 while chunk: 855 f.write(chunk) 856 chunk = g.read(8192) 857 g.close() 858 f.flush() 859 f.close()
860
861 -def extract_edb(tbz2file, dbpath = None):
862 863 old = open(tbz2file, "rb") 864 if not dbpath: 865 dbpath = tbz2file[:-5] + ".db" 866 867 start_position = locate_edb(old) 868 if not start_position: 869 old.close() 870 try: 871 os.remove(dbpath) 872 except OSError: 873 return None 874 return None 875 876 db = open(dbpath, "wb") 877 data = old.read(1024) 878 while data: 879 db.write(data) 880 data = old.read(1024) 881 db.flush() 882 db.close() 883 884 return dbpath
885
886 -def locate_edb(fileobj):
887 888 # position old to the end 889 fileobj.seek(0, os.SEEK_END) 890 # read backward until we find 891 bytes = fileobj.tell() 892 counter = bytes - 1 893 894 db_tag = etpConst['databasestarttag'] 895 db_tag_len = len(db_tag) 896 give_up_threshold = 1024000 * 30 # 30Mb 897 entry_point = db_tag[::-1][0] 898 max_read_len = 8 899 start_position = None 900 901 while counter >= 0: 902 cur_threshold = abs((counter-bytes)) 903 if cur_threshold >= give_up_threshold: 904 start_position = None 905 break 906 fileobj.seek(counter-bytes, os.SEEK_END) 907 read_bytes = fileobj.read(max_read_len) 908 read_len = len(read_bytes) 909 entry_idx = read_bytes.rfind(entry_point) 910 if entry_idx != -1: 911 rollback = (read_len - entry_idx) * -1 912 fileobj.seek(rollback, os.SEEK_CUR) 913 chunk = fileobj.read(db_tag_len) 914 if chunk == db_tag: 915 start_position = fileobj.tell() 916 break 917 counter -= read_len 918 919 return start_position
920
921 -def remove_edb(tbz2file, savedir):
922 old = open(tbz2file, "rb") 923 924 start_position = locate_edb(old) 925 if not start_position: 926 old.close() 927 return None 928 929 new_path = os.path.join(savedir, os.path.basename(tbz2file)) 930 new = open(new_path, "wb") 931 932 old.seek(0) 933 counter = 0 934 max_read_len = 1024 935 db_tag = etpConst['databasestarttag'] 936 db_tag_len = len(db_tag) 937 start_position -= db_tag_len 938 939 while counter < start_position: 940 delta = start_position - counter 941 if delta < max_read_len: 942 max_read_len = delta 943 bytes = old.read(max_read_len) 944 read_bytes = len(bytes) 945 new.write(bytes) 946 counter += read_bytes 947 948 new.flush() 949 new.close() 950 old.close() 951 return savedir+"/"+os.path.basename(tbz2file)
952 953 # This function creates the .md5 file related to the given package file
954 -def create_md5_file(filepath):
955 md5hash = md5sum(filepath) 956 hashfile = filepath+etpConst['packagesmd5fileext'] 957 f = open(hashfile,"w") 958 name = os.path.basename(filepath) 959 f.write(md5hash+" "+name+"\n") 960 f.flush() 961 f.close() 962 return hashfile
963
964 -def create_sha512_file(filepath):
965 sha512hash = sha512(filepath) 966 hashfile = filepath+etpConst['packagessha512fileext'] 967 f = open(hashfile,"w") 968 tbz2name = os.path.basename(filepath) 969 f.write(sha512hash+" "+tbz2name+"\n") 970 f.flush() 971 f.close() 972 return hashfile
973
974 -def create_sha256_file(filepath):
975 sha256hash = sha256(filepath) 976 hashfile = filepath+etpConst['packagessha256fileext'] 977 f = open(hashfile,"w") 978 tbz2name = os.path.basename(filepath) 979 f.write(sha256hash+" "+tbz2name+"\n") 980 f.flush() 981 f.close() 982 return hashfile
983
984 -def create_sha1_file(filepath):
985 sha1hash = sha1(filepath) 986 hashfile = filepath+etpConst['packagessha1fileext'] 987 f = open(hashfile,"w") 988 tbz2name = os.path.basename(filepath) 989 f.write(sha1hash+" "+tbz2name+"\n") 990 f.flush() 991 f.close() 992 return hashfile
993
994 -def compare_md5(filepath,checksum):
995 checksum = str(checksum) 996 result = md5sum(filepath) 997 result = str(result) 998 if checksum == result: 999 return True 1000 return False
1001
1002 -def compare_sha512(filepath, checksum):
1003 checksum = str(checksum) 1004 result = sha512(filepath) 1005 result = str(result) 1006 if checksum == result: 1007 return True 1008 return False
1009
1010 -def compare_sha256(filepath, checksum):
1011 checksum = str(checksum) 1012 result = sha256(filepath) 1013 result = str(result) 1014 if checksum == result: 1015 return True 1016 return False
1017
1018 -def compare_sha1(filepath, checksum):
1019 checksum = str(checksum) 1020 result = sha1(filepath) 1021 result = str(result) 1022 if checksum == result: 1023 return True 1024 return False
1025
1026 -def md5string(string):
1027 m = hashlib.md5() 1028 m.update(string) 1029 return m.hexdigest()
1030 1031 # used to properly sort /usr/portage/profiles/updates files
1032 -def sort_update_files(update_list):
1033 sort_dict = {} 1034 # sort per year 1035 for item in update_list: 1036 # get year 1037 year = item.split("-")[1] 1038 if sort_dict.has_key(year): 1039 sort_dict[year].append(item) 1040 else: 1041 sort_dict[year] = [] 1042 sort_dict[year].append(item) 1043 new_list = [] 1044 keys = sort_dict.keys() 1045 keys.sort() 1046 for key in keys: 1047 sort_dict[key].sort() 1048 new_list += sort_dict[key] 1049 del sort_dict 1050 return new_list
1051
1052 -def generic_file_content_parser(filepath):
1053 data = [] 1054 if os.access(filepath, os.R_OK | os.F_OK): 1055 gen_f = open(filepath,"r") 1056 content = gen_f.readlines() 1057 gen_f.close() 1058 # filter comments and white lines 1059 content = [x.strip().rsplit("#", 1)[0].strip() for x in content \ 1060 if not x.startswith("#") and x.strip()] 1061 for line in content: 1062 if line in data: 1063 continue 1064 data.append(line) 1065 return data
1066 1067 # used by equo, this function retrieves the new safe Gentoo-aware file path
1068 -def allocate_masked_file(file, fromfile):
1069 1070 # check if file and tofile are equal 1071 if os.path.isfile(file) and os.path.isfile(fromfile): 1072 old = md5sum(fromfile) 1073 new = md5sum(file) 1074 if old == new: 1075 return file, False 1076 1077 counter = -1 1078 newfile = "" 1079 previousfile = "" 1080 1081 while 1: 1082 counter += 1 1083 txtcounter = str(counter) 1084 oldtxtcounter = str(counter-1) 1085 txtcounter_len = 4-len(txtcounter) 1086 cnt = 0 1087 while cnt < txtcounter_len: 1088 txtcounter = "0"+txtcounter 1089 oldtxtcounter = "0"+oldtxtcounter 1090 cnt += 1 1091 newfile = os.path.dirname(file)+"/"+"._cfg"+txtcounter+"_"+os.path.basename(file) 1092 if counter > 0: 1093 previousfile = os.path.dirname(file)+"/"+"._cfg"+oldtxtcounter+"_"+os.path.basename(file) 1094 else: 1095 previousfile = os.path.dirname(file)+"/"+"._cfg0000_"+os.path.basename(file) 1096 if not os.path.exists(newfile): 1097 break 1098 if not newfile: 1099 newfile = os.path.dirname(file)+"/"+"._cfg0000_"+os.path.basename(file) 1100 else: 1101 1102 if os.path.exists(previousfile): 1103 1104 # compare fromfile with previousfile 1105 new = md5sum(fromfile) 1106 old = md5sum(previousfile) 1107 if new == old: 1108 return previousfile, False 1109 1110 # compare old and new, if they match, suggest previousfile directly 1111 new = md5sum(file) 1112 old = md5sum(previousfile) 1113 if (new == old): 1114 return previousfile, False 1115 1116 return newfile, True
1117
1118 -def extract_elog(file):
1119 1120 logline = False 1121 logoutput = [] 1122 f = open(file,"r") 1123 reallog = f.readlines() 1124 f.close() 1125 1126 for line in reallog: 1127 if line.startswith("INFO: postinst") or line.startswith("LOG: postinst"): 1128 logline = True 1129 continue 1130 # disable all the others 1131 elif line.startswith("LOG:"): 1132 logline = False 1133 continue 1134 if (logline) and (line.strip()): 1135 # trap ! 1136 logoutput.append(line.strip()) 1137 return logoutput
1138 1139 # Imported from Gentoo portage_dep.py 1140 # Copyright 2003-2004 Gentoo Foundation 1141 # done to avoid the import of portage_dep here 1142 1143 ver_regexp = re.compile("^(cvs\\.)?(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?$") 1144 suffix_regexp = re.compile("^(alpha|beta|rc|pre|p)(\\d*)$") 1145 suffix_value = {"pre": -2, "p": 0, "alpha": -4, "beta": -3, "rc": -1} 1146 endversion_keys = ["pre", "p", "alpha", "beta", "rc"] 1147 1148
1149 -def isjustpkgname(mypkg):
1150 myparts = mypkg.split('-') 1151 for x in myparts: 1152 if ververify(x): 1153 return 0 1154 return 1
1155
1156 -def ververify(myverx, silent=1):
1157 1158 myver = myverx[:] 1159 if myver.endswith("*"): 1160 myver = myver[:-1] 1161 if ver_regexp.match(myver): 1162 return 1 1163 else: 1164 if not silent: 1165 print "!!! syntax error in version: %s" % myver 1166 return 0
1167 1168 1169 # Copyright 2003-2004 Gentoo Foundation 1170 # Distributed under the terms of the GNU General Public License v2 1171 # $Id: dep.py 11813 2008-11-06 04:56:17Z zmedico $ 1172 valid_category = re.compile("^\w[\w-]*") 1173 invalid_atom_chars_regexp = re.compile("[()|@]") 1174
1175 -def isvalidatom(myatom, allow_blockers = True):
1176 """ 1177 Check to see if a depend atom is valid 1178 1179 Example usage: 1180 >>> isvalidatom('media-libs/test-3.0') 1181 0 1182 >>> isvalidatom('>=media-libs/test-3.0') 1183 1 1184 1185 @param atom: The depend atom to check against 1186 @type atom: String 1187 @rtype: Integer 1188 @return: One of the following: 1189 1) 0 if the atom is invalid 1190 2) 1 if the atom is valid 1191 """ 1192 atom = remove_tag(myatom) 1193 atom = remove_usedeps(atom) 1194 if invalid_atom_chars_regexp.search(atom): 1195 return 0 1196 if allow_blockers and atom[:1] == "!": 1197 if atom[1:2] == "!": 1198 atom = atom[2:] 1199 else: 1200 atom = atom[1:] 1201 1202 # media-sound/amarok/x ? 1203 if atom.count("/") > 1: 1204 return 0 1205 1206 cpv = dep_getcpv(atom) 1207 cpv_catsplit = catsplit(cpv) 1208 mycpv_cps = None 1209 if cpv: 1210 if len(cpv_catsplit) == 2: 1211 if valid_category.match(cpv_catsplit[0]) is None: 1212 return 0 1213 if cpv_catsplit[0] == "null": 1214 # "null" category is valid, missing category is not. 1215 mycpv_cps = catpkgsplit(cpv.replace("null/", "cat/", 1)) 1216 if mycpv_cps: 1217 mycpv_cps = list(mycpv_cps) 1218 mycpv_cps[0] = "null" 1219 if not mycpv_cps: 1220 mycpv_cps = catpkgsplit(cpv) 1221 1222 operator = get_operator(atom) 1223 if operator: 1224 if operator[0] in "<>" and remove_slot(atom).endswith("*"): 1225 return 0 1226 if mycpv_cps: 1227 if len(cpv_catsplit) == 2: 1228 # >=cat/pkg-1.0 1229 return 1 1230 else: 1231 return 0 1232 else: 1233 # >=cat/pkg or >=pkg-1.0 (no category) 1234 return 0 1235 if mycpv_cps: 1236 # cat/pkg-1.0 1237 return 0 1238 1239 if len(cpv_catsplit) == 2: 1240 # cat/pkg 1241 return 1 1242 return 0
1243
1244 -def catsplit(mydep):
1245 return mydep.split("/", 1)
1246
1247 -def get_operator(mydep):
1248 """ 1249 Return the operator used in a depstring. 1250 1251 Example usage: 1252 >>> from portage.dep import * 1253 >>> get_operator(">=test-1.0") 1254 '>=' 1255 1256 @param mydep: The dep string to check 1257 @type mydep: String 1258 @rtype: String 1259 @return: The operator. One of: 1260 '~', '=', '>', '<', '=*', '>=', or '<=' 1261 """ 1262 if mydep: 1263 mydep = remove_slot(mydep) 1264 if not mydep: 1265 return None 1266 if mydep[0] == "~": 1267 operator = "~" 1268 elif mydep[0] == "=": 1269 if mydep[-1] == "*": 1270 operator = "=*" 1271 else: 1272 operator = "=" 1273 elif mydep[0] in "><": 1274 if len(mydep) > 1 and mydep[1] == "=": 1275 operator = mydep[0:2] 1276 else: 1277 operator = mydep[0] 1278 else: 1279 operator = None 1280 1281 return operator
1282
1283 -def isjustname(mypkg):
1284 """ 1285 Checks to see if the depstring is only the package name (no version parts) 1286 1287 Example usage: 1288 >>> isjustname('media-libs/test-3.0') 1289 0 1290 >>> isjustname('test') 1291 1 1292 >>> isjustname('media-libs/test') 1293 1 1294 1295 @param mypkg: The package atom to check 1296 @param mypkg: String 1297 @rtype: Integer 1298 @return: One of the following: 1299 1) 0 if the package string is not just the package name 1300 2) 1 if it is 1301 """ 1302 1303 myparts = mypkg.split('-') 1304 for x in myparts: 1305 if ververify(x): 1306 return 0 1307 return 1
1308
1309 -def isspecific(mypkg):
1310 """ 1311 Checks to see if a package is in category/package-version or package-version format, 1312 possibly returning a cached result. 1313 1314 Example usage: 1315 >>> isspecific('media-libs/test') 1316 0 1317 >>> isspecific('media-libs/test-3.0') 1318 1 1319 1320 @param mypkg: The package depstring to check against 1321 @type mypkg: String 1322 @rtype: Integer 1323 @return: One of the following: 1324 1) 0 if the package string is not specific 1325 2) 1 if it is 1326 """ 1327 mysplit = mypkg.split("/") 1328 if not isjustname(mysplit[-1]): 1329 return 1 1330 return 0
1331 1332
1333 -def catpkgsplit(mydata,silent=1):
1334 """ 1335 Takes a Category/Package-Version-Rev and returns a list of each. 1336 1337 @param mydata: Data to split 1338 @type mydata: string 1339 @param silent: suppress error messages 1340 @type silent: Boolean (integer) 1341 @rype: list 1342 @return: 1343 1. If each exists, it returns [cat, pkgname, version, rev] 1344 2. If cat is not specificed in mydata, cat will be "null" 1345 3. if rev does not exist it will be '-r0' 1346 4. If cat is invalid (specified but has incorrect syntax) 1347 an InvalidData Exception will be thrown 1348 """ 1349 1350 # Categories may contain a-zA-z0-9+_- but cannot start with - 1351 mysplit=mydata.split("/") 1352 p_split=None 1353 if len(mysplit)==1: 1354 retval=["null"] 1355 p_split=pkgsplit(mydata,silent=silent) 1356 elif len(mysplit)==2: 1357 retval=[mysplit[0]] 1358 p_split=pkgsplit(mysplit[1],silent=silent) 1359 if not p_split: 1360 return None 1361 retval.extend(p_split) 1362 return retval
1363
1364 -def pkgsplit(mypkg,silent=1):
1365 myparts=mypkg.split("-") 1366 1367 if len(myparts)<2: 1368 if not silent: 1369 print "!!! Name error in",mypkg+": missing a version or name part." 1370 return None 1371 for x in myparts: 1372 if len(x)==0: 1373 if not silent: 1374 print "!!! Name error in",mypkg+": empty \"-\" part." 1375 return None 1376 1377 #verify rev 1378 revok=0 1379 myrev=myparts[-1] 1380 1381 if len(myrev) and myrev[0]=="r": 1382 try: 1383 int(myrev[1:]) 1384 revok=1 1385 except ValueError: # from int() 1386 pass 1387 if revok: 1388 verPos = -2 1389 revision = myparts[-1] 1390 else: 1391 verPos = -1 1392 revision = "r0" 1393 1394 if ververify(myparts[verPos]): 1395 if len(myparts)== (-1*verPos): 1396 return None 1397 else: 1398 for x in myparts[:verPos]: 1399 if ververify(x): 1400 return None 1401 #names can't have versiony looking parts 1402 myval=["-".join(myparts[:verPos]),myparts[verPos],revision] 1403 return myval 1404 else: 1405 return None
1406
1407 -def dep_getkey(mydepx):
1408 """ 1409 Return the category/package-name of a depstring. 1410 1411 Example usage: 1412 >>> dep_getkey('media-libs/test-3.0') 1413 'media-libs/test' 1414 1415 @param mydep: The depstring to retrieve the category/package-name of 1416 @type mydep: String 1417 @rtype: String 1418 @return: The package category/package-version 1419 """ 1420 if not mydepx: return mydepx 1421 mydep = mydepx[:] 1422 mydep = remove_tag(mydep) 1423 mydep = remove_usedeps(mydep) 1424 1425 mydep = dep_getcpv(mydep) 1426 if mydep and isspecific(mydep): 1427 mysplit = catpkgsplit(mydep) 1428 if not mysplit: 1429 return mydep 1430 return mysplit[0] + "/" + mysplit[1] 1431 1432 return mydep
1433 1434
1435 -def dep_getcpv(mydep):
1436 """ 1437 Return the category-package-version with any operators/slot specifications stripped off 1438 1439 Example usage: 1440 >>> dep_getcpv('>=media-libs/test-3.0') 1441 'media-libs/test-3.0' 1442 1443 @param mydep: The depstring 1444 @type mydep: String 1445 @rtype: String 1446 @return: The depstring with the operator removed 1447 """ 1448 1449 if mydep and mydep[0] == "*": 1450 mydep = mydep[1:] 1451 if mydep and mydep[-1] == "*": 1452 mydep = mydep[:-1] 1453 if mydep and mydep[0] == "!": 1454 mydep = mydep[1:] 1455 if mydep[:2] in [">=", "<="]: 1456 mydep = mydep[2:] 1457 elif mydep[:1] in "=<>~": 1458 mydep = mydep[1:] 1459 colon = mydep.rfind(":") 1460 if colon != -1: 1461 mydep = mydep[:colon] 1462 1463 return mydep
1464
1465 -def dep_getslot(mydep):
1466 """ 1467 1468 # Imported from portage.dep 1469 # $Id: dep.py 11281 2008-07-30 06:12:19Z zmedico $ 1470 1471 Retrieve the slot on a depend. 1472 1473 Example usage: 1474 >>> dep_getslot('app-misc/test:3') 1475 '3' 1476 1477 @param mydep: The depstring to retrieve the slot of 1478 @type mydep: String 1479 @rtype: String 1480 @return: The slot 1481 """ 1482 colon = mydep.find(":") 1483 if colon != -1: 1484 bracket = mydep.find("[", colon) 1485 if bracket == -1: 1486 return mydep[colon+1:] 1487 else: 1488 return mydep[colon+1:bracket] 1489 return None
1490
1491 -def dep_getusedeps(depend):
1492 1493 """ 1494 1495 # Imported from portage.dep 1496 # $Id: dep.py 11281 2008-07-30 06:12:19Z zmedico $ 1497 1498 Pull a listing of USE Dependencies out of a dep atom. 1499 1500 Example usage: 1501 >>> dep_getusedeps('app-misc/test:3[foo,-bar]') 1502 ('foo','-bar') 1503 1504 @param depend: The depstring to process 1505 @type depend: String 1506 @rtype: List 1507 @return: List of use flags ( or [] if no flags exist ) 1508 """ 1509 1510 use_list = [] 1511 open_bracket = depend.find('[') 1512 # -1 = failure (think c++ string::npos) 1513 comma_separated = False 1514 bracket_count = 0 1515 while( open_bracket != -1 ): 1516 bracket_count += 1 1517 if bracket_count > 1: 1518 raise InvalidAtom("USE Dependency with more " + \ 1519 "than one set of brackets: %s" % (depend,)) 1520 close_bracket = depend.find(']', open_bracket ) 1521 if close_bracket == -1: 1522 raise InvalidAtom("USE Dependency with no closing bracket: %s" % depend ) 1523 use = depend[open_bracket + 1: close_bracket] 1524 # foo[1:1] may return '' instead of None, we don't want '' in the result 1525 if not use: 1526 raise InvalidAtom("USE Dependency with " + \ 1527 "no use flag ([]): %s" % depend ) 1528 if not comma_separated: 1529 comma_separated = "," in use 1530 1531 if comma_separated and bracket_count > 1: 1532 raise InvalidAtom("USE Dependency contains a mixture of " + \ 1533 "comma and bracket separators: %s" % depend ) 1534 1535 if comma_separated: 1536 for x in use.split(","): 1537 if x: 1538 use_list.append(x) 1539 else: 1540 raise InvalidAtom("USE Dependency with no use " + \ 1541 "flag next to comma: %s" % depend ) 1542 else: 1543 use_list.append(use) 1544 1545 # Find next use flag 1546 open_bracket = depend.find( '[', open_bracket+1 ) 1547 1548 return tuple(use_list)
1549
1550 -def remove_usedeps(depend):
1551 mydepend = depend[:] 1552 1553 close_bracket = mydepend.find(']') 1554 after_closebracket = '' 1555 if close_bracket != -1: after_closebracket = mydepend[close_bracket+1:] 1556 1557 open_bracket = mydepend.find('[') 1558 if open_bracket != -1: mydepend = mydepend[:open_bracket] 1559 1560 return mydepend+after_closebracket
1561
1562 -def remove_slot(mydep):
1563 """ 1564 1565 # Imported from portage.dep 1566 # $Id: dep.py 11281 2008-07-30 06:12:19Z zmedico $ 1567 1568 Removes dep components from the right side of an atom: 1569 * slot 1570 * use 1571 * repo 1572 """ 1573 colon = mydep.find(":") 1574 if colon != -1: 1575 mydep = mydep[:colon] 1576 else: 1577 bracket = mydep.find("[") 1578 if bracket != -1: 1579 mydep = mydep[:bracket] 1580 return mydep
1581 1582 # input must be a valid package version or a full atom
1583 -def remove_revision(ver):
1584 myver = ver.split("-") 1585 if myver[-1][0] == "r": 1586 return '-'.join(myver[:-1]) 1587 return ver
1588
1589 -def remove_tag(mydep):
1590 colon = mydep.rfind("#") 1591 if colon == -1: 1592 return mydep 1593 return mydep[:colon]
1594
1595 -def remove_entropy_revision(mydep):
1596 dep = remove_package_operators(mydep) 1597 operators = mydep[:-len(dep)] 1598 colon = dep.rfind("~") 1599 if colon == -1: 1600 return mydep 1601 return operators+dep[:colon]
1602
1603 -def dep_get_entropy_revision(mydep):
1604 #dep = remove_package_operators(mydep) 1605 colon = mydep.rfind("~") 1606 if colon != -1: 1607 myrev = mydep[colon+1:] 1608 try: 1609 myrev = int(myrev) 1610 except ValueError: 1611 return None 1612 return myrev 1613 return None
1614 1615 1616 dep_revmatch = re.compile('^r[0-9]')
1617 -def dep_get_portage_revision(mydep):
1618 myver = mydep.split("-") 1619 myrev = myver[-1] 1620 if dep_revmatch.match(myrev): 1621 return myrev 1622 else: 1623 return "r0"
1624 1625
1626 -def dep_get_match_in_repos(mydep):
1627 colon = mydep.rfind("@") 1628 if colon != -1: 1629 mydata = mydep[colon+1:] 1630 mydata = mydata.split(",") 1631 if not mydata: 1632 mydata = None 1633 return mydep[:colon],mydata 1634 else: 1635 return mydep,None
1636
1637 -def dep_gettag(dep):
1638 1639 """ 1640 Retrieve the slot on a depend. 1641 1642 Example usage: 1643 >>> dep_gettag('app-misc/test#2.6.23-sabayon-r1') 1644 '2.6.23-sabayon-r1' 1645 1646 """ 1647 1648 colon = dep.rfind("#") 1649 if colon != -1: 1650 mydep = dep[colon+1:] 1651 rslt = remove_slot(mydep) 1652 return rslt 1653 return None
1654
1655 -def remove_package_operators(atom):
1656 try: 1657 while atom: 1658 if atom[0] in ('>','<','=','~',): 1659 atom = atom[1:] 1660 continue 1661 break 1662 except IndexError: 1663 pass 1664 return atom
1665 1666 # Version compare function taken from portage_versions.py 1667 # portage_versions.py -- core Portage functionality 1668 # Copyright 1998-2006 Gentoo Foundation
1669 -def compare_versions(ver1, ver2):
1670 1671 if ver1 == ver2: 1672 return 0 1673 #mykey=ver1+":"+ver2 1674 match1 = None 1675 match2 = None 1676 if ver1: 1677 match1 = ver_regexp.match(ver1) 1678 if ver2: 1679 match2 = ver_regexp.match(ver2) 1680 1681 # checking that the versions are valid 1682 invalid = False 1683 invalid_rc = 0 1684 if not match1: 1685 invalid = True 1686 elif not match1.groups(): 1687 invalid = True 1688 elif not match2: 1689 invalid_rc = 1 1690 invalid = True 1691 elif not match2.groups(): 1692 invalid_rc = 1 1693 invalid = True 1694 if invalid: return invalid_rc 1695 1696 # building lists of the version parts before the suffix 1697 # first part is simple 1698 list1 = [int(match1.group(2))] 1699 list2 = [int(match2.group(2))] 1700 1701 # this part would greatly benefit from a fixed-length version pattern 1702 if len(match1.group(3)) or len(match2.group(3)): 1703 vlist1 = match1.group(3)[1:].split(".") 1704 vlist2 = match2.group(3)[1:].split(".") 1705 for i in range(0, max(len(vlist1), len(vlist2))): 1706 # Implcit .0 is given a value of -1, so that 1.0.0 > 1.0, since it 1707 # would be ambiguous if two versions that aren't literally equal 1708 # are given the same value (in sorting, for example). 1709 if len(vlist1) <= i or len(vlist1[i]) == 0: 1710 list1.append(-1) 1711 list2.append(int(vlist2[i])) 1712 elif len(vlist2) <= i or len(vlist2[i]) == 0: 1713 list1.append(int(vlist1[i])) 1714 list2.append(-1) 1715 # Let's make life easy and use integers unless we're forced to use floats 1716 elif (vlist1[i][0] != "0" and vlist2[i][0] != "0"): 1717 list1.append(int(vlist1[i])) 1718 list2.append(int(vlist2[i])) 1719 # now we have to use floats so 1.02 compares correctly against 1.1 1720 else: 1721 list1.append(float("0."+vlist1[i])) 1722 list2.append(float("0."+vlist2[i])) 1723 1724 # and now the final letter 1725 if len(match1.group(5)): 1726 list1.append(ord(match1.group(5))) 1727 if len(match2.group(5)): 1728 list2.append(ord(match2.group(5))) 1729 1730 for i in range(0, max(len(list1), len(list2))): 1731 if len(list1) <= i: 1732 return -1 1733 elif len(list2) <= i: 1734 return 1 1735 elif list1[i] != list2[i]: 1736 return list1[i] - list2[i] 1737 1738 # main version is equal, so now compare the _suffix part 1739 list1 = match1.group(6).split("_")[1:] 1740 list2 = match2.group(6).split("_")[1:] 1741 1742 for i in range(0, max(len(list1), len(list2))): 1743 if len(list1) <= i: 1744 s1 = ("p","0") 1745 else: 1746 s1 = suffix_regexp.match(list1[i]).groups() 1747 if len(list2) <= i: 1748 s2 = ("p","0") 1749 else: 1750 s2 = suffix_regexp.match(list2[i]).groups() 1751 if s1[0] != s2[0]: 1752 return suffix_value[s1[0]] - suffix_value[s2[0]] 1753 if s1[1] != s2[1]: 1754 # it's possible that the s(1|2)[1] == '' 1755 # in such a case, fudge it. 1756 try: 1757 r1 = int(s1[1]) 1758 except ValueError: 1759 r1 = 0 1760 try: 1761 r2 = int(s2[1]) 1762 except ValueError: 1763 r2 = 0 1764 return r1 - r2 1765 1766 # the suffix part is equal to, so finally check the revision 1767 if match1.group(10): 1768 r1 = int(match1.group(10)) 1769 else: 1770 r1 = 0 1771 if match2.group(10): 1772 r2 = int(match2.group(10)) 1773 else: 1774 r2 = 0 1775 return r1 - r2
1776
1777 -def entropy_compare_versions(listA,listB):
1778 ''' 1779 @description: compare two lists composed by [version,tag,revision] and [version,tag,revision] 1780 if listA > listB --> positive number 1781 if listA == listB --> 0 1782 if listA < listB --> negative number 1783 @input package: listA[version,tag,rev] and listB[version,tag,rev] 1784 @output: integer number 1785 ''' 1786 1787 # if both are tagged, check tag first 1788 rc = 0 1789 if listA[1] and listB[1]: 1790 rc = cmp(listA[1],listB[1]) 1791 if rc == 0: 1792 rc = compare_versions(listA[0],listB[0]) 1793 1794 if rc == 0: 1795 # check tag 1796 if listA[1] > listB[1]: 1797 return 1 1798 elif listA[1] < listB[1]: 1799 return -1 1800 else: 1801 # check rev 1802 if listA[2] > listB[2]: 1803 return 1 1804 elif listA[2] < listB[2]: 1805 return -1 1806 else: 1807 return 0 1808 return rc
1809
1810 -def g_n_w_cmp(a,b):
1811 ''' 1812 @description: reorder a version list 1813 @input versionlist: a list 1814 @output: the ordered list 1815 ''' 1816 rc = compare_versions(a,b) 1817 if rc < 0: return -1 1818 elif rc > 0: return 1 1819 else: return 0
1820 -def get_newer_version(versions):
1821 return sorted(versions,g_n_w_cmp,reverse = True)
1822
1823 -def get_newer_version_stable(versions):
1824 1825 if len(versions) == 1: 1826 return versions 1827 1828 versionlist = versions[:] 1829 1830 rc = False 1831 while not rc: 1832 change = False 1833 for x in range(len(versionlist)): 1834 pkgA = versionlist[x] 1835 try: 1836 pkgB = versionlist[x+1] 1837 except: 1838 pkgB = "0" 1839 result = compare_versions(pkgA,pkgB) 1840 if result < 0: 1841 versionlist[x] = pkgB 1842 versionlist[x+1] = pkgA 1843 change = True 1844 if not change: 1845 rc = True 1846 1847 return versionlist
1848 1849
1850 -def g_e_n_w_cmp(a,b):
1851 ''' 1852 @description: reorder a version list 1853 @input versionlist: a list 1854 @output: the ordered list 1855 ''' 1856 rc = entropy_compare_versions(a,b) 1857 if rc < 0: return -1 1858 elif rc > 0: return 1 1859 else: return 0
1860
1861 -def get_entropy_newer_version(versions):
1862 return sorted(versions,g_e_n_w_cmp,reverse = True)
1863
1864 -def get_entropy_newer_version_stable(versions):
1865 ''' 1866 descendent order 1867 versions = [(version,tag,revision),(version,tag,revision)] 1868 ''' 1869 if len(versions) == 1: 1870 return versions 1871 1872 myversions = versions[:] 1873 # ease the work 1874 1875 rc = False 1876 while not rc: 1877 change = False 1878 for x in range(len(myversions)): 1879 pkgA = myversions[x] 1880 try: 1881 pkgB = myversions[x+1] 1882 except: 1883 pkgB = ("0","",0) 1884 result = entropy_compare_versions(pkgA,pkgB) 1885 if result < 0: 1886 myversions[x] = pkgB 1887 myversions[x+1] = pkgA 1888 change = True 1889 if not change: 1890 rc = True 1891 1892 return myversions
1893 1894
1895 -def isnumber(x):
1896 try: 1897 t = int(x) 1898 del t 1899 return True 1900 except: 1901 return False
1902 1903
1904 -def istextfile(filename, blocksize = 512):
1905 f = open(filename) 1906 r = istext(f.read(blocksize)) 1907 f.close() 1908 return r
1909
1910 -def istext(s):
1911 import string 1912 _null_trans = string.maketrans("", "") 1913 text_characters = "".join(map(chr, range(32, 127)) + list("\n\r\t\b")) 1914 1915 if "\0" in s: 1916 return False 1917 1918 if not s: # Empty files are considered text 1919 return True 1920 1921 # Get the non-text characters (maps a character to itself then 1922 # use the 'remove' option to get rid of the text characters.) 1923 t = s.translate(_null_trans, text_characters) 1924 1925 # If more than 30% non-text characters, then 1926 # this is considered a binary file 1927 if len(t)/len(s) > 0.30: 1928 return False 1929 return True
1930 1931 # this functions removes duplicates without breaking the list order 1932 # nameslist: a list that contains duplicated names 1933 # @returns filtered list
1934 -def filter_duplicated_entries(alist):
1935 mydata = {} 1936 return [mydata.setdefault(e,e) for e in alist if e not in mydata]
1937 1938 1939 # Escapeing functions 1940 mappings = { 1941 "'":"''", 1942 '"':'""', 1943 ' ':'+' 1944 } 1945
1946 -def escape(*args):
1947 arg_lst = [] 1948 if len(args)==1: 1949 return escape_single(args[0]) 1950 for x in args: 1951 arg_lst.append(escape_single(x)) 1952 return tuple(arg_lst)
1953
1954 -def escape_single(x):
1955 if type(x)==type(()) or type(x)==type([]): 1956 return escape(x) 1957 if type(x)==type(""): 1958 tmpstr='' 1959 for d in range(len(x)): 1960 if x[d] in mappings.keys(): 1961 if x[d] in ("'", '"'): 1962 if d+1<len(x): 1963 if x[d+1]!=x[d]: 1964 tmpstr+=mappings[x[d]] 1965 else: 1966 tmpstr+=mappings[x[d]] 1967 else: 1968 tmpstr+=mappings[x[d]] 1969 else: 1970 tmpstr+=x[d] 1971 else: 1972 tmpstr=x 1973 return tmpstr
1974
1975 -def unescape(val):
1976 if type(val)==type(""): 1977 tmpstr='' 1978 for key,item in mappings.items(): 1979 val=val.replace(item,key) 1980 tmpstr = val 1981 else: 1982 tmpstr=val 1983 return tmpstr
1984
1985 -def unescape_list(*args):
1986 arg_lst = [] 1987 for x in args: 1988 arg_lst.append(unescape(x)) 1989 return tuple(arg_lst)
1990
1991 -def extract_ftp_host_from_uri(uri):
1992 myuri = spliturl(uri)[1] 1993 # remove username:pass@ 1994 myuri = myuri.split("@")[len(myuri.split("@"))-1] 1995 return myuri
1996
1997 -def spliturl(url):
1998 import urlparse 1999 return urlparse.urlsplit(url)
2000
2001 -def compress_tar_bz2(storepath, pathtocompress):
2002 cmd = "cd \""+pathtocompress+"\" && tar cjf \""+storepath+"\" " + \ 2003 ". &> /dev/null" 2004 return subprocess.call(cmd, shell = True)
2005
2006 -def spawn_function(f, *args, **kwds):
2007 2008 uid = kwds.get('spf_uid') 2009 if uid != None: kwds.pop('spf_uid') 2010 2011 gid = kwds.get('spf_gid') 2012 if gid != None: kwds.pop('spf_gid') 2013 2014 write_pid_func = kwds.get('write_pid_func') 2015 if write_pid_func != None: 2016 kwds.pop('write_pid_func') 2017 2018 try: 2019 import cPickle as pickle 2020 except ImportError: 2021 import pickle 2022 pread, pwrite = os.pipe() 2023 pid = os.fork() 2024 if pid > 0: 2025 if write_pid_func != None: 2026 write_pid_func(pid) 2027 os.close(pwrite) 2028 f = os.fdopen(pread, 'rb') 2029 status, result = pickle.load(f) 2030 os.waitpid(pid, 0) 2031 f.close() 2032 if status == 0: 2033 return result 2034 else: 2035 raise result 2036 else: 2037 os.close(pread) 2038 if gid != None: 2039 os.setgid(gid) 2040 if uid != None: 2041 os.setuid(uid) 2042 try: 2043 result = f(*args, **kwds) 2044 status = 0 2045 except Exception, exc: 2046 result = exc 2047 status = 1 2048 f = os.fdopen(pwrite, 'wb') 2049 try: 2050 pickle.dump((status,result), f, pickle.HIGHEST_PROTOCOL) 2051 except pickle.PicklingError, exc: 2052 pickle.dump((2,exc), f, pickle.HIGHEST_PROTOCOL) 2053 f.close() 2054 os._exit(0)
2055 2056 # tar* uncompress function...
2057 -def uncompress_tar_bz2(filepath, extractPath = None, catchEmpty = False):
2058 2059 if extractPath == None: 2060 extractPath = os.path.dirname(filepath) 2061 if not os.path.isfile(filepath): 2062 raise FileNotFound('FileNotFound: archive does not exist') 2063 2064 try: 2065 tar = tarfile.open(filepath,"r") 2066 except tarfile.ReadError: 2067 if catchEmpty: 2068 return 0 2069 raise 2070 except EOFError: 2071 return -1 2072 2073 def fix_uid_gid(tarinfo, epath): 2074 # workaround for buggy tar files 2075 uname = tarinfo.uname 2076 gname = tarinfo.gname 2077 ugdata_valid = False 2078 try: 2079 int(gname) 2080 int(uname) 2081 except ValueError: 2082 ugdata_valid = True 2083 try: 2084 if ugdata_valid: # FIXME: will be removed in 2011 2085 # get uid/gid 2086 # if not found, returns -1 that won't change anything 2087 uid, gid = get_uid_from_user(uname), \ 2088 get_gid_from_group(gname) 2089 os.lchown(epath, uid, gid) 2090 except OSError: 2091 pass
2092 2093 def mycmp(a,b): 2094 return cmp(a[0].name, b[0].name) 2095 2096 try: 2097 2098 encoded_path = extractPath.encode('utf-8') 2099 def mymf(tarinfo): 2100 epath = os.path.join(encoded_path, tarinfo.name) 2101 if tarinfo.isdir(): 2102 # Extract directory with a safe mode, so that 2103 # all files below can be extracted as well. 2104 try: 2105 os.makedirs(epath, 0777) 2106 except EnvironmentError: 2107 pass 2108 return tarinfo, epath 2109 2110 tar.extract(tarinfo, encoded_path) 2111 2112 del tar.members[:] 2113 return tarinfo, epath 2114 2115 entries = sorted(map(mymf, tar), mycmp, reverse = True) 2116 2117 # Set correct owner, mtime and filemode on directories. 2118 def mymf2(tardata): 2119 tarinfo, epath = tardata 2120 try: 2121 2122 tar.chown(tarinfo, epath) 2123 fix_uid_gid(tarinfo, epath) 2124 tar.utime(tarinfo, epath) 2125 mode = tarinfo.mode 2126 # xorg-server /usr/bin/X symlink of /usr/bin/Xorg 2127 # which is setuid. Symlinks don't need chmod. PERIOD! 2128 if not os.path.islink(epath): 2129 tar.chmod(tarinfo, epath) 2130 2131 except tarfile.ExtractError: 2132 if tar.errorlevel > 1: 2133 raise 2134 2135 done = map(mymf2, entries) 2136 del done 2137 2138 except EOFError: 2139 return -1 2140 2141 finally: 2142 tar.close() 2143 2144 if os.listdir(extractPath): 2145 return 0 2146 return -1 2147
2148 -def bytes_into_human(bytes):
2149 size = str(round(float(bytes)/1024,1)) 2150 if bytes < 1024: 2151 size = str(round(float(bytes)))+"b" 2152 elif bytes < 1023999: 2153 size += "kB" 2154 elif bytes > 1023999: 2155 size = str(round(float(size)/1024,1)) 2156 size += "MB" 2157 return size
2158
2159 -def hide_ftp_password(uri):
2160 ftppassword = uri.split("@")[:-1] 2161 if not ftppassword: return uri 2162 ftppassword = '@'.join(ftppassword) 2163 ftppassword = ftppassword.split(":")[-1] 2164 if not ftppassword: 2165 return uri 2166 newuri = uri.replace(ftppassword,"xxxxxxxx") 2167 return newuri
2168
2169 -def extract_ftp_data(ftpuri):
2170 ftpuser = ftpuri.split("ftp://")[-1].split(":")[0] 2171 if (ftpuser == ""): 2172 ftpuser = "anonymous@" 2173 ftppassword = "anonymous" 2174 else: 2175 ftppassword = ftpuri.split("@")[:-1] 2176 if len(ftppassword) > 1: 2177 ftppassword = '@'.join(ftppassword) 2178 ftppassword = ftppassword.split(":")[-1] 2179 if (ftppassword == ""): 2180 ftppassword = "anonymous" 2181 else: 2182 ftppassword = ftppassword[0] 2183 ftppassword = ftppassword.split(":")[-1] 2184 if (ftppassword == ""): 2185 ftppassword = "anonymous" 2186 2187 ftpport = ftpuri.split(":")[-1] 2188 try: 2189 ftpport = int(ftpport) 2190 except ValueError: 2191 ftpport = 21 2192 2193 ftpdir = '/' 2194 if ftpuri.count("/") > 2: 2195 ftpdir = ftpuri.split("ftp://")[-1] 2196 ftpdir = ftpdir.split("/")[-1] 2197 ftpdir = ftpdir.split(":")[0] 2198 if ftpdir.endswith("/"): 2199 ftpdir = ftpdir[:len(ftpdir)-1] 2200 if not ftpdir: ftpdir = "/" 2201 2202 return ftpuser, ftppassword, ftpport, ftpdir
2203
2204 -def get_file_unix_mtime(path):
2205 return os.path.getmtime(path)
2206
2207 -def get_random_temp_file():
2208 if not os.path.isdir(etpConst['packagestmpdir']): 2209 os.makedirs(etpConst['packagestmpdir']) 2210 path = os.path.join(etpConst['packagestmpdir'],"temp_"+str(get_random_number())) 2211 while os.path.lexists(path): 2212 path = os.path.join(etpConst['packagestmpdir'],"temp_"+str(get_random_number())) 2213 return path
2214
2215 -def get_file_timestamp(path):
2216 from datetime import datetime 2217 # used in this way for convenience 2218 unixtime = os.path.getmtime(path) 2219 humantime = datetime.fromtimestamp(unixtime) 2220 # format properly 2221 humantime = str(humantime) 2222 outputtime = "" 2223 for char in humantime: 2224 if char != "-" and char != " " and char != ":": 2225 outputtime += char 2226 return outputtime
2227
2228 -def convert_unix_time_to_human_time(unixtime):
2229 from datetime import datetime 2230 humantime = str(datetime.fromtimestamp(unixtime)) 2231 return humantime
2232
2233 -def convert_unix_time_to_datetime(unixtime):
2234 from datetime import datetime 2235 return datetime.fromtimestamp(unixtime)
2236
2237 -def get_current_unix_time():
2238 return time.time()
2239
2240 -def get_year():
2241 return time.strftime("%Y")
2242
2243 -def convert_seconds_to_fancy_output(seconds):
2244 2245 mysecs = seconds 2246 myminutes = 0 2247 myhours = 0 2248 mydays = 0 2249 2250 while mysecs >= 60: 2251 mysecs -= 60 2252 myminutes += 1 2253 2254 while myminutes >= 60: 2255 myminutes -= 60 2256 myhours += 1 2257 2258 while myhours >= 24: 2259 myhours -= 24 2260 mydays += 1 2261 2262 output = [] 2263 output.append(str(mysecs)+"s") 2264 if myminutes > 0 or myhours > 0: 2265 output.append(str(myminutes)+"m") 2266 if myhours > 0 or mydays > 0: 2267 output.append(str(myhours)+"h") 2268 if mydays > 0: 2269 output.append(str(mydays)+"d") 2270 output.reverse() 2271 return ':'.join(output)
2272 2273 # Temporary files cleaner
2274 -def cleanup(toCleanDirs = []):
2275 2276 if not toCleanDirs: 2277 toCleanDirs = [ etpConst['packagestmpdir'], etpConst['logdir'] ] 2278 counter = 0 2279 2280 for xdir in toCleanDirs: 2281 print_info(red(" * ")+"Cleaning "+darkgreen(xdir)+" directory...", back = True) 2282 if os.path.isdir(xdir): 2283 dircontent = os.listdir(xdir) 2284 if dircontent != []: 2285 for data in dircontent: 2286 subprocess.call(["rm","-rf",os.path.join(xdir,data)]) 2287 counter += 1 2288 2289 print_info(green(" * ")+"Cleaned: "+str(counter)+" files and directories") 2290 return 0
2291
2292 -def flatten(l, ltypes=(list, tuple)):
2293 i = 0 2294 while i < len(l): 2295 while isinstance(l[i], ltypes): 2296 if not l[i]: 2297 l.pop(i) 2298 if not len(l): 2299 break 2300 else: 2301 l[i:i+1] = list(l[i]) 2302 i += 1 2303 return l
2304
2305 -def read_repositories_conf():
2306 content = [] 2307 if os.path.isfile(etpConst['repositoriesconf']): 2308 f = open(etpConst['repositoriesconf']) 2309 content = f.readlines() 2310 f.close() 2311 return content
2312
2313 -def write_ordered_repositories_entries(ordered_repository_list):
2314 content = read_repositories_conf() 2315 content = [x.strip() for x in content] 2316 repolines = [x for x in content if x.startswith("repository|") and (len(x.split("|")) == 5)] 2317 content = [x for x in content if x not in repolines] 2318 for repoid in ordered_repository_list: 2319 # get repoid from repolines 2320 for x in repolines: 2321 repoidline = x.split("|")[1] 2322 if repoid == repoidline: 2323 content.append(x) 2324 _save_repositories_content(content)
2325
2326 -def save_repository_settings(repodata, remove = False, disable = False, enable = False):
2327 2328 if repodata['repoid'].endswith(".tbz2"): 2329 return 2330 2331 content = read_repositories_conf() 2332 content = [x.strip() for x in content] 2333 if not disable and not enable: 2334 content = [x for x in content if not x.startswith("repository|"+repodata['repoid'])] 2335 if remove: 2336 # also remove possible disable repo 2337 content = [x for x in content if not (x.startswith("#") and not x.startswith("##") and (x.find("repository|"+repodata['repoid']) != -1))] 2338 if not remove: 2339 2340 repolines = [x for x in content if x.startswith("repository|") or (x.startswith("#") and not x.startswith("##") and (x.find("repository|") != -1))] 2341 content = [x for x in content if x not in repolines] # exclude lines from repolines 2342 # filter sane repolines lines 2343 repolines = [x for x in repolines if (len(x.split("|")) == 5)] 2344 repolines_data = {} 2345 repocount = 0 2346 for x in repolines: 2347 repolines_data[repocount] = {} 2348 repolines_data[repocount]['repoid'] = x.split("|")[1] 2349 repolines_data[repocount]['line'] = x 2350 if disable and x.split("|")[1] == repodata['repoid']: 2351 if not x.startswith("#"): 2352 x = "#"+x 2353 repolines_data[repocount]['line'] = x 2354 elif enable and x.split("|")[1] == repodata['repoid'] and x.startswith("#"): 2355 repolines_data[repocount]['line'] = x[1:] 2356 repocount += 1 2357 2358 if not disable and not enable: # so it's a add 2359 2360 line = "repository|%s|%s|%s|%s#%s#%s,%s" % ( repodata['repoid'], 2361 repodata['description'], 2362 ' '.join(repodata['plain_packages']), 2363 repodata['plain_database'], 2364 repodata['dbcformat'], 2365 repodata['service_port'], 2366 repodata['ssl_service_port'], 2367 ) 2368 2369 # seek in repolines_data for a disabled entry and remove 2370 to_remove = set() 2371 for cc in repolines_data: 2372 if repolines_data[cc]['line'].startswith("#") and \ 2373 (repolines_data[cc]['line'].find("repository|"+repodata['repoid']) != -1): 2374 # then remove 2375 to_remove.add(cc) 2376 for x in to_remove: 2377 del repolines_data[x] 2378 2379 repolines_data[repocount] = {} 2380 repolines_data[repocount]['repoid'] = repodata['repoid'] 2381 repolines_data[repocount]['line'] = line 2382 2383 # inject new repodata 2384 keys = repolines_data.keys() 2385 keys.sort() 2386 for cc in keys: 2387 #repoid = repolines_data[cc]['repoid'] 2388 # write the first 2389 line = repolines_data[cc]['line'] 2390 content.append(line) 2391 2392 try: 2393 _save_repositories_content(content) 2394 except OSError: # permission denied? 2395 return False 2396 return True
2397
2398 -def _save_repositories_content(content):
2399 if os.path.isfile(etpConst['repositoriesconf']): 2400 if os.path.isfile(etpConst['repositoriesconf']+".old"): 2401 os.remove(etpConst['repositoriesconf']+".old") 2402 shutil.copy2(etpConst['repositoriesconf'],etpConst['repositoriesconf']+".old") 2403 f = open(etpConst['repositoriesconf'],"w") 2404 for x in content: 2405 f.write(x+"\n") 2406 f.flush() 2407 f.close()
2408
2409 -def write_parameter_to_file(config_file, name, data):
2410 2411 # check write perms 2412 if not os.access(os.path.dirname(config_file),os.W_OK): 2413 return False 2414 2415 content = [] 2416 if os.path.isfile(config_file): 2417 f = open(config_file,"r") 2418 content = [x.strip() for x in f.readlines()] 2419 f.close() 2420 2421 # write new 2422 config_file_tmp = config_file+".tmp" 2423 f = open(config_file_tmp,"w") 2424 param_found = False 2425 if data: 2426 proposed_line = "%s|%s" % (name,data,) 2427 myreg = re.compile('^(%s)?[|].*$' % (name,)) 2428 else: 2429 proposed_line = "# %s|" % (name,) 2430 myreg_rem = re.compile('^(%s)?[|].*$' % (name,)) 2431 myreg = re.compile('^#([ \t]+?)?(%s)?[|].*$' % (name,)) 2432 new_content = [] 2433 for line in content: 2434 if myreg_rem.match(line): 2435 continue 2436 new_content.append(line) 2437 content = new_content 2438 2439 for line in content: 2440 if myreg.match(line): 2441 param_found = True 2442 line = proposed_line 2443 f.write(line+"\n") 2444 if not param_found: 2445 f.write(proposed_line+"\n") 2446 f.flush() 2447 f.close() 2448 shutil.move(config_file_tmp,config_file) 2449 return True
2450
2451 -def write_new_branch(branch):
2452 return write_parameter_to_file(etpConst['repositoriesconf'],"branch",branch)
2453
2454 -def is_entropy_package_file(tbz2file):
2455 if not os.path.exists(tbz2file): 2456 return False 2457 try: 2458 obj = open(tbz2file, "r") 2459 entry_point = locate_edb(obj) 2460 if entry_point is None: 2461 obj.close() 2462 return False 2463 obj.close() 2464 return True 2465 except (IOError, OSError,): 2466 return False
2467
2468 -def is_valid_string(string):
2469 invalid = [ord(x) for x in string if ord(x) not in xrange(32,127)] 2470 if invalid: return False 2471 return True
2472
2473 -def is_valid_path(path):
2474 try: 2475 os.stat(path) 2476 except OSError: 2477 return False 2478 return True
2479
2480 -def is_valid_md5(myhash):
2481 if re.findall(r'(?i)(?<![a-z0-9])[a-f0-9]{32}(?![a-z0-9])', myhash): 2482 return True 2483 return False
2484
2485 -def open_buffer():
2486 try: 2487 import cStringIO as stringio 2488 except ImportError: 2489 import StringIO as stringio 2490 return stringio.StringIO()
2491
2492 -def seek_till_newline(f):
2493 count = 0 2494 f.seek(count, os.SEEK_END) 2495 size = f.tell() 2496 while count > (size*-1): 2497 count -= 1 2498 f.seek(count, os.SEEK_END) 2499 myc = f.read(1) 2500 if myc == "\n": 2501 break 2502 f.seek(count+1, os.SEEK_END) 2503 pos = f.tell() 2504 f.truncate(pos)
2505
2506 -def read_elf_class(elf_file):
2507 import struct 2508 f = open(elf_file,"rb") 2509 f.seek(4) 2510 elf_class = f.read(1) 2511 f.close() 2512 elf_class = struct.unpack('B',elf_class)[0] 2513 return elf_class
2514
2515 -def is_elf_file(elf_file):
2516 import struct 2517 f = open(elf_file,"rb") 2518 data = f.read(4) 2519 f.close() 2520 try: 2521 data = struct.unpack('BBBB',data) 2522 except struct.error: 2523 return False 2524 if data == (127, 69, 76, 70): 2525 return True 2526 return False
2527
2528 -def resolve_dynamic_library(library, requiring_executable):
2529 """ 2530 Resolve given library name (as contained into ELF metadata) to 2531 a library path. 2532 2533 @param library: library name (as contained into ELF metadata) 2534 @type library: string 2535 @param requiring_executable: path to ELF object that contains the given 2536 library name 2537 @type requiring_executable: string 2538 @return: resolved library path 2539 @rtype: string 2540 """ 2541 def do_resolve(mypaths): 2542 found_path = None 2543 for mypath in mypaths: 2544 mypath = os.path.join(etpConst['systemroot']+mypath, library) 2545 if not os.access(mypath, os.R_OK): 2546 continue 2547 if os.path.isdir(mypath): 2548 continue 2549 if not is_elf_file(mypath): 2550 continue 2551 found_path = mypath 2552 break 2553 return found_path
2554 2555 mypaths = collect_linker_paths() 2556 found_path = do_resolve(mypaths) 2557 2558 if not found_path: 2559 mypaths = read_elf_linker_paths(requiring_executable) 2560 found_path = do_resolve(mypaths) 2561 2562 return found_path 2563 2564 readelf_avail_check = False 2565 ldd_avail_check = False
2566 -def read_elf_dynamic_libraries(elf_file):
2567 global readelf_avail_check 2568 if not readelf_avail_check: 2569 if not os.access(etpConst['systemroot']+"/usr/bin/readelf",os.X_OK): 2570 raise FileNotFound('FileNotFound: no readelf') 2571 readelf_avail_check = True 2572 return set([x.strip().split()[-1][1:-1] for x in getstatusoutput('/usr/bin/readelf -d %s' % (elf_file,))[1].split("\n") if (x.find("(NEEDED)") != -1)])
2573
2574 -def read_elf_broken_symbols(elf_file):
2575 global ldd_avail_check 2576 if not ldd_avail_check: 2577 if not os.access(etpConst['systemroot']+"/usr/bin/ldd",os.X_OK): 2578 raise FileNotFound('FileNotFound: no ldd') 2579 ldd_avail_check = True 2580 return set([x.strip().split("\t")[0].split()[-1] for x in getstatusoutput('/usr/bin/ldd -r %s' % (elf_file,))[1].split("\n") if (x.find("undefined symbol:") != -1)])
2581
2582 -def read_elf_linker_paths(elf_file):
2583 global readelf_avail_check 2584 if not readelf_avail_check: 2585 if not os.access(etpConst['systemroot']+"/usr/bin/readelf",os.X_OK): 2586 raise FileNotFound('FileNotFound: no readelf') 2587 readelf_avail_check = True 2588 data = [x.strip().split()[-1][1:-1].split(":") for x in getstatusoutput('readelf -d %s' % (elf_file,))[1].split("\n") if not ((x.find("(RPATH)") == -1) and (x.find("(RUNPATH)") == -1))] 2589 mypaths = [] 2590 for mypath in data: 2591 for xpath in mypath: 2592 xpath = xpath.replace("$ORIGIN",os.path.dirname(elf_file)) 2593 mypaths.append(xpath) 2594 return mypaths
2595
2596 -def xml_from_dict_extended(dictionary):
2597 from xml.dom import minidom 2598 doc = minidom.Document() 2599 ugc = doc.createElement("entropy") 2600 for key, value in dictionary.items(): 2601 item = doc.createElement('item') 2602 item.setAttribute('value',key) 2603 if isinstance(value,str): 2604 mytype = "str" 2605 elif isinstance(value,unicode): 2606 mytype = "unicode" 2607 elif isinstance(value,list): 2608 mytype = "list" 2609 elif isinstance(value,set): 2610 mytype = "set" 2611 elif isinstance(value,frozenset): 2612 mytype = "frozenset" 2613 elif isinstance(value,dict): 2614 mytype = "dict" 2615 elif isinstance(value,tuple): 2616 mytype = "tuple" 2617 elif isinstance(value,int): 2618 mytype = "int" 2619 elif isinstance(value,float): 2620 mytype = "float" 2621 elif value == None: 2622 mytype = "None" 2623 value = "None" 2624 else: raise TypeError 2625 item.setAttribute('type',mytype) 2626 item_value = doc.createTextNode("%s" % (value,)) 2627 item.appendChild(item_value) 2628 ugc.appendChild(item) 2629 doc.appendChild(ugc) 2630 return doc.toxml()
2631
2632 -def dict_from_xml_extended(xml_string):
2633 from xml.dom import minidom 2634 doc = minidom.parseString(xml_string) 2635 entropies = doc.getElementsByTagName("entropy") 2636 if not entropies: return {} 2637 entropy = entropies[0] 2638 items = entropy.getElementsByTagName('item') 2639 2640 my_map = { 2641 "str": str, 2642 "unicode": unicode, 2643 "list": list, 2644 "set": set, 2645 "frozenset": frozenset, 2646 "dict": dict, 2647 "tuple": tuple, 2648 "int": int, 2649 "float": float, 2650 "None": None, 2651 } 2652 2653 mydict = {} 2654 for item in items: 2655 key = item.getAttribute('value') 2656 if not key: continue 2657 mytype = item.getAttribute('type') 2658 mytype_m = my_map.get(mytype) 2659 if mytype_m == None: raise TypeError 2660 try: 2661 data = item.firstChild.data 2662 except AttributeError: 2663 data = '' 2664 if mytype in ("list","set","frozenset","dict","tuple",): 2665 if data: 2666 if data[0] not in ("(","[","s","{",): data = '' 2667 mydict[key] = eval(data) 2668 elif mytype == "None": 2669 mydict[key] = None 2670 else: 2671 mydict[key] = mytype_m(data) 2672 return mydict
2673
2674 -def xml_from_dict(dictionary):
2675 from xml.dom import minidom 2676 doc = minidom.Document() 2677 ugc = doc.createElement("entropy") 2678 for key, value in dictionary.items(): 2679 item = doc.createElement('item') 2680 item.setAttribute('value',key) 2681 item_value = doc.createTextNode(value) 2682 item.appendChild(item_value) 2683 ugc.appendChild(item) 2684 doc.appendChild(ugc) 2685 return doc.toxml()
2686
2687 -def dict_from_xml(xml_string):
2688 from xml.dom import minidom 2689 doc = minidom.parseString(xml_string) 2690 entropies = doc.getElementsByTagName("entropy") 2691 if not entropies: 2692 return {} 2693 entropy = entropies[0] 2694 items = entropy.getElementsByTagName('item') 2695 mydict = {} 2696 for item in items: 2697 key = item.getAttribute('value') 2698 if not key: continue 2699 try: 2700 data = item.firstChild.data 2701 except AttributeError: 2702 data = '' 2703 mydict[key] = data 2704 return mydict
2705
2706 -def create_package_filename(category, name, version, package_tag):
2707 if package_tag: 2708 package_tag = "#%s" % (package_tag,) 2709 else: 2710 package_tag = '' 2711 2712 package_name = "%s:%s-%s" % (category, name, version,) 2713 package_name += package_tag 2714 package_name += etpConst['packagesext'] 2715 return package_name
2716
2717 -def create_package_atom_string(category, name, version, package_tag):
2718 if package_tag: 2719 package_tag = "#%s" % (package_tag,) 2720 else: 2721 package_tag = '' 2722 package_name = "%s/%s-%s" % (category,name,version,) 2723 package_name += package_tag 2724 return package_name
2725
2726 -def extract_packages_from_set_file(filepath):
2727 f = open(filepath,"r") 2728 items = set() 2729 line = f.readline() 2730 while line: 2731 x = line.strip().rsplit("#",1)[0] 2732 if x and (not x.startswith('#')): 2733 items.add(x) 2734 line = f.readline() 2735 f.close() 2736 return items
2737
2738 -def collect_linker_paths():
2739 2740 ldpaths = [] 2741 try: 2742 f = open(etpConst['systemroot']+"/etc/ld.so.conf","r") 2743 paths = f.readlines() 2744 for path in paths: 2745 path = path.strip() 2746 if path: 2747 if path[0] == "/": 2748 ldpaths.append(os.path.normpath(path)) 2749 f.close() 2750 except (IOError,OSError,TypeError,ValueError,IndexError,): 2751 pass 2752 2753 # can happen that /lib /usr/lib are not in LDPATH 2754 if "/lib" not in ldpaths: 2755 ldpaths.append("/lib") 2756 if "/usr/lib" not in ldpaths: 2757 ldpaths.append("/usr/lib") 2758 2759 return ldpaths
2760
2761 -def collect_paths():
2762 path = set() 2763 paths = os.getenv("PATH") 2764 if paths != None: 2765 paths = set(paths.split(":")) 2766 path |= paths 2767 return path
2768
2769 -def list_to_utf8(mylist):
2770 mynewlist = [] 2771 for item in mylist: 2772 try: 2773 mynewlist.append(item.decode("utf-8")) 2774 except UnicodeDecodeError: 2775 try: 2776 mynewlist.append(item.decode("latin1").decode("utf-8")) 2777 except: 2778 raise 2779 return mynewlist
2780