1# linux-lib.pl 2# Mount table functions for linux 3 4if (!$no_check_support) { 5 my %support; 6 my $fsfile = &read_file_contents("/proc/filesystems"); 7 foreach my $l (split(/\r?\n/, $fsfile)) { 8 my @w = split(/\s+/, $l); 9 my $fs = pop(@w); 10 $support{$fs} = 1; 11 } 12 if (&has_command("amd")) { 13 local $amd = &read_amd_conf(); 14 $amd_support = $amd =~ /\[\s*global\s*\]/i ? 2 : 1; 15 } 16 $autofs_support = &has_command("automount"); 17 if (&has_command("mount.cifs")) { 18 $cifs_support = 4; 19 } 20 if (&has_command("mount.smbfs")) { 21 $smbfs_support = &backquote_command("mount.smbfs -v 2>&1", 1) =~ /username=/i ? 4 : 3; 22 $smbfs_fs = "smbfs"; 23 } 24 elsif (&has_command("mount.smb")) { 25 $smbfs_support = &backquote_command("mount.smb -v 2>&1", 1) =~ /username=/i ? 4 : 3; 26 $smbfs_fs = "smb"; 27 } 28 elsif (&has_command("smbmount")) { 29 $smbfs_support = &backquote_command("smbmount -v 2>&1", 1) =~ /Version\s+2/i ? 2 : 1; 30 $smbfs_fs = "smbfs"; 31 } 32 $swaps_support = -r "/proc/swaps"; 33 $tmpfs_support = 1; 34 $ext3_support = 1; 35 $no_mount_check = 1; 36 $bind_support = 1; 37 if ($support{'ext4'}) { 38 $ext4_support = 1; 39 } 40 if ($support{'xfs'} || &has_command("mkfs.xfs")) { 41 $xfs_support = 1; 42 } 43 if ($support{'jfs'} || &has_command("mkfs.jfs")) { 44 $jfs_support = 1; 45 } 46 if ($support{'btrfs'} || &has_command("mkfs.btrfs")) { 47 $btrfs_support = 1; 48 } 49 } 50 51# We always need to check this, to fix up LABEL= mounts 52if (&has_command("e2label")) { 53 $has_e2label = 1; 54 } 55if (&has_command("xfs_db")) { 56 $has_xfs_db = 1; 57 } 58if (&has_command("vol_id")) { 59 $has_volid = 1; 60 } 61if (&has_command("reiserfstune")) { 62 $has_reiserfstune = 1; 63 } 64$uuid_directory = "/dev/disk/by-uuid"; 65 66# Return information about a filesystem, in the form: 67# directory, device, type, options, fsck_order, mount_at_boot 68# If a field is unused or ignored, a - appears instead of the value. 69# Swap-filesystems (devices or files mounted for VM) have a type of 'swap', 70# and 'swap' in the directory field 71sub list_mounts 72{ 73return @list_mounts_cache if (@list_mounts_cache); 74local(@rv, @p, @o, $_, $i, $j); 75$i = 0; 76 77# Get /etc/fstab mounts 78open(FSTAB, "<".$config{fstab_file}); 79while(<FSTAB>) { 80 local(@o, $at_boot); 81 chop; s/#.*$//g; 82 if (!/\S/ || /\signore\s/) { next; } 83 if (/\t+[^\t]+\t+[^\t+]\t+/) { 84 # Contains at least 3 tabs .. assume tab separation 85 @p = split(/\t+/, $_); 86 } 87 else { 88 @p = split(/\s+/, $_); 89 } 90 $p[0] =~ s/\\040/ /g; 91 $p[1] =~ s/\\040/ /g; 92 if ($p[2] eq "proc") { $p[0] = "proc"; } 93 elsif ($p[2] eq "auto") { $p[2] = "*"; } 94 elsif ($p[2] eq "swap") { $p[1] = "swap"; } 95 elsif ($p[2] eq $smbfs_fs || $p[2] eq "cifs") { 96 $p[0] =~ s/\\040/ /g; 97 $p[0] =~ s/\//\\/g; 98 } 99 $p[1] = &simplify_path($p[1]); 100 $rv[$i] = [ $p[1], $p[0], $p[2] ]; 101 $rv[$i]->[5] = "yes"; 102 @o = split(/,/ , $p[3] eq "defaults" ? "" : $p[3]); 103 if (($j = &indexof("noauto", @o)) >= 0) { 104 # filesytem is not mounted at boot 105 splice(@o, $j, 1); 106 $rv[$i]->[5] = "no"; 107 } 108 if (($j = &indexof("bind", @o)) >= 0) { 109 # Special bind option, which indicates a loopback filesystem 110 splice(@o, $j, 1); 111 $rv[$i]->[2] = "bind"; 112 } 113 $rv[$i]->[3] = (@o ? join(',' , @o) : "-"); 114 $rv[$i]->[4] = (@p >= 5 ? $p[5] : 0); 115 $i++; 116 } 117close(FSTAB); 118 119if ($amd_support == 1) { 120 # Get old automounter configuration, as used by redhat 121 local $amd = &read_amd_conf(); 122 if ($amd =~ /MOUNTPTS='(.*)'/) { 123 @p = split(/\s+/, $1); 124 for($j=0; $j<@p; $j+=2) { 125 $rv[$i++] = [ $p[$j], $p[$j+1], "auto", 126 "-", 0, "yes" ]; 127 } 128 } 129 } 130elsif ($amd_support == 2) { 131 # Guess what? There's now a *new* amd config file format, introduced 132 # in redhat 6.1 and caldera 2.3 133 local @amd = &parse_amd_conf(); 134 local @sp = split(/:/, $amd[0]->{'opts'}->{'search_path'}); 135 local ($am, $sp); 136 foreach $am (@amd) { 137 local $mn = $am->{'opts'}->{'map_name'}; 138 if ($mn !~ /^\//) { 139 foreach $sp (@sp) { 140 if (-r "$sp/$mn") { 141 $mn = "$sp/$mn"; 142 last; 143 } 144 } 145 } 146 $rv[$i++] = [ $am->{'dir'}, $mn, 147 "auto", $am->{'opts'}, 0, "yes" ] 148 if ($am->{'dir'} ne 'global'); 149 } 150 } 151 152# Get kernel automounter configuration 153if ($autofs_support) { 154 open(AUTO, "<".$config{'autofs_file'}); 155 while(<AUTO>) { 156 chop; 157 s/#.*$//g; 158 if (/^\s*(\S+)\s+(\S+)\s*(.*)$/) { 159 $rv[$i++] = [ $1, $2, "autofs", 160 ($3 ? &autofs_options($3) : "-"), 161 0, "yes" ]; 162 } 163 } 164 close(AUTO); 165 } 166 167@list_mounts_cache = @rv; 168return @rv; 169} 170 171 172# create_mount(directory, device, type, options, fsck_order, mount_at_boot) 173# Add a new entry to the fstab file, old or new automounter file 174sub create_mount 175{ 176local(@mlist, @amd, $_, $opts); 177 178if ($_[2] eq "auto") { 179 if ($amd_support == 1) { 180 # Adding an old automounter mount 181 local $amd = &read_amd_conf(); 182 local $m = "$_[0] $_[1]"; 183 if ($amd =~ /MOUNTPTS=''/) { 184 $amd =~ s/MOUNTPTS=''/MOUNTPTS='$m'/; 185 } 186 else { 187 $amd =~ s/MOUNTPTS='(.*)'/MOUNTPTS='$1 $m'/; 188 } 189 &write_amd_conf($amd); 190 } 191 elsif ($amd_support == 2) { 192 # Adding a new automounter mount 193 local @amfs = split(/\s+/, $config{'auto_file'}); 194 &open_tempfile(AMD, ">>$amfs[0]"); 195 &print_tempfile(AMD, "\n"); 196 &print_tempfile(AMD, "[ $_[0] ]\n"); 197 &print_tempfile(AMD, "map_name = $_[1]\n"); 198 &close_tempfile(AMD); 199 } 200 } 201elsif ($_[2] eq "autofs") { 202 # Adding a new automounter mount 203 &open_tempfile(AUTO, ">> $config{'autofs_file'}"); 204 &print_tempfile(AUTO, "$_[0] $_[1]"); 205 if ($_[3]) { 206 &print_tempfile(AUTO, " ",&autofs_args($_[3])); 207 } 208 &print_tempfile(AUTO, "\n"); 209 &close_tempfile(AUTO); 210 } 211else { 212 # Adding a normal mount to the fstab file 213 local $dev = $_[1]; 214 if ($_[2] eq $smbfs_fs || $_[2] eq "cifs") { 215 $dev =~ s/\\/\//g; 216 } 217 $dev =~ s/ /\\040/g; 218 local $mp = $_[0]; 219 $mp =~ s/ /\\040/g; 220 &open_tempfile(FSTAB, ">> $config{fstab_file}"); 221 &print_tempfile(FSTAB, $dev."\t".$mp."\t".$_[2]); 222 local @opts = $_[3] eq "-" ? ( ) : split(/,/, $_[3]); 223 if ($_[5] eq "no") { 224 push(@opts, "noauto"); 225 } 226 else { 227 @opts = grep { $_ !~ /^(auto|noauto)$/ } @opts; 228 } 229 if ($_[2] eq "bind") { 230 push(@opts, "bind"); 231 } 232 if (!@opts) { &print_tempfile(FSTAB, "\t"."defaults"); } 233 else { &print_tempfile(FSTAB, "\t".join(",", @opts)); } 234 &print_tempfile(FSTAB, "\t"."0"."\t"); 235 &print_tempfile(FSTAB, $_[4] eq "-" ? "0\n" : "$_[4]\n"); 236 &close_tempfile(FSTAB); 237 } 238undef(@list_mounts_cache); 239} 240 241 242# change_mount(num, directory, device, type, options, fsck_order, mount_at_boot) 243# Change an existing permanent mount 244sub change_mount 245{ 246local($i, @fstab, $line, $opts, $j, @amd); 247$i = 0; 248 249# Update fstab file 250open(FSTAB, "<".$config{fstab_file}); 251@fstab = <FSTAB>; 252close(FSTAB); 253&open_tempfile(FSTAB, "> $config{fstab_file}"); 254foreach (@fstab) { 255 chop; ($line = $_) =~ s/#.*$//g; 256 if ($line =~ /\S/ && $line !~ /\signore\s/ && $i++ == $_[0]) { 257 # Found the line to replace 258 local $dev = $_[2]; 259 if ($_[3] eq $smbfs_fs || $_[3] eq "cifs") { 260 $dev =~ s/\\/\//g; 261 } 262 $dev =~ s/ /\\040/g; 263 local $mp = $_[1]; 264 $mp =~ s/ /\\040/g; 265 &print_tempfile(FSTAB, $dev."\t".$mp."\t".$_[3]); 266 local @opts = $_[4] eq "-" ? ( ) : split(/,/, $_[4]); 267 if ($_[6] eq "no") { 268 push(@opts, "noauto"); 269 } 270 else { 271 @opts = grep { $_ !~ /^(auto|noauto)$/ } @opts; 272 } 273 if ($_[3] eq "bind") { 274 push(@opts, "bind"); 275 } 276 if (!@opts) { &print_tempfile(FSTAB, "\t"."defaults"); } 277 else { &print_tempfile(FSTAB, "\t".join(",", @opts)); } 278 &print_tempfile(FSTAB, "\t"."0"."\t"); 279 &print_tempfile(FSTAB, $_[5] eq "-" ? "0\n" : "$_[5]\n"); 280 } 281 else { &print_tempfile(FSTAB, $_,"\n"); } 282 } 283&close_tempfile(FSTAB); 284 285if ($amd_support == 1) { 286 # Update older amd configuration 287 local $amd = &read_amd_conf(); 288 if ($amd =~ /MOUNTPTS='(.*)'/) { 289 # found mount points line.. 290 local @mpts = split(/\s+/, $1); 291 for($j=0; $j<@mpts; $j+=2) { 292 if ($i++ == $_[0]) { 293 $mpts[$j] = $_[1]; 294 $mpts[$j+1] = $_[2]; 295 } 296 } 297 local $mpts = join(" ", @mpts); 298 $amd =~ s/MOUNTPTS='(.*)'/MOUNTPTS='$mpts'/; 299 } 300 &write_amd_conf($amd); 301 } 302elsif ($amd_support == 2) { 303 # Update new amd configuration 304 local @amd = &parse_amd_conf(); 305 foreach $am (@amd) { 306 next if ($am->{'dir'} eq 'global'); 307 if ($i++ == $_[0]) { 308 local $lref = &read_file_lines($am->{'file'}); 309 local @nl = ( "[ $_[1] ]" ); 310 local %opts = %{$am->{'opts'}}; 311 $opts{'map_name'} = $_[2]; 312 foreach $o (keys %opts) { 313 push(@nl, "$o = $opts{$o}"); 314 } 315 splice(@$lref, $am->{'line'}, 316 $am->{'eline'} - $am->{'line'} + 1, @nl); 317 &flush_file_lines(); 318 } 319 } 320 } 321 322# Update autofs configuration 323if ($autofs_support) { 324 open(AUTO, "<".$config{'autofs_file'}); 325 @auto = <AUTO>; 326 close(AUTO); 327 &open_tempfile(AUTO, "> $config{'autofs_file'}"); 328 foreach (@auto) { 329 chop; ($line = $_) =~ s/#.*$//g; 330 if ($line =~ /\S/ && $i++ == $_[0]) { 331 &print_tempfile(AUTO, "$_[1] $_[2]"); 332 if ($_[4]) { 333 &print_tempfile(AUTO, " ",&autofs_args($_[4])); 334 } 335 &print_tempfile(AUTO, "\n"); 336 } 337 else { 338 &print_tempfile(AUTO, $_,"\n"); 339 } 340 } 341 &close_tempfile(AUTO); 342 } 343undef(@list_mounts_cache); 344} 345 346 347# delete_mount(index) 348# Delete an existing permanent mount 349sub delete_mount 350{ 351local($i, @fstab, $line, $opts, $j, @amd); 352$i = 0; 353 354# Update fstab file 355open(FSTAB, "<".$config{fstab_file}); 356@fstab = <FSTAB>; 357close(FSTAB); 358&open_tempfile(FSTAB, ">$config{fstab_file}"); 359foreach (@fstab) { 360 chop; ($line = $_) =~ s/#.*$//g; 361 if ($line !~ /\S/ || $line =~ /\signore\s/ || $i++ != $_[0]) { 362 # Don't delete this line 363 &print_tempfile(FSTAB, $_,"\n"); 364 } 365 } 366&close_tempfile(FSTAB); 367 368if ($amd_support == 1) { 369 # Update older amd configuration 370 local $foundamd = 0; 371 local $amd = &read_amd_conf(); 372 if ($amd =~ /MOUNTPTS='(.*)'/) { 373 # found mount points line.. 374 local @mpts = split(/\s+/, $1); 375 for($j=0; $j<@mpts; $j+=2) { 376 if ($i++ == $_[0]) { 377 splice(@mpts, $j, 2); 378 $foundamd = 1; 379 } 380 } 381 local $mpts = join(" ", @mpts); 382 $amd =~ s/MOUNTPTS='(.*)'/MOUNTPTS='$mpts'/; 383 } 384 &write_amd_conf($amd) if ($foundamd); 385 } 386elsif ($amd_support == 2) { 387 # Update new amd configuration 388 local @amd = &parse_amd_conf(); 389 foreach $am (@amd) { 390 next if ($am->{'dir'} eq 'global'); 391 if ($i++ == $_[0]) { 392 local $lref = &read_file_lines($am->{'file'}); 393 splice(@$lref, $am->{'line'}, 394 $am->{'eline'} - $am->{'line'} + 1); 395 &flush_file_lines(); 396 } 397 } 398 } 399 400# Update AMD file 401if ($amd_support) { 402 open(AMD, "<".$config{auto_file}); 403 @amd = <AMD>; 404 close(AMD); 405 &open_tempfile(AMD, ">$config{auto_file}"); 406 foreach (@amd) { 407 if (/MOUNTPTS='(.*)'/) { 408 # found mount points line.. 409 @mpts = split(/\s+/, $1); 410 for($j=0; $j<@mpts; $j+=2) { 411 if ($i++ != $_[0]) { 412 push(@nmpts, $mpts[$j]); 413 push(@nmpts, $mpts[$j+1]); 414 } 415 } 416 &print_tempfile(AMD, "MOUNTPTS='".join(' ', @nmpts)."'\n"); 417 } 418 else { &print_tempfile(AMD, $_); } 419 } 420 &close_tempfile(AMD); 421 } 422 423# Update autofs file 424if ($autofs_support) { 425 open(AUTO, "<".$config{'autofs_file'}); 426 @auto = <AUTO>; 427 close(AUTO); 428 &open_tempfile(AUTO, ">$config{'autofs_file'}"); 429 foreach (@auto) { 430 chop; ($line = $_) =~ s/#.*$//g; 431 if ($line !~ /\S/ || $i++ != $_[0]) { 432 # keep this line 433 &print_tempfile(AUTO, $_,"\n"); 434 } 435 } 436 &close_tempfile(AUTO); 437 } 438undef(@list_mounts_cache); 439} 440 441 442# list_mounted([no-label]) 443# Return a list of all the currently mounted filesystems and swap files. 444# The list is in the form: 445# directory device type options 446sub list_mounted 447{ 448return @list_mounted_cache 449 if (@list_mounted_cache && $list_mounted_cache_mode == $_[0]); 450local(@rv, @p, @o, $mo, $_, %smbopts); 451 452# Do any filesystems use labels that we need to resolve? 453local @mounts = &list_mounts(); 454local $anylabel = 0; 455local $anyuuid = 0; 456foreach my $m (@mounts) { 457 if ($m->[1] =~ /^LABEL=/) { 458 $anylabel++; 459 } 460 if ($m->[1] =~ /^UUID=/) { 461 $anyuuid++; 462 } 463 } 464 465&read_smbopts(); 466open(MTAB, "</etc/mtab"); 467while(<MTAB>) { 468 chop; 469 s/#.*$//g; 470 if (!/\S/) { next; } 471 @p = split(/\s+/, $_); 472 next if ($p[0] eq "rootfs"); # Bogus pseudo-fs 473 $p[1] = &simplify_path($p[1]); 474 if ($p[2] eq "auto" || $p[0] =~ /^\S+:\(pid\d+\)$/) { 475 # Automounter map.. turn the map= option into the device 476 @o = split(/,/ , $p[3]); 477 ($mo) = grep {/^map=/} (@o); 478 $mo =~ /^map=(.*)$/; $p[0] = $1; 479 $p[3] = join(',' , grep {!/^map=/} (@o)); 480 $p[2] = "auto"; 481 } 482 elsif ($p[2] eq "autofs") { 483 # Kernel automounter map.. use the pid to find the map 484 $p[0] =~ /automount\(pid(\d+)\)/ || next; 485 $out = &backquote_command("ps hwwww $1", 1); 486 $out =~ /automount\s+(.*)\s*(\S+)\s+(file|program|yp)(,\S+)?\s+(\S+)/ || next; 487 $p[0] = $5; 488 $p[3] = $1 ? &autofs_options($1) : "-"; 489 } 490 elsif ($p[2] eq $smbfs_fs || $p[2] eq "cifs") { 491 # Change from //FOO/BAR to \\foo\bar 492 $p[0] = &lowercase_share_path($p[0]); 493 $p[3] = $smbopts{$p[1]}; 494 } 495 elsif ($p[2] eq "proc") { 496 # The source for proc mounts is always proc 497 $p[0] = "proc"; 498 } 499 if (!$_[0] && $anylabel) { 500 # Check for a label on this partition, and there is one 501 # and this filesystem is in fstab with the label, change 502 # the device. 503 local $label = &get_filesystem_label(@p); 504 if (defined($label)) { 505 foreach my $m (@mounts) { 506 if ($m->[0] eq $p[1] && 507 $m->[1] eq "LABEL=$label") { 508 $p[0] = "LABEL=$label"; 509 last; 510 } 511 } 512 } 513 } 514 515 # Check for a UUID on this partition, and if there is one 516 # and the filesystem is in fstab with the label, change 517 # the device. 518 if (!$_[0] && $anyuuid) { 519 local $uuid = &device_to_uuid($p[0], \@mounts); 520 if ($uuid) { 521 $p[0] = "UUID=$uuid"; 522 } 523 } 524 525 # check fstab for a mount on the same dir which is a symlink 526 # to the device 527 local @st = stat($p[0]); 528 foreach $m (@mounts) { 529 if ($m->[0] eq $p[1]) { 530 local @fst = stat($m->[1]); 531 if ($fst[0] == $st[0] && $fst[1] == $st[1]) { 532 # symlink to the same place! 533 $p[0] = $m->[1]; 534 last; 535 } 536 } 537 } 538 539 if ($p[3] =~ s/,bind,// || $p[3] =~ s/^bind,// || 540 $p[3] =~ s/,bind$// || $p[3] =~ s/^bind$//) { 541 # Special bind option, which indicates a loopback filesystem 542 $p[2] = "bind"; 543 } 544 545 push(@rv, [ $p[1], $p[0], $p[2], $p[3] ]); 546 } 547close(MTAB); 548open(SWAPS, "</proc/swaps"); 549while(<SWAPS>) { 550 chop; 551 if (/^(\/\S+)\s+/) { 552 local $sf = $1; 553 554 # check fstab for a mount on a device which is a symlink 555 # to the path in /proc/swaps 556 local @st = stat($sf); 557 foreach $m (@mounts) { 558 local @fst = stat($m->[1]); 559 if ($m->[2] eq 'swap' && $fst[0] == $st[0] && 560 $fst[1] == $st[1]) { 561 $sf = $m->[1]; 562 last; 563 } 564 } 565 566 # Convert to UUID format if used in fstab 567 if (!$_[0]) { 568 local $uuid = &device_to_uuid($sf, \@mounts); 569 if ($uuid) { 570 $sf = "UUID=$uuid"; 571 } 572 } 573 push(@rv, [ "swap", $sf, "swap", "-" ]); 574 } 575 } 576close(SWAPS); 577@list_mounted_cache = @rv; 578$list_mounted_cache_mode = $_[0]; 579return @rv; 580} 581 582# device_to_uuid(device, [&mounts]) 583# Given a device name like /dev/sda1, return the UUID for it. 584# If a list of mounts are given, only match if found in mount list. 585sub device_to_uuid 586{ 587local ($device, $mounts) = @_; 588local $uuid; 589if ($device =~ /^\Q$uuid_directory\E\/([^\/]+)$/) { 590 # Device is already under the UUID directory, so ID can be found 591 # immediately from the path 592 $uuid = $1; 593 } 594elsif ($device =~ /^\/dev\// && ($has_volid || -d $uuid_directory)) { 595 # Device is like /dev/sda1, so try to find the UUID for it by either 596 # looking in /dev/disk/by-uuid or using the volid command 597 if (-d $uuid_directory) { 598 # Use UUID mapping directory 599 opendir(DIR, $uuid_directory); 600 foreach my $f (readdir(DIR)) { 601 local $linkdest = &simplify_path( 602 &resolve_links("$uuid_directory/$f")); 603 if ($linkdest eq $device) { 604 $uuid = $f; 605 last; 606 } 607 } 608 closedir(DIR); 609 } 610 else { 611 # Use vol_id command 612 local $out = &backquote_command( 613 "vol_id ".quotemeta($device)." 2>&1", 1); 614 if ($out =~ /ID_FS_UUID=(\S+)/) { 615 $uuid = $1; 616 } 617 } 618 } 619if ($uuid && @$mounts) { 620 my $found; 621 foreach my $m (@$mounts) { 622 if ($m->[1] eq "UUID=$uuid") { 623 $found++; 624 last; 625 } 626 } 627 $uuid = undef if (!$found); 628 } 629return $uuid; 630} 631 632# mount_dir(directory, device, type, options) 633# Mount a new directory from some device, with some options. Returns 0 if ok, 634# or an error string if failed 635sub mount_dir 636{ 637local($out, $opts, $shar, %options, %smbopts); 638local @opts = $_[3] eq "-" || $_[3] eq "" ? ( ) : 639 grep { $_ ne "noauto" } split(/,/, $_[3]); 640if ($_[2] eq "bind") { 641 push(@opts, "bind"); 642 } 643$opts = @opts ? "-o ".quotemeta(join(",", @opts)) : ""; 644&parse_options($_[2], $_[3]); 645 646# Work out args for label or UUID 647local $devargs; 648if ($_[1] =~ /LABEL=(.*)/) { 649 $devargs = "-L ".quotemeta($1); 650 } 651elsif ($_[1] =~ /UUID=(\S+)/) { 652 $devargs = "-U ".quotemeta($1); 653 } 654else { 655 $devargs = quotemeta($_[1]); 656 } 657 658if ($_[2] eq "swap") { 659 # Use swapon to add the swap space.. 660 local $priarg = $options{'pri'} ne "" ? "-p $options{'pri'}" : ""; 661 $out = &backquote_logged("swapon $priarg $devargs 2>&1"); 662 if ($out =~ /Invalid argument/) { 663 # looks like this swap partition isn't ready yet.. set it up 664 $out = &backquote_logged("mkswap $devargs 2>&1"); 665 if ($?) { return "mkswap failed : <pre>$out</pre>"; } 666 $out = &backquote_logged("swapon $devargs 2>&1"); 667 } 668 if ($?) { return "<pre>$out</pre>"; } 669 } 670elsif ($_[2] eq "auto") { 671 # Old automounter filesystem 672 $out = &backquote_logged("amd $_[0] $_[1] >/dev/null 2>/dev/null"); 673 if ($?) { return $text{'linux_eamd'}; } 674 } 675elsif ($_[2] eq "autofs") { 676 # New automounter filesystem 677 $opts = &autofs_args($_[3]); 678 $type = $_[1] !~ /^\// ? "yp" : 679 (-x $_[1]) ? "program" : "file"; 680 $out = &backquote_logged("automount $opts $_[0] $type $_[1] 2>&1"); 681 if ($?) { return &text('linux_eauto', "<pre>$out</pre>"); } 682 } 683elsif ($_[2] eq $smbfs_fs || $_[2] eq "cifs") { 684 local $shar = $_[1]; 685 $shar =~ s/\\/\//g if ($shar =~ /^\\/); 686 local $support = $_[2] eq $smbfs_fs ? $smbfs_support : $cifs_support; 687 return uc($_[2])." not supported" if (!$support); 688 local $qshar = quotemeta($shar); 689 if ($support >= 3) { 690 # SMB filesystem mounted with mount command 691 local $temp = &transname(); 692 local $ex = &system_logged("mount -t $_[2] $opts $qshar $_[0] >$temp 2>&1 </dev/null"); 693 local $out = &read_file_contents($temp); 694 unlink($temp); 695 if ($ex || $out =~ /failed|error/i) { 696 &system_logged("umount $_[0] >/dev/null 2>&1"); 697 return "<pre>$out</pre>"; 698 } 699 } 700 elsif ($support == 2) { 701 # SMB filesystem mounted with version 2.x smbmount 702 $opts = 703 ($options{'user'} ? "-U $options{'user'} " : ""). 704 ($options{'passwd'} ? "" : "-N "). 705 ($options{'workgroup'} ? "-W $options{'workgroup'} " : ""). 706 ($options{'clientname'} ? "-n $options{'clientname'} " : ""). 707 ($options{'machinename'} ? "-I $options{'machinename'} " : ""); 708 &foreign_require("proc"); 709 local ($fh, $fpid) = &proc::pty_process_exec_logged( 710 "sh -c 'smbmount $shar $_[0] -d 0 $opts'"); 711 if ($options{'passwd'}) { 712 local $w = &wait_for($fh, "word:"); 713 if ($w < 0) { 714 &system_logged("umount $_[0] >/dev/null 2>&1"); 715 return $text{'linux_esmbconn'}; 716 } 717 local $p = "$options{'passwd'}\n"; 718 syswrite($fh, $p, length($p)); 719 } 720 local $got; 721 while(<$fh>) { 722 $got .= $_; 723 } 724 if ($got =~ /failed/) { 725 &system_logged("umount $_[0] >/dev/null 2>&1"); 726 return "<pre>$got</pre>\n"; 727 } 728 close($fh); 729 } 730 elsif ($support == 1) { 731 # SMB filesystem mounted with older smbmount 732 $shortname = &get_system_hostname(); 733 if ($shortname =~ /^([^\.]+)\.(.+)$/) { $shortname = $1; } 734 $opts = 735 ($options{servername} ? "-s $options{servername} " : ""). 736 ($options{clientname} ? "-c $options{clientname} " 737 : "-c $shortname "). 738 ($options{machinename} ? "-I $options{machinename} " : ""). 739 ($options{user} ? "-U $options{user} " : ""). 740 ($options{passwd} ? "-P $options{passwd} " : "-n "). 741 ($options{uid} ? "-u $options{uid} " : ""). 742 ($options{gid} ? "-g $options{gid} " : ""). 743 ($options{fmode} ? "-f $options{fmode} " : ""). 744 ($options{dmode} ? "-d $options{dmode} " : ""); 745 $out = &backquote_logged("smbmount $shar $_[0] $opts 2>&1 </dev/null"); 746 if ($out) { 747 &system_logged("umount $_[0] >/dev/null 2>&1"); 748 return "<pre>$out</pre>"; 749 } 750 } 751 &read_smbopts(); 752 $smbopts{$_[0]} = $_[3] eq "-" ? "dummy=1" : $_[3]; 753 &write_smbopts(); 754 } 755else { 756 # some filesystem supported by mount 757 local $fs = $_[2] eq "*" ? "auto" : $_[2]; 758 $cmd = "mount -t $fs $opts $devargs ".quotemeta($_[0]); 759 $out = &backquote_logged("$cmd 2>&1 </dev/null"); 760 if ($?) { return "<pre>$out</pre>"; } 761 } 762undef(@list_mounted_cache); 763return 0; 764} 765 766# os_remount_dir(directory, device, type, options) 767# Adjusts the options for some mounted filesystem, by re-mounting 768sub os_remount_dir 769{ 770if ($_[2] eq "swap" || $_[2] eq "auto" || $_[2] eq "autofs" || 771 $_[2] eq $smbfs_fs || $_[2] eq "cifs") { 772 # Cannot use remount 773 local $err = &unmount_dir(@_); 774 return $err if ($err); 775 return &mount_dir(@_); 776 } 777else { 778 # Attempt to use remount 779 local @opts = $_[3] eq "-" || $_[3] eq "" ? ( ) : 780 grep { $_ ne "noauto" } split(/,/, $_[3]); 781 push(@opts, "remount"); 782 local $opts = @opts ? "-o ".quotemeta(join(",", @opts)) : ""; 783 local $fs = $_[2] eq "*" ? "auto" : $_[2]; 784 if ($_[1] =~ /LABEL=(.*)/) { 785 $cmd = "mount -t $fs -L $1 $opts $_[0]"; 786 } 787 elsif ($_[1] =~ /UUID=(\S+)/) { 788 $cmd = "mount -t $fs -U $1 $opts $_[0]"; 789 } 790 else { 791 $cmd = "mount -t $fs $opts $_[1] $_[0]"; 792 } 793 $out = &backquote_logged("$cmd 2>&1 </dev/null"); 794 if ($?) { return "<pre>$out</pre>"; } 795 undef(@list_mounted_cache); 796 return undef; 797 } 798} 799 800# unmount_dir(directory, device, type, options, [force]) 801# Unmount a directory that is currently mounted. Returns 0 if ok, 802# or an error string if failed 803sub unmount_dir 804{ 805local($out, %smbopts, $dir); 806if ($_[2] eq "swap") { 807 # Use swapoff to remove the swap space.. 808 $out = &backquote_logged("swapoff $_[1]"); 809 if ($?) { return "<pre>$out</pre>"; } 810 } 811elsif ($_[2] eq "auto") { 812 # Kill the amd process 813 $dir = $_[0]; 814 if (&backquote_command("cat /etc/mtab") =~ /:\(pid([0-9]+)\)\s+$dir\s+(auto|nfs)\s+/) { 815 &kill_logged('TERM', $1) || return $text{'linux_ekillamd'}; 816 } 817 sleep(2); 818 } 819elsif ($_[2] eq "autofs") { 820 # Kill the automount process 821 $dir = $_[0]; 822 &backquote_command("cat /etc/mtab") =~ /automount\(pid([0-9]+)\)\s+$dir\s+autofs\s+/; 823 &kill_logged('TERM', $1) || return $text{'linux_ekillauto'}; 824 sleep(2); 825 } 826else { 827 local $fflag = $_[4] ? "-l" : ""; 828 $out = &backquote_logged("umount $fflag $_[0] 2>&1"); 829 if ($?) { return "<pre>$out</pre>"; } 830 if ($_[2] eq $smbfs_fs || $_[2] eq "cifs") { 831 # remove options from list 832 &read_smbopts(); 833 delete($smbopts{$_[0]}); 834 &write_smbopts(); 835 &execute_command("rmmod smbfs"); 836 &execute_command("rmmod cifs"); 837 } 838 } 839undef(@list_mounted_cache); 840return 0; 841} 842 843# can_force_unmount_dir(directory, device, type) 844# Returns 1 if some directory can be forcibly un-mounted 845sub can_force_unmount_dir 846{ 847if ($_[2] ne "swap" && $_[2] ne "auto" && $_[2] ne "autofs") { 848 # All filesystems using the normal 'mount' command can be 849 return 1; 850 } 851else { 852 return 0; 853 } 854} 855 856# mount_modes(type) 857# Given a filesystem type, returns 4 numbers that determine how the file 858# system can be mounted, and whether it can be fsck'd 859# 0 - cannot be permanently recorded 860# (smbfs under linux before 2.2) 861# 1 - can be permanently recorded, and is always mounted at boot 862# (swap under linux) 863# 2 - can be permanently recorded, and may or may not be mounted at boot 864# (most normal filesystems) 865# The second is: 866# 0 - mount is always permanent => mounted when saved 867# (swap under linux before 2.2, or any filesystem that is always 868# mounted at boot by some script) 869# 1 - doesn't have to be permanent 870# (normal fs types) 871# The third is: 872# 0 - cannot be fsck'd at boot time 873# 1 - can be be fsck'd at boot 874# The fourth is: 875# 0 - can be unmounted 876# 1 - cannot be unmounted 877# The (optional) fourth is: 878# 0 - can be edited 879# 1 - cannot be edited (because is always mounted at boot by some script) 880sub mount_modes 881{ 882if ($_[0] eq "swap") 883 { return (1, $swaps_support ? 1 : 0, 0, 0); } 884elsif ($_[0] eq "auto" || $_[0] eq "autofs") 885 { return (1, 1, 0, 0); } 886elsif ($_[0] eq $smbfs_fs) 887 { return ($smbfs_support >= 3 ? 2 : 0, 1, 0, 0); } 888elsif ($_[0] eq "cifs") { return (2, 1, 0, 0); } 889elsif ($_[0] =~ /^ext\d+$/ || $_[0] eq "minix" || 890 $_[0] eq "xiafs" || $_[0] eq "xfs" || $_[0] eq "jfs" || $_[0] eq "btrfs") 891 { return (2, 1, 1, 0); } 892else 893 { return (2, 1, 0, 0); } 894} 895 896 897# disk_space(type, directory) 898# Returns the amount of total and free space for some filesystem, or an 899# empty array if not appropriate. 900sub disk_space 901{ 902if (&get_mounted($_[1], "*") < 0) { return (); } 903if ($_[0] eq "proc" || $_[0] eq "swap" || 904 $_[0] eq "auto" || $_[0] eq "autofs") { return (); } 905&clean_language(); 906local $out = &backquote_command("df -k ".quotemeta($_[1]), 1); 907&reset_environment(); 908if ($out =~ /Mounted on\n\S+\s+(\S+)\s+\S+\s+(\S+)/) { 909 return ($1, $2); 910 } 911return ( ); 912} 913 914# inode_space(type, directory) 915# Returns the total and free number of inodes for some filesystem. 916sub inode_space 917{ 918if (&get_mounted($_[1], "*") < 0) { return (); } 919&clean_language(); 920local $out = &backquote_command("df -i $_[1]", 1); 921&reset_environment(); 922if ($out =~ /Mounted on\n\S+\s+(\S+)\s+\S+\s+(\S+)/) { 923 return ($1, $2); 924 } 925return ( ); 926} 927 928# list_fstypes() 929# Returns an array of all the supported filesystem types. If a filesystem is 930# found that is not one of the supported types, generate_location() and 931# generate_options() will not be called for it. 932sub list_fstypes 933{ 934local @sup = ("ext2", "msdos", "nfs", "nfs4", "iso9660", "ext", 935 "hpfs", "fat", "vfat", "umsdos", "sysv", "reiserfs", 936 "ntfs", "hfs", "fatx"); 937push(@sup, $smbfs_fs) if ($smbfs_support); 938push(@sup, "cifs") if ($cifs_support); 939push(@sup, "auto") if ($amd_support); 940push(@sup, "autofs") if ($autofs_support); 941push(@sup, "tmpfs") if ($tmpfs_support); 942push(@sup, "ext3") if ($ext3_support); 943push(@sup, "ext4") if ($ext4_support); 944push(@sup, "xfs") if ($xfs_support); 945push(@sup, "btrfs") if ($btrfs_support); 946push(@sup, "jfs") if ($jfs_support); 947push(@sup, "bind") if ($bind_support); 948push(@sup, "swap"); 949return @sup; 950} 951 952 953# fstype_name(type) 954# Given a short filesystem type, return a human-readable name for it 955sub fstype_name 956{ 957local(%fsmap); 958%fsmap = ("ext2","Old Linux Native Filesystem", 959 "ext3","Linux Native Filesystem", 960 "ext4","New Linux Native Filesystem", 961 "minix","Minix Filesystem", 962 "msdos","MS-DOS Filesystem", 963 "nfs","Network Filesystem", 964 "nfs4","Network Filesystem v4", 965 $smbfs_fs,"Windows Networking Filesystem", 966 "cifs","Common Internet Filesystem", 967 "iso9660","ISO9660 CD-ROM", 968 "ext","Old EXT Linux Filesystem", 969 "xiafs","Old XIAFS Linux Filesystem", 970 "hpfs","OS/2 Filesystem", 971 "fat","MS-DOS Filesystem", 972 "vfat","Windows Filesystem", 973 "umsdos","Linux on top of MS-DOS Filesystem", 974 "sysv","System V Filesystem", 975 "swap","Virtual Memory", 976 "proc","Kernel Filesystem", 977 "sysfs","Kernel Filesystem", 978 "devpts","Pseudoterminal Device Filesystem", 979 "auto",($autofs_support ? "Old " : "")."Automounter Filesystem", 980 "reiserfs","Reiser Filesystem", 981 "autofs","New Automounter Filesystem", 982 "usbdevfs","USB Devices", 983 "shm","SysV Shared Memory", 984 "tmpfs","RAM/Swap Disk", 985 "devtmpfs","RAM/Swap Disk", 986 "ramfs","RAM Disk", 987 "btrfs","Oracle B-Tree Filesystem", 988 "ocfs2","Oracle Clustering Filesystem", 989 "gfs2","RedHat Clustering Filesystem", 990 "xfs","Linux XFS Filesystem", 991 "jfs","IBM Journalling Filesystem", 992 "ntfs","Windows NT Filesystem", 993 "bind","Loopback Filesystem", 994 "hfs","Apple Filesystem", 995 "fatx","XBOX Filesystem", 996 "btrfs","BTR Filesystem", 997 ); 998return $config{long_fstypes} && $fsmap{$_[0]} ? $fsmap{$_[0]} : uc($_[0]); 999} 1000 1001 1002# multiple_mount(type) 1003# Returns 1 if filesystems of this type can be mounted multiple times, 0 if not 1004sub multiple_mount 1005{ 1006return ($_[0] eq "nfs" || $_[0] eq "nfs4" || $_[0] eq "auto" || 1007 $_[0] eq "autofs" || $_[0] eq "bind" || $_[0] eq "tmpfs"); 1008} 1009 1010 1011# generate_location(type, location) 1012# Output HTML for editing the mount location of some filesystem. 1013sub generate_location 1014{ 1015local ($type, $loc) = @_; 1016if ($type eq "nfs" || $type eq "nfs4") { 1017 # NFS mount from some host and directory 1018 local ($host, $dir) = $loc =~ /^([^:]+):(.*)$/ ? ( $1, $2 ) : ( ); 1019 print &ui_table_row(&hlink($text{'linux_nfshost'}, "nfshost"), 1020 &ui_textbox("nfs_host", $host, 30). 1021 &nfs_server_chooser_button("nfs_host"). 1022 " ". 1023 "<b>".&hlink($text{'linux_nfsdir'}, "nfsdir")."</b> ". 1024 &ui_textbox("nfs_dir", 1025 ($type eq "nfs4") && ($dir eq "") ? "/" : $dir, 30). 1026 &nfs_export_chooser_button("nfs_host", "nfs_dir")); 1027 } 1028elsif ($type eq "auto") { 1029 # Using some automounter map 1030 print &ui_table_row($text{'linux_map'}, 1031 &ui_textbox("auto_map", $loc, 30)." ". 1032 &file_chooser_button("auto_map", 0)); 1033 } 1034elsif ($type eq "autofs") { 1035 # Using some kernel automounter map 1036 print &ui_table_row($text{'linux_map'}, 1037 &ui_textbox("autofs_map", $loc, 30)." ". 1038 &file_chooser_button("autofs_map", 0)); 1039 } 1040elsif ($type eq "swap") { 1041 # Swap file or device 1042 &foreign_require("fdisk"); 1043 local @opts; 1044 local ($found, $ufound, $lnx_dev); 1045 1046 # Show partitions input 1047 local $sel = &fdisk::partition_select("lnx_disk", $loc, 3, \$found); 1048 push(@opts, [ 0, $text{'linux_disk'}, $sel ]); 1049 $lnx_dev = 0 if ($found); 1050 1051 # Show UUID input 1052 if ($has_volid || -d $uuid_directory) { 1053 local $u = $loc =~ /UUID=(\S+)/ ? $1 : undef; 1054 local $usel = &fdisk::volid_select("lnx_uuid", $u, \$ufound); 1055 if ($usel) { 1056 push(@opts, [ 5, $text{'linux_usel'}, $usel ]); 1057 $lnx_dev = 5 if ($ufound); 1058 } 1059 } 1060 1061 # Show other file input 1062 $lnx_dev = 1 if (!$found && !$ufound); 1063 push(@opts, [ 1, $text{'linux_swapfile'}, 1064 &ui_textbox("lnx_other", $loc, 40)." ". 1065 &file_chooser_button("lnx_other") ]); 1066 print &ui_table_row($text{'linux_swapfile'}, 1067 &ui_radio_table("lnx_dev", $lnx_dev, \@opts)); 1068 } 1069elsif ($type eq $smbfs_fs || $type eq "cifs") { 1070 # Windows filesystem 1071 local ($server, $share) = $loc =~ /^\\\\([^\\]*)\\(.*)$/ ? 1072 ($1, $2) : ( ); 1073 print &ui_table_row($text{'linux_smbserver'}, 1074 &ui_textbox("smbfs_server", $server, 30)." ". 1075 &smb_server_chooser_button("smbfs_server")." ". 1076 " ". 1077 "<b>$text{'linux_smbshare'}</b> ". 1078 &ui_textbox("smbfs_share", $share, 30)." ". 1079 &smb_share_chooser_button("smbfs_server", "smbfs_share")); 1080 } 1081elsif ($type eq "tmpfs") { 1082 # RAM disk (no location needed) 1083 } 1084elsif ($type eq "bind") { 1085 # Loopback filesystem, mounted from some other directory 1086 print &ui_table_row($text{'linux_bind'}, 1087 &ui_textbox("bind_dir", $loc, 40)." ". 1088 &file_chooser_button("bind_dir", 1)); 1089 } 1090else { 1091 # This is some linux disk-based filesystem 1092 &foreign_require("fdisk"); 1093 local ($found, $rfound, $lfound, $vfound, $ufound, $rsel, $c); 1094 local ($lnx_dev, @opts); 1095 1096 # Show regular partition input 1097 local $sel = &fdisk::partition_select("lnx_disk", $loc, 0, \$found); 1098 push(@opts, [ 0, $text{'linux_disk'}, $sel ]); 1099 $lnx_dev = 0 if ($found); 1100 1101 # Show RAID input 1102 if (&foreign_check("raid")) { 1103 &foreign_require("raid"); 1104 local $conf = &raid::get_raidtab(); 1105 local @ropts; 1106 foreach $c (@$conf) { 1107 if ($c->{'active'}) { 1108 $c->{'value'} =~ /(\d+)$/; 1109 push(@ropts, [ $c->{'value'}, 1110 &text('linux_rdev', "$1") ]); 1111 $rfound++ if ($loc eq $c->{'value'}); 1112 } 1113 } 1114 $lnx_dev = 2 if ($rfound); 1115 if (@ropts) { 1116 push(@opts, [ 2, $text{'linux_raid'}, 1117 &ui_select("lnx_raid", $loc, \@ropts) ]); 1118 } 1119 } 1120 1121 # Show LVM input 1122 if (&foreign_check("lvm")) { 1123 &foreign_require("lvm"); 1124 local @vgs = &lvm::list_volume_groups(); 1125 local @lvs; 1126 foreach $v (@vgs) { 1127 push(@lvs, &lvm::list_logical_volumes($v->{'name'})); 1128 } 1129 local @lopts; 1130 foreach $l (@lvs) { 1131 local $sf = &same_file($loc, $l->{'device'}); 1132 push(@lopts, [ $l->{'device'}, 1133 &text('linux_ldev', $l->{'vg'}, $l->{'name'}) ]); 1134 $vfound = $l->{'device'} if ($sf); 1135 } 1136 $lnx_dev = 4 if ($vfound); 1137 if (@lopts) { 1138 push(@opts, [ 4, $text{'linux_lvm'}, 1139 &ui_select("lnx_lvm", $vfound, \@lopts) ]); 1140 } 1141 } 1142 1143 # Show label input 1144 if ($has_e2label || $has_xfs_db || $has_reiserfstune) { 1145 local $l = $_[1] =~ /LABEL=(.*)/ ? $1 : undef; 1146 local $esel = &fdisk::label_select("lnx_label", $l, \$lfound); 1147 if ($esel) { 1148 push(@opts, [ 3, $text{'linux_lsel'}, $esel ]); 1149 $lnx_dev = 3 if ($lfound); 1150 } 1151 } 1152 1153 # Show UUID input 1154 if ($has_volid || -d $uuid_directory) { 1155 local $u = $loc =~ /UUID=(\S+)/ ? $1 : undef; 1156 local $usel = &fdisk::volid_select("lnx_uuid", $u, \$ufound); 1157 if ($usel) { 1158 push(@opts, [ 5, $text{'linux_usel'}, $usel ]); 1159 $lnx_dev = 5 if ($ufound); 1160 } 1161 } 1162 1163 # Show other device input 1164 local $anyfound = $found || $rfound || $lfound || $vfound || $ufound; 1165 $lnx_dev = 1 if (!$anyfound); 1166 push(@opts, [ 1, $text{'linux_other'}, 1167 &ui_textbox("lnx_other", $anyfound ? "" : $loc, 40). 1168 " ".&file_chooser_button("lnx_other") ]); 1169 1170 print &ui_table_row(&fstype_name($_[0]), 1171 &ui_radio_table("lnx_dev", $lnx_dev, \@opts)); 1172 } 1173} 1174 1175 1176# generate_options(type, newmount) 1177# Output HTML for editing mount options for a particular filesystem 1178# under this OS 1179sub generate_options 1180{ 1181local ($type, $newmount) = @_; 1182if ($type ne "swap" && $type ne "auto" && 1183 $type ne "autofs" && $type ne $smbfs_fs && $type ne "cifs") { 1184 # Lots of options are common to all linux filesystems 1185 print &ui_table_row(&hlink($text{'linux_ro'}, "linux_ro"), 1186 &ui_yesno_radio("lnx_ro", defined($options{"ro"}))); 1187 1188 print &ui_table_row(&hlink($text{'linux_sync'}, "linux_sync"), 1189 &ui_yesno_radio("lnx_sync", defined($options{"sync"}), 0, 1)); 1190 1191 print &ui_table_row(&hlink($text{'linux_user'}, "linux_user"), 1192 &ui_yesno_radio("lnx_user", defined($options{"user"}))); 1193 1194 print &ui_table_row(&hlink($text{'linux_nodev'}, "linux_nodev"), 1195 &ui_radio("lnx_nodev", defined($options{"nodev"}) ? 1 : 1196 defined($options{"dev"}) ? 0 : 2, 1197 [ [ 1, $text{'yes'} ], 1198 [ 0, $text{'no'} ], 1199 [ 2, $text{'linux_ifuser'} ] ])); 1200 1201 print &ui_table_row(&hlink($text{'linux_noexec'}, "linux_noexec"), 1202 &ui_radio("lnx_noexec", defined($options{"noexec"}) ? 1 : 1203 defined($options{"dev"}) ? 0 : 2, 1204 [ [ 1, $text{'yes'} ], 1205 [ 0, $text{'no'} ], 1206 [ 2, $text{'linux_ifuser'} ] ])); 1207 1208 print &ui_table_row(&hlink($text{'linux_nosuid'}, "linux_nosuid"), 1209 &ui_radio("lnx_nosuid", defined($options{"nosuid"}) ? 1 : 1210 defined($options{"dev"}) ? 0 : 2, 1211 [ [ 1, $text{'yes'} ], 1212 [ 0, $text{'no'} ], 1213 [ 2, $text{'linux_ifuser'} ] ])); 1214 1215 print &ui_table_row(&hlink($text{'linux_noatime'}, "linux_noatime"), 1216 &ui_yesno_radio("lnx_noatime", defined($options{"noatime"}))); 1217 1218 print &ui_table_row(&hlink($text{'linux_netdev'}, "linux_netdev"), 1219 &ui_yesno_radio("lnx_netdev", defined($options{"_netdev"}))); 1220 1221 print &ui_table_row(&hlink($text{'linux_nofail'}, "linux_nofail"), 1222 &ui_yesno_radio("lnx_nofail", defined($options{"nofail"}))); 1223 } 1224 1225if ($type =~ /^ext\d+$/) { 1226 # Ext2+ has lots more options.. 1227 print &ui_table_hr(); 1228 1229 if ($no_mount_check) { 1230 print &ui_table_row($text{'linux_df'}, 1231 &ui_yesno_radio("ext2_df", defined($options{"minixdf"}))); 1232 } 1233 else { 1234 print &ui_table_row($text{'linux_check'}, 1235 &ui_select("ext2_check", 1236 $options{"check"} eq "" ? "normal" : 1237 defined($options{"nocheck"}) ? "none" : 1238 $options{"check"}, 1239 [ [ "normal", $text{'linux_normal'} ], 1240 [ "strict", $text{'linux_strict'} ], 1241 [ "none", $text{'linux_none'} ] ])); 1242 } 1243 1244 print &ui_table_row($text{'linux_errors'}, 1245 &ui_select("ext2_errors", 1246 !defined($options{"errors"}) ? "default" : 1247 $options{"errors"}, 1248 [ [ "default", $text{'default'} ], 1249 [ "continue", $text{'linux_continue'} ], 1250 [ "remount-ro", $text{'linux_remount_ro'} ], 1251 [ "panic", $text{'linux_panic'} ] ])); 1252 1253 print &ui_table_row($text{'linux_grpid'}, 1254 &ui_yesno_radio("ext2_grpid", defined($options{"grpid"}) || 1255 defined($options{"bsdgroups"}))); 1256 1257 my $usrquota = defined($options{"usrquota"}) || 1258 defined($options{"usrjquota"}); 1259 my $grpquota = defined($options{"grpquota"}) || 1260 defined($options{"grpjquota"}); 1261 print &ui_table_row($text{'linux_quotas'}, 1262 &ui_select("ext2_quota", $usrquota && $grpquota ? 3 : 1263 $grpquota ? 2 : 1264 $usrquota ? 1 : 0, 1265 [ [ 0, $text{'no'} ], 1266 [ 1, $text{'linux_usrquota'} ], 1267 [ 2, $text{'linux_grpquota'} ], 1268 [ 3, $text{'linux_usrgrpquota'} ] ])); 1269 1270 print &ui_table_row($text{'linux_quotaj'}, 1271 &ui_radio("ext2_quotaj", 1272 defined($options{"usrjquota"}) || 1273 defined($options{"grpjquota"}) ? 1 : 0, 1274 [ [ 1, $text{'linux_quotaj1'} ], 1275 [ 0, $text{'linux_quotaj0'} ] ])); 1276 1277 print &ui_table_row($text{'linux_resuid'}, 1278 &ui_user_textbox("ext2_resuid", defined($options{"resuid"}) ? 1279 getpwuid($options{"resuid"}) : "")); 1280 1281 print &ui_table_row($text{'linux_resgid'}, 1282 &ui_group_textbox("ext2_resgid", defined($options{"resgid"}) ? 1283 getgrgid($options{"resgid"}) : "")); 1284 } 1285elsif ($type eq "nfs" || $type eq "nfs4") { 1286 # Linux nfs has some more options... 1287 print &ui_table_hr(); 1288 1289 print &ui_table_row(&hlink($text{'linux_port'}, "linux_port"), 1290 &ui_opt_textbox("nfs_port", $options{"port"}, 6, 1291 $text{'default'})); 1292 1293 print &ui_table_row(&hlink($text{'linux_bg'}, "linux_bg"), 1294 &ui_yesno_radio("nfs_bg", defined($options{"bg"}))); 1295 1296 print &ui_table_row(&hlink($text{'linux_soft'}, "linux_soft"), 1297 &ui_yesno_radio("nfs_soft", defined($options{"soft"}))); 1298 1299 print &ui_table_row(&hlink($text{'linux_timeo'}, "linux_timeo"), 1300 &ui_opt_textbox("nfs_timeo", $options{"timeo"}, 6, 1301 $text{'default'})); 1302 1303 print &ui_table_row(&hlink($text{'linux_retrans'}, "linux_retrans"), 1304 &ui_opt_textbox("nfs_retrans", $options{"restrans"}, 6, 1305 $text{'default'})); 1306 1307 print &ui_table_row(&hlink($text{'linux_intr'}, "linux_intr"), 1308 &ui_yesno_radio("nfs_intr", defined($options{"intr"}))); 1309 1310 local $proto = defined($options{"udp"}) ? "udp" : 1311 defined($options{"tcp"}) ? "tcp" : ""; 1312 print &ui_table_row(&hlink($text{'linux_transfert'}, "linux_transfert"), 1313 &ui_select("nfs_transfert", $proto, 1314 [ [ '', $text{'default'} ], 1315 [ 'tcp', 'TCP' ], 1316 [ 'udp', 'UDP' ] ])); 1317 1318 print &ui_table_row(&hlink($text{'linux_rsize'}, "linux_rsize"), 1319 &ui_opt_textbox("nfs_rsize", $options{"rsize"}, 6, 1320 $text{'default'})); 1321 1322 print &ui_table_row(&hlink($text{'linux_wsize'}, "linux_wsize"), 1323 &ui_opt_textbox("nfs_wsize", $options{"wsize"}, 6, 1324 $text{'default'})); 1325 1326 my ($auth, $sec) = $options{"sec"} =~ /^(ntlmssp|ntlmv2|ntlm|spkm|lkey|krb5|sys)(p|i|)/ ? ($1, $2) : ( ); 1327 print &ui_table_row(&hlink($text{'linux_auth'}, "linux_auth"), 1328 &ui_radio("nfs_auth", $auth, 1329 [ [ '', 'sys' ], 1330 [ 'krb5', 'krb5 (Kerberos 5)' ], 1331 [ 'lkey', 'lkey' ], 1332 [ 'spkm', 'spkm-3' ], 1333 [ 'ntlm', 'ntlm (NTLM)' ], 1334 [ 'ntmlv2', 'ntmlv2 (NTLM version 2)' ], 1335 [ 'ntlmssp', 'ntlmssp (NTLMv2 in NTLMSSP)' ] ])); 1336 1337 print &ui_table_row(&hlink($text{'linux_sec'}, "linux_sec"), 1338 &ui_radio("nfs_sec", $sec, 1339 [ [ '', $text{'config_none'} ], 1340 [ 'i', $text{'linux_integrity'} ], 1341 [ 'p', $text{'linux_privacy'} ] ])); 1342 1343 print &ui_table_row(&hlink($text{'linux_nfsvers'}, "linux_nfsvers"), 1344 &ui_select("nfs_nfsvers", $options{"nfsvers"}, 1345 [ [ "", $text{'linux_nfsdefault'} ], 1346 2, 3, 4, 4.1 ])); 1347 } 1348elsif ($type eq "fat" || $type eq "vfat" || $type eq "msdos" || 1349 $type eq "umsdos" || $type eq "fatx"){ 1350 # All dos-based filesystems share some options 1351 print &ui_table_hr(); 1352 1353 print &ui_table_row($text{'linux_uid'}, 1354 &ui_user_textbox("fat_uid", defined($options{'uid'}) ? 1355 getpwuid($options{'uid'}) : "")); 1356 1357 print &ui_table_row($text{'linux_gid'}, 1358 &ui_group_textbox("fat_gid", defined($options{'gid'}) ? 1359 getgrgid($options{'gid'}) : "")); 1360 1361 print &ui_table_row($text{'linux_rules'}, 1362 &ui_select("fat_check", substr($options{"check"}, 0, 1), 1363 [ [ '', $text{'default'} ], 1364 [ 'r', $text{'linux_relaxed'} ], 1365 [ 'n', $text{'linux_normal'} ], 1366 [ 's', $text{'linux_strict'} ] ])); 1367 1368 $conv = substr($options{"conv"}, 0, 1); 1369 $conv = '' if ($conv eq 'b'); 1370 print &ui_table_row($text{'linux_conv'}, 1371 &ui_select("fat_conv", $conv, 1372 [ [ 'b', $text{'linux_none'} ], 1373 [ 't', $text{'linux_allfiles'} ], 1374 [ 'a', $text{'linux_textfiles'} ] ])); 1375 1376 print &ui_table_row($text{'linux_umask'}, 1377 &ui_opt_textbox("fat_umask", $options{"umask"}, 6, 1378 $text{'default'})); 1379 1380 print &ui_table_row($text{'linux_quiet'}, 1381 &ui_yesno_radio("fat_quiet", defined($options{"quiet"}), 0, 1)); 1382 1383 1384 if ($_[0] eq "vfat") { 1385 # vfat has some extra options beyond fat 1386 print &ui_table_row($text{'linux_uni_xlate'}, 1387 &ui_yesno_radio("fat_uni_xlate", 1388 defined($options{"uni_xlate"}))); 1389 1390 print &ui_table_row($text{'linux_posix'}, 1391 &ui_yesno_radio("fat_posix", 1392 defined($options{"posix"}))); 1393 } 1394 } 1395elsif ($type eq "hpfs") { 1396 # OS/2 filesystems has some more options.. 1397 print &ui_table_hr(); 1398 1399 print &ui_table_row($text{'linux_uid'}, 1400 &ui_user_textbox("hpfs_uid", defined($options{'uid'}) ? 1401 getpwuid($options{'uid'}) : "")); 1402 1403 print &ui_table_row($text{'linux_gid'}, 1404 &ui_group_textbox("hpfs_gid", defined($options{'gid'}) ? 1405 getgrgid($options{'gid'}) : "")); 1406 1407 print &ui_table_row($text{'linux_umask'}, 1408 &ui_opt_textbox("hpfs_umask", $options{"umask"}, 6, 1409 $text{'default'})); 1410 1411 print &ui_table_row($text{'linux_conv2'}, 1412 &ui_select("hpfs_conv", substr($options{"conv"}, 0, 1) || "b", 1413 [ [ 'b', $text{'linux_none'} ], 1414 [ 't', $text{'linux_allfiles'} ], 1415 [ 'a', $text{'linux_textfiles'} ] ])); 1416 } 1417elsif ($type eq "iso9660") { 1418 # CD-ROM filesystems have some more options.. 1419 print &ui_table_hr(); 1420 1421 print &ui_table_row($text{'linux_uid'}, 1422 &ui_user_textbox("iso9660_uid", defined($options{'uid'}) ? 1423 getpwuid($options{'uid'}) : "")); 1424 1425 print &ui_table_row($text{'linux_gid'}, 1426 &ui_group_textbox("iso9660_gid", defined($options{'gid'}) ? 1427 getgrgid($options{'gid'}) : "")); 1428 1429 print &ui_table_row($text{'linux_rock'}, 1430 &ui_yesno_radio("iso9660_norock", defined($options{"norock"}))); 1431 1432 print &ui_table_row($text{'linux_mode'}, 1433 &ui_textbox("iso9660_mode", defined($options{"mode"}) ? 1434 $options{"mode"} : "444", 10)); 1435 } 1436elsif ($type eq "auto") { 1437 # Don't know how to set options for auto filesystems yet.. 1438 print &ui_table_span("<i>$text{'linux_noopts'}</i>"); 1439 } 1440elsif ($_[0] eq "autofs") { 1441 print &ui_table_span("<b>$text{'edit_autofs_opt'}</b>"); 1442 1443 print &ui_table_row($text{'linux_timeout'}, 1444 &ui_opt_textbox("autofs_timeout", $options{'timeout'}, 6, 1445 $text{'default'})); 1446 1447 print &ui_table_row($text{'linux_pid_file'}, 1448 &ui_opt_textbox("autofs_pid-file", $options{'pid-file'}, 40, 1449 $text{'no'}, $text{'yes'})." ". 1450 &file_chooser_button("autofs_pid-file", 0), 3); 1451 } 1452elsif ($type eq "swap") { 1453 # Swap has no options.. 1454 print &ui_table_row($text{'linux_swappri'}, 1455 &ui_opt_textbox("swap_pri", $options{'pri'}, 6, 1456 $text{'default'})); 1457 } 1458elsif ($type eq $smbfs_fs || $type eq "cifs") { 1459 # SMB filesystems have a few options.. 1460 $support = $_[0] eq $smbfs_fs ? $smbfs_support : $cifs_support; 1461 if (keys(%options) == 0 && !$_[1]) { 1462 print &ui_table_span("<i>$text{'linux_smbwarn'}</i>"); 1463 } 1464 1465 print &ui_table_row($text{'linux_username'}, 1466 &ui_textbox("smbfs_user", 1467 $support == 4 ? $options{'username'} : $options{'user'}, 20)); 1468 1469 print &ui_table_row($text{'linux_password'}, 1470 &ui_password("smbfs_passwd", 1471 $support == 4 ? $options{'password'} : $options{'passwd'}, 20)); 1472 1473 if ($support == 4) { 1474 print &ui_table_row($text{'linux_credentials'}, 1475 &ui_textbox("smbfs_creds", $options{"credentials"}, 30). 1476 " ". 1477 ($access{'browse'} ? 1478 &file_chooser_button("smbfs_creds", 0) : "")); 1479 } 1480 1481 if ($support != 2) { 1482 print &ui_table_row($text{'linux_uid'}, 1483 &ui_user_textbox("smbfs_uid", 1484 defined($options{'uid'}) ? getpwuid($options{'uid'}) 1485 : "")); 1486 1487 print &ui_table_row($text{'linux_gid'}, 1488 &ui_group_textbox("smbfs_gid", 1489 defined($options{'gid'}) ? getgrgid($options{'gid'}) 1490 : "")); 1491 } 1492 1493 if ($support == 1) { 1494 print &ui_table_row($text{'linux_sname'}, 1495 &ui_opt_textbox("smbfs_sname", $options{"servername"}, 1496 20, $text{'linux_auto'})); 1497 } 1498 elsif ($support == 2) { 1499 print &ui_table_row($text{'linux_wg'}, 1500 &ui_opt_textbox("smbfs_wg", $options{"workgroup"}, 1501 20, $text{'linux_auto'})); 1502 } 1503 1504 if ($support < 3) { 1505 print &ui_table_row($text{'linux_cname'}, 1506 &ui_opt_textbox("smbfs_cname", $options{"clientname"}, 1507 20, $text{'linux_auto'})); 1508 1509 print &ui_table_row($text{'linux_mname'}, 1510 &ui_opt_textbox("smbfs_mname", $options{"machinename"}, 1511 20, $text{'linux_auto'})); 1512 } 1513 1514 if ($support == 1) { 1515 print &ui_table_row($text{'linux_fmode'}, 1516 &ui_textbox("smbfs_fmode", 1517 defined($options{'fmode'}) ? $options{'fmode'} : "755", 1518 5)); 1519 1520 print &ui_table_row($text{'linux_dmode'}, 1521 &ui_textbox("smbfs_dmode", 1522 defined($options{'dmode'}) ? $options{'dmode'} : "755", 1523 5)); 1524 } 1525 elsif ($support >= 3) { 1526 print &ui_table_row($text{'linux_fmode'}, 1527 &ui_opt_textbox("smbfs_file_mode", 1528 $options{'file_mode'}, 5, 1529 $text{'default'})); 1530 1531 print &ui_table_row($text{'linux_dmode'}, 1532 &ui_opt_textbox("smbfs_dir_mode", 1533 $options{'dir_mode'}, 5, 1534 $text{'default'})); 1535 1536 print &ui_table_row($text{'linux_ro'}, 1537 &ui_yesno_radio("smbfs_ro", defined($options{"ro"}))); 1538 } 1539 if ($support == 4) { 1540 print &ui_table_row($text{'linux_user'}, 1541 &ui_yesno_radio("smbfs_user2", defined($options{"user"}))); 1542 1543 print &ui_table_row($text{'linux_cname'}, 1544 &ui_opt_textbox("smbfs_cname", $options{"netbiosname"}, 1545 40, $text{'linux_auto'}), 3); 1546 1547 print &ui_table_row($text{'linux_mname'}, 1548 &ui_opt_textbox("smbfs_mname", $options{"ip"}, 1549 40, $text{'linux_auto'}), 3); 1550 1551 print &ui_table_row($text{'linux_wg'}, 1552 &ui_opt_textbox("smbfs_wg", $options{"workgroup"}, 1553 10, $text{'linux_auto'})); 1554 1555 } 1556 1557 if ($type eq "cifs") { 1558 # Show cifs-only options 1559 print &ui_table_row($text{'linux_codepage'}, 1560 &ui_opt_textbox("smbfs_codepage", 1561 $options{'codepage'}, 10, $text{'default'})); 1562 1563 print &ui_table_row($text{'linux_iocharset'}, 1564 &ui_opt_textbox("smbfs_iocharset", 1565 $options{'iocharset'}, 10, $text{'default'})); 1566 1567 print &ui_table_row($text{'linux_nounix'}, 1568 &ui_yesno_radio("smbfs_nounix", 1569 defined($options{"nounix"}))); 1570 1571 print &ui_table_row($text{'linux_cvers'}, 1572 &ui_opt_textbox("smbfs_vers", $options{"vers"}, 1573 5, $text{'linux_auto'})); 1574 1575 print &ui_table_row($text{'linux_noserverino'}, 1576 &ui_yesno_radio("smbfs_noserverino", 1577 defined($options{"noserverino"}))); 1578 } 1579 } 1580elsif ($type eq "reiserfs") { 1581 # Reiserfs is a new super-efficient filesystem 1582 print &ui_table_hr(); 1583 1584 print &ui_table_row($text{'linux_notail'}, 1585 &ui_yesno_radio("lnx_notail", defined($options{"notail"}))); 1586 } 1587elsif ($type eq "tmpfs") { 1588 # Tmpfs has some size options 1589 print &ui_table_hr(); 1590 1591 print &ui_table_row($text{'linux_tmpsize'}, 1592 &ui_opt_textbox("lnx_tmpsize", $options{"size"}, 10, 1593 $text{'linux_unlimited'})." bytes"); 1594 1595 print &ui_table_row($text{'linux_nr_blocks'}, 1596 &ui_opt_textbox("lnx_nr_blocks", $options{"nr_blocks"}, 10, 1597 $text{'linux_unlimited'})); 1598 1599 print &ui_table_row($text{'linux_nr_inodes'}, 1600 &ui_opt_textbox("lnx_nr_inodes", $options{"nr_inodes"}, 10, 1601 $text{'linux_unlimited'})); 1602 1603 print &ui_table_row($text{'linux_tmpmode'}, 1604 &ui_opt_textbox("lnx_tmpmode", $options{"mode"}, 3, 1605 $text{'default'})); 1606 } 1607elsif ($type eq "xfs") { 1608 # Show options for XFS 1609 print &ui_table_hr(); 1610 1611 print &ui_table_row($text{'linux_usrquotas'}, 1612 &ui_radio("xfs_usrquota", 1613 defined($options{"quota"}) || 1614 defined($options{"usrquota"}) ? 1 : 1615 defined($options{"uqnoenforce"}) ? 2 : 0, 1616 [ [ 1, $text{'yes'} ], 1617 [ 2, $text{'linux_noenforce'} ], 1618 [ 0, $text{'no'} ] ])); 1619 1620 print &ui_table_row($text{'linux_grpquotas'}, 1621 &ui_radio("xfs_grpquota", 1622 defined($options{"quota"}) || 1623 defined($options{"grpquota"}) ? 1 : 1624 defined($options{"uqnoenforce"}) ? 2 : 0, 1625 [ [ 1, $text{'yes'} ], 1626 [ 2, $text{'linux_noenforce'} ], 1627 [ 0, $text{'no'} ] ])); 1628 } 1629elsif ($type eq "jfs") { 1630 # No other JFS options yet! 1631 } 1632elsif ($type eq "ntfs") { 1633 # Windows NT/XP/2000 filesystem 1634 print &ui_table_hr(); 1635 1636 print &ui_table_row($text{'linux_uid'}, 1637 &ui_user_textbox("ntfs_uid", defined($options{'uid'}) ? 1638 getpwuid($options{'uid'}) : "")); 1639 1640 print &ui_table_row($text{'linux_gid'}, 1641 &ui_group_textbox("ntfs_gid", defined($options{'gid'}) ? 1642 getgrgid($options{'gid'}) : "")); 1643 } 1644} 1645 1646 1647# check_location(type) 1648# Parse and check inputs from %in, calling &error() if something is wrong. 1649# Returns the location string for storing in the fstab file 1650sub check_location 1651{ 1652if (($_[0] eq "nfs") || ($_[0] eq "nfs4")) { 1653 local($out, $temp, $mout, $dirlist, @dirlist); 1654 1655 if (&has_command("showmount") && $config{'nfs_check'}) { 1656 # Use ping and showmount to see if the host exists and is up 1657 if ($in{nfs_host} !~ /^\S+$/) { 1658 &error(&text('linux_ehost', $in{'nfs_host'})); 1659 } 1660 $out = &backquote_command( 1661 "ping -c 1 ".quotemeta($in{nfs_host})." 2>&1"); 1662 if ($out =~ /unknown host/) { 1663 &error(&text('linux_ehost2', $in{'nfs_host'})); 1664 } 1665 elsif ($out =~ /100\% packet loss/) { 1666 &error(&text('linux_edown', $in{'nfs_host'})); 1667 } 1668 $out = &backquote_command( 1669 "showmount -e ".quotemeta($in{nfs_host})." 2>&1"); 1670 if ($out =~ /Unable to receive/) { 1671 &error(&text('linux_enfs', $in{'nfs_host'})); 1672 } 1673 elsif ($?) { 1674 &error(&text('linux_elist', $out)); 1675 } 1676 } 1677 1678 # Validate directory name for NFSv3 (in v4 '/' exists) 1679 foreach (split(/\n/, $out)) { 1680 if (/^(\/\S+)/) { 1681 $dirlist .= "$1\n"; 1682 push(@dirlist, $1); 1683 } 1684 } 1685 1686 if ($_[0] ne "nfs4" && $in{'nfs_dir'} !~ /^\/.*$/ && 1687 &indexof($in{'nfs_dir'}, @dirlist) < 0) { 1688 &error(&text('linux_enfsdir', $in{'nfs_dir'}, 1689 $in{'nfs_host'}, "<pre>$dirlist</pre>")); 1690 } 1691 1692 # Try a test mount to see if filesystem is available 1693 $temp = &tempname(); 1694 &make_dir($temp, 0755); 1695 &execute_command("mount -t $_[0] ". 1696 quotemeta("$in{nfs_host}:$in{nfs_dir}")." ". 1697 quotemeta($temp), 1698 undef, \$mout, \$mout); 1699 if ($mout =~ /No such file or directory/i) { 1700 &error(&text('linux_enfsdir', $in{'nfs_dir'}, 1701 $in{'nfs_host'}, "<pre>$dirlist</pre>")); 1702 } 1703 elsif ($mout =~ /Permission denied/i) { 1704 &error(&text('linux_enfsperm', $in{'nfs_dir'}, $in{'nfs_host'})); 1705 } 1706 elsif ($?) { 1707 &error(&text('linux_enfsmount', "<tt>$mout</tt>")); 1708 } 1709 # It worked! unmount 1710 local $umout; 1711 &execute_command("umount ".quotemeta($temp), undef, \$umout, \$umout); 1712 if ($?) { 1713 &error(&text('linux_enfsmount', "<tt>$umout</tt>")); 1714 } 1715 rmdir(&translate_filename($temp)); # Don't delete mounted files! 1716 1717 return "$in{nfs_host}:$in{nfs_dir}"; 1718 } 1719elsif ($_[0] eq "auto") { 1720 # Check if the automounter map exists.. 1721 (-r $in{auto_map}) || &error(&text('linux_eautomap', $in{'auto_map'})); 1722 return $in{auto_map}; 1723 } 1724elsif ($_[0] eq "autofs") { 1725 # Check if the map exists (if it is a file) 1726 if ($in{'autofs_map'} =~ /^\// && !(-r $in{'autofs_map'})) { 1727 &error(&text('linux_eautomap', $in{'autofs_map'})); 1728 } 1729 return $in{autofs_map}; 1730 } 1731elsif ($_[0] eq $smbfs_fs || $_[0] eq "cifs") { 1732 # No real checking done 1733 $in{'smbfs_server'} =~ /\S/ || &error($text{'linux_eserver'}); 1734 $in{'smbfs_share'} =~ /\S/ || &error($text{'linux_eshare'}); 1735 return &lowercase_share_path( 1736 "\\\\".$in{'smbfs_server'}."\\".$in{'smbfs_share'}); 1737 } 1738elsif ($_[0] eq "tmpfs") { 1739 # No location needed 1740 return "tmpfs"; 1741 } 1742elsif ($_[0] eq "bind") { 1743 # Just check the directory 1744 -d $in{'bind_dir'} || &error($text{'linux_ebind'}); 1745 return $in{'bind_dir'}; 1746 } 1747else { 1748 # This is some kind of disk-based linux filesystem.. get the device name 1749 if ($in{'lnx_dev'} == 0) { 1750 $dv = $in{'lnx_disk'}; 1751 } 1752 elsif ($in{'lnx_dev'} == 2) { 1753 $dv = $in{'lnx_raid'}; 1754 } 1755 elsif ($in{'lnx_dev'} == 3) { 1756 $dv = "LABEL=".$in{'lnx_label'}; 1757 } 1758 elsif ($in{'lnx_dev'} == 4) { 1759 $dv = $in{'lnx_lvm'}; 1760 } 1761 elsif ($in{'lnx_dev'} == 5) { 1762 $dv = "UUID=".$in{'lnx_uuid'}; 1763 } 1764 else { 1765 $dv = $in{'lnx_other'}; 1766 $dv || &error($text{'linux_edev'}); 1767 } 1768 1769 # If the device entered is a symlink, follow it 1770 #if ($dvlink = readlink($dv)) { 1771 # if ($dvlink =~ /^\//) { $dv = $dvlink; } 1772 # else { $dv =~ /^(.*\/)[^\/]+$/; 1773 # $dv = $1.$dvlink; 1774 # } 1775 # } 1776 1777 # Check if the device actually exists and uses the right filesystem 1778 if (!-r $dv && $dv !~ /LABEL=/ && $dv !~ /UUID=/) { 1779 if ($_[0] eq "swap" && $dv !~ /\/dev/) { 1780 &swap_form($dv); 1781 } 1782 else { 1783 &error(&text('linux_edevfile', $dv)); 1784 } 1785 } 1786 return $dv; 1787 } 1788} 1789 1790# check_options(type, device, directory) 1791# Read options for some filesystem from %in, and use them to update the 1792# %options array. Options handled by the user interface will be set or 1793# removed, while unknown options will be left untouched. 1794sub check_options 1795{ 1796local($k, @rv); 1797 1798# Parse the common options first.. 1799if ($_[0] ne "swap" && $_[0] ne "auto" && 1800 $_[0] ne "autofs" && $_[0] ne $smbfs_fs && $_[0] ne "cifs") { 1801 delete($options{"ro"}); delete($options{"rw"}); 1802 if ($in{lnx_ro}) { $options{"ro"} = ""; } 1803 1804 delete($options{"sync"}); delete($options{"async"}); 1805 if ($in{lnx_sync}) { $options{"sync"} = ""; } 1806 1807 delete($options{"dev"}); delete($options{"nodev"}); 1808 if ($in{lnx_nodev} == 1) { $options{"nodev"} = ""; } 1809 elsif ($in{lnx_nodev} == 0) { $options{"dev"} = ""; } 1810 1811 delete($options{"exec"}); delete($options{"noexec"}); 1812 if ($in{lnx_noexec} == 1) { $options{"noexec"} = ""; } 1813 elsif ($in{lnx_noexec} == 0) { $options{"exec"} = ""; } 1814 1815 delete($options{"suid"}); delete($options{"nosuid"}); 1816 if ($in{lnx_nosuid} == 1) { $options{"nosuid"} = ""; } 1817 elsif ($in{lnx_nosuid} == 0) { $options{"suid"} = ""; } 1818 1819 delete($options{"user"}); delete($options{"nouser"}); 1820 if ($in{lnx_user}) { $options{"user"} = ""; } 1821 1822 delete($options{"noatime"}); 1823 $options{"noatime"} = "" if ($in{'lnx_noatime'}); 1824 delete($options{"relatime"}) if ($in{'lnx_noatime'}); 1825 1826 delete($options{"_netdev"}); 1827 $options{"_netdev"} = "" if ($in{'lnx_netdev'}); 1828 1829 delete($options{"nofail"}); 1830 $options{"nofail"} = "" if ($in{'lnx_nofail'}); 1831 } 1832 1833if (($_[0] eq "nfs") || ($_[0] eq "nfs4")) { 1834 # NFS has a few specific options.. 1835 delete($options{"bg"}); delete($options{"fg"}); 1836 if ($in{nfs_bg}) { $options{"bg"} = ""; } 1837 1838 delete($options{"soft"}); delete($options{"hard"}); 1839 if ($in{nfs_soft}) { $options{"soft"} = ""; } 1840 1841 delete($options{"timeo"}); 1842 if (!$in{nfs_timeo_def}) { 1843 $in{nfs_timeo} =~ /^\d+$/ && $in{nfs_timeo} > 0 || 1844 &error($text{'linux_etimeo'}); 1845 $options{"timeo"} = $in{nfs_timeo}; 1846 } 1847 1848 delete($options{"retrans"}); 1849 if (!$in{nfs_retrans_def}) { $options{"retrans"} = $in{nfs_retrans}; } 1850 1851 delete($options{"port"}); 1852 if (!$in{nfs_port_def}) { $options{"port"} = $in{nfs_port}; } 1853 1854 delete($options{"intr"}); delete($options{"nointr"}); 1855 if ($in{nfs_intr}) { $options{"intr"} = ""; } 1856 1857 delete($options{"tcp"}); delete($options{"udp"}); 1858 if ($in{nfs_transfert} eq "tcp") { 1859 $options{"tcp"} = ""; 1860 } 1861 elsif ($in{nfs_transfert} eq "udp") { 1862 $options{"udp"} = ""; 1863 } 1864 1865 delete($options{"wsize"}); 1866 if (!$in{nfs_wsize_def}) { $options{"wsize"} = $in{nfs_wsize}; } 1867 1868 delete($options{"rsize"}); 1869 if (!$in{nfs_rsize_def}) { $options{"rsize"} = $in{nfs_rsize}; } 1870 1871 delete($options{"sec"}); 1872 1873 # Only sys and krb5 for the moment 1874 if ($in{nfs_auth}) { 1875 $options{"sec"} = $in{"nfs_auth"}.$in{"nfs_sec"}; 1876 } 1877 1878 if ($in{'nfs_nfsvers'}) { 1879 $options{'nfsvers'} = $in{'nfs_nfsvers'}; 1880 } else { 1881 delete($options{'nfsvers'}); 1882 } 1883 } 1884elsif ($_[0] =~ /^ext\d+$/) { 1885 # More options for ext2.. 1886 if ($no_mount_check) { 1887 delete($options{"bsddf"}); delete($options{"minixdf"}); 1888 $options{"minixdf"} = "" if ($in{'ext2_df'}); 1889 } 1890 else { 1891 delete($options{"check"}); delete($options{"nocheck"}); 1892 if ($in{ext2_check} ne "normal") { 1893 $options{"check"} = $in{ext2_check}; 1894 } 1895 } 1896 1897 delete($options{"errors"}); 1898 if ($in{ext2_errors} ne "default") { 1899 $options{"errors"} = $in{ext2_errors}; 1900 } 1901 1902 delete($options{"grpid"}); delete($options{"bsdgroups"}); 1903 delete($options{"sysvgroups"}); delete($options{"nogrpid"}); 1904 if ($in{ext2_grpid}) { 1905 $options{"grpid"} = ""; 1906 } 1907 1908 delete($options{"resuid"}); delete($options{"resgid"}); 1909 if ($in{'ext2_resuid'}) 1910 { $options{"resuid"} = getpwnam($in{'ext2_resuid'}); } 1911 if ($in{'ext2_resgid'}) 1912 { $options{"resgid"} = getgrnam($in{'ext2_resgid'}); } 1913 1914 my $jufile = $options{"usrjquota"}; 1915 my $jgfile = $options{"grpjquota"}; 1916 delete($options{"quota"}); delete($options{"noquota"}); 1917 delete($options{"usrquota"}); delete($options{"grpquota"}); 1918 delete($options{"usrjquota"}); delete($options{"grpjquota"}); 1919 my ($u, $g) = ("usrquota", "grpquota"); 1920 if ($in{'ext2_quotaj'}) { 1921 ($u, $g) = ("usrjquota", "grpjquota"); 1922 $jufile ||= "aquota.user"; 1923 $jgfile ||= "aquota.group"; 1924 $options{"jqfmt"} = "vfsv0"; 1925 } 1926 else { 1927 $jufile = ""; 1928 $jgfile = ""; 1929 delete($options{"jqfmt"}); 1930 } 1931 if ($in{'ext2_quota'} == 1) { $options{$u} = $jufile; } 1932 elsif ($in{'ext2_quota'} == 2) { $options{$g} = $jgfile; } 1933 elsif ($in{'ext2_quota'} == 3) { $options{$u} = $jufile; $options{$g} = $jgfile; } 1934 } 1935elsif ($_[0] eq "fat" || $_[0] eq "vfat" || 1936 $_[0] eq "msdos" || $_[0] eq "umsdos" || $_[0] eq "fatx") { 1937 # All dos-based filesystems have similar options 1938 delete($options{"uid"}); delete($options{"gid"}); 1939 if ($in{fat_uid} ne "") { $options{"uid"} = getpwnam($in{'fat_uid'}); } 1940 if ($in{fat_gid} ne "") { $options{"gid"} = getgrnam($in{'fat_gid'}); } 1941 1942 delete($options{"check"}); 1943 if ($in{fat_check} ne "") { $options{"check"} = $in{fat_check}; } 1944 1945 delete($options{"conv"}); 1946 if ($in{fat_conv} ne "") { $options{"conv"} = $in{fat_conv}; } 1947 1948 delete($options{"umask"}); 1949 if (!$in{fat_umask_def}) { 1950 $in{fat_umask} =~ /^[0-7]{3}$/ || 1951 &error(&text('linux_emask', $in{'fat_umask'})); 1952 $options{"umask"} = $in{fat_umask}; 1953 } 1954 1955 delete($options{"quiet"}); 1956 if ($in{fat_quiet}) { 1957 $options{"quiet"} = ""; 1958 } 1959 1960 if ($_[0] eq "vfat") { 1961 # Parse extra vfat options.. 1962 delete($options{"uni_xlate"}); 1963 if ($in{fat_uni_xlate}) { $options{"uni_xlate"} = ""; } 1964 1965 delete($options{"posix"}); 1966 if ($in{fat_posix}) { $options{"posix"} = ""; } 1967 } 1968 } 1969elsif ($_[0] eq "hpfs") { 1970 # OS/2 filesystem options.. 1971 delete($options{"uid"}); delete($options{"gid"}); 1972 if ($in{hpfs_uid} ne "") { $options{"uid"} = getpwnam($in{hpfs_uid}); } 1973 if ($in{hpfs_gid} ne "") { $options{"gid"} = getgrnam($in{hpfs_gid}); } 1974 1975 delete($options{"umask"}); 1976 if (!$in{hpfs_umask_def}) { 1977 $in{hpfs_umask} =~ /^[0-7]{3}$/ || 1978 &error(&text('linux_emask', $in{'hpfs_umask'})); 1979 $options{"umask"} = $in{hpfs_umask}; 1980 } 1981 1982 delete($options{"conv"}); 1983 if ($in{hpfs_conv} ne "") { $options{"conv"} = $in{hpfs_conv}; } 1984 } 1985elsif ($_[0] eq "iso9660") { 1986 # Options for iso9660 cd-roms 1987 delete($options{"uid"}); delete($options{"gid"}); 1988 if ($in{iso9660_uid} ne "") 1989 { $options{"uid"} = getpwnam($in{iso9660_uid}); } 1990 if ($in{iso9660_gid} ne "") 1991 { $options{"gid"} = getgrnam($in{iso9660_gid}); } 1992 1993 delete($options{"norock"}); 1994 if ($in{iso9660_norock}) { $options{"norock"} = ""; } 1995 1996 delete($options{"mode"}); 1997 $in{iso9660_mode} =~ /^[0-7]{3}$/ || 1998 &error(&text('linux_emask', $in{'iso9660_mode'})); 1999 $options{"mode"} = $in{iso9660_mode}; 2000 } 2001elsif ($_[0] eq "autofs") { 2002 # Options for automounter filesystems 2003 delete($options{'timeout'}); 2004 if (!$in{'autofs_timeout_def'}) { 2005 $in{'autofs_timeout'} =~ /^\d+$/ || 2006 &error(&text('linux_etimeout', $in{'autofs_timeout'})); 2007 $options{'timeout'} = $in{'autofs_timeout'}; 2008 } 2009 delete($options{'pid-file'}); 2010 if (!$in{'autofs_pid-file_def'}) { 2011 $in{'autofs_pid-file'} =~ /^\/\S+$/ || 2012 &error(&text('linux_epidfile', $in{'autofs_pid-file'})); 2013 $options{'pid-file'} = $in{'autofs_pid-file'}; 2014 } 2015 } 2016elsif ($_[0] eq $smbfs_fs || $_[0] eq "cifs") { 2017 # Options for smb filesystems.. 2018 local $support = $_[0] eq $smbfs_fs ? $smbfs_support : $cifs_support; 2019 delete($options{'user'}); delete($options{'username'}); 2020 if ($in{smbfs_user}) { 2021 $options{$support == 4 ? 'username' : 'user'} = $in{smbfs_user}; 2022 } 2023 2024 delete($options{'passwd'}); delete($options{'password'}); 2025 if ($in{smbfs_passwd}) { 2026 $options{$support == 4 ? 'password' : 'passwd'} = $in{smbfs_passwd}; 2027 } 2028 2029 if ($support == 4) { 2030 delete($options{'credentials'}); 2031 if ($in{smbfs_creds}) { 2032 $options{'credentials'} = $in{smbfs_creds}; 2033 } 2034 } 2035 2036 if ($support != 2) { 2037 delete($options{uid}); 2038 if ($in{smbfs_uid} ne "") { $options{uid} = getpwnam($in{smbfs_uid}); } 2039 2040 delete($options{gid}); 2041 if ($in{smbfs_gid} ne "") { $options{gid} = getgrnam($in{smbfs_gid}); } 2042 } 2043 2044 if ($support == 1) { 2045 delete($options{servername}); 2046 if (!$in{smbfs_sname_def}) 2047 { $options{servername} = $in{smbfs_sname}; } 2048 } 2049 elsif ($support == 2 || $support == 4) { 2050 delete($options{workgroup}); 2051 if (!$in{smbfs_wg_def}) 2052 { $options{workgroup} = $in{smbfs_wg}; } 2053 } 2054 2055 if ($support < 3) { 2056 delete($options{clientname}); 2057 if (!$in{smbfs_cname_def}) 2058 { $options{clientname} = $in{smbfs_cname}; } 2059 2060 delete($options{machinename}); 2061 if (!$in{smbfs_mname_def}) 2062 { $options{machinename} = $in{smbfs_mname}; } 2063 elsif (!&to_ipaddress($in{'smbfs_server'})) { 2064 # No hostname found for the server.. try to guess 2065 local($out, $sname); 2066 $sname = $in{'smbfs_server'}; 2067 $out = &backquote_command("$config{'nmblookup_path'} -d 0 $sname 2>&1"); 2068 if (!$? && $out =~ /^([0-9\.]+)\s+$sname\n/) { 2069 $options{machinename} = $1; 2070 } 2071 } 2072 } 2073 elsif ($support == 4) { 2074 delete($options{"netbiosname"}); 2075 if (!$in{"smbfs_cname_def"}) { 2076 $in{"smbfs_cname"} =~ /^\S+$/ || 2077 &error($text{'linux_ecname'}); 2078 $options{"netbiosname"} = $in{"smbfs_cname"}; 2079 } 2080 delete($options{"ip"}); 2081 if (!$in{"smbfs_mname_def"}) { 2082 &to_ipaddress($in{"smbfs_mname"}) || 2083 &error($text{'linux_emname'}); 2084 $options{"ip"} = $in{"smbfs_mname"}; 2085 } 2086 } 2087 2088 if ($support == 1) { 2089 delete($options{fmode}); 2090 if ($in{smbfs_fmode} !~ /^[0-7]{3}$/) { 2091 &error(&text('linux_efmode', $in{'smbfs_fmode'})); 2092 } 2093 elsif ($in{smbfs_fmode} ne "755") 2094 { $options{fmode} = $in{smbfs_fmode}; } 2095 2096 delete($options{dmode}); 2097 if ($in{smbfs_dmode} !~ /^[0-7]{3}$/) { 2098 &error(&text('linux_edmode', $in{'smbfs_dmode'})); 2099 } 2100 elsif ($in{smbfs_dmode} ne "755") 2101 { $options{dmode} = $in{smbfs_dmode}; } 2102 } 2103 elsif ($support >= 3) { 2104 if ($in{'smbfs_file_mode_def'}) { 2105 delete($options{'file_mode'}); 2106 } 2107 else { 2108 $in{'smbfs_file_mode'} =~ /^0?[0-7]{3}$/ || 2109 &error(&text('linux_efmode', $in{'smbfs_file_mode'})); 2110 $options{'file_mode'} = $in{'smbfs_file_mode'}; 2111 } 2112 2113 if ($in{'smbfs_dir_mode_def'}) { 2114 delete($options{'dir_mode'}); 2115 } 2116 else { 2117 $in{'smbfs_dir_mode'} =~ /^0?[0-7]{3}$/ || 2118 &error(&text('linux_edmode', $in{'smbfs_dir_mode'})); 2119 $options{'dir_mode'} = $in{'smbfs_dir_mode'}; 2120 } 2121 2122 delete($options{'ro'}); delete($options{'rw'}); 2123 if ($in{'smbfs_ro'}) { $options{'ro'} = ''; } 2124 } 2125 if ($support == 4) { 2126 delete($options{'user'}); 2127 if ($in{'smbfs_user2'}) { $options{'user'} = ''; } 2128 } 2129 2130 if ($_[0] eq "cifs") { 2131 # Parse CIFS-specific options 2132 delete($options{'codepage'}); 2133 if (!$in{'smbfs_codepage_def'}) { 2134 $in{'smbfs_codepage'} =~ /^\S+$/ || 2135 &error($text{'linux_ecodepage'}); 2136 $options{'codepage'} = $in{'smbfs_codepage'}; 2137 } 2138 2139 delete($options{'iocharset'}); 2140 if (!$in{'smbfs_iocharset_def'}) { 2141 $in{'smbfs_iocharset'} =~ /^\S+$/ || 2142 &error($text{'linux_eiocharset'}); 2143 $options{'iocharset'} = $in{'smbfs_iocharset'}; 2144 } 2145 2146 delete($options{'nounix'}); 2147 if ($in{'smbfs_nounix'}) { $options{'nounix'} = ''; } 2148 2149 delete($options{'noserverino'}); 2150 if ($in{'smbfs_noserverino'}) { $options{'noserverino'} = ''; } 2151 2152 delete($options{'vers'}); 2153 if (!$in{'smbfs_vers_def'}) { 2154 $in{'smbfs_vers'} =~ /^[0-9\.]+$/ || 2155 &error($text{'linux_ecvers'}); 2156 $options{'vers'} = $in{'smbfs_vers'}; 2157 } 2158 } 2159 } 2160elsif ($_[0] eq "reiserfs") { 2161 # Save reiserfs options 2162 delete($options{'notail'}); 2163 $options{'notail'} = "" if ($in{'lnx_notail'}); 2164 2165 if ($in{'lnx_user'} && !$in{'lnx_noexec'}) { 2166 # Have to force on the exec option 2167 $options{"exec"} = ""; 2168 } 2169 } 2170elsif ($_[0] eq "tmpfs") { 2171 # Save tmpfs options 2172 if ($in{'lnx_tmpsize_def'}) { 2173 delete($options{'size'}); 2174 } 2175 else { 2176 $in{'lnx_tmpsize'} =~ /^(\d+)([kmg]?)$/ || 2177 &error($text{'lnx_etmpsize'}); 2178 $options{'size'} = $in{'lnx_tmpsize'}; 2179 } 2180 2181 if ($in{'lnx_nr_blocks_def'}) { 2182 delete($options{'nr_blocks'}); 2183 } 2184 else { 2185 $in{'lnx_nr_blocks'} =~ /^\d+$/ || 2186 &error($text{'lnx_enr_blocks'}); 2187 $options{'nr_blocks'} = $in{'lnx_nr_blocks'}; 2188 } 2189 2190 if ($in{'lnx_nr_inodes_def'}) { 2191 delete($options{'nr_inodes'}); 2192 } 2193 else { 2194 $in{'lnx_nr_inodes'} =~ /^\d+$/ || 2195 &error($text{'lnx_enr_inodes'}); 2196 $options{'nr_inodes'} = $in{'lnx_nr_inodes'}; 2197 } 2198 2199 if ($in{'lnx_tmpmode_def'}) { 2200 delete($options{'mode'}); 2201 } 2202 else { 2203 $in{'lnx_tmpmode'} =~ /^[0-7]{3,4}$/ || 2204 &error($text{'lnx_etmpmode'}); 2205 $options{'mode'} = $in{'lnx_tmpmode'}; 2206 } 2207 } 2208elsif ($_[0] eq "xfs") { 2209 # Save XFS options 2210 delete($options{'quota'}); 2211 delete($options{'usrquota'}); 2212 delete($options{'uqnoenforce'}); 2213 $options{'usrquota'} = "" if ($in{'xfs_usrquota'} == 1); 2214 $options{'uqnoenforce'} = "" if ($in{'xfs_usrquota'} == 2); 2215 2216 delete($options{'grpquota'}); 2217 delete($options{'gqnoenforce'}); 2218 $options{'grpquota'} = "" if ($in{'xfs_grpquota'} == 1); 2219 $options{'gqnoenforce'} = "" if ($in{'xfs_grpquota'} == 2); 2220 } 2221elsif ($_[0] eq "ntfs") { 2222 # Save NTFS options 2223 delete($options{"uid"}); delete($options{"gid"}); 2224 if ($in{ntfs_uid} ne "") 2225 { $options{"uid"} = getpwnam($in{ntfs_uid}); } 2226 if ($in{ntfs_gid} ne "") 2227 { $options{"gid"} = getgrnam($in{ntfs_gid}); } 2228 } 2229elsif ($_[0] eq "swap") { 2230 # Save SWAP options 2231 if ($in{'swap_pri_def'}) { 2232 delete($options{'pri'}); 2233 } 2234 else { 2235 $in{'swap_pri'} =~ /^\d+$/ && $in{'swap_pri'} <= 32767 || 2236 &error($text{'linux_eswappri'}); 2237 $options{'pri'} = $in{'swap_pri'}; 2238 } 2239 } 2240 2241# Add loop option if mounting a normal file 2242if ($_[0] ne "swap" && $_[0] ne "auto" && $_[0] ne "autofs" && 2243 $_[0] ne $smbfs_fs && $_[0] ne "cifs" && $_[0] ne "nfs" && 2244 $_[0] ne "nfs4" && $_[0] ne "tmpfs") { 2245 local(@st); 2246 @st = stat($_[1]); 2247 if (@st && ($st[2] & 0xF000) == 0x8000) { 2248 # a regular file.. add the loop option 2249 if (!$options{'loop'}) { 2250 $options{'loop'} = ""; 2251 } 2252 } 2253 } 2254 2255# Return options string 2256foreach $k (sort { ($b eq "user" ? 1 : 0) <=> ($a eq "user" ? 1 : 0) } (keys %options)) { 2257 if ($options{$k} eq "") { push(@rv, $k); } 2258 else { push(@rv, "$k=$options{$k}"); } 2259 } 2260return @rv ? join(',' , @rv) : "-"; 2261} 2262 2263 2264# Get the smbfs options from 'smbfs_opts' file in the current directory. This 2265# is sadly necessary because there is no way to get the current options for 2266# an existing smbfs mount... so webmin has to save them in a file when 2267# mounting. Blech. 2268sub read_smbopts 2269{ 2270local($_); 2271open(SMBOPTS, "<$module_config_directory/smbfs"); 2272while(<SMBOPTS>) { 2273 /^(\S+)\s+(\S+)$/; 2274 $smbopts{$1} = $2; 2275 } 2276close(SMBOPTS); 2277} 2278 2279sub write_smbopts 2280{ 2281local($_); 2282&open_tempfile(SMBOPTS, "> $module_config_directory/smbfs"); 2283foreach (keys %smbopts) { 2284 &print_tempfile(SMBOPTS, "$_\t$smbopts{$_}\n"); 2285 } 2286&close_tempfile(SMBOPTS); 2287} 2288 2289 2290# create_swap(file, size, units) 2291# Calls dd and mkswap to setup a swap file 2292sub create_swap 2293{ 2294local($out, $bl); 2295$bl = $_[1] * ($_[2] eq "t" ? 1024*1024*1024 : 2296 $_[2] eq "g" ? 1024*1024 : 2297 $_[2] eq "m" ? 1024 : 1); 2298$out = &backquote_logged("dd if=/dev/zero of=$_[0] bs=1024 count=$bl 2>&1"); 2299if ($?) { return "dd failed : $out"; } 2300$out = &backquote_logged("mkswap $_[0] $bl 2>&1"); 2301if ($?) { return "mkswap failed : $out"; } 2302&system_logged("sync >/dev/null 2>&1"); 2303return 0; 2304} 2305 2306# exports_list(host, dirarray, clientarray) 2307# Fills the directory and client array references with exports from some 2308# host. Returns an error string if something went wrong 2309sub exports_list 2310{ 2311local($dref, $cref, $out, $_); 2312$dref = $_[1]; $cref = $_[2]; 2313$out = &backquote_command("showmount -e ".quotemeta($_[0])." 2>&1", 1); 2314if ($?) { return $out; } 2315 2316# Add '/' if the server is in NFSv4 2317if (nfs_max_version($_[0]) >= 4) { 2318 push(@$dref, "/"); push(@$cref, "*"); } 2319 2320foreach (split(/\n/, $out)) { 2321 if (/^(\/\S*)\s+(.*)$/) { 2322 push(@$dref, $1); push(@$cref, $2); 2323 } 2324 } 2325return undef; 2326} 2327 2328# nfs_max_version(host) 2329# Return the max NFS version allowed on a server 2330sub nfs_max_version 2331{ 2332 local($_, $max, $out); 2333 $max = 0; 2334 $out = &backquote_command("/usr/sbin/rpcinfo -p ".quotemeta($_[0])." 2>&1", 1); 2335 if ($?) { return $out; } 2336 foreach (split(/\n/, $out)) { 2337 if ((/ +(\d) +.*nfs/) && ($1 > $max)) { 2338 $max = $1; } 2339 } 2340 return $max; 2341} 2342 2343# broadcast_addr() 2344# Returns a useable broadcast address for finding NFS servers 2345sub broadcast_addr 2346{ 2347local($out); 2348$out = &backquote_command("ifconfig -a 2>&1", 1); 2349if ($out =~ /(eth|tr)\d\s+.*\n.*Bcast:(\S+)\s+/) { return $2; } 2350return "255.255.255.255"; 2351} 2352 2353# autofs_options(string) 2354# Converts a string of options line --timeout 60 to something like timeout=60 2355sub autofs_options 2356{ 2357local(@options); 2358if ($_[0] =~ /--timeout\s+(\d+)/ || $_[0] =~ /-t\s+(\d+)/) { 2359 push(@options, "timeout=$1"); 2360 } 2361if ($_[0] =~ /--pid-file\s+(\S+)/ || $_[0] =~ /-p\s+(\d+)/) { 2362 push(@options, "pid-file=$1"); 2363 } 2364return join(',', @options); 2365} 2366 2367# autofs_args(string) 2368# Convert a comma-separated options string into args for automount 2369sub autofs_args 2370{ 2371local(%options, $args); 2372&parse_options("autofs", $_[0]); 2373if (defined($options{'timeout'})) { 2374 $args .= " --timeout $options{'timeout'}"; 2375 } 2376if (defined($options{'pid-file'})) { 2377 $args .= " --pid-file $options{'pid-file'}"; 2378 } 2379return $args; 2380} 2381 2382# read_amd_conf() 2383# Returns the entire amd config file as a string 2384sub read_amd_conf 2385{ 2386local $sl = $/; 2387$/ = undef; 2388local $rv; 2389foreach $f (split(/\s+/, $config{'auto_file'})) { 2390 open(AMD, "<".$f); 2391 $rv .= <AMD>; 2392 close(AMD); 2393 } 2394$/ = $sl; 2395return $rv; 2396} 2397 2398# write_amd_conf(text) 2399sub write_amd_conf 2400{ 2401local @af = split(/\s+/, $config{'auto_file'}); 2402&open_tempfile(AMD, ">$config{'auto_file'}"); 2403&print_tempfile(AMD, $_[0]); 2404&close_tempfile(AMD); 2405} 2406 2407# parse_amd_conf() 2408# Parses a new-style amd.conf file into a hashtable 2409sub parse_amd_conf 2410{ 2411local (@rv, $str); 2412foreach $f (split(/\s+/, $config{'auto_file'})) { 2413 local $lnum = 0; 2414 open(AMD, "<".$f); 2415 while(<AMD>) { 2416 s/\r|\n//g; 2417 s/#.*$//g; 2418 if (/\[\s*(\S+)\s*\]/) { 2419 $str = { 'dir' => $1, 2420 'line' => $lnum, 2421 'eline' => $lnum, 2422 'file' => $f }; 2423 push(@rv, $str); 2424 } 2425 elsif (/(\S+)\s*=\s*"(.*)"/ || /(\S+)\s*=\s*(\S+)/) { 2426 $str->{'opts'}->{$1} = $2; 2427 $str->{'eline'} = $lnum; 2428 } 2429 $lnum++; 2430 } 2431 close(AMD); 2432 } 2433return @rv; 2434} 2435 2436# device_name(device, [non-local]) 2437# Converts a device name to a human-readable form 2438sub device_name 2439{ 2440# First try to get name from fdisk module, as it knowns better about IDE 2441# and SCSI devices 2442if (&foreign_check("fdisk") && !$_[1]) { 2443 &foreign_require("fdisk"); 2444 my @disks = &fdisk::list_disks_partitions(); 2445 foreach my $d (@disks) { 2446 if ($d->{'device'} eq $_[0]) { 2447 return $d->{'desc'}; 2448 } 2449 foreach my $p (@{$d->{'parts'}}) { 2450 if ($p->{'device'} eq $_[0]) { 2451 return $p->{'desc'}; 2452 } 2453 } 2454 } 2455 } 2456 2457if (!$text{'select_part'}) { 2458 local %flang = &load_language('fdisk'); 2459 foreach $k (keys %flang) { 2460 $text{$k} = $flang{$k} if ($k =~ /^select_/); 2461 } 2462 } 2463return $_[0] =~ /^\/dev\/(s|h|xv|v)d([a-z]+)(\d+)$/ ? 2464 &text('select_part', $1 eq 's' ? 'SCSI' : $1 eq 'xv' ? 'Xen' : 2465 $1 eq 'v' ? 'VirtIO' : 'IDE', 2466 uc($2), "$3") : 2467 $_[0] =~ /^\/dev\/(s|h|xv|v)d([a-z]+)$/ ? 2468 &text('select_device', $1 eq 's' ? 'SCSI' : $1 eq 'xv' ? 'Xen' : 2469 $1 eq 'v' ? 'VirtIO' : 'IDE', 2470 uc($2)) : 2471 $_[0] =~ /^\/dev\/mmcblk(\d+)p(\d+)$/ ? 2472 &text('select_part', "SD-Card", "$1", "$2") : 2473 $_[0] =~ /^\/dev\/mmcblk(\d+)$/ ? 2474 &text('select_device', "SD-Card", "$1") : 2475 $_[0] =~ /rd\/c(\d+)d(\d+)p(\d+)$/ ? 2476 &text('select_mpart', "$1", "$2", "$3") : 2477 $_[0] =~ /ida\/c(\d+)d(\d+)p(\d+)$/ ? 2478 &text('select_cpart', "$1", "$2", "$3") : 2479 $_[0] =~ /cciss\/c(\d+)d(\d+)p(\d+)$/ ? 2480 &text('select_smartpart', "$1", "$2", "$3") : 2481 $_[0] =~ /scsi\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/part(\d+)/ ? 2482 &text('select_spart', "$1", "$2", "$3", "$4", "$5") : 2483 $_[0] =~ /scsi\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/disc/ ? 2484 &text('select_scsi', "$1", "$2", "$3", "$4") : 2485 $_[0] =~ /ide\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/part(\d+)/ ? 2486 &text('select_snewide', "$1", "$2", "$3", "$4", "$5") : 2487 $_[0] =~ /ide\/host(\d+)\/bus(\d+)\/target(\d+)\/lun(\d+)\/disc/ ? 2488 &text('select_newide', "$1", "$2", "$3", "$4") : 2489 $_[0] =~ /ataraid\/disc(\d+)\/part(\d+)$/ ? 2490 &text('select_ppart', "$1", "$2") : 2491 $_[0] =~ /fd(\d+)$/ ? 2492 &text('select_fd', "$1") : 2493 $_[0] =~ /md(\d+)$/ ? 2494 &text('linux_rdev', "$1") : 2495 $_[0] =~ /\/dev\/([^\/]+)\/([^\/]+)$/ && $1 ne "cdroms" ? 2496 &text('linux_ldev', "$1", "$2") : 2497 $_[0] =~ /LABEL=(\S+)/i ? 2498 &text('linux_label', "$1") : 2499 $_[0] =~ /UUID=(\S+)/i ? 2500 &text('linux_uuid', "$1") : 2501 $_[0] eq '/dev/cdrom' ? 2502 $text{'linux_cddev'} : 2503 $_[0] eq '/dev/burner' ? 2504 $text{'linux_burnerdev'} : 2505 $_[0] =~ /cdroms\/cdrom(\d+)$/ ? 2506 &text('linux_cddev2', "$1") : 2507 $_[0]; 2508} 2509 2510sub files_to_lock 2511{ 2512return ( $config{'fstab_file'}, $config{'autofs_file'}, 2513 split(/\s+/, $config{'auto_file'}) ); 2514} 2515 2516# lowercase_share_path(path) 2517# Converts a share spec like //FOO/BAR/Smeg to //foo/bar/Smeg 2518sub lowercase_share_path 2519{ 2520local ($path) = @_; 2521$path =~ s/\//\\/g; 2522if ($path =~ /^\\\\([^\\]+)\\([^\\]+)(\\.*)?/) { 2523 $path = "\\\\".lc($1)."\\".lc($2).$3; 2524 } 2525return $path; 2526} 2527 2528# get_filesystem_label(device, mount, type) 2529# Returns the label if there is one for this filesystem, or undef 2530sub get_filesystem_label 2531{ 2532local @p = @_; 2533if (defined($get_filesystem_label_cache{$p[0]})) { 2534 return $get_filesystem_label_cache{$p[0]}; 2535 } 2536local $rv = ""; 2537if ($p[2] =~ /^ext\d+$/ && $has_e2label || 2538 $p[2] eq "xfs" && $has_xfs_db || 2539 $p[2] eq "reiserfs" && $has_reiserfstune) { 2540 local $label; 2541 if ($p[2] eq "xfs") { 2542 local $out = &backquote_command( 2543 "xfs_db -x -p xfs_admin -c label -r ". 2544 quotemeta($p[0])." 2>&1", 1); 2545 $label = $1 if ($out =~ /label\s*=\s*"(.*)"/ && 2546 $1 ne '(null)'); 2547 } 2548 elsif ($p[2] eq "reiserfs") { 2549 local $out = &backquote_command( 2550 "reiserfstune ".quotemeta($p[0])." 2>&1"); 2551 if ($out =~ /LABEL:\s*(\S+)/) { 2552 $label = $1; 2553 } 2554 } 2555 else { 2556 $label = &backquote_command( 2557 "e2label ".quotemeta($p[0])." 2>&1", 1); 2558 chop($label); 2559 } 2560 $rv = $label if (!$?); 2561 } 2562$get_filesystem_label_cache{$p[0]} = $rv; 2563return $rv; 2564} 2565 25661; 2567 2568