1 """
2
3 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
4 @contact: lxnay@sabayonlinux.org
5 @copyright: Fabio Erculiani
6 @license: GPL-2
7
8 B{Entropy Framework constants module}.
9
10 This module contains all the Entropy constants used all around
11 the "entropy" package.
12
13 Some of the constants in this module are used as "default" for
14 the SystemSettings interface. So, make sure to read the documentation
15 of SystemSettings in the "entropy.core" module.
16
17 Even if possible, etpConst, etpUi, etpCache and etpSys objects
18 *SHOULD* be I{never ever modified manually}. This freedom could change
19 in future, so, if you want to produce a stable code, DON'T do that at all!
20
21 Basic Entropy constants handling functions are available in this module
22 and are all prefixed with "I{const_*}" or "I{initconfig_*}".
23 If you are writing a third party application, you should always try
24 to avoid to deal directly with functions here unless specified otherwise.
25 In fact, usually these here are wrapper in upper-level modules
26 (entropy.client, entropy.server, entropy.services).
27
28
29 """
30
31
32 from __future__ import with_statement
33 import sys, os, stat
34 from entropy.i18n import _
35 import gzip
36 import bz2
37
38
39
40 ETP_ARCH_MAP = {
41 ("i386", "i486", "i586", "i686",): "x86",
42 ("x86_64",): "amd64",
43 ("sun4u",): None,
44 ("ppc",): None,
45 }
46 _uname_m = os.uname()[4]
47 ETP_ARCH_CONST = 'UNKNOWN'
48 for arches, arch in ETP_ARCH_MAP.items():
49 if _uname_m in arches:
50 ETP_ARCH_CONST = arch
51
52 etpSys = {
53 'archs': ["x86", "amd64"],
54 'keywords': set([ETP_ARCH_CONST,"~"+ETP_ARCH_CONST]),
55 'api': '3',
56 'arch': ETP_ARCH_CONST,
57 'rootdir': "",
58 'maxthreads': 100,
59 'dirstoclean': set(),
60 'serverside': False,
61 'killpids': set(),
62 }
63
64 etpUi = {
65 'debug': False,
66 'quiet': False,
67 'verbose': False,
68 'ask': False,
69 'pretend': False,
70 'mute': False,
71 'nolog': False,
72 'clean': False,
73 'warn': True,
74 }
75 if "--debug" in sys.argv:
76 etpUi['debug'] = True
77
78
79 ETP_LOGLEVEL_NORMAL = 1
80 ETP_LOGLEVEL_VERBOSE = 2
81 ETP_LOGPRI_INFO = "[ INFO ]"
82 ETP_LOGPRI_WARNING = "[ WARNING ]"
83 ETP_LOGPRI_ERROR = "[ ERROR ]"
84
85
86 etpCache = {
87
88
89 'configfiles': 'conf/scanfs',
90 'dbMatch': 'match/db',
91 'dbSearch': 'search/db',
92
93 'atomMatch': 'atom_match/atom_match_',
94 'install': 'resume/resume_install',
95 'remove': 'resume/resume_remove',
96 'world': 'resume/resume_world',
97 'world_update': 'world_update/world_cache_',
98 'critical_update': 'critical_update/critical_cache_',
99 'world_available': 'world_available/available_cache_',
100 'check_package_update': 'check_update/package_update_',
101 'advisories': 'security/advisories_cache_',
102 'dep_tree': 'deptree/dep_tree_',
103 'depends_tree': 'depends/depends_tree_',
104 'filter_satisfied_deps': 'depfilter/filter_satisfied_deps_',
105 'library_breakage': 'libs_break/library_breakage_',
106 'repolist': 'repos/repolist',
107 'repository_server': 'reposerver/item',
108 'eapi3_fetch': 'eapi3/segment_',
109 'ugc_votes': 'ugc/ugc_votes',
110 'ugc_downloads': 'ugc/ugc_downloads',
111 'ugc_docs': 'ugc/ugc_docs',
112 'ugc_srv_cache': 'ugc/ugc_srv_cache'
113 }
114
115 etpConst = {}
116
118
119 """
120 Main constants configurators, this is the only function that you should
121 call from the outside, anytime you want. it will reset all the variables
122 excluding those backed up previously.
123
124 @param rootdir: current root directory, if any, or ""
125 @type rootdir: string
126 @rtype: None
127 @return: None
128 @raise AttributeError: when specified rootdir is not a directory
129 """
130
131 if rootdir and not os.path.isdir(rootdir):
132 raise AttributeError("not a valid chroot.")
133
134
135 if etpConst.has_key('backed_up'):
136 backed_up_settings = etpConst.pop('backed_up')
137 else:
138 backed_up_settings = {}
139
140 const_default_settings(rootdir)
141 const_read_entropy_release()
142 const_create_working_dirs()
143 const_setup_entropy_pid()
144 const_configure_lock_paths()
145
146
147 etpConst.update(backed_up_settings)
148 etpConst['backed_up'] = backed_up_settings.copy()
149
150 if sys.excepthook == sys.__excepthook__:
151 sys.excepthook = __const_handle_exception
152
154
155 """
156 Initialization of all the Entropy base settings.
157
158 @param rootdir: current root directory, if any, or ""
159 @type rootdir: string
160 @rtype: None
161 @return: None
162 """
163
164 default_etp_dir = rootdir+"/var/lib/entropy"
165 default_etp_tmpdir = "/tmp"
166 default_etp_repodir = "/packages/"+ETP_ARCH_CONST
167 default_etp_portdir = rootdir+"/usr/portage"
168 default_etp_distfilesdir = "/distfiles"
169 default_etp_dbdir = "/database/"+ETP_ARCH_CONST
170 default_etp_dbfile = "packages.db"
171 default_etp_dbclientfile = "equo.db"
172 default_etp_client_repodir = "/client"
173 default_etp_triggersdir = "/triggers/"+ETP_ARCH_CONST
174 default_etp_smartappsdir = "/smartapps/"+ETP_ARCH_CONST
175 default_etp_smartpackagesdir = "/smartpackages/"+ETP_ARCH_CONST
176 default_etp_cachesdir = "/caches/"
177 default_etp_securitydir = "/glsa/"
178 default_etp_setsdirname = "sets"
179 default_etp_setsdir = "/%s/" % (default_etp_setsdirname,)
180 default_etp_logdir = default_etp_dir+"/"+"logs"
181 default_etp_confdir = rootdir+"/etc/entropy"
182 default_etp_packagesdir = default_etp_confdir+"/packages"
183 default_etp_ugc_confdir = default_etp_confdir+"/ugc"
184 default_etp_syslogdir = rootdir+"/var/log/entropy/"
185 default_etp_vardir = rootdir+"/var/tmp/entropy"
186 edb_counter = rootdir+"/var/cache/edb/counter"
187
188 cmdline = []
189 cmdline_file = "/proc/cmdline"
190 if os.access(cmdline_file, os.R_OK) and os.path.isfile(cmdline_file):
191 with open(cmdline_file, "r") as cmdline_f:
192 cmdline = cmdline_f.readline().strip().split()
193
194 etpConst.clear()
195 my_const = {
196 'server_repositories': {},
197 'community': {
198 'mode': False,
199 },
200 'cmdline': cmdline,
201 'backed_up': {},
202
203 'installdir': '/usr/lib/entropy',
204
205 'packagestmpdir': default_etp_dir+default_etp_tmpdir,
206
207
208
209
210
211 'packagesbindir': default_etp_dir+default_etp_repodir,
212
213 'smartappsdir': default_etp_dir+default_etp_smartappsdir,
214
215
216 'smartpackagesdir': default_etp_dir+default_etp_smartpackagesdir,
217
218 'triggersdir': default_etp_dir+default_etp_triggersdir,
219
220 'portagetreedir': default_etp_portdir,
221
222 'distfilesdir': default_etp_portdir+default_etp_distfilesdir,
223
224 'confdir': default_etp_confdir,
225
226 'confpackagesdir': default_etp_packagesdir,
227
228 'confsetsdir': default_etp_packagesdir+default_etp_setsdir,
229
230 'confsetsdirname': default_etp_setsdirname,
231
232 'entropyconf': default_etp_confdir+"/entropy.conf",
233
234 'repositoriesconf': default_etp_confdir+"/repositories.conf",
235
236 'serverconf': default_etp_confdir+"/server.conf",
237
238 'clientconf': default_etp_confdir+"/client.conf",
239
240 'socketconf': default_etp_confdir+"/socket.conf",
241
242 'packagesrelativepath': "packages/"+ETP_ARCH_CONST+"/",
243
244 'entropyworkdir': default_etp_dir,
245
246 'entropyunpackdir': default_etp_vardir,
247
248 'entropyimagerelativepath': "image",
249
250 'entropyxpakrelativepath': "xpak",
251
252 'entropyxpakdatarelativepath': "data",
253
254 'entropyxpakfilename': "metadata.xpak",
255
256
257 'etpdatabasetimestampfile': default_etp_dbfile+".timestamp",
258
259 'etpdatabasepkglist': default_etp_dbfile+".pkglist",
260 'etpdatabaseconflictingtaggedfile': default_etp_dbfile + \
261 ".conflicting_tagged",
262
263
264 'etpdatabasesytemmaskfile': default_etp_dbfile+".system_mask",
265 'etpdatabasemaskfile': default_etp_dbfile+".mask",
266 'etpdatabaseupdatefile': default_etp_dbfile+".repo_updates",
267 'etpdatabaselicwhitelistfile': default_etp_dbfile+".lic_whitelist",
268 'etpdatabasecriticalfile': default_etp_dbfile+".critical",
269
270 'etpdatabaserevisionfile': default_etp_dbfile+".revision",
271
272 'etpdatabasemissingdepsblfile': default_etp_dbfile + \
273 ".missing_deps_blacklist",
274
275
276 'etpdatabasemetafilesfile': default_etp_dbfile+".meta",
277
278
279 'etpdatabasemetafilesnotfound': default_etp_dbfile+".meta_notfound",
280 'etpdatabasehashfile': default_etp_dbfile+".md5",
281
282
283
284 'etpdatabaselockfile': default_etp_dbfile+".lock",
285
286 'etpdatabaseeapi3lockfile': default_etp_dbfile+".eapi3_lock",
287
288 'etpdatabasedownloadlockfile': default_etp_dbfile+".download.lock",
289 'etpdatabasecacertfile': "ca.cert",
290 'etpdatabaseservercertfile': "server.cert",
291
292
293 'etpdatabasetaintfile': default_etp_dbfile+".tainted",
294
295
296
297 'etpdatabasefile': default_etp_dbfile,
298
299 'etpdatabasefilegzip': default_etp_dbfile+".gz",
300
301 'etpdatabasefilebzip2': default_etp_dbfile+".bz2",
302
303
304 'etpdatabasefilegziplight': default_etp_dbfile+".light.gz",
305 'etpdatabasefilehashgziplight': default_etp_dbfile+".light.gz.md5",
306
307 'etpdatabasefilebzip2light': default_etp_dbfile+".light.bz2",
308 'etpdatabasefilehashbzip2light': default_etp_dbfile+".light.bz2.md5",
309
310
311 'etpdatabasedumpbzip2': default_etp_dbfile+".dump.bz2",
312 'etpdatabasedumphashfilebz2': default_etp_dbfile+".dump.bz2.md5",
313
314 'etpdatabasedumpgzip': default_etp_dbfile+".dump.gz",
315 'etpdatabasedumphashfilegzip': default_etp_dbfile+".dump.gz.md5",
316
317
318 'etpdatabasedump': default_etp_dbfile+".dump",
319
320
321 'etpdatabasedumplightbzip2': default_etp_dbfile+".dumplight.bz2",
322
323 'etpdatabasedumplightgzip': default_etp_dbfile+".dumplight.gz",
324
325 'etpdatabasedumplighthashfilebz2': default_etp_dbfile+".dumplight.bz2.md5",
326 'etpdatabasedumplighthashfilegzip': default_etp_dbfile+".dumplight.gz.md5",
327 'etpdatabasedumplight': default_etp_dbfile+".dumplight",
328
329
330 'etpdatabaseexpbasedpkgsrm': default_etp_dbfile+".fatscope",
331
332
333 'etpdatabasefileformat': "bz2",
334
335 'etpdatabasesupportedcformats': ["bz2", "gz"],
336 'etpdatabasecompressclasses': {
337 "bz2": (bz2.BZ2File, "unpack_bzip2", "etpdatabasefilebzip2",
338 "etpdatabasedumpbzip2", "etpdatabasedumphashfilebz2",
339 "etpdatabasedumplightbzip2", "etpdatabasedumplighthashfilebz2",
340 "etpdatabasefilebzip2light","etpdatabasefilehashbzip2light",),
341 "gz": (gzip.GzipFile, "unpack_gzip", "etpdatabasefilegzip",
342 "etpdatabasedumpgzip", "etpdatabasedumphashfilegzip",
343 "etpdatabasedumplightgzip", "etpdatabasedumplighthashfilegzip",
344 "etpdatabasefilegziplight","etpdatabasefilehashgziplight",)
345 },
346
347 'rss-feed': True,
348
349 'rss-name': "packages.rss",
350 'rss-light-name': "updates.rss",
351
352
353 'rss-base-url': "http://packages.sabayonlinux.org/",
354
355
356 'rss-website-url': "http://www.sabayonlinux.org/",
357
358 'rss-dump-name': "rss_database_actions",
359 'rss-max-entries': 10000,
360 'rss-light-max-entries': 300,
361 'rss-managing-editor': "lxnay@sabayonlinux.org",
362
363 'rss-notice-board': "notice.rss",
364
365 'packagesetprefix': "@",
366 'userpackagesetsid': "__user__",
367 'setsconffilename': "sets.conf",
368 'cachedumpext': ".dmp",
369 'packagesext': ".tbz2",
370 'smartappsext': ".esa",
371
372
373 'packagesmd5fileext': ".md5",
374 'packagessha512fileext': ".sha512",
375 'packagessha256fileext': ".sha256",
376 'packagessha1fileext': ".sha1",
377
378 'packagesexpirationfileext': ".expired",
379
380 'packagesexpirationdays': 15,
381
382
383 'triggername': "trigger",
384 'trigger_sh_interpreter': rootdir+"/usr/sbin/entropy.sh",
385
386 'etp_hw_hash_gen': rootdir+"/usr/bin/entropy_hwgen.sh",
387
388 'etp_post_branch_hop_script': default_etp_dbfile+".post_branch.sh",
389
390 'etp_post_branch_upgrade_script': default_etp_dbfile+".post_upgrade.sh",
391
392 'etp_previous_branch_file': default_etp_confdir+"/.previous_branch",
393
394 'proxy': {
395 'ftp': None,
396 'http': None,
397 'username': None,
398 'password': None
399 },
400
401 'entropyloglevel': 1,
402
403 'socketloglevel': 2,
404 'spmloglevel': 1,
405
406 'logdir': default_etp_logdir,
407
408 'syslogdir': default_etp_syslogdir,
409 'entropylogfile': default_etp_syslogdir+"entropy.log",
410 'equologfile': default_etp_syslogdir+"equo.log",
411 'spmlogfile': default_etp_syslogdir+"spm.log",
412 'socketlogfile': default_etp_syslogdir+"socket.log",
413
414 'etpdatabaseclientdir': default_etp_dir + default_etp_client_repodir + \
415 default_etp_dbdir,
416
417 'etpdatabaseclientfilepath': default_etp_dir + \
418 default_etp_client_repodir + default_etp_dbdir + "/" + \
419 default_etp_dbclientfile,
420
421
422 'dbnamerepoprefix': "repo_",
423
424 'dbbackupprefix': 'etp_backup_',
425
426
427 'etpapi': etpSys['api'],
428
429 'currentarch': etpSys['arch'],
430
431 'supportedarchs': etpSys['archs'],
432
433
434 'branch': "4",
435
436 'keywords': etpSys['keywords'].copy(),
437
438
439
440 'expiration_based_scope': False,
441 'edbcounter': edb_counter,
442
443 'officialserverrepositoryid': "sabayonlinux.org",
444
445 'officialrepositoryid': "sabayonlinux.org",
446 'conntestlink': "http://www.sabayonlinux.org",
447
448 'databasestarttag': "|ENTROPY:PROJECT:DB:MAGIC:START|",
449 'pidfile': default_etp_dir+"/entropy.lock",
450 'applicationlock': False,
451
452
453 'filesbackup': True,
454
455 'forcedupdates': True,
456
457 'collisionprotect': 1,
458
459
460 'configprotect': [],
461
462 'configprotectmask': [],
463
464
465 'configprotectskip': [],
466
467 'dbconfigprotect': [],
468
469 'dbconfigprotectmask': [],
470
471
472 'configprotectcounter': 0,
473
474 'entropyversion': "1.0",
475
476 'systemname': "Sabayon Linux",
477
478 'product': "standard",
479 'errorstatus': default_etp_confdir+"/code",
480 'systemroot': rootdir,
481 'uid': os.getuid(),
482 'entropygid': None,
483 'sysgroup': "entropy",
484 'defaultumask': 022,
485 'storeumask': 002,
486 'gentle_nice': 15,
487 'current_nice': 0,
488 'default_nice': 0,
489 'server_treeupdatescalled': set(),
490 'client_treeupdatescalled': set(),
491 'spm': {
492 '(r)depend_id': 0,
493 'pdepend_id': 1,
494 'mdepend_id': 2,
495 'ebuild_file_extension': "ebuild",
496 'preinst_phase': "preinst",
497 'postinst_phase': "postinst",
498 'prerm_phase': "prerm",
499 'postrm_phase': "postrm",
500 'setup_phase': "setup",
501 'compile_phase': "compile",
502 'install_phase': "install",
503 'unpack_phase': "unpack",
504 'ebuild_pkg_tag_var': "ENTROPY_PROJECT_TAG",
505 'global_make_conf': rootdir+"/etc/make.conf",
506 'global_package_keywords': rootdir+"/etc/portage/package.keywords",
507 'global_package_use': rootdir+"/etc/portage/package.use",
508 'global_package_mask': rootdir+"/etc/portage/package.mask",
509 'global_package_unmask': rootdir+"/etc/portage/package.unmask",
510 'global_make_profile': rootdir+"/etc/make.profile",
511 'global_make_profile_link_name' : "profile.link",
512
513 'exec': rootdir+"/usr/bin/emerge",
514 'env_update_cmd': rootdir+"/usr/sbin/env-update",
515 'source_profile': ["source", rootdir+"/etc/profile"],
516 'source_build_ext': ".ebuild",
517 'ask_cmd': "--ask",
518 'info_cmd': "--info",
519 'remove_cmd': "-C",
520 'nodeps_cmd': "--nodeps",
521 'fetchonly_cmd': "--fetchonly",
522 'buildonly_cmd': "--buildonly",
523 'oneshot_cmd': "--oneshot",
524 'pretend_cmd': "--pretend",
525 'verbose_cmd': "--verbose",
526 'nocolor_cmd': "--color=n",
527 'backend': "portage",
528 'available_backends': ["portage"],
529 'cache': {},
530 'xpak_entries': {
531 'description': "DESCRIPTION",
532 'homepage': "HOMEPAGE",
533 'chost': "CHOST",
534 'category': "CATEGORY",
535 'cflags': "CFLAGS",
536 'cxxflags': "CXXFLAGS",
537 'license': "LICENSE",
538 'src_uri': "SRC_URI",
539 'use': "USE",
540 'iuse': "IUSE",
541 'slot': "SLOT",
542 'provide': "PROVIDE",
543 'depend': "DEPEND",
544 'rdepend': "RDEPEND",
545 'pdepend': "PDEPEND",
546 'needed': "NEEDED",
547 'inherited': "INHERITED",
548 'keywords': "KEYWORDS",
549 'contents': "CONTENTS",
550 'counter': "COUNTER",
551 'defined_phases': "DEFINED_PHASES",
552 'pf': "PF",
553 },
554 'system_packages': [],
555 'ignore-spm-downgrades': False,
556 },
557
558
559 'downloadspeedlimit': None,
560
561
562
563 'dumpstoragedir': default_etp_dir+default_etp_cachesdir,
564
565 'securitydir': default_etp_dir+default_etp_securitydir,
566 'securityurl': "http://community.sabayonlinux.org/security"
567 "/security-advisories.tar.bz2",
568
569 'safemodeerrors': {
570 'clientdb': 1,
571 },
572 'safemodereasons': {
573 0: _("All fine"),
574 1: _("Corrupted Client Repository. Please restore a backup."),
575 },
576
577 'misc_counters': {
578 'forced_atoms_update_ids': {
579 '__idtype__': 1,
580 'kde': 1,
581 },
582 },
583
584 'system_settings_plugins_ids': {
585 'client_plugin': "client_plugin",
586 'server_plugin': "server_plugin",
587 'server_plugin_fatscope': "server_plugin_fatscope",
588 },
589
590 'clientserverrepoid': "__system__",
591 'clientdbid': "client",
592 'serverdbid': "etpdb:",
593 'genericdbid': "generic",
594 'systemreleasefile': "/etc/sabayon-release",
595
596
597
598 'socket_service': {
599 'hostname': "localhost",
600 'port': 1026,
601 'ssl_port': 1027,
602 'timeout': 200,
603 'forked_requests_timeout': 300,
604 'max_command_length': 768000,
605 'threads': 5,
606 'session_ttl': 15,
607 'default_uid': 0,
608 'max_connections': 5,
609 'max_connections_per_host': 15,
610 'max_connections_per_host_barrier': 8,
611 'disabled_cmds': set(),
612 'ip_blacklist': set(),
613 'ssl_key': default_etp_confdir+"/socket_server.key",
614 'ssl_cert': default_etp_confdir+"/socket_server.crt",
615 'ssl_ca_cert': default_etp_confdir+"/socket_server.CA.crt",
616 'ssl_ca_pkey': default_etp_confdir+"/socket_server.CA.key",
617 'answers': {
618 'ok': chr(0)+"OK"+chr(0),
619 'er': chr(0)+"ER"+chr(1),
620 'no': chr(0)+"NO"+chr(2),
621 'cl': chr(0)+"CL"+chr(3),
622 'mcr': chr(0)+"MCR"+chr(4),
623 'eos': chr(0),
624 'noop': chr(0)+"NOOP"+chr(0)
625 },
626 },
627
628 'install_sources': {
629 'unknown': 0,
630 'user': 1,
631 'automatic_dependency': 2,
632 },
633
634 'ugc_doctypes': {
635 'comments': 1,
636 'bbcode_doc': 2,
637 'image': 3,
638 'generic_file': 4,
639 'youtube_video': 5,
640 },
641 'ugc_doctypes_description': {
642 1: _('Comments'),
643 2: _('BBcode Documents'),
644 3: _('Images/Screenshots'),
645 4: _('Generic Files'),
646 5: _('YouTube(tm) Videos'),
647 },
648 'ugc_doctypes_description_singular': {
649 1: _('Comment'),
650 2: _('BBcode Document'),
651 3: _('Image/Screenshot'),
652 4: _('Generic File'),
653 5: _('YouTube(tm) Video'),
654 },
655 'ugc_accessfile': default_etp_ugc_confdir+"/access.xml",
656 'ugc_voterange': range(1, 6),
657
658
659 'handlers': {
660
661 'md5sum': "md5sum.php?arch="+etpSys['arch']+"&package=",
662 },
663
664 }
665
666
667 try:
668 my_const['current_nice'] = os.nice(0)
669 except OSError:
670 pass
671
672 etpConst.update(my_const)
673
675 """
676 Change current process scheduler "nice" level.
677
678 @param nice_level: new valid nice level
679 @type nice_level: int
680 @rtype: int
681 @return: current_nice new nice level
682 """
683 default_nice = etpConst['default_nice']
684 current_nice = etpConst['current_nice']
685 delta = current_nice - default_nice
686 try:
687 etpConst['current_nice'] = os.nice(delta*-1+nice_level)
688 except OSError:
689 pass
690 return current_nice
691
693
694 """
695 Extract repository information from the provided repository string,
696 usually contained in the repository settings file, repositories.conf.
697
698 @param repostring: valid repository identifier
699 @type repostring: string
700 @rtype: tuple (string, dict)
701 @return: tuple composed by (repository identifier, extracted repository
702 metadata)
703 """
704
705 if branch == None:
706 branch = etpConst['branch']
707 if product == None:
708 product = etpConst['product']
709
710 reponame = repostring.split("|")[1].strip()
711 repodesc = repostring.split("|")[2].strip()
712 repopackages = repostring.split("|")[3].strip()
713 repodatabase = repostring.split("|")[4].strip()
714
715 eapi3_port = int(etpConst['socket_service']['port'])
716 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
717 eapi3_formatcolon = repodatabase.rfind("#")
718 if eapi3_formatcolon != -1:
719 try:
720 ports = repodatabase[eapi3_formatcolon+1:].split(",")
721 eapi3_port = int(ports[0])
722 if len(ports) > 1:
723 eapi3_ssl_port = int(ports[1])
724 repodatabase = repodatabase[:eapi3_formatcolon]
725 except (ValueError, IndexError,):
726 eapi3_port = int(etpConst['socket_service']['port'])
727 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
728
729 dbformat = etpConst['etpdatabasefileformat']
730 dbformatcolon = repodatabase.rfind("#")
731 if dbformatcolon != -1:
732 if dbformat in etpConst['etpdatabasesupportedcformats']:
733 try:
734 dbformat = repodatabase[dbformatcolon+1:]
735 except (IndexError, ValueError, TypeError,):
736 pass
737 repodatabase = repodatabase[:dbformatcolon]
738
739 mydata = {}
740 mydata['repoid'] = reponame
741 mydata['service_port'] = eapi3_port
742 mydata['ssl_service_port'] = eapi3_ssl_port
743 mydata['description'] = repodesc
744 mydata['packages'] = []
745 mydata['plain_packages'] = []
746
747 mydata['dbpath'] = etpConst['etpdatabaseclientdir'] + "/" + reponame + \
748 "/" + product + "/" + etpConst['currentarch'] + "/" + branch
749
750 mydata['dbcformat'] = dbformat
751 if not dbformat in etpConst['etpdatabasesupportedcformats']:
752 mydata['dbcformat'] = etpConst['etpdatabasesupportedcformats'][0]
753
754 mydata['plain_database'] = repodatabase
755
756 mydata['database'] = repodatabase + "/" + product + "/" + \
757 reponame + "/database/" + etpConst['currentarch'] + \
758 "/" + branch
759
760 mydata['notice_board'] = mydata['database'] + "/" + \
761 etpConst['rss-notice-board']
762
763 mydata['local_notice_board'] = mydata['dbpath'] + "/" + \
764 etpConst['rss-notice-board']
765
766 mydata['dbrevision'] = "0"
767 dbrevision_file = os.path.join(mydata['dbpath'],
768 etpConst['etpdatabaserevisionfile'])
769 if os.path.isfile(dbrevision_file) and os.access(dbrevision_file, os.R_OK):
770 with open(dbrevision_file, "r") as dbrev_f:
771 mydata['dbrevision'] = dbrev_f.readline().strip()
772
773
774
775 mydata['post_branch_hop_script'] = mydata['dbpath'] + "/" + \
776 etpConst['etp_post_branch_hop_script']
777 mydata['post_branch_upgrade_script'] = mydata['dbpath'] + "/" + \
778 etpConst['etp_post_branch_upgrade_script']
779
780
781
782 mydata['configprotect'] = None
783 mydata['configprotectmask'] = None
784 repopackages = [x.strip() for x in repopackages.split() if x.strip()]
785 repopackages = [x for x in repopackages if (x.startswith('http://') or \
786 x.startswith('ftp://') or x.startswith('file://'))]
787
788 for repo_package in repopackages:
789 try:
790 repo_package = str(repo_package)
791 except (UnicodeDecodeError,UnicodeEncodeError,):
792 continue
793 mydata['plain_packages'].append(repo_package)
794 mydata['packages'].append(repo_package + "/" + product + "/" + reponame)
795
796 return reponame, mydata
797
799 """
800 Read Entropy release file content and fill etpConst['entropyversion']
801
802 @rtype: None
803 @return: None
804 """
805
806 revision_file = "../libraries/revision"
807 if not os.path.isfile(revision_file):
808 revision_file = os.path.join(etpConst['installdir'],
809 'libraries/revision')
810 if os.path.isfile(revision_file) and \
811 os.access(revision_file,os.R_OK):
812
813 with open(revision_file, "r") as rev_f:
814 myrev = rev_f.readline().strip()
815 etpConst['entropyversion'] = myrev
816
817
819
820 """
821 Setup Entropy pid file, if possible and if UID = 0 (root).
822 If the application is run with --no-pid-handling argument,
823 this function will have no effect. If just_read is specified,
824 this function will only try to read the current pid string in
825 the Entropy pid file (etpConst['pidfile']). If any other entropy
826 istance is currently owning the contained pid, etpConst['applicationlock']
827 becomes True.
828
829 @param just_read: only read the current pid file, if any and if possible
830 @type just_read: bool
831 @rtype: None
832 @return: None
833 """
834
835 if ("--no-pid-handling" in sys.argv) and (not just_read):
836 return
837
838
839 pid = os.getpid()
840 pid_file = etpConst['pidfile']
841 if os.path.isfile(pid_file) and os.access(pid_file, os.R_OK):
842
843 try:
844 with open(pid_file,"r") as pid_f:
845 found_pid = str(pid_f.readline().strip())
846 except (IOError, OSError, UnicodeEncodeError, UnicodeDecodeError,):
847 found_pid = "0000"
848
849 if found_pid != str(pid):
850
851 pid_path = "%s/proc/%s" % (etpConst['systemroot'], found_pid,)
852 if os.path.isdir(pid_path) and found_pid:
853 etpConst['applicationlock'] = True
854 elif not just_read:
855
856
857 if os.access(pid_file, os.W_OK):
858 try:
859 with open(pid_file,"w") as pid_f:
860 pid_f.write(str(pid))
861 pid_f.flush()
862 except IOError, err:
863 if err.errno == 30:
864 pass
865 else:
866 raise
867 try:
868 const_chmod_entropy_pid()
869 except OSError:
870 pass
871
872 elif not just_read:
873
874
875 if os.access(os.path.dirname(pid_file), os.W_OK):
876
877 if os.path.exists(pid_file):
878 if os.path.islink(pid_file):
879 os.remove(pid_file)
880 elif os.path.isdir(pid_file):
881 import shutil
882 shutil.rmtree(pid_file)
883
884 with open(pid_file,"w") as pid_fw:
885 pid_fw.write(str(pid))
886 pid_fw.flush()
887
888 try:
889 const_chmod_entropy_pid()
890 except OSError:
891 pass
892
894 """
895 Setup entropy file needing strict permissions, no world readable.
896
897 @param config_file: valid config file path
898 @type config_file: string
899 @rtype: None
900 @return: None
901 """
902 try:
903 mygid = const_get_entropy_gid()
904 except KeyError:
905 mygid = 0
906 try:
907 const_setup_file(config_file, mygid, 0660)
908 except (OSError, IOError,):
909 pass
910
912 """
913 Setup entropy pid file permissions, if possible.
914
915 @return: None
916 """
917 try:
918 mygid = const_get_entropy_gid()
919 except KeyError:
920 mygid = 0
921 const_setup_file(etpConst['pidfile'], mygid, 0664)
922
924
925 """
926 Setup Entropy directory structure, as much automagically as possible.
927
928 @rtype: None
929 @return: None
930 """
931
932
933 piddir = os.path.dirname(etpConst['pidfile'])
934 if not os.path.exists(piddir) and (etpConst['uid'] == 0):
935 os.makedirs(piddir)
936
937
938
939
940
941
942
943 gid = None
944 try:
945 gid = const_get_entropy_gid()
946 except KeyError:
947 if etpConst['uid'] == 0:
948
949
950 const_add_entropy_group()
951 try:
952 gid = const_get_entropy_gid()
953 except KeyError:
954 pass
955
956
957 keys = [x for x in etpConst if isinstance(etpConst[x], basestring)]
958 for key in keys:
959
960 if not etpConst[key] or \
961 etpConst[key].endswith(".conf") or \
962 not os.path.isabs(etpConst[key]) or \
963 etpConst[key].endswith(".cfg") or \
964 etpConst[key].endswith(".tmp") or \
965 etpConst[key].find(".db") != -1 or \
966 etpConst[key].find(".log") != -1 or \
967 os.path.isdir(etpConst[key]) or \
968 not key.endswith("dir"):
969 continue
970
971
972
973 try:
974 key_dir = etpConst[key]
975 d_paths = []
976 while not os.path.isdir(key_dir):
977 d_paths.append(key_dir)
978 key_dir = os.path.dirname(key_dir)
979 d_paths = sorted(d_paths)
980 for d_path in d_paths:
981 os.mkdir(d_path)
982 const_setup_file(d_path, gid, 0775)
983 except (OSError, IOError,):
984 pass
985
986 if gid:
987 etpConst['entropygid'] = gid
988 if not os.path.isdir(etpConst['entropyworkdir']):
989 try:
990 os.makedirs(etpConst['entropyworkdir'])
991 except OSError:
992 pass
993 w_gid = os.stat(etpConst['entropyworkdir'])[stat.ST_GID]
994 if w_gid != gid:
995 const_setup_perms(etpConst['entropyworkdir'], gid)
996
997 if not os.path.isdir(etpConst['entropyunpackdir']):
998 try:
999 os.makedirs(etpConst['entropyunpackdir'])
1000 except OSError:
1001 pass
1002 try:
1003 w_gid = os.stat(etpConst['entropyunpackdir'])[stat.ST_GID]
1004 if w_gid != gid:
1005 if os.path.isdir(etpConst['entropyunpackdir']):
1006 const_setup_perms(etpConst['entropyunpackdir'], gid)
1007 except OSError:
1008 pass
1009
1010 if not const_islive():
1011
1012 const_setup_perms(etpConst['etpdatabaseclientdir'], gid)
1013
1025
1026
1028 """
1029 Analyze a server repository string (usually contained in server.conf),
1030 extracting all the parameters.
1031
1032 @param repostring: repository string
1033 @type repostring: string
1034 @keyword product: system product which repository belongs to
1035 @rtype: None
1036 @return: None
1037 """
1038
1039 if product == None:
1040 product = etpConst['product']
1041
1042 mydata = {}
1043 repoid = repostring.split("|")[1].strip()
1044 repodesc = repostring.split("|")[2].strip()
1045 repouris = repostring.split("|")[3].strip()
1046 repohandlers = repostring.split("|")[4].strip()
1047
1048 service_url = None
1049 eapi3_port = int(etpConst['socket_service']['port'])
1050 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
1051 if len(repostring.split("|")) > 5:
1052 service_url = repostring.split("|")[5].strip()
1053
1054 eapi3_formatcolon = service_url.rfind("#")
1055 if eapi3_formatcolon != -1:
1056 try:
1057 ports = service_url[eapi3_formatcolon+1:].split(",")
1058 eapi3_port = int(ports[0])
1059 if len(ports) > 1:
1060 eapi3_ssl_port = int(ports[1])
1061 service_url = service_url[:eapi3_formatcolon]
1062 except (ValueError, IndexError,):
1063 eapi3_port = int(etpConst['socket_service']['port'])
1064 eapi3_ssl_port = int(etpConst['socket_service']['ssl_port'])
1065
1066 mydata = {}
1067 mydata['repoid'] = repoid
1068 mydata['description'] = repodesc
1069 mydata['mirrors'] = []
1070 mydata['community'] = False
1071 mydata['service_url'] = service_url
1072 mydata['service_port'] = eapi3_port
1073 mydata['ssl_service_port'] = eapi3_ssl_port
1074 if repohandlers:
1075 repohandlers = os.path.join(repohandlers, product, repoid, "handlers")
1076 mydata['handler'] = repohandlers
1077 uris = repouris.split()
1078 for uri in uris:
1079 mydata['mirrors'].append(uri)
1080
1081 return repoid, mydata
1082
1084 """
1085 Setup permissions and group id (GID) to a directory, recursively.
1086
1087 @param mydir: valid file path
1088 @type mydir: string
1089 @param gid: valid group id (GID)
1090 @type gid: int
1091 @rtype: None
1092 @return: None
1093 """
1094 if gid == None:
1095 return
1096 for currentdir, subdirs, files in os.walk(mydir):
1097 try:
1098 cur_gid = os.stat(currentdir)[stat.ST_GID]
1099 if cur_gid != gid:
1100 os.chown(currentdir, -1, gid)
1101 cur_mod = const_get_chmod(currentdir)
1102 if cur_mod != oct(0775):
1103 os.chmod(currentdir, 0775)
1104 except OSError:
1105 pass
1106 for item in files:
1107 item = os.path.join(currentdir, item)
1108 try:
1109 const_setup_file(item, gid, 0664)
1110 except OSError:
1111 pass
1112
1114 """
1115 Setup file permissions and group id (GID).
1116
1117 @param myfile: valid file path
1118 @type myfile: string
1119 @param gid: valid group id (GID)
1120 @type gid: int
1121 @param chmod: permissions
1122 @type chmod: integer representing an octal
1123 @rtype: None
1124 @return: None
1125 """
1126 cur_gid = os.stat(myfile)[stat.ST_GID]
1127 if cur_gid != gid:
1128 os.chown(myfile, -1, gid)
1129 const_set_chmod(myfile, chmod)
1130
1131
1133 """
1134 This function get the current permissions of the specified
1135 file. If you want to use the returning value with const_set_chmod
1136 you need to convert it back to int.
1137
1138 @param myfile: valid file path
1139 @type myfile: string
1140 @rtype: integer(8) (octal)
1141 @return: octal representing permissions
1142 """
1143 myst = os.stat(myfile)[stat.ST_MODE]
1144 return oct(myst & 0777)
1145
1147 """
1148 This function sets specified permissions to a file.
1149 If they differ from the current ones.
1150
1151 @param myfile: valid file path
1152 @type myfile: string
1153 @param chmod: permissions
1154 @type chmod: integer representing an octal
1155 @rtype: None
1156 @return: None
1157 """
1158 cur_mod = const_get_chmod(myfile)
1159 if cur_mod != oct(chmod):
1160 os.chmod(myfile, chmod)
1161
1163 """
1164 This function tries to retrieve the "entropy" user group
1165 GID.
1166
1167 @rtype: None
1168 @return: None
1169 @raise KeyError: when "entropy" system GID is not available
1170 """
1171 group_file = etpConst['systemroot']+'/etc/group'
1172 if not os.path.isfile(group_file):
1173 raise KeyError
1174
1175 with open(group_file,"r") as group_f:
1176 for line in group_f.readlines():
1177 if line.startswith('%s:' % (etpConst['sysgroup'],)):
1178 try:
1179 gid = int(line.split(":")[2])
1180 except ValueError:
1181 raise KeyError
1182 return gid
1183 raise KeyError
1184
1186 """
1187 This function looks for an "entropy" user group.
1188 If not available, it tries to create one.
1189
1190 @rtype: None
1191 @return: None
1192 @raise KeyError: if ${ROOT}/etc/group is not found
1193 """
1194 group_file = etpConst['systemroot']+'/etc/group'
1195 if not os.path.isfile(group_file):
1196 raise KeyError
1197 ids = set()
1198
1199 with open(group_file,"r") as group_f:
1200 for line in group_f.readlines():
1201 if line and line.split(":"):
1202 try:
1203 myid = int(line.split(":")[2])
1204 except ValueError:
1205 pass
1206 ids.add(myid)
1207 if ids:
1208
1209 new_id = 1000
1210 while 1:
1211 new_id += 1
1212 if new_id not in ids:
1213 break
1214 else:
1215 new_id = 10000
1216
1217 with open(group_file,"aw") as group_fw:
1218 group_fw.seek(0, 2)
1219 app_line = "entropy:x:%s:\n" % (new_id,)
1220 group_fw.write(app_line)
1221 group_fw.flush()
1222
1224 """
1225 Live environments (Operating System running off a CD/DVD)
1226 must feature the "cdroot" parameter in kernel /proc/cmdline
1227
1228 Sample code:
1229 >>> from entropy.const import const_islive
1230 >>> const_islive()
1231 False
1232
1233 @rtype: bool
1234 @return: determine wether this is a Live system or not
1235 """
1236 if "cdroot" in etpConst['cmdline']:
1237 return True
1238 return False
1239
1241 """
1242 Entropy threads killer. Even if Python threads cannot
1243 be stopped or killed, TimeScheduled ones can, exporting
1244 the kill() method.
1245
1246 Sample code:
1247 >>> from entropy.const import const_kill_threads
1248 >>> const_kill_threads()
1249
1250 @rtype: None
1251 @return: None
1252 """
1253 import threading
1254 threads = threading.enumerate()
1255 for running_t in threads:
1256
1257 if running_t.getName() == 'MainThread':
1258 continue
1259 if hasattr(running_t,'kill'):
1260 running_t.kill()
1261 running_t.join()
1262
1264 """
1265 Our default Python exception handler. It kills
1266 all the threads generated by Entropy before
1267 raising exceptions. Overloads sys.excepthook,
1268 internal function !!
1269
1270 @param etype: exception type
1271 @type etype: exception type
1272 @param value: exception data
1273 @type value: string
1274 @param t_back: traceback object?
1275 @type t_back: Python traceback object
1276 @rtype: default Python exceptions hook
1277 @return: sys.__excepthook__
1278 """
1279 try:
1280 const_kill_threads()
1281 except (AttributeError, ImportError,):
1282 pass
1283 return sys.__excepthook__(etype, value, t_back)
1284
1286 """
1287 Entropy debugging output write functions.
1288
1289 @param identifier: debug identifier
1290 @type identifier: string
1291 @param msg: debugging message
1292 @type msg: string
1293 @rtype: None
1294 @return: None
1295 """
1296 if etpUi['debug']:
1297 sys.stdout.write("%s: %s" % (identifier, msg + "\n"))
1298
1299
1300 initconfig_entropy_constants(etpSys['rootdir'])
1301