summaryrefslogtreecommitdiffstats
path: root/perl-install/partition_table.pm
blob: 4f42120ecb5c86f5ee27e585c1c1bd7cd38522f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
package partition_table; # $Id$

#use diagnostics;
#use strict;
#use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK @important_types @important_types2 @fields2save);

@ISA = qw(Exporter);
%EXPORT_TAGS = (
    types => [ qw(type2name type2fs name2type fs2type isExtended isExt2 isReiserfs isXfs isJfs isTrueFS isSwap isDos isWin isFat isSunOS isOtherAvailableFS isPrimary isNfs isSupermount isLVM isRAID isMDRAID isLVMBased isHFS isNT isMountableRW isNonMountable isApplePartMap isLoopback isApple isAppleBootstrap) ],
);
@EXPORT_OK = map { @$_ } values %EXPORT_TAGS;


use common;
use partition_table_raw;
use log;

if (arch() =~ /ppc/) {
    @important_types = ('Linux native', 'Linux swap', 'Apple HFS Partition', 'Apple Bootstrap');
} else {
    @important_types = ('Linux native', 'Linux swap', if_(arch() =~ /i.86/, 'ReiserFS', 'JFS', 'DOS FAT16', 'Win98 FAT32'));
}
@important_types2 = ('Linux RAID', 'Linux Logical Volume Manager partition');

@fields2save = qw(primary extended totalsectors isDirty needKernelReread);

@bad_types = ('Empty', 'DOS 3.3+ Extended Partition', 'Win95: Extended partition, LBA-mapped', 'Linux extended partition');

my %types = (
  0x0 => 'Empty',
arch() =~ /^ppc/ ? (
  0x401	=> 'Apple Partition',
  0x401	=> 'Apple Bootstrap',
  0x402	=> 'Apple HFS Partition',
) : arch() =~ /^i.86/ ? (
  0x183 => 'ReiserFS',
  0x283 => 'XFS',
  0x383 => 'JFS',
) : arch() =~ /^sparc/ ? (
  0x1 => 'SunOS boot',
  0x2 => 'SunOS root',
  0x3 => 'SunOS swap',
  0x4 => 'SunOS usr',
  0x5 => 'Whole disk',
  0x6 => 'SunOS stand',
  0x7 => 'SunOS var',
  0x8 => 'SunOS home',
) : (
  0x1 => 'DOS 12-bit FAT',
  0x2 => 'XENIX root',
  0x3 => 'XENIX /usr',
  0x4 => 'DOS 16-bit FAT (up to 32M)',
  0x5 => 'DOS 3.3+ Extended Partition',
  0x6 => 'DOS FAT16',
  0x7 => 'NTFS (or HPFS)',
  0x8 => 'OS/2 (v1.0-1.3 only) / AIX boot partition / SplitDrive / Commodore DOS / DELL partition spanning multiple drives / QNX 1.x and 2.x ("qny")',
),
  0x9 => 'AIX data partition / Coherent filesystem / QNX 1.x and 2.x ("qnz")',
  0xa => 'OS/2 Boot Manager / Coherent swap partition / OPUS',
  0xb => 'Win98 FAT32',
  0xc => 'Win98 FAT32, LBA-mapped',
  0xe => 'Win95: DOS 16-bit FAT, LBA-mapped',
  0xf => 'Win95: Extended partition, LBA-mapped',
  0x10 => 'OPUS (?)',
  0x11 => 'Hidden DOS 12-bit FAT',
  0x12 => 'Compaq/HP config partition',
  0x14 => 'Hidden DOS 16-bit FAT <32M',
  0x16 => 'Hidden DOS 16-bit FAT >=32M',
  0x17 => 'Hidden IFS (e.g., HPFS)',
  0x18 => 'AST Windows swapfile',
  0x1b => 'Hidden WIN95 OSR2 32-bit FAT',
  0x1c => 'Hidden WIN95 OSR2 32-bit FAT, LBA-mapped',
  0x1e => 'Hidden FAT95',
  0x22 => 'Used for Oxygen Extended Partition Table by ekstazya@sprint.ca.',
  0x24 => 'NEC DOS 3.x',
  0x38 => 'THEOS ver 3.2 2gb partition',
  0x39 => 'THEOS ver 4 spanned partition',
  0x3a => 'THEOS ver 4 4gb partition',
  0x3b => 'THEOS ver 4 extended partition',
  0x3c => 'PartitionMagic recovery partition',
  0x40 => 'Venix 80286',
  0x41 => 'Linux/MINIX (sharing disk with DRDOS) / Personal RISC Boot / PPC PReP (Power PC Reference Platform) Boot',
  0x42 => 'Linux swap (sharing disk with DRDOS) / SFS (Secure Filesystem) / W2K marker',
  0x43 => 'Linux native (sharing disk with DRDOS)',
  0x45 => 'EUMEL/Elan',
  0x46 => 'EUMEL/Elan 0x46',
  0x47 => 'EUMEL/Elan 0x47',
  0x48 => 'EUMEL/Elan 0x48',
  0x4d => 'QNX4.x',
  0x4e => 'QNX4.x 2nd part',
  0x4f => 'QNX4.x 3rd part / Oberon partition',
  0x50 => 'OnTrack Disk Manager (older versions) RO',
  0x51 => 'OnTrack Disk Manager RW (DM6 Aux1) / Novell',
  0x52 => 'CP/M / Microport SysV/AT',
  0x53 => 'Disk Manager 6.0 Aux3',
  0x54 => 'Disk Manager 6.0 Dynamic Drive Overlay',
  0x55 => 'EZ-Drive',
  0x56 => 'Golden Bow VFeature Partitioned Volume. / DM converted to EZ-BIOS',
  0x57 => 'DrivePro',
  0x5c => 'Priam EDisk',
  0x61 => 'SpeedStor',
  0x63 => 'Unix System V (SCO, ISC Unix, UnixWare, ...), Mach, GNU Hurd',
  0x64 => 'PC-ARMOUR protected partition / Novell Netware 2.xx',
  0x65 => 'Novell Netware 3.xx or 4.xx',
  0x67 => 'Novell',
  0x68 => 'Novell 0x68',
  0x69 => 'Novell 0x69',
  0x70 => 'DiskSecure Multi-Boot',
  0x75 => 'IBM PC/IX',
  0x80 => 'MINIX until 1.4a',
  0x81 => 'MINIX since 1.4b, early Linux / Mitac disk manager',
  0x82 => 'Linux swap',
  0x83 => 'Linux native',
  0x84 => 'OS/2 hidden C: drive / Hibernation partition',
  0x85 => 'Linux extended partition',
  0x86 => 'Old Linux RAID partition superblock / NTFS volume set',
  0x87 => 'NTFS volume set',
  0x8a => 'Linux Kernel Partition (used by AiR-BOOT)',
  0x8e => 'Linux Logical Volume Manager partition',
  0x93 => 'Amoeba',
  0x94 => 'Amoeba bad block table',
  0x99 => 'DCE376 logical drive',
  0xa0 => 'IBM Thinkpad hibernation partition / Phoenix NoteBIOS Power Management "Save-to-Disk" partition',
  0xa5 => 'BSD/386, 386BSD, NetBSD, FreeBSD',
  0xa6 => 'OpenBSD',
  0xa7 => 'NEXTSTEP',
  0xa9 => 'NetBSD',
  0xaa => 'Olivetti Fat 12 1.44Mb Service Partition',
  0xb7 => 'BSDI filesystem',
  0xb8 => 'BSDI swap partition',
  0xbe => 'Solaris boot partition',
  0xc0 => 'CTOS / REAL/32 secure small partition',
  0xc1 => 'DRDOS/secured (FAT-12)',
  0xc4 => 'DRDOS/secured (FAT-16, < 32M)',
  0xc6 => 'DRDOS/secured (FAT-16, >= 32M) / Windows NT corrupted FAT16 volume/stripe set',
  0xc7 => 'Windows NT corrupted NTFS volume/stripe set / Syrinx boot',
  0xcb => 'reserved for DRDOS/secured (FAT32)',
  0xcc => 'reserved for DRDOS/secured (FAT32, LBA)',
  0xcd => 'CTOS Memdump?',
  0xce => 'reserved for DRDOS/secured (FAT16, LBA)',
  0xd0 => 'REAL/32 secure big partition',
  0xd1 => 'Old Multiuser DOS secured FAT12',
  0xd4 => 'Old Multiuser DOS secured FAT16 <32M',
  0xd5 => 'Old Multiuser DOS secured extended partition',
  0xd6 => 'Old Multiuser DOS secured FAT16 >=32M',
  0xd8 => 'CP/M-86',
  0xdb => 'Digital Research CP/M, Concurrent CP/M, Concurrent DOS / CTOS (Convergent Technologies OS -Unisys) / KDG Telemetry SCPU boot',
  0xdd => 'Hidden CTOS Memdump?',
  0xe1 => 'DOS access or SpeedStor 12-bit FAT extended partition',
  0xe3 => 'DOS R/O or SpeedStor',
  0xe4 => 'SpeedStor 16-bit FAT extended partition < 1024 cyl.',
  0xeb => 'BeOS',
  0xee => 'Indication that this legacy MBR is followed by an EFI header',
  0xef => 'Partition that contains an EFI file system',
  0xf1 => 'SpeedStor 0xf1',
  0xf2 => 'DOS 3.3+ secondary partition',
  0xf4 => 'SpeedStor large partition / Prologue single-volume partition',
  0xf5 => 'Prologue multi-volume partition',
  0xfd => 'Linux RAID',
  0xfe => 'SpeedStor > 1024 cyl. or LANstep / IBM PS/2 IML (Initial Microcode Load) partition, located at the end of the disk. / Windows NT Disk Administrator hidden partition / Linux Logical Volume Manager partition (old)',
  0xff => 'Xenix Bad Block Table',
);

my %type2fs = (
arch() =~ /^ppc/ ? (
  0x07 => 'hpfs',
) : (
  0x07 => 'ntfs',
),
arch() !~ /sparc/ ? (
  0x01 => 'vfat',
  0x04 => 'vfat',
  0x05 => 'ignore',
  0x06 => 'vfat',
) : (
  0x01 => 'ufs',
  0x02 => 'ufs',
  0x04 => 'ufs',
  0x06 => 'ufs',
  0x07 => 'ufs',
  0x08 => 'ufs',
),
  0x0b => 'vfat',
  0x0c => 'vfat',
  0x0e => 'vfat',
  0x1b => 'vfat',
  0x1c => 'vfat',
  0x1e => 'vfat',
  0x82 => 'swap',
  0x83 => 'ext2',
  0x183=> 'reiserfs',
  0x283=> 'xfs',
  0x383=> 'jfs',
  0x401 => 'apple',
  0x402 => 'hfs',
  nfs  => 'nfs', #- hack
);

my %types_rev = reverse %types;
my %fs2type = reverse %type2fs;


1;

sub important_types { 
    my @l = (@important_types, if_($::expert, @important_types2, sort values %types));
    difference2(\@l, \@bad_types);
}

sub type2name($) { $types{$_[0]} || $_[0] }
sub type2fs($) { $type2fs{$_[0]} }
sub fs2type($) { $fs2type{$_[0]} }
sub name2type($) { 
    local ($_) = @_;
    /0x(.*)/ ? hex $1 : $types_rev{$_} || $_;
}

sub isWholedisk($) { arch() =~ /^sparc/ && $_[0]{type} == 5 }
sub isExtended($) { arch() !~ /^sparc/ && ($_[0]{type} == 5 || $_[0]{type} == 0xf || $_[0]{type} == 0x85) }
sub isLVM($) { $_[0]{type} == 0x8e }
sub isRAID($) { $_[0]{type} == 0xfd }
sub isMDRAID { $_[0]{device} =~ /^md/ }
sub isLVMBased { $_[0]{LVMname} }
sub isSwap($) { $type2fs{$_[0]{type}} eq 'swap' }
sub isExt2($) { $type2fs{$_[0]{type}} eq 'ext2' }
sub isReiserfs($) { $type2fs{$_[0]{type}} eq 'reiserfs' }
sub isXfs($) { $type2fs{$_[0]{type}} eq 'xfs' }
sub isJfs($) { $type2fs{$_[0]{type}} eq 'jfs' }
sub isDos($) { arch() !~ /^sparc/ && $ {{ 1=>1, 4=>1, 6=>1 }}{$_[0]{type}} }
sub isWin($) { $ {{ 0xb=>1, 0xc=>1, 0xe=>1, 0x1b=>1, 0x1c=>1, 0x1e=>1 }}{$_[0]{type}} }
sub isFat($) { isDos($_[0]) || isWin($_[0]) }
sub isSunOS($) { arch() =~ /sparc/ && $ {{ 0x1=>1, 0x2=>1, 0x4=>1, 0x6=>1, 0x7=>1, 0x8=>1 }}{$_[0]{type}} }
sub isSolaris($) { 0; } #- hack to search for getting the difference ? TODO
sub isOtherAvailableFS($) { isFat($_[0]) || isSunOS($_[0]) || isHFS($_[0]) } #- other OS that linux can access its filesystem
sub isNfs($) { $_[0]{type} eq 'nfs' } #- small hack
sub isNT($) { arch() !~ /^sparc/ && $_[0]{type} == 0x7 }
sub isSupermount($) { $_[0]{type} eq 'supermount' }
sub isHFS($) { $type2fs{$_[0]{type}} eq 'hfs' }
sub isApple($) { $type2fs{$_[0]{type}} eq 'apple' && defined $_[0]{isDriver} }
sub isAppleBootstrap($) { $type2fs{$_[0]{type}} eq 'apple' && defined $_[0]{isBoot} }
sub isHiddenMacPart { defined $_[0]{isMap} }
sub isLoopback { defined $_[0]{loopback_file} }
sub isTrueFS { isExt2($_[0]) || isReiserfs($_[0]) || isXfs($_[0]) || isJfs($_[0]) }
sub isMountableRW { isTrueFS($_[0]) || isOtherAvailableFS($_[0]) }
sub isNonMountable { isRAID($_[0]) || isLVM($_[0]) }

sub isPrimary($$) {
    my ($part, $hd) = @_;
    foreach (@{$hd->{primary}{raw}}) { $part eq $_ and return 1; }
    0;
}

sub adjustStartAndEnd($$) {
    my ($hd, $part) = @_;

    $hd->adjustStart($part);
    $hd->adjustEnd($part);
}

sub verifyNotOverlap($$) {
    my ($a, $b) = @_;
    $a->{start} + $a->{size} <= $b->{start} || $b->{start} + $b->{size} <= $a->{start};
}
sub verifyInside($$) {
    my ($a, $b) = @_;
    $b->{start} <= $a->{start} && $a->{start} + $a->{size} <= $b->{start} + $b->{size};
}

sub verifyParts_ {
    foreach my $i (@_) {
	foreach (@_) {
	    next if !$i || !$_ || $i == $_ || isWholedisk($i) || isExtended($i); #- avoid testing twice for simplicity :-)
	    if (isWholedisk($_)) {
		verifyInside($i, $_) or
		  cdie sprintf("partition sector #$i->{start} (%s) is not inside whole disk (%s)!",
			       formatXiB($i->{size}, 512), formatXiB($_->{size}, 512));
	    } elsif (isExtended($_)) {
		verifyNotOverlap($i, $_) or
		  log::l(sprintf("warning partition sector #$i->{start} (%s) is overlapping with extended partition!",
				 formatXiB($i->{size}, 512))); #- only warning for this one is acceptable
	    } else {
		verifyNotOverlap($i, $_) or
		  cdie sprintf("partitions sector #$i->{start} (%s) and sector #$_->{start} (%s) are overlapping!",
			       formatXiB($i->{size}, 512), formatXiB($_->{size}, 512));
	    }
	}
    }
}
sub verifyParts($) {
    my ($hd) = @_;
    verifyParts_(get_normal_parts($hd));
}
sub verifyPrimary($) {
    my ($pt) = @_;
    $_->{start} > 0 || arch() =~ /^sparc/ || die "partition must NOT start at sector 0" foreach @{$pt->{normal}};
    verifyParts_(@{$pt->{normal}}, $pt->{extended});
}

sub assign_device_numbers($) {
    my ($hd) = @_;

    my $i = 1;
    my $start = 1; 
    
    #- on PPC we need to assign device numbers to the holes too - big FUN!
    if (arch() =~ /ppc/) {
	#- first sort the normal parts
	$hd->{primary}{normal} = [sort { $a->{start} <=> $b->{start} } @{$hd->{primary}{normal}} ];
    
	#- now loop through them, assigning partition numbers - reserve one for the holes
	foreach (@{$hd->{primary}{normal}}) {
	    if ($_->{start} > $start) {
		log::l("PPC: found a hole on $hd->{prefix} before $_->{start}, skipping device..."); 
		$i++;
	    }
	    $_->{device} = $hd->{prefix} . $i++;
	    $start = $_->{start} + $_->{size};
	}
    } else {	    
	$_->{device} = $hd->{prefix} . $i++ foreach @{$hd->{primary}{raw}},
                                                map { $_->{normal} } @{$hd->{extended} || []};
    }

    #- try to figure what the windobe drive letter could be!
    #
    #- first verify there's at least one primary dos partition, otherwise it
    #- means it is a secondary disk and all will be false :(
    my ($c, @others) = grep { isFat($_) } @{$hd->{primary}{normal}};

    $i = ord 'C';
    $c->{device_windobe} = chr($i++) if $c;
    $_->{device_windobe} = chr($i++) foreach grep { isFat($_) } map { $_->{normal} } @{$hd->{extended}};
    $_->{device_windobe} = chr($i++) foreach @others;
}

sub remove_empty_extended($) {
    my ($hd) = @_;
    my $last = $hd->{primary}{extended} or return;
    @{$hd->{extended}} = grep {
	if ($_->{normal}) {
	    $last = $_;
	} else {
	    %{$last->{extended}} = $_->{extended} ? %{$_->{extended}} : ();
	}
	$_->{normal};
    } @{$hd->{extended}};
    adjust_main_extended($hd);
}

sub adjust_main_extended($) {
    my ($hd) = @_;

    if (!is_empty_array_ref $hd->{extended}) {
	my ($l, @l) = @{$hd->{extended}};

	# the first is a special case, must recompute its real size
	my $start = round_down($l->{normal}{start} - 1, $hd->{geom}{sectors});
	my $end = $l->{normal}{start} + $l->{normal}{size};
	my $only_linux = 1; my $has_win_lba = 0;
	foreach (map $_->{normal}, $l, @l) {
	    $start = min($start, $_->{start});
	    $end = max($end, $_->{start} + $_->{size});
	    $only_linux &&= isTrueFS($_) || isSwap($_);
	    $has_win_lba ||= $_->{type} == 0xc || $_->{type} == 0xe;
	}
	$l->{start} = $hd->{primary}{extended}{start} = $start;
	$l->{size} = $hd->{primary}{extended}{size} = $end - $start;
	$hd->{primary}{extended}{type} = $only_linux ? 0x85 : $has_win_lba ? 0xf : 0x5 if !$::expert;
    }
    unless (@{$hd->{extended} || []} || !$hd->{primary}{extended}) {
	%{$hd->{primary}{extended}} = (); #- modify the raw entry
	delete $hd->{primary}{extended};
    }
    verifyParts($hd); #- verify everything is all right
}

sub adjust_local_extended($$) {
    my ($hd, $part) = @_;
    
    foreach (@{$hd->{extended} || []}) {
	$_->{normal} == $part or next;
	$_->{size} = $part->{size} + $part->{start} - $_->{start};
	last;
    }
}

sub get_normal_parts($) {
    my ($hd) = @_;

    #- HACK !!
    $hd->{raid} and return grep {$_} @{$hd->{raid}};
    $hd->{loopback} and return grep {$_} @{$hd->{loopback}};

    @{$hd->{primary}{normal} || []}, map { $_->{normal} } @{$hd->{extended} || []}
}

sub get_holes($) {
    my ($hd) = @_;

    my $start = arch() eq "alpha" ? 2048 : 1;

    map {
	my $current = $start;
	$start = $_->{start} + $_->{size};
	{ start => $current, size => $_->{start} - $current }
    } sort { $a->{start} <=> $b->{start} } grep { !isWholedisk($_) } get_normal_parts($hd), { start => $hd->{totalsectors}, size => 0 };    
}


sub read_one($$) {
    my ($hd, $sector) = @_;
    my ($pt, $info);

    #- it can be safely considered that the first sector is used to probe the partition table
    #- but other sectors (typically for extended partition ones) have to match this type!
    if (!$sector) {
	my @parttype = arch() =~ /^sparc/ ? ('sun', 'bsd', 'unknown') : ('dos', 'bsd', 'sun', 'mac', 'unknown');
	foreach ('empty', @parttype) {
	    /unknown/ and die "unknown partition table format";
	    eval {
		require("partition_table_$_.pm");
		bless $hd, "partition_table_$_";
		($pt, $info) = $hd->read($sector);
		log::l("found a $_ partition table on $hd->{file} at sector $sector");
	    };
	    $@ or last;
	}
    } else {
	#- keep current blessed object for that, this means it is neccessary to read sector 0 before.
	($pt, $info) = $hd->read($sector);
    }

    my @extended = $hd->hasExtended ? grep { isExtended($_) } @$pt : ();
    my @normal = grep { $_->{size} && $_->{type} && !isExtended($_) } @$pt;

    @extended > 1 and die "more than one extended partition";

    $_->{rootDevice} = $hd->{device} foreach @normal, @extended;
    { raw => $pt, extended => $extended[0], normal => \@normal, info => $info };
}

sub read($;$) {
    my ($hd, $clearall) = @_;
    if ($clearall) {
	partition_table_raw::zero_MBR_and_dirty($hd);
	return 1;
    }
    my $pt = read_one($hd, 0) or return 0;
    $hd->{primary} = $pt;
    undef $hd->{extended};
    verifyPrimary($pt);
    eval {
	$pt->{extended} and read_extended($hd, $pt->{extended}) || return 0;
    }; die "extended partition: $@" if $@;

    assign_device_numbers($hd);
    remove_empty_extended($hd);
    1;
}

sub read_extended {
    my ($hd, $extended) = @_;

    my $pt = read_one($hd, $extended->{start}) or return 0;
    $pt = { %$extended, %$pt };

    push @{$hd->{extended}}, $pt;
    @{$hd->{extended}} > 100 and die "oops, seems like we're looping here :(  (or you have more than 100 extended partitions!)";

    @{$pt->{normal}} <= 1 or die "more than one normal partition in extended partition";
    @{$pt->{normal}} >= 1 or cdie "no normal partition in extended partition";
    $pt->{normal} = $pt->{normal}[0];
    #- in case of extended partitions, the start sector is local to the partition or to the first extended_part!
    $pt->{normal}{start} += $pt->{start};

    #- the following verification can broke an existing partition table that is
    #- correctly read by fdisk or cfdisk. maybe the extended partition can be
    #- recomputed to get correct size.
    if (!verifyInside($pt->{normal}, $extended)) {
	$extended->{size} = $pt->{normal}{start} + $pt->{normal}{size};
	verifyInside($pt->{normal}, $extended) or die "partition $pt->{normal}{device} is not inside its extended partition";
    }

    if ($pt->{extended}) {
	$pt->{extended}{start} += $hd->{primary}{extended}{start};
	read_extended($hd, $pt->{extended}) or return 0;
    }
    1;
}

# write the partition table
sub write($) {
    my ($hd) = @_;
    $hd->{isDirty} or return;

    #- set first primary partition active if no primary partitions are marked as active.
    for ($hd->{primary}{raw}) {
	(grep { $_->{local_start} = $_->{start}; $_->{active} ||= 0 } @$_) or $_->[0]{active} = 0x80;
    }

    #- last chance for verification, this make sure if an error is detected,
    #- it will never be writed back on partition table.
    verifyParts($hd);

    $hd->write(0, $hd->{primary}{raw}, $hd->{primary}{info}) or die "writing of partition table failed";

    #- should be fixed but a extended exist with no real extended partition, that blanks mbr!
    if (arch() !~ /^sparc/) {
	foreach (@{$hd->{extended}}) {
	    # in case of extended partitions, the start sector must be local to the partition
	    $_->{normal}{local_start} = $_->{normal}{start} - $_->{start};
	    $_->{extended} and $_->{extended}{local_start} = $_->{extended}{start} - $hd->{primary}{extended}{start};

	    $hd->write($_->{start}, $_->{raw}) or die "writing of partition table failed";
	}
    }
    $hd->{isDirty} = 0;
    $hd->{hasBeenDirty} = 1; #- used in undo (to know if undo should believe isDirty or not)

    #- now sync disk and re-read the partition table
    if ($hd->{needKernelReread}) {
	common::sync();
	$hd->kernel_read;
	$hd->{needKernelReread} = 0;
    }
}

sub active($$) {
    my ($hd, $part) = @_;

    $_->{active} = 0 foreach @{$hd->{primary}{normal}};
    $part->{active} = 0x80;
    $hd->{isDirty} = 1;
}


# remove a normal partition from hard drive hd
sub remove($$) {
    my ($hd, $part) = @_;
    my $i;

    #- first search it in the primary partitions
    $i = 0; foreach (@{$hd->{primary}{normal}}) {
	if ($_ eq $part) {
	    splice(@{$hd->{primary}{normal}}, $i, 1);
	    %$_ = (); #- blank it

	    return $hd->{isDirty} = $hd->{needKernelReread} = 1;
	}
	$i++;
    }

    my ($first, $second, $third) = map { $_->{normal} } @{$hd->{extended} || []};
    if ($third && $first eq $part) {
	die "Can't handle removing hda5 when hda6 is not the second partition" if $second->{start} > $third->{start};
    }      

    #- otherwise search it in extended partitions
    foreach (@{$hd->{extended} || []}) {
	$_->{normal} eq $part or next;

	delete $_->{normal}; #- remove it
	remove_empty_extended($hd);

	return $hd->{isDirty} = $hd->{needKernelReread} = 1;
    }
    0;
}

# create of partition at starting at `start', of size `size' and of type `type' (nice comment, uh?)
sub add_primary($$) {
    my ($hd, $part) = @_;

    {
	local $hd->{primary}{normal}; #- save it to fake an addition of $part, that way add_primary do not modify $hd if it fails
	push @{$hd->{primary}{normal}}, $part;
	adjust_main_extended($hd); #- verify
	raw_add($hd->{primary}{raw}, $part);
    }
    push @{$hd->{primary}{normal}}, $part; #- really do it
}

sub add_extended {
    arch() =~ /^sparc|ppc/ and die _("Extended partition not supported on this platform");

    my ($hd, $part, $extended_type) = @_;
    $extended_type =~ s/Extended_?//;

    my $e = $hd->{primary}{extended};

    if ($e && !verifyInside($part, $e)) {
	#-die "sorry, can't add outside the main extended partition" unless $::unsafe;
	my $end = $e->{start} + $e->{size};
	my $start = min($e->{start}, $part->{start});
	$end = max($end, $part->{start} + $part->{size}) - $start;

	{ #- faking a resizing of the main extended partition to test for problems
	    local $e->{start} = $start;
	    local $e->{size} = $end - $start;
	    eval { verifyPrimary($hd->{primary}) };
	    $@ and die
_("You have a hole in your partition table but I can't use it.
The only solution is to move your primary partitions to have the hole next to the extended partitions");
	}
    }

    if ($e && $part->{start} < $e->{start}) {
	my $l = first (@{$hd->{extended}});

	#- the first is a special case, must recompute its real size
	$l->{start} = round_down($l->{normal}{start} - 1, $hd->cylinder_size());
	$l->{size} = $l->{normal}{start} + $l->{normal}{size} - $l->{start};
	my $ext = { %$l };
	unshift @{$hd->{extended}}, { type => 5, raw => [ $part, $ext, {}, {} ], normal => $part, extended => $ext };
	#- size will be autocalculated :)
    } else {
	my ($ext, $ext_size) = is_empty_array_ref($hd->{extended}) ?
	  ($hd->{primary}, -1) : #- -1 size will be computed by adjust_main_extended
	  (top(@{$hd->{extended}}), $part->{size});
	my %ext = ( type => $extended_type || 5, start => $part->{start}, size => $ext_size );

	raw_add($ext->{raw}, \%ext);
	$ext->{extended} = \%ext;
	push @{$hd->{extended}}, { %ext, raw => [ $part, {}, {}, {} ], normal => $part };
    }
    $part->{start}++; $part->{size}--; #- let it start after the extended partition sector
    adjustStartAndEnd($hd, $part);

    adjust_main_extended($hd);
}

sub add($$;$$) {
    my ($hd, $part, $primaryOrExtended, $forceNoAdjust) = @_;

    get_normal_parts($hd) >= ($hd->{device} =~ /^rd/ ? 7 : $hd->{device} =~ /^(sd|ida|cciss)/ ? 15 : 63) and cdie "maximum number of partitions handled by linux reached";

    $part->{notFormatted} = 1;
    $part->{isFormatted} = 0;
    $part->{rootDevice} = $hd->{device};
    $hd->{isDirty} = $hd->{needKernelReread} = 1;
    $part->{start} ||= 1 if arch() !~ /^sparc/; #- starting at sector 0 is not allowed
    adjustStartAndEnd($hd, $part) unless $forceNoAdjust;

    my $e = $hd->{primary}{extended};
    my $nb_primaries = $hd->{device} =~ /^rd/ ? 3 : 1;

    if (arch() =~ /^sparc|ppc/ ||
	$primaryOrExtended eq 'Primary' ||
	$primaryOrExtended !~ /Extended/ && @{$hd->{primary}{normal} || []} < $nb_primaries) {
	eval { add_primary($hd, $part) };
	return unless $@;
    }
    eval { add_extended($hd, $part, $primaryOrExtended) } if $hd->hasExtended; #- try adding extended
    if ($@ || !$hd->hasExtended) {
	eval { add_primary($hd, $part) };
	die $@ if $@; #- send the add extended error which should be better
    }
}

# search for the next partition
sub next($$) {
    my ($hd, $part) = @_;

    first(
	  sort { $a->{start} <=> $b->{start} }
	  grep { $_->{start} >= $part->{start} + $part->{size} }
	  get_normal_parts($hd)
	 );
}
sub next_start($$) {
    my ($hd, $part) = @_;
    my $next = &next($hd, $part);
    $next ? $next->{start} : $hd->{totalsectors};
}

sub can_raw_add {
    my ($hd) = @_;
    $_->{size} || $_->{type} or return 1 foreach @{$hd->{primary}{raw}};
    0;
}
sub raw_add {
    my ($raw, $part) = @_;

    foreach (@$raw) {
	$_->{size} || $_->{type} and next;
	$_ = $part;
	return;
    }
    die "raw_add: partition table already full";
}

sub load($$;$) {
    my ($hd, $file, $force) = @_;

    local *F;
    open F, $file or die _("Error reading file %s", $file);

    my $h;
    {
	local $/ = "\0";
	eval <F>;
    }
    $@ and die _("Restoring from file %s failed: %s", $file, $@);

    ref $h eq 'ARRAY' or die _("Bad backup file");

    my %h; @h{@fields2save} = @$h;

    $h{totalsectors} == $hd->{totalsectors} or $force or cdie "bad totalsectors";

    #- unsure we don't modify totalsectors
    local $hd->{totalsectors};

    @{$hd}{@fields2save} = @$h;

    delete @$_{qw(isMounted isFormatted notFormatted toFormat toFormatUnsure)} foreach get_normal_parts($hd);
    $hd->{isDirty} = $hd->{needKernelReread} = 1;
}

sub save($$) {
    my ($hd, $file) = @_;
    my @h = @{$hd}{@fields2save};
    local *F;
    require Data::Dumper;
    open F, ">$file"
      and print F Data::Dumper->Dump([\@h], ['$h']), "\0"
      or die _("Error writing to file %s", $file);
}
ter") #: ../control-center:1484 #, fuzzy, c-format msgid "%s %s (%s) Control Center" msgstr "Trung Tâm Điều Khiển %s" #. -PO: here %s is eg: "1999-2008" #: ../control-center:1489 #, c-format msgid "Copyright (C) %s Mandriva SA" msgstr "Bản quyền (C) %s Mandriva SA" #: ../control-center:1489 #, fuzzy, c-format msgid "Copyright (C) %s Mageia" msgstr "Bản quyền (C) %s Mandriva SA" #: ../control-center:1495 #, c-format msgid "Authors" msgstr "Tác giả" #: ../control-center:1496 #, fuzzy, c-format msgid "Mageia Contributors" msgstr "Người Đóng Góp Cho Mandriva Linux" #: ../drakconsole:27 #, c-format msgid "DrakConsole" msgstr "DrakConsole" #: ../drakxconf:28 #, c-format msgid "Display" msgstr "Hiển thị" #: ../drakxconf:29 #, c-format msgid "Keyboard" msgstr "Bàn phím" #: ../drakxconf:30 #, c-format msgid "Mouse" msgstr "Chuột" #: ../drakxconf:32 #, c-format msgid "Users and groups" msgstr "Người Dùng và Nhóm" #: ../drakxconf:33 #, c-format msgid "Services" msgstr "Dịch vụ" #: ../drakxconf:34 #, c-format msgid "Firewall" msgstr "Tường lửa" #: ../drakxconf:35 #, c-format msgid "Boot loader" msgstr "Trình nạp khởi động" #: ../drakxconf:36 #, c-format msgid "Auto Install" msgstr "Cài đặt tự động" #: ../drakxconf:37 #, c-format msgid "Internet connection sharing" msgstr "Chia sẻ kết nối internet" #: ../drakxconf:38 #, c-format msgid "3D Desktop effects" msgstr "" #: ../drakxconf:39 #, c-format msgid "Partitions" msgstr "Phân vùng" #: ../drakxconf:42 #, c-format msgid "Control Center" msgstr "Trung Tâm Điều Khiển" #: ../drakxconf:42 #, c-format msgid "Choose the tool you want to use" msgstr "Chọn công cụ bạn muốn dùng" #: ../lib/MDV/Control_Center.pm:55 ../lib/MDV/Control_Center.pm:56 #, fuzzy, c-format msgid "Configure 3D Desktop effects" msgstr "Cấu hình máy chủ newsgroup" #: ../lib/MDV/Control_Center.pm:68 #, c-format msgid "" "Select the authentication method (local, NIS, LDAP, Windows Domain, ...)" msgstr "Chọn phương thức chứng thực (local, NIS, LDAP, Windows Domain, ...)" #: ../lib/MDV/Control_Center.pm:77 #, fuzzy, c-format msgid "Set up autologin to automatically log in" msgstr "Bật autologin và chọn người dùng để đăng nhập tự động" #: ../lib/MDV/Control_Center.pm:78 #, c-format msgid "Enable autologin and select the user to automatically log in" msgstr "Bật autologin và chọn người dùng để đăng nhập tự động" #: ../lib/MDV/Control_Center.pm:87 #, c-format msgid "Backups" msgstr "Sao lưu" #: ../lib/MDV/Control_Center.pm:88 #, c-format msgid "Configure backups of the system and of the users' data" msgstr "Cấu hình sao lưu hệ thống và dữ liệu của người dùng" #: ../lib/MDV/Control_Center.pm:98 #, c-format msgid "Snapshots" msgstr "" #: ../lib/MDV/Control_Center.pm:108 #, fuzzy, c-format msgid "Set up boot system" msgstr "Thiết lập cách khởi động hệ thống" #: ../lib/MDV/Control_Center.pm:109 #, c-format msgid "Set up how the system boots" msgstr "Thiết lập cách khởi động hệ thống" #: ../lib/MDV/Control_Center.pm:118 #, fuzzy, c-format msgid "Set up boot graphical theme of system" msgstr "Chọn theme đồ họa khi hệ thống khởi động" #: ../lib/MDV/Control_Center.pm:119 #, c-format msgid "Select the graphical theme of the system while booting" msgstr "Chọn theme đồ họa khi hệ thống khởi động" #: ../lib/MDV/Control_Center.pm:128 ../lib/MDV/Control_Center.pm:129 #, c-format msgid "Share the Internet connection with other local machines" msgstr "Chia sẻ kết nối Internet với các máy khác trong mạng nội bộ" #: ../lib/MDV/Control_Center.pm:138 ../lib/MDV/Control_Center.pm:139 #, c-format msgid "Set up a new network interface (LAN, ISDN, ADSL, ...)" msgstr "Thiết lập giao diện mạng mới (LAN, ISDN, ADSL, ...)" #: ../lib/MDV/Control_Center.pm:148 #, c-format msgid "Internet access" msgstr "Truy cập internet" #: ../lib/MDV/Control_Center.pm:149 #, c-format msgid "Alter miscellaneous internet settings" msgstr "Thay đổi các thiết lập internet khác" #: ../lib/MDV/Control_Center.pm:158 ../lib/MDV/Control_Center.pm:159 #, fuzzy, c-format msgid "Open a console as administrator" msgstr "Mở một console" #: ../lib/MDV/Control_Center.pm:169 ../lib/MDV/Control_Center.pm:170 #, fuzzy, c-format msgid "Manage date and time" msgstr "Ngày và Giờ" #: ../lib/MDV/Control_Center.pm:179 #, fuzzy, c-format msgid "Set up display manager" msgstr "Trình quản lý hiển thị" #: ../lib/MDV/Control_Center.pm:180 #, c-format msgid "Choose the display manager that enables to select which user to log in" msgstr "Chọn trình quản lý hiển thị để cho phép chọn người dùng đăng nhập" #: ../lib/MDV/Control_Center.pm:189 ../lib/MDV/Control_Center.pm:190 #, c-format msgid "Configure a fax server" msgstr "Cấu hình fax server" #: ../lib/MDV/Control_Center.pm:199 #, c-format msgid "Set up your personal firewall" msgstr "" #: ../lib/MDV/Control_Center.pm:200 #, c-format msgid "" "Set up a personal firewall in order to protect the computer and the network" msgstr "Thiết lập tường lửa cá nhân để bảo vệ mạng và máy tính" #: ../lib/MDV/Control_Center.pm:209 ../lib/MDV/Control_Center.pm:210 #, c-format msgid "Manage, add and remove fonts. Import Windows(TM) fonts" msgstr "Quản lý, thêm, bỏ phông chữ. Nhập phông chữ từ Windows®" #: ../lib/MDV/Control_Center.pm:219 ../lib/MDV/Control_Center.pm:220 #, c-format msgid "Set up the graphical server" msgstr "Thiết lập máy chủ đồ họa" #: ../lib/MDV/Control_Center.pm:229 #, fuzzy, c-format msgid "Manage disk partitions" msgstr "DrakHOSTS quản lý định nghĩa của các máy" #: ../lib/MDV/Control_Center.pm:230 #, c-format msgid "Create, delete and resize hard disk partitions" msgstr "Tạo, xoá và thay đổi phân vùng đĩa cứng" #: ../lib/MDV/Control_Center.pm:239 ../lib/MDV/Control_Center.pm:240 #, fuzzy, c-format msgid "Browse and configure hardware" msgstr "Xem và cấu hình phần cứng" #: ../lib/MDV/Control_Center.pm:250 ../lib/MDV/Control_Center.pm:251 #, fuzzy, c-format msgid "Sound Configuration" msgstr "Cấu hình proxy" #: ../lib/MDV/Control_Center.pm:260 #, c-format msgid "Hosts definitions" msgstr "" #: ../lib/MDV/Control_Center.pm:261 #, fuzzy, c-format msgid "Manage hosts definitions" msgstr "DrakHOSTS quản lý định nghĩa của các máy" #: ../lib/MDV/Control_Center.pm:270 #, fuzzy, c-format msgid "Install & Remove Software" msgstr "Cài đặt Phần mềm" #: ../lib/MDV/Control_Center.pm:271 #, fuzzy, c-format msgid "Install, uninstall software" msgstr "Phầm mềm đã cài đặt" #: ../lib/MDV/Control_Center.pm:281 #, c-format msgid "Advanced setup for network interfaces and firewall" msgstr "" #: ../lib/MDV/Control_Center.pm:282 #, c-format msgid "Set up network interfaces failover and firewall replication" msgstr "" #: ../lib/MDV/Control_Center.pm:291 ../lib/MDV/Control_Center.pm:292 #, c-format msgid "Set up the keyboard layout" msgstr "Thiết lập tổ chức bàn phím" #: ../lib/MDV/Control_Center.pm:301 #, c-format msgid "Kolab" msgstr "Kolab" #: ../lib/MDV/Control_Center.pm:302 #, c-format msgid "Set up a groupware server" msgstr "Thiết lập máy chủ groupware" #: ../lib/MDV/Control_Center.pm:311 #, c-format msgid "Manage localization for your system" msgstr "" #: ../lib/MDV/Control_Center.pm:312 #, c-format msgid "Select the language and the country or region of the system" msgstr "Thiết lập ngôn ngữ, quốc gia hay vùng cho hệ thống" #: ../lib/MDV/Control_Center.pm:320 ../lib/MDV/Control_Center.pm:321 #, c-format msgid "View and search system logs" msgstr "Xem và tìm kiếm bản ghi hệ thống" #: ../lib/MDV/Control_Center.pm:330 #, c-format msgid "Manage connections" msgstr "Quản lý kết nối" #: ../lib/MDV/Control_Center.pm:331 #, c-format msgid "Reconfigure a network interface" msgstr "Cấu hình lại giao diện mạng" #: ../lib/MDV/Control_Center.pm:340 #, c-format msgid "Manage computer group" msgstr "Quản trị nhóm máy tính" #: ../lib/MDV/Control_Center.pm:341 #, c-format msgid "Manage installed software packages on a group of computers" msgstr "Quản lý gói phần mềm đã cài đặt của một nhóm" #: ../lib/MDV/Control_Center.pm:349 #, c-format msgid "Configure authentication for Mageia tools" msgstr "" #: ../lib/MDV/Control_Center.pm:350 #, c-format msgid "" "Define authentication required to access individual Mageia configuration " "tools " msgstr "" #: ../lib/MDV/Control_Center.pm:358 #, c-format msgid "Update your system" msgstr "" #: ../lib/MDV/Control_Center.pm:359 #, c-format msgid "" "Look at available updates and apply any fixes or upgrades to installed " "packages" msgstr "" "Xem các cập nhật hiện có và thực hiện cập nhật hay nâng cấp các gói đã cài " "đặt " #: ../lib/MDV/Control_Center.pm:369 #, c-format msgid "Menu Style" msgstr "Kiểu dáng Menu" #: ../lib/MDV/Control_Center.pm:370 #, fuzzy, c-format msgid "Menu Style Configuration" msgstr "Trung Tâm Cấu Hình Menu" #: ../lib/MDV/Control_Center.pm:379 ../lib/MDV/Control_Center.pm:380 #, c-format msgid "Import Windows(TM) documents and settings" msgstr "" #: ../lib/MDV/Control_Center.pm:389 #, c-format msgid "Monitor connections" msgstr "Theo dõi kết nối" #: ../lib/MDV/Control_Center.pm:390 #, c-format msgid "Monitor the network connections" msgstr "Theo dõi kết nối mạng" #: ../lib/MDV/Control_Center.pm:399 ../lib/MDV/Control_Center.pm:400 #, c-format msgid "Set up the pointer device (mouse, touchpad)" msgstr "Thiết lập thiết bị con trỏ (mouse, touchpad)" #: ../lib/MDV/Control_Center.pm:408 ../lib/MDV/Control_Center.pm:409 #, c-format msgid "Parental Controls" msgstr "" #: ../lib/MDV/Control_Center.pm:418 #, fuzzy, c-format msgid "Network Center" msgstr "Mạng & Internet" #: ../lib/MDV/Control_Center.pm:428 #, fuzzy, c-format msgid "Manage different network profiles" msgstr "Dịch vụ mạng" #: ../lib/MDV/Control_Center.pm:429 #, c-format msgid "Activate and manage network profiles" msgstr "" #: ../lib/MDV/Control_Center.pm:438 #, c-format msgid "Access NFS shared drives and directories" msgstr "" #: ../lib/MDV/Control_Center.pm:439 #, c-format msgid "Set NFS mount points" msgstr "Lập điểm gắn kết NFS" #: ../lib/MDV/Control_Center.pm:448 #, c-format msgid "Share drives and directories using NFS" msgstr "" #: ../lib/MDV/Control_Center.pm:449 #, fuzzy, c-format msgid "Manage NFS shares" msgstr "DrakSamba quản lý điểm chia sẻ Samba" #: ../lib/MDV/Control_Center.pm:459 #, c-format msgid "Package Stats" msgstr "Trạng thái gói" #: ../lib/MDV/Control_Center.pm:460 #, c-format msgid "Show statistics about usage of installed software packages" msgstr "Hiển thị thống kê về việc dùng các gói phần mềm trong hệ thống" #: ../lib/MDV/Control_Center.pm:469 #, fuzzy, c-format msgid "Share your hard disk partitions" msgstr "Thiết lập việc chia sẻ các phân vùng đĩa cứng" #: ../lib/MDV/Control_Center.pm:470 #, c-format msgid "Set up sharing of your hard disk partitions" msgstr "Thiết lập việc chia sẻ các phân vùng đĩa cứng" #: ../lib/MDV/Control_Center.pm:479 ../lib/MDV/Control_Center.pm:481 #, c-format msgid "Set up the printer(s), the print job queues, ..." msgstr "Thiết lập máy in, hàng đợi in,..." #: ../lib/MDV/Control_Center.pm:491 #, c-format msgid "Scheduled tasks" msgstr "Tác vụ theo lịch" #: ../lib/MDV/Control_Center.pm:492 #, c-format msgid "Schedule programs to run periodically or at given times" msgstr "Lên lịch chạy chương trình theo định kỳ hay theo thời gian cụ thể" #: ../lib/MDV/Control_Center.pm:501 #, c-format msgid "Proxy" msgstr "Proxy" #: ../lib/MDV/Control_Center.pm:502 #, c-format msgid "Set up a proxy server for files and web browsing" msgstr "Thiết lập proxy server để duyệt web và tập tin" #: ../lib/MDV/Control_Center.pm:510 #, c-format msgid "Remote Control (Linux/Unix, Windows)" msgstr "Điều khiển từ xa (Linux/Unix, Windows)" #: ../lib/MDV/Control_Center.pm:511 #, c-format msgid "Remote Control of another machine (Linux/Unix, Windows)" msgstr "Điều khiển máy tính từ xa (Linux/Unix, Windows)" #: ../lib/MDV/Control_Center.pm:520 #, c-format msgid "Remove a connection" msgstr "Bỏ kết nối" #: ../lib/MDV/Control_Center.pm:521 #, c-format msgid "Delete a network interface" msgstr "Xoá giao diện mạng" #: ../lib/MDV/Control_Center.pm:531 ../lib/MDV/Control_Center.pm:532 #, c-format msgid "Wireless connection" msgstr "Kết nối không dây" #: ../lib/MDV/Control_Center.pm:541 #, c-format msgid "Access Windows (SMB) shared drives and directories" msgstr "" #: ../lib/MDV/Control_Center.pm:542 #, c-format msgid "Configuration of Windows (Samba) shared drives and directories" msgstr "" #: ../lib/MDV/Control_Center.pm:551 #, c-format msgid "Share drives and directories with Windows (SMB) systems" msgstr "" #: ../lib/MDV/Control_Center.pm:552 #, fuzzy, c-format msgid "Manage configuration of Samba" msgstr "Cấu hình việc in ấn" #: ../lib/MDV/Control_Center.pm:561 ../lib/MDV/Control_Center.pm:562 #, c-format msgid "Set up scanner" msgstr "Thiết lập máy quét" #: ../lib/MDV/Control_Center.pm:571 #, fuzzy, c-format msgid "Configure system security, permissions and audit" msgstr "Tinh chỉnh quyền hạn bảo mật cho hệ thống" #: ../lib/MDV/Control_Center.pm:572 #, fuzzy, c-format msgid "Set the system security level, periodic security audit and permissions" msgstr "Đặt mức bảo mật hệ thống và kiểm tra bảo mật định kỳ" #: ../lib/MDV/Control_Center.pm:582 ../lib/MDV/Control_Center.pm:583 #, c-format msgid "Manage system services by enabling or disabling them" msgstr "" #: ../lib/MDV/Control_Center.pm:592 #, c-format msgid "Configure media sources for install and update" msgstr "" #: ../lib/MDV/Control_Center.pm:593 #, fuzzy, c-format msgid "Select from where software packages are downloaded " msgstr "Chọn nơi tải về các gói để cập nhật hệ thống" #: ../lib/MDV/Control_Center.pm:603 #, fuzzy, c-format msgid "Configure updates frequency" msgstr "Cấu hình groupware" #: ../lib/MDV/Control_Center.pm:612 #, c-format msgid "Access to extended maintenance" msgstr "" #: ../lib/MDV/Control_Center.pm:621 #, c-format msgid "Configure TOMOYO Linux policy" msgstr "" #: ../lib/MDV/Control_Center.pm:622 #, c-format msgid "View and configure TOMOYO Linux security policy" msgstr "" # -PO: here power means electrical power #. -PO: here power means electrical power #. -PO: UPS==Uninterruptible power supply #: ../lib/MDV/Control_Center.pm:634 ../lib/MDV/Control_Center.pm:637 #, c-format msgid "Set up a UPS for power monitoring" msgstr "Thiết lập UPS để theo dõi nguồn điện" #: ../lib/MDV/Control_Center.pm:647 #, fuzzy, c-format msgid "Manage users on system" msgstr "Thêm, bỏ hay thay đổi người dùng của hệ thống" #: ../lib/MDV/Control_Center.pm:648 #, c-format msgid "Add, remove or change users of the system" msgstr "Thêm, bỏ hay thay đổi người dùng của hệ thống" #: ../lib/MDV/Control_Center.pm:658 #, c-format msgid "Virtualization" msgstr "" #: ../lib/MDV/Control_Center.pm:659 #, c-format msgid "Virtual machines management" msgstr "" #: ../lib/MDV/Control_Center.pm:668 ../lib/MDV/Control_Center.pm:669 #, fuzzy, c-format msgid "Configure VPN connection to secure network access" msgstr "Theo dõi kết nối" #: ../lib/MDV/Control_Center.pm:678 #, c-format msgid "Access WebDAV shared drives and directories" msgstr "" #: ../lib/MDV/Control_Center.pm:679 #, c-format msgid "Set WebDAV mount points" msgstr "Lập điểm gắn kết WebDAV" #: ../menus_launcher.pl:19 ../menus_launcher.pl:41 #, c-format msgid "Menu Configuration Center" msgstr "Trung Tâm Cấu Hình Menu" #: ../menus_launcher.pl:28 #, c-format msgid "System menu" msgstr "Menu hệ thống" #: ../menus_launcher.pl:29 ../menus_launcher.pl:36 ../print_launcher.pl:31 #, c-format msgid "Configure..." msgstr "Cấu hình..." #: ../menus_launcher.pl:31 #, c-format msgid "User menu" msgstr "Menu người dùng" #: ../menus_launcher.pl:41 #, c-format msgid "" "\n" "\n" "Choose which menu you want to configure" msgstr "" "\n" "\n" "Hãy chọn menu để cấu hình" #: ../print_launcher.pl:14 ../print_launcher.pl:21 #, c-format msgid "Printing configuration" msgstr "Cấu hình việc in ấn" #: ../print_launcher.pl:30 #, c-format msgid "Click here to configure the printing system" msgstr "Nhấn vào đây để cấu hình hệ thống in" #: ../print_launcher.pl:37 #, c-format msgid "Done" msgstr "Hoàn thành" #: ../data/autologin.desktop.in.h:1 msgid "Autologin" msgstr "Đăng nhập tự động" #: ../data/clock.desktop.in.h:1 msgid "Date and time" msgstr "Ngày và Giờ" #: ../data/connection.desktop.in.h:1 msgid "New connection" msgstr "Kết nối mới" #: ../data/drakautoinst.desktop.in.h:1 msgid "Auto Install floppy" msgstr "Đĩa mềm cài đặt tự động" #: ../data/drakboot.desktop.in.h:1 msgid "Boot Loading" msgstr "Nạp khởi động" #: ../data/drakcronat.desktop.in.h:1 msgid "Programs scheduling" msgstr "Tác vụ theo lịch" #: ../data/drakdm.desktop.in.h:1 msgid "Display manager" msgstr "Trình quản lý hiển thị" #: ../data/drakfloppy.desktop.in.h:1 msgid "Boot floppy" msgstr "Đĩa mềm khởi động" #: ../data/drakfont.desktop.in.h:1 msgid "Fonts" msgstr "Phông chữ" #: ../data/drakperm.desktop.in.h:1 msgid "Permissions" msgstr "Quyền hạn" #: ../data/draksec.desktop.in.h:1 msgid "Levels and Checks" msgstr "Mức độ và việc kiểm tra" #: ../data/drakxtv.desktop.in.h:1 msgid "TV Cards" msgstr "TV Card" #: ../data/fileshare.desktop.in.h:1 msgid "Partition Sharing" msgstr "Chia sẻ phân vùng đĩa" #: ../data/harddrive.desktop.in.h:1 msgid "Hard Drives" msgstr "Đĩa Cứng" #: ../data/logdrake.desktop.in.h:1 msgid "Logs" msgstr "Bản ghi (log)" #: ../data/menudrake.desktop.in.h:1 msgid "Menus" msgstr "Menu" #: ../data/MountPoints.directory.in.h:1 msgid "Mount Points" msgstr "Điểm Gắn Kết" #: ../data/nfs.desktop.in.h:1 msgid "NFS mount points" msgstr "Điểm gắn kết NFS" #: ../data/printerdrake.desktop.in.h:1 msgid "Printers" msgstr "Máy in" #: ../data/proxy.desktop.in.h:1 msgid "Proxy Configuration" msgstr "Cấu hình proxy" #: ../data/removable.desktop.in.h:1 msgid "Removable devices" msgstr "Thiết bị tháo lắp" #: ../data/remove-connection.desktop.in.h:1 msgid "Remove Connection" msgstr "Bỏ kết nối" #: ../data/samba.desktop.in.h:1 msgid "Samba mount points" msgstr "Điểm gắn kết Samba" #: ../data/scannerdrake.desktop.in.h:1 msgid "Scanners" msgstr "Máy quét" #: ../data/SystemConfig.directory.in.h:1 msgid "System Settings" msgstr "Thiết lập của hệ thống" #: ../data/userdrake.desktop.in.h:1 msgid "Users and Groups" msgstr "Người Dùng và Nhóm" #: ../data/webdav.desktop.in.h:1 msgid "WebDAV mount points" msgstr "Điểm gắn kết WebDAV" #: ../data/XFDrake.desktop.in.h:1 msgid "Graphical server" msgstr "Máy chủ đồ họa" #: ../data/XFDrake-Monitor.desktop.in.h:1 msgid "Monitor" msgstr "Monitor" #: ../data/XFDrake-Resolution.desktop.in.h:1 msgid "Screen Resolution" msgstr "Độ phân giải màn hình" #: ../drakconf.desktop.in.h:1 #, fuzzy msgid "Mageia Control Center" msgstr "Trung Tâm Điều Khiển" #~ msgid "Configure Your Computer" #~ msgstr "Cấu hình máy tính" #, fuzzy #~ msgid "Mandriva Linux" #~ msgstr "Mandriva Online" #, fuzzy #~ msgid "Set up security level and audit" #~ msgstr "Đặt mức bảo mật hệ thống và kiểm tra bảo mật định kỳ" #, fuzzy #~ msgid "Tune permissions on system" #~ msgstr "Tinh chỉnh quyền hạn bảo mật cho hệ thống" #~ msgid "Welcome to the %s Control Center" #~ msgstr "Chào Mừng Trung Tâm Điều Khiển %s" #~ msgid "Generate an Auto Install floppy" #~ msgstr "Tạo đĩa mềm cài đặt tự động" #~ msgid "Generate a standalone boot floppy" #~ msgstr "Tạo đĩa mềm khởi động độc lập" #, fuzzy #~ msgid "Upload your configuration to get information on upgrades" #~ msgstr "" #~ "Tải lên cấu hình của bạn để duy trì thông báo về các cập nhật bảo mật và " #~ "nâng cấp hữu ích" #, fuzzy #~ msgid "" #~ "Upload your configuration in order to keep you informed about security " #~ "and useful upgrades" #~ msgstr "" #~ "Tải lên cấu hình của bạn để duy trì thông báo về các cập nhật bảo mật và " #~ "nâng cấp hữu ích" #~ msgid "Floppy drive" #~ msgstr "Ổ đĩa mềm" #~ msgid "Set where your floppy drive is mounted" #~ msgstr "Lập điểm gắn kết ổ đĩa mềm" #~ msgid "/_Upload the hardware list" #~ msgstr "/_Tải lên danh sách phần cứng" #, fuzzy #~ msgid "<control>U" #~ msgstr "<control>Q" #~ msgid "Upload the hardware list" #~ msgstr "Tải lên danh sách phần cứng" #~ msgid "Account:" #~ msgstr "Tài khoản:" #~ msgid "Password:" #~ msgstr "Mật khẩu:" #~ msgid "Hostname:" #~ msgstr "Tên máy chủ:" #~ msgid "Please wait" #~ msgstr "Hãy đợi" #, fuzzy #~ msgid "Manage software" #~ msgstr "DrakSamba quản lý điểm chia sẻ Samba" #, fuzzy #~ msgid "Use NFS shares" #~ msgstr "DrakSamba quản lý điểm chia sẻ Samba" #, fuzzy #~ msgid "Manage Samba configuration" #~ msgstr "Cấu hình Thư Cảnh Báo" #, fuzzy #~ msgid "Use WebDAV shares" #~ msgstr "Cấu hình máy chủ web" #~ msgid "CD-ROM" #~ msgstr "CD-ROM" #~ msgid "Boot theme" #~ msgstr "Theme khởi động" #~ msgid "Console" #~ msgstr "Console" #~ msgid "Adjust the date and the time" #~ msgstr "Hiệu chỉnh Ngày & Giờ" #~ msgid "Fax" #~ msgstr "Fax" #~ msgid "Software Media Manager" #~ msgstr "Trình Quản Lý Nguồn Phần Mềm" #, fuzzy #~ msgid "Invictus Firewall" #~ msgstr "Tường lửa" #~ msgid "Language" #~ msgstr "Ngôn ngữ" #~ msgid "Country / Region" #~ msgstr "Quốc gia / Vùng" #~ msgid "Updates" #~ msgstr "Cập nhật" #, fuzzy #~ msgid "Control and configure network connections" #~ msgstr "Theo dõi kết nối mạng" #, fuzzy #~ msgid "Network Profiles" #~ msgstr "Dịch vụ mạng" #~ msgid "Local disk sharing" #~ msgstr "Chia sẻ ổ đĩa cục bộ" #~ msgid "Level and checks" #~ msgstr "Mức độ và việc kiểm tra" #~ msgid "Enable or disable the system services" #~ msgstr "Bật hay tắt các dịch vụ hệ thống" #~ msgid "Media Manager" #~ msgstr "Trình quản lý phương tiện" #~ msgid "UPS" #~ msgstr "UPS" #, fuzzy #~ msgid "VPN configuration" #~ msgstr "Cấu hình DVB" #, fuzzy #~ msgid "Configure Software management" #~ msgstr "Quản Lý Phần Mềm" #~ msgid "Install" #~ msgstr "Cài đặt" #~ msgid "Look at installable software and install software packages" #~ msgstr "Xem phần mềm có thể cài đặt và cài đặt gói phần mềm" #~ msgid "Remove" #~ msgstr "Gỡ bỏ" #~ msgid "Look at installed software and uninstall software packages" #~ msgstr "Xem các gói đã và chưa cài đặt" #~ msgid "Screen resolution" #~ msgstr "Độ phân giải màn hình" #~ msgid "Change the screen resolution" #~ msgstr "Thay đổi độ phân giải màn hình" #~ msgid "TV card" #~ msgstr "TV card" #~ msgid "Set up TV card" #~ msgstr "Thiết lập TV card" #~ msgid "/_Expert mode" #~ msgstr "/Chế độ _Chuyên Gia" #~ msgid "Set Samba mount points" #~ msgstr "Lập điểm gắn kết Samba" #, fuzzy #~ msgid "Samba printing configuration" #~ msgstr "Cấu hình việc in ấn" #~ msgid "(original C version)" #~ msgstr "(phiên bản C gốc)" #~ msgid "(design)" #~ msgstr "(thiết kế)" #~ msgid "" #~ "Select the application menu layout and change which programs are shown on " #~ "the menu" #~ msgstr "" #~ "Chọn layout cho menu của ứng dụng và thay đổi chương trình nào được hiển " #~ "thị trên menu" #~ msgid "" #~ "We are about to switch from the \"%s\" profile to the \"%s\" profile.\n" #~ "\n" #~ "Are you sure you want to do the switch?" #~ msgstr "" #~ "Sẽ chuyển từ lý lịch \"%s\" sang lý lịch \"%s\".\n" #~ "\n" #~ "Bạn có chắc chắn muốn chuyển không?" #~ msgid "/_Profiles" #~ msgstr "/_Lý lịch" #~ msgid "/_New" #~ msgstr "/Mớ_i" #~ msgid "New profile..." #~ msgstr "Lý lịch mới..." #~ msgid "" #~ "Name of the profile to create (the new profile is created as a copy of " #~ "the current one):" #~ msgstr "" #~ "Tên lý lịch để tạo (lý lịch mới được tạo như bản sao của lý lịch hiện " #~ "thời):" #~ msgid "Ok" #~ msgstr "Ok" #~ msgid "The \"%s\" profile already exists!" #~ msgstr "Lý lịch \"%s\" đang tồn tại rồi!" #~ msgid "Delete profile" #~ msgstr "Xóa lý lịch" #~ msgid "Profile to delete:" #~ msgstr "Xóa lý lịch:" #~ msgid "You can not delete the current profile" #~ msgstr "Bạn không thể xóa lý lịch hiện thời"