~xubuntu-dev/ubiquity/lp1437180_feh

« back to all changes in this revision

Viewing changes to ubiquity/misc.py

  • Committer: Colin Watson
  • Date: 2012-04-30 23:38:41 UTC
  • mfrom: (5402 trunk)
  • mto: This revision was merged to the branch mainline in revision 5403.
  • Revision ID: cjwatson@canonical.com-20120430233841-xb0qsk46lnhski7m
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
101
101
        set_groups_for_uid(uid)
102
102
    if gid is not None:
103
103
        gid = int(gid)
104
 
        osextras.setresgid(gid, gid, 0)
 
104
        os.setresgid(gid, gid, 0)
105
105
    if uid is not None:
106
 
        osextras.setresuid(uid, uid, 0)
 
106
        os.setresuid(uid, uid, 0)
107
107
 
108
108
def regain_privileges_save():
109
109
    """Recover our real UID/GID after calling drop_privileges_save."""
110
110
    assert _dropped_privileges is not None and _dropped_privileges > 0
111
 
    osextras.setresuid(0, 0, 0)
112
 
    osextras.setresgid(0, 0, 0)
 
111
    os.setresuid(0, 0, 0)
 
112
    os.setresgid(0, 0, 0)
113
113
    os.setgroups([])
114
114
 
115
115
@contextlib.contextmanager
190
190
            syslog.syslog(syslog.LOG_ERR, line)
191
191
    return l
192
192
 
 
193
@raise_privileges
193
194
def boot_device():
194
195
    from ubiquity.parted_server import PartedServer
195
196
 
260
261
    fsname = ''
261
262
    fstype = ''
262
263
    writable = ''
263
 
    with contextlib.closing(open('/proc/mounts')) as fp:
 
264
    with open('/proc/mounts') as fp:
264
265
        for line in fp:
265
266
            line = line.split()
266
267
            if line[1] == path:
293
294
    udevadm_disk = udevadm_info(['-p', disk_syspath])
294
295
    return udevadm_disk.get('DEVNAME', partition)
295
296
 
 
297
def is_boot_device_removable():
 
298
    return is_removable(boot_device())
 
299
 
 
300
def cdrom_mount_info():
 
301
    """Return mount information for /cdrom.
 
302
 
 
303
    This is the same as mount_info, except that the partition is converted to
 
304
    its containing disk, and we don't care whether the mount point is
 
305
    writable.
 
306
    """
 
307
    cdsrc, cdfs, _ = mount_info('/cdrom')
 
308
    cdsrc = partition_to_disk(cdsrc)
 
309
    return cdsrc, cdfs
 
310
 
296
311
@raise_privileges
 
312
def grub_device_map():
 
313
    """Return the contents of the default GRUB device map."""
 
314
    subp = subprocess.Popen(['grub-mkdevicemap', '--no-floppy', '-m', '-'],
 
315
                            stdout=subprocess.PIPE)
 
316
    return subp.communicate()[0].splitlines()
 
317
 
297
318
def grub_default():
298
319
    """Return the default GRUB installation target."""
299
320
 
302
323
    # grub-installer is run.  Pursuant to that, we intentionally run this in
303
324
    # the installer root as /target might not yet be available.
304
325
 
305
 
    bootremovable = is_removable(boot_device())
 
326
    bootremovable = is_boot_device_removable()
306
327
    if bootremovable is not None:
307
328
        return bootremovable
308
329
 
309
 
    subp = subprocess.Popen(['grub-mkdevicemap', '--no-floppy', '-m', '-'],
310
 
                            stdout=subprocess.PIPE)
311
 
    devices = subp.communicate()[0].splitlines()
 
330
    devices = grub_device_map()
312
331
    target = None
313
332
    if devices:
314
333
        try:
319
338
    if target is None:
320
339
        target = '(hd0)'
321
340
 
322
 
    cdsrc, cdfs, type = mount_info('/cdrom')
