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