323
 
    cdsrc = partition_to_disk(cdsrc)
 
341
    cdsrc, cdfs = cdrom_mount_info()
324
342
    try:
325
343
        # The target is usually under /dev/disk/by-id/, so string equality
326
344
        # is insufficient.
327
345
        same = os.path.samefile(cdsrc, target)
328
346
    except OSError:
329
347
        same = False
330
 
    if (same or target == '(hd0)') and cdfs and cdfs != 'iso9660':
 
348
    if ((same or target == '(hd0)') and
 
349
        (cdfs and cdfs != 'iso9660') or is_removable(cdsrc)):
331
350
        # Installing from removable media other than a CD.  Make sure that
332
351
        # we don't accidentally install GRUB to it.
333
352
        boot = boot_device()
400
419
 
401
420
def windows_startup_folder(mount_path):
402
421
    locations = [
 
422
        # Windows 8
 
423
        'ProgramData/Microsoft/Windows/Start Menu/Programs/StartUp',
403
424
        # Windows 7
404
425
        'ProgramData/Microsoft/Windows/Start Menu/Programs/Startup',
405
426
        # Windows XP
534
555
@raise_privileges
535
556
def dmimodel():
536
557
    model = ''
 
558
    kwargs = {}
 
559
    if os.geteuid() != 0:
 
560
        # Silence annoying warnings during the test suite.
 
561
        kwargs['stderr'] = open('/dev/null', 'w')
537
562
    try:
538
563
        proc = subprocess.Popen(['dmidecode', '--string',
539
 
            'system-manufacturer'], stdout=subprocess.PIPE)
 
564
            'system-manufacturer'], stdout=subprocess.PIPE, **kwargs)
540
565
        manufacturer = proc.communicate()[0]
541
566
        if not manufacturer:
542
567
            return
565
590
            return
566
591
    except Exception:
567
592
        syslog.syslog(syslog.LOG_ERR, 'Unable to determine the model from DMI')
 
593
    finally:
 
594
        if 'stderr' in kwargs:
 
595
            kwargs['stderr'].close()
568
596
    return model
569
597
 
570
 
def set_indicator_keymaps(locale):
571
 
    import warnings
572
 
    warnings.warn('set_indicator_keymaps: this function currently does not work')
573
 
    return
574
 
 
 
598
def set_indicator_keymaps(lang):
575
599
    import libxml2
576
 
    import xklavier
577
 
    from gi.repository import Gdk
578
 
    from ubiquity import gconftool
579
 
 
580
 
    # FIXME: Code below needs porting to gsettings (not done yet as the function is disabled)
 
600
    from gi.repository import Xkl, GdkX11
 
601
    # GdkX11.x11_get_default_xdisplay() segfaults if Gtk hasn't been
 
602
    # imported; possibly finer-grained than this, but anything using this
 
603
    # will already have imported Gtk anyway ...
 
604
    from gi.repository import Gtk
 
605
    from ubiquity import gsettings
 
606
 
 
607
    # pacify pyflakes
 
608
    Gtk
 
609
 
581
610
    xpath = "//iso_639_3_entry[@part1_code='%s']"
582
 
    gconf_key = '/desktop/gnome/peripherals/keyboard/kbd/layouts'
 
611
    gsettings_key = ['org.gnome.libgnomekbd.keyboard','layouts']
 
612
    lang = lang.split('_')[0]
583
613
    variants = []
 
614
 
 
615
    # Map inspired from that of gfxboot-theme-ubuntu that's itself
 
616
    # based on console-setup's. This one has been restricted to
 
617
    # language => keyboard layout not locale => keyboard layout as
 
618
    # we don't actually know the exact locale
 
619
    default_keymap = {
 
620
        'ar': 'ara',
 
621
        'bs': 'ba',
 
622
        'de': 'de',
 
623
        'el': 'gr',
 
624
        'en': 'us',
 
625
        'eo': 'epo',
 
626
        'fr': 'fr_oss',
 
627
        'gu': 'in_guj',
 
628
        'hi': 'in',
 
629
        'hr': 'hr',
 
630
        'hy': 'am',
 
631
        'ka': 'ge',
 
632
        'kn': 'in_kan',
 
633
        'lo': 'la',
 
634
        'ml': 'in_mal',
 
635
        'pa': 'in_guru',
 
636
        'sr': 'rs',
 
637
        'sv': 'se',
 
638
        'ta': 'in_tam',
 
639
        'te': 'in_tel',
 
640
        'zh': 'cn',
 
641
    }
 
642
 
 
643
    def item_str(s):
 
644
        '''Convert a zero-terminated byte array to a proper str'''
 
645
        i = s.find(b'\x00')
 
646
        return s[:i].decode()
 
647
 
584
648
    def process_variant(*args):
585
 
        if hasattr(args[2], 'get_name'):
586
 
            variants.append('%s\t%s' % (args[1].get_name(), args[2].get_name()))
587
 
        else:
588
 
            variants.append(args[1].get_name())
589
 
 
590
 
    lang = locale.split('_')[0]
 
649
        if hasattr(args[2], 'name'):
 
650
            variants.append('%s\t%s' % (item_str(args[1].name), item_str(args[2].name)))
 
651
        else:
 
652
            variants.append(item_str(args[1].name))
 
653
 
 
654
    def restrict_list(variants):
 
655
        new_variants = []
 
656
 
 
657
        # Start by looking by an explicit default layout in the keymap
 
658
        if lang in default_keymap:
 
659
            if default_keymap[lang] in variants:
 
660
                variants.remove(default_keymap[lang])
 
661
                new_variants.append(default_keymap[lang])
 
662
            else:
 
663
                tab_keymap = default_keymap[lang].replace('_', '\t')
 
664
                if tab_keymap in variants:
 
665
                    variants.remove(tab_keymap)
 
666
                    new_variants.append(tab_keymap)
 
667
 
 
668
        # Prioritize the layout matching the language (if any)
 
669
        if lang in variants:
 
670
            variants.remove(lang)
 
671
            new_variants.append(lang)
 
672
 
 
673
        # Uniquify our list (just in case)
 
674
        variants = list(set(variants))
 
675
 
 
676
        if len(variants) > 4:
 
677
            # We have a problem, X only supports 4
 
678
 
 
679
            # Add as many entry as we can that are layouts without variant
 
680
            country_variants = sorted([entry for entry in variants if '\t' not in entry])
 
681
            for entry in country_variants[:4-len(new_variants)]:
 
682
                new_variants.append(entry)
 
683
                variants.remove(entry)
 
684
 
 
685
            if len(new_variants) < 4:
 
686
                # We can add some more
 
687
                simple_variants = sorted([entry for entry in variants if '_' not in entry])
 
688
                for entry in simple_variants[:4-len(new_variants)]:
 
689
                    new_variants.append(entry)
 
690
                    variants.remove(entry)
 
691
 
 
692
            if len(new_variants) < 4:
 
693
                # Now just add anything left
 
694
                for entry in variants[:4-len(new_variants)]:
 
695
                    new_variants.append(entry)
 
696
                    variants.remove(entry)
 
697
        else:
 
698
            new_variants += list(variants)
 
699
 
 
700
        # gsettings doesn't understand utf8
 
701
        new_variants = [str(variant) for variant in new_variants]
 
702
 
 
703
        return new_variants
 
704
 
 
705
    def call_setxkbmap(variants):
 
706
        kb_layouts = []
 
707
        kb_variants = []
 
708
 
 
709
        for entry in variants:
 
710
            fields = entry.split('\t')
 
711
            if len(fields) > 1:
 
712
                kb_layouts.append(fields[0])
 
713
                kb_variants.append(fields[1])
 
714
            else:
 
715
                kb_layouts.append(fields[0])
 
716
                kb_variants.append("")
 
717
 
 
718
        execute("setxkbmap", "-layout", ",".join(kb_layouts), "-variant", ",".join(kb_variants))
 
719
 
591
720
    fp = libxml2.parseFile('/usr/share/xml/iso-codes/iso_639_3.xml')
592
721
    context = fp.xpathNewContext()
593
722
    nodes = context.xpathEvalExpression(xpath % lang)
 
723
    display = GdkX11.x11_get_default_xdisplay()
 
724
    engine = Xkl.Engine.get_instance(display)
594
725
    if nodes:
595
 
        code = nodes[0].prop('part2_code')
596
 
        display = Gdk.Display.get_default()
597
 
        engine = xklavier.Engine(display)
598
 
        configreg = xklavier.ConfigRegistry(engine)
 
726
        configreg = Xkl.ConfigRegistry.get_instance(engine)
599
727
        configreg.load(False)
600
 
        configreg.foreach_language_variant(code, process_variant)
601
 
        if variants:
602
 
            gconftool.set_list(gconf_key, 'string', variants)
603
 
            return
604
 
    # Use the system default if no other keymaps can be determined.
605
 
    gconftool.set_list(gconf_key, 'string', '')
 
728
 
 
729
        # Apparently part2_code doesn't always work (fails with French)
 
730
        for prop in ('part2_code', 'id', 'part1_code'):
 
731
            if nodes[0].hasProp(prop):
 
732
                code = nodes[0].prop(prop)
 
733
                configreg.foreach_language_variant(code, process_variant, None)
 
734
                if variants:
 
735
                    restricted_variants = restrict_list(variants)
 
736
                    call_setxkbmap(restricted_variants)
 
737
                    gsettings.set_list(gsettings_key[0], gsettings_key[1], restricted_variants)
 
738
                    break
 
739
        else:
 
740
            # Use the system default if no other keymaps can be determined.
 
741
            gsettings.set_list(gsettings_key[0], gsettings_key[1], [])
 
742
 
 
743
    engine.lock_group(0)
606
744
 
607
745
NM = 'org.freedesktop.NetworkManager'
608
746
NM_STATE_CONNECTED_GLOBAL = 70
630
768
        func(state == NM_STATE_CONNECTED_GLOBAL)
631
769
    bus = dbus.SystemBus()
632
770
    bus.add_signal_receiver(connection_cb, 'StateChanged', NM, NM)
633
 
    func(has_connection())
 
771
    try:
 
772
        func(has_connection())
 
773
    except dbus.DBusException:
 
774
        # We can't talk to NM, so no idea.  Wild guess: we're connected
 
775
        # using ssh with X forwarding, and are therefore connected.  This
 
776
        # allows us to proceed with a minimum of complaint.
 
777
        func(True)
 
778
 
 
779
def install_size():
 
780
    if min_install_size:
 
781
        return min_install_size
 
782
 
 
783
    # Fallback size to 5 GB
 
784
    size = 5 * 1024 * 1024 * 1024
 
785
 
 
786
    # Maximal size to 8 GB
 
787
    max_size = 8 * 1024 * 1024 * 1024
 
788
 
 
789
    try:
 
790
        with open('/cdrom/casper/filesystem.size') as fp:
 
791
            size = int(fp.readline())
 
792
    except IOError:
 
793
        pass
 
794
 
 
795
    # TODO substitute into the template for the state box.
 
796
    min_disk_size = size * 2 # fudge factor.
 
797
 
 
798
    # Set minimum size to 8GB if current minimum size is larger
 
799
    # than 8GB and we still have an extra 20% of free space
 
800
    if min_disk_size > max_size and size * 1.2 < max_size:
 
801
        min_disk_size = max_size
 
802
 
 
803
    return min_disk_size
 
804
min_install_size = None
634
805
 
635
806
# vim:ai:et:sts=4:tw=80:sw=4: