1# openbsd-lib.pl 2# Mount table functions for openbsd 3 4$uname_release = `uname -r`; 5 6# Return information about a filesystem, in the form: 7# directory, device, type, options, fsck_order, mount_at_boot 8# If a field is unused or ignored, a - appears instead of the value. 9# Swap-filesystems (devices or files mounted for VM) have a type of 'swap', 10# and 'swap' in the directory field 11sub list_mounts 12{ 13local(@rv, @p, @o, $_, $i, $j); $i = 0; 14 15# Get /etc/fstab mounts 16open(FSTAB, "<".$config{'fstab_file'}); 17while(<FSTAB>) { 18 local(@o, $at_boot); 19 chop; s/#.*$//g; 20 if (!/\S/) { next; } 21 @p = split(/\s+/, $_); 22 if ($p[2] eq "proc" || $p[2] eq "procfs") { $p[2] = $p[0] = "proc"; } 23 if ($p[2] eq "swap") { $p[1] = "swap"; } 24 $rv[$i] = [ $p[1], $p[0], $p[2] ]; 25 $rv[$i]->[5] = "yes"; 26 @o = split(/,/ , $p[3] eq "defaults" ? "" : $p[3]); 27 if (($j = &indexof("noauto", @o)) >= 0) { 28 # filesytem is not mounted at boot 29 splice(@o, $j, 1); 30 $rv[$i]->[5] = "no"; 31 } 32 $rv[$i]->[3] = (@o ? join(',' , @o) : "-"); 33 $rv[$i]->[4] = (@p >= 5 ? $p[5] : 0); 34 $i++; 35 } 36close(FSTAB); 37return @rv; 38} 39 40 41# create_mount(directory, device, type, options, fsck_order, mount_at_boot) 42# Add a new entry to the fstab file, old or new automounter file 43sub create_mount 44{ 45local(@mlist, @amd, $_); local($opts); 46 47# Adding a normal mount to the fstab file 48&open_tempfile(FSTAB, ">>$config{'fstab_file'}"); 49&print_tempfile(FSTAB, "$_[1] $_[0] $_[2]"); 50$opts = $_[3] eq "-" ? "" : $_[3]; 51if ($_[5] eq "no") { 52 $opts = join(',' , (split(/,/ , $opts) , "noauto")); 53 } 54if ($opts eq "") { &print_tempfile(FSTAB, " defaults"); } 55else { &print_tempfile(FSTAB, " $opts"); } 56&print_tempfile(FSTAB, " 0 "); 57&print_tempfile(FSTAB, $_[4] eq "-" ? "0\n" : "$_[4]\n"); 58&close_tempfile(FSTAB); 59} 60 61 62# change_mount(num, directory, device, type, options, fsck_order, mount_at_boot) 63# Change an existing permanent mount 64sub change_mount 65{ 66local($i, @fstab, $line, $opts, $j, @amd); 67$i = 0; 68 69# Update fstab file 70open(FSTAB, "<".$config{'fstab_file'}); 71@fstab = <FSTAB>; 72close(FSTAB); 73&open_tempfile(FSTAB, ">$config{'fstab_file'}"); 74foreach (@fstab) { 75 chop; ($line = $_) =~ s/#.*$//g; 76 if ($line =~ /\S/ && $i++ == $_[0]) { 77 # Found the line to replace 78 &print_tempfile(FSTAB, "$_[2] $_[1] $_[3]"); 79 $opts = $_[4] eq "-" ? "" : $_[4]; 80 if ($_[6] eq "no") { 81 $opts = join(',' , (split(/,/ , $opts) , "noauto")); 82 } 83 if ($opts eq "") { &print_tempfile(FSTAB, " defaults"); } 84 else { &print_tempfile(FSTAB, " $opts"); } 85 &print_tempfile(FSTAB, " 0 "); 86 &print_tempfile(FSTAB, $_[5] eq "-" ? "0\n" : "$_[5]\n"); 87 } 88 else { 89 &print_tempfile(FSTAB, $_,"\n"); 90 } 91 } 92&close_tempfile(FSTAB); 93} 94 95 96# delete_mount(index) 97# Delete an existing permanent mount 98sub delete_mount 99{ 100local($i, @fstab, $line, $opts, $j, @amd); 101$i = 0; 102 103# Update fstab file 104open(FSTAB, "<".$config{'fstab_file'}); 105@fstab = <FSTAB>; 106close(FSTAB); 107&open_tempfile(FSTAB, ">$config{'fstab_file'}"); 108foreach (@fstab) { 109 chop; ($line = $_) =~ s/#.*$//g; 110 if ($line !~ /\S/ || $i++ != $_[0]) { 111 # Don't delete this line 112 &print_tempfile(FSTAB, $_,"\n"); 113 } 114 } 115&close_tempfile(FSTAB); 116} 117 118 119# list_mounted() 120# Return a list of all the currently mounted filesystems and swap files. 121# The list is in the form: 122# directory device type options 123# Under OpenBSD, there seems to be no way to get additional mount options 124# used by filesystems like NFS etc. Even getting the full details of mounted 125# filesystems requires C code! So we have to call a specially-written external 126# program to get the mount list 127sub list_mounted 128{ 129# get the list of mounted filesystems 130local(@rv, $_); 131local $cmd = $uname_release =~ /^[3456789]\.[0-9]/ ? "netbsd-mounts-3" : 132 $uname_release =~ /^2\.[0-9]/ ? "netbsd-mounts-2" : 133 "netbsd-mounts"; 134&compile_program($cmd); 135open(CMD, "$module_config_directory/$cmd |"); 136while(<CMD>) { 137 local @p = split(/\t/, $_); 138 if ($p[2] eq "procfs" || $p[1] eq "procfs") { $p[1] = $p[2] = "proc"; } 139 push(@rv, \@p); 140 } 141close(CMD); 142 143# add output from swapinfo 144&open_execute_command(SWAP, "swapinfo", 1, 1); 145while(<SWAP>) { 146 if (/^(\/\S+)\s+\d+\s+\d+/) { 147 push(@rv, [ "swap", $1, "swap", "-" ]); 148 } 149 } 150close(SWAP); 151return @rv; 152} 153 154 155# mount_dir(directory, device, type, options) 156# Mount a new directory from some device, with some options. Returns 0 if ok, 157# or an error string if failed 158sub mount_dir 159{ 160local($out, $opts, $shar, %options, %smbopts); 161if ($_[2] eq "swap") { 162 # Use swapon to add the swap space.. 163 $out = &backquote_logged("swapon $_[1] 2>&1"); 164 if ($?) { return "<pre>$out</pre>"; } 165 } 166else { 167 # some disk-based filesystem 168 $opts = $_[3] eq "-" ? "" : "-o \"$_[3]\""; 169 $opts = join(',', grep { !/quota/ } split(/,/, $opts)); 170 $out = &backquote_logged("mount -t $_[2] $opts $_[1] $_[0] 2>&1"); 171 if ($?) { return "<pre>$out</pre>"; } 172 } 173return 0; 174} 175 176 177# unmount_dir(directory, device, type) 178# Unmount a directory that is currently mounted. Returns 0 if ok, 179# or an error string if failed 180sub unmount_dir 181{ 182local($out, %smbopts, $dir); 183if ($_[2] eq "swap") { 184 # Not possible! 185 &error("Swap space cannot be removed"); 186 } 187else { 188 $out = &backquote_logged("umount $_[0] 2>&1"); 189 if ($?) { return "<pre>$out</pre>"; } 190 } 191return 0; 192} 193 194 195# mount_modes(type) 196# Given a filesystem type, returns 4 numbers that determine how the file 197# system can be mounted, and whether it can be fsck'd 198# The first is: 199# 0 - cannot be permanently recorded 200# (smbfs under linux) 201# 1 - can be permanently recorded, and is always mounted at boot 202# (swap under linux) 203# 2 - can be permanently recorded, and may or may not be mounted at boot 204# (most normal filesystems) 205# The second is: 206# 0 - mount is always permanent => mounted when saved 207# (swap under linux) 208# 1 - doesn't have to be permanent 209# (normal fs types) 210# The third is: 211# 0 - cannot be fsck'd at boot time 212# 1 - can be be fsck'd at boot 213# The fourth is: 214# 0 - can be unmounted 215# 1 - cannot be unmounted 216sub mount_modes 217{ 218if ($_[0] eq "swap") 219 { return (2, 1, 0, 1); } 220elsif ($_[0] eq "ffs") 221 { return (2, 1, 1, 0); } 222else 223 { return (2, 1, 0, 0); } 224} 225 226 227# disk_space(type, directory) 228# Returns the amount of total and free space for some filesystem, or an 229# empty array if not appropriate. 230sub disk_space 231{ 232if (&get_mounted($_[1], "*") < 0) { return (); } 233if ($_[0] eq "proc" || $_[0] eq "swap") { return (); } 234if (&backquote_command("df -k ".quotemeta($_[1]), 1) =~ 235 /Mounted on\n\S+\s+(\S+)\s+\S+\s+(\S+)/) { 236 return ($1, $2); 237 } 238return ( ); 239} 240 241 242# list_fstypes() 243# Returns an array of all the supported filesystem types. If a filesystem is 244# found that is not one of the supported types, generate_location() and 245# generate_options() will not be called for it. 246sub list_fstypes 247{ 248local @rv = ("ffs", "nfs", "cd9660", "msdos", "swap"); 249push(@rv, "ext2fs") if (&has_command("mount_ext2fs")); 250return @rv; 251} 252 253 254# fstype_name(type) 255# Given a short filesystem type, return a human-readable name for it 256sub fstype_name 257{ 258local(%fsmap); 259%fsmap = ("ffs", "NetBSD Unix Filesystem", 260 "nfs","Network Filesystem", 261 "cd9660","ISO9660 CD-ROM", 262 "msdos","MS-DOS Filesystem", 263 "ext2fs","Linux Filesystem", 264 "swap","Virtual Memory", 265 "proc","Process Image Filesystem"); 266return $config{long_fstypes} && $fsmap{$_[0]} ? $fsmap{$_[0]} : uc($_[0]); 267} 268 269 270# multiple_mount(type) 271# Returns 1 if filesystems of this type can be mounted multiple times, 0 if not 272sub multiple_mount 273{ 274return $_[0] eq "nfs"; 275} 276 277 278# generate_location(type, location) 279# Output HTML for editing the mount location of some filesystem. 280sub generate_location 281{ 282local ($type, $loc) = @_; 283if ($type eq "nfs") { 284 # NFS mount from some host and directory 285 local ($host, $dir) = $loc =~ /^([^:]+):(.*)$/ ? ( $1, $2 ) : ( ); 286 print &ui_table_row(&hlink($text{'linux_nfshost'}, "nfshost"), 287 &ui_textbox("nfs_host", $host, 30). 288 &nfs_server_chooser_button("nfs_host"). 289 " ". 290 "<b>".&hlink($text{'linux_nfsdir'}, "nfsdir")."</b> ". 291 &ui_textbox("nfs_dir", 292 ($type eq "nfs4") && ($dir eq "") ? "/" : $dir, 30). 293 &nfs_export_chooser_button("nfs_host", "nfs_dir")); 294 } 295else { 296 local $msg; 297 if ($type eq "swap") { 298 # Swap file or device 299 $msg = $text{'linux_swapfile'}; 300 } 301 else { 302 # Disk-based filesystem 303 $msg = &fstype_name($type); 304 } 305 local ($disk_dev, $ide_t, $ide_s, $ide_p, $scsi_t, $scsi_s, $scsi_p); 306 if ($loc =~ /^\/dev\/wd(\d)s(\d)([a-z]*)$/) { 307 $disk_dev = 0; $ide_t = $1; $ide_s = $2; $ide_p = $3; 308 } 309 elsif ($loc =~ /^\/dev\/sd(\d)s(\d)([a-z]*)$/) { 310 $disk_dev = 1; $scsi_t = $1; $scsi_s = $2; $scsi_p = $3; 311 } 312 else { $disk_dev = 2; } 313 314 print &ui_table_row($msg, 315 &ui_radio_table("disk_dev", $disk_dev, 316 [ [ 0, $text{'freebsd_ide'}, 317 $text{'freebsd_device'}." ". 318 &ui_textbox("ide_t", $ide_t, 4)." ". 319 $text{'freebsd_slice'}." ". 320 &ui_textbox("ide_s", $ide_s, 4)." ". 321 $text{'freebsd_part'}." ". 322 &ui_textbox("ide_p", $ide_p, 4) ], 323 [ 1, $text{'freebsd_scsi'}, 324 $text{'freebsd_device'}." ". 325 &ui_textbox("scsi_t", $scsi_t, 4)." ". 326 $text{'freebsd_slice'}." ". 327 &ui_textbox("scsi_s", $scsi_s, 4)." ". 328 $text{'freebsd_part'}." ". 329 &ui_textbox("scsi_p", $scsi_p, 4) ], 330 [ 2, $text{'freebsd_other'}, 331 &ui_textbox("dev_path", $disk_dev == 2 ? $loc : "", 40). 332 " ".&file_chooser_button("dev_path", 0) ] ])); 333 } 334} 335 336 337# generate_options(type, newmount) 338# Output HTML for editing mount options for a particular filesystem 339# under this OS 340sub generate_options 341{ 342if ($_[0] ne "swap") { 343 # These options are common to all filesystems 344 print "<tr> <td><b>Read-only?</b></td>\n"; 345 printf "<td nowrap><input type=radio name=bsd_ro value=1 %s> Yes\n", 346 defined($options{"rdonly"}) || defined($options{"ro"}) 347 ? "checked" : ""; 348 printf "<input type=radio name=bsd_ro value=0 %s> No</td>\n", 349 defined($options{"rdonly"}) || defined($options{"ro"}) 350 ? "" : "checked"; 351 352 print "<td><b>Buffer writes to filesystem?</b></td>\n"; 353 printf"<td nowrap><input type=radio name=bsd_sync value=0 %s> Yes\n", 354 defined($options{"sync"}) ? "" : "checked"; 355 printf "<input type=radio name=bsd_sync value=1 %s> No</td> </tr>\n", 356 defined($options{"sync"}) ? "checked" : ""; 357 358 print "<tr> <td><b>Allow device files?</b></td>\n"; 359 printf "<td nowrap><input type=radio name=bsd_nodev value=0 %s> Yes\n", 360 defined($options{"nodev"}) ? "" : "checked"; 361 printf "<input type=radio name=bsd_nodev value=1 %s> No</td>\n", 362 defined($options{"nodev"}) ? "checked" : ""; 363 364 print "<td><b>Allow execution of binaries?</b></td>\n"; 365 printf"<td nowrap><input type=radio name=bsd_noexec value=0 %s> Yes\n", 366 defined($options{"noexec"}) ? "" : "checked"; 367 printf "<input type=radio name=bsd_noexec value=1 %s> No</td> </tr>\n", 368 defined($options{"noexec"}) ? "checked" : ""; 369 370 print "<tr> <td><b>Disallow setuid programs?</b></td>\n"; 371 printf "<td nowrap><input type=radio name=bsd_nosuid value=1 %s> Yes\n", 372 defined($options{"nosuid"}) ? "checked" : ""; 373 printf "<input type=radio name=bsd_nosuid value=0 %s> No</td>\n", 374 defined($options{"nosuid"}) ? "" : "checked"; 375 376 print "<td><b>Update access times?</b></td>\n"; 377 printf"<td nowrap><input type=radio name=bsd_noatime value=0 %s> Yes\n", 378 defined($options{"noatime"}) ? "" : "checked"; 379 printf "<input type=radio name=bsd_noatime value=1 %s> No</td> </tr>\n", 380 defined($options{"noatime"}) ? "checked" : ""; 381 382 } 383 384if ($_[0] eq "ffs") { 385 # FFS filesystems support quotas 386 print "<tr> <td><b>User quotas at boot</b></td> <td colspan=3>\n"; 387 printf "<input type=radio name=ffs_userquota value=0 %s> Disabled\n", 388 defined($options{'userquota'}) ? "" : "checked"; 389 printf "<input type=radio name=ffs_userquota value=1 %s> Enabled\n", 390 defined($options{'userquota'}) && $options{'userquota'} eq "" 391 ? "checked" : ""; 392 printf "<input type=radio name=ffs_userquota value=2 %s>\n", 393 $options{'userquota'} ? "checked" : ""; 394 print "Enabled, use file\n"; 395 printf "<input name=ffs_userquota_file size=30 value=\"%s\">\n", 396 $options{'userquota'}; 397 print "</td> </tr>\n"; 398 399 print "<tr> <td><b>Group quotas at boot</b></td> <td colspan=3>\n"; 400 printf "<input type=radio name=ffs_groupquota value=0 %s> Disabled\n", 401 defined($options{'groupquota'}) ? "" : "checked"; 402 printf "<input type=radio name=ffs_groupquota value=1 %s> Enabled\n", 403 defined($options{'groupquota'}) && $options{'groupquota'} eq "" 404 ? "checked" : ""; 405 printf "<input type=radio name=ffs_groupquota value=2 %s>\n", 406 $options{'groupquota'} ? "checked" : ""; 407 print "Enabled, use file\n"; 408 printf "<input name=ffs_groupquota_file size=30 value=\"%s\">\n", 409 $options{'groupquota'}; 410 print "</td> </tr>\n"; 411 } 412elsif ($_[0] eq "nfs") { 413 # NFS filesystems have lots more options 414 print "<tr> <td><b>Retry mounts in background?</b></td>\n"; 415 printf "<td nowrap><input type=radio name=nfs_b value=1 %s> Yes\n", 416 defined($options{"-b"}) ? "checked" : ""; 417 printf "<input type=radio name=nfs_b value=0 %s> No</td>\n", 418 defined($options{"-b"}) ? "" : "checked"; 419 420 print "<td><b>Return error on timeouts?</b></td>\n"; 421 printf "<td nowrap><input type=radio name=nfs_s value=1 %s> Yes\n", 422 defined($options{"-s"}) ? "checked" : ""; 423 printf "<input type=radio name=nfs_s value=0 %s> No</td> </tr>\n", 424 defined($options{"-s"}) ? "" : "checked"; 425 426 print "<tr> <td><b>Timeout</b></td>\n"; 427 printf "<td nowrap><input type=radio name=nfs_t_def value=1 %s> Default\n", 428 defined($options{"-t"}) ? "" : "checked"; 429 printf "<input type=radio name=nfs_t_def value=0 %s>\n", 430 defined($options{"-t"}) ? "checked" : ""; 431 printf "<input size=5 name=nfs_t value=\"$options{'-t'}\"></td>\n"; 432 433 print "<td><b>Number of Retransmissions</b></td>\n"; 434 printf "<td nowrap><input type=radio name=nfs_x_def value=1 %s> Default\n", 435 defined($options{"-x"}) ? "" : "checked"; 436 printf "<input type=radio name=nfs_x_def value=0 %s>\n", 437 defined($options{"-x"}) ? "checked" : ""; 438 print "<input size=5 name=nfs_x value=\"$options{'-x'}\"></td> </tr>\n"; 439 440 print "<tr> <td><b>NFS version</b></td> <td nowrap>\n"; 441 local $v = defined($options{"-2"}) ? 2 : 442 defined($options{"-3"}) ? 3 : 0; 443 printf "<input type=radio name=nfs_ver value=0 %s> Auto\n", 444 $v ? "" : "checked"; 445 printf "<input type=radio name=nfs_ver value=2 %s> V2\n", 446 $v == 2 ? "checked" : ""; 447 printf "<input type=radio name=nfs_ver value=3 %s> V3</td>\n", 448 $v == 3 ? "checked" : ""; 449 450 print "<td><b>Mount retries</b></td>\n"; 451 printf "<td nowrap><input type=radio name=nfs_r_def value=1 %s> Default\n", 452 defined($options{"-R"}) ? "" : "checked"; 453 printf "<input type=radio name=nfs_r_def value=0 %s>\n", 454 defined($options{"-R"}) ? "checked" : ""; 455 print "<input size=5 name=nfs_r value=\"$options{'-R'}\"></td> </tr>\n"; 456 457 print "<tr> <td><b>Read-ahead blocks</b></td>\n"; 458 printf "<td nowrap><input type=radio name=nfs_a_def value=1 %s> Default\n", 459 defined($options{"-a"}) ? "" : "checked"; 460 printf "<input type=radio name=nfs_a_def value=0 %s>\n", 461 defined($options{"-a"}) ? "checked" : ""; 462 print "<input size=5 name=nfs_a value=\"$options{'-a'}\"></td> </tr>\n"; 463 464 print "<tr> <td><b>RPC Protocol</b></td>\n"; 465 printf "<td nowrap><input type=radio name=nfs_t2 value=1 %s> TCP\n", 466 defined($options{"-T"}) ? "checked" : ""; 467 printf "<input type=radio name=nfs_t2 value=0 %s> UDP</td> </tr>\n", 468 defined($options{"-T"}) ? "" : "checked"; 469 } 470elsif ($_[0] eq "msdos"){ 471 # MS-DOS filesystems options deal with filling in 472 # missing unix functionality 473 print "<tr> <td><b>User files are owned by</b></td>\n"; 474 printf "<td><input name=msdos_u size=8 value=\"%s\">\n", 475 defined($options{"-u"}) ? getpwuid($options{"-u"}) : ""; 476 print &user_chooser_button("msdos_u", 0),"</td>\n"; 477 478 print "<td><b>Group files are owned by</b></td>\n"; 479 printf "<td><input name=msdos_g size=8 value=\"%s\">\n", 480 defined($options{"-g"}) ? getgrgid($options{"-g"}) : ""; 481 print &group_chooser_button("msdos_g", 0),"</td>\n"; 482 483 print "<tr> <td><b>File permissions mask</b></td>\n"; 484 printf "<td><input type=radio name=msdos_m_def value=1 %s> Default\n", 485 defined($options{"-m"}) ? "" : "checked"; 486 printf "<input type=radio name=msdos_m_def value=0 %s>\n", 487 defined($options{"-m"}) ? "checked" : ""; 488 print "<input size=5 name=msdos_m value=\"$options{'-m'}\"></td>\n"; 489 } 490elsif ($_[0] eq "cd9660") { 491 # CDROM filesystem 492 print "<tr> <td><b>Ignore Unix Attributes?</b></td>\n"; 493 printf "<td><input type=radio name=cd9660_r value=1 %s> Yes\n", 494 defined($options{"-r"}) ? "checked" : ""; 495 printf "<input type=radio name=cd9660_r value=0 %s> No</td>\n", 496 defined($options{"-r"}) ? "" : "checked"; 497 498 print "<td><b>Show version numbers?</b></td>\n"; 499 printf "<td><input type=radio name=cd9660_g value=1 %s> Yes\n", 500 defined($options{"-g"}) ? "checked" : ""; 501 printf "<input type=radio name=cd9660_g value=0 %s> No</td> </tr>\n", 502 defined($options{"-g"}) ? "" : "checked"; 503 504 print "<tr> <td><b>Use extended attributes?</b></td>\n"; 505 printf "<td><input type=radio name=cd9660_e value=1 %s> Yes\n", 506 defined($options{"-e"}) ? "checked" : ""; 507 printf "<input type=radio name=cd9660_e value=0 %s> No</td> </tr>\n", 508 defined($options{"-e"}) ? "" : "checked"; 509 } 510elsif ($_[0] eq "swap") { 511 # Swap has no options.. 512 print "<tr> <td><i>No Options Available</i></td> </tr>\n"; 513 } 514} 515 516 517# check_location(type) 518# Parse and check inputs from %in, calling &error() if something is wrong. 519# Returns the location string for storing in the fstab file 520sub check_location 521{ 522if ($_[0] eq "nfs") { 523 local($out, $temp, $mout, $dirlist); 524 525 if ($config{'nfs_check'}) { 526 # Use ping and showmount to see if the host exists and is up 527 if ($in{nfs_host} !~ /^\S+$/) { 528 &error("'$in{nfs_host}' is not a valid hostname"); 529 } 530 $out = &backquote_command("ping -c 1 '$in{nfs_host}' 2>&1"); 531 if ($out =~ /unknown host/i) { 532 &error("The host '$in{nfs_host}' does not exist"); 533 } 534 elsif ($out =~ /100\% packet loss/) { 535 &error("The host '$in{nfs_host}' is down"); 536 } 537 $out = &backquote_command("showmount -e '$in{nfs_host}' 2>&1"); 538 if ($out =~ /Unable to receive/) { 539 &error("The host '$in{nfs_host}' does not support NFS"); 540 } 541 elsif ($?) { 542 &error("Failed to get mount list : $out"); 543 } 544 } 545 546 # Validate directory name 547 foreach (split(/\n/, $out)) { 548 if (/^(\/\S+)/) { $dirlist .= "$1\n"; } 549 } 550 if ($in{nfs_dir} !~ /^\/\S+$/) { 551 &error("'$in{nfs_dir}' is not a valid directory name. The ". 552 "available directories on $in{nfs_host} are:". 553 "<pre>$dirlist</pre>"); 554 } 555 556 # Try a test mount to see if filesystem is available 557 $temp = &transname(); 558 &make_dir($temp, 0755); 559 $mout = &backquote_command("mount $in{nfs_host}:$in{nfs_dir} $temp 2>&1"); 560 if ($mout =~ /No such file or directory/) { 561 &error("The directory '$in{nfs_dir}' does not exist on the ". 562 "host $in{nfs_host}. The available directories are:". 563 "<pre>$dirlist</pre>"); 564 } 565 elsif ($mout =~ /Permission denied/) { 566 &error("This host is not allowed to mount the directory ". 567 "$in{nfs_dir} from $in{nfs_host}"); 568 } 569 elsif ($?) { 570 &error("NFS Error - $mout"); 571 } 572 # It worked! unmount 573 &execute_command("umount $temp"); 574 &unlink_file($temp); 575 return "$in{nfs_host}:$in{nfs_dir}"; 576 } 577else { 578 # This is some kind of disk-based filesystem.. get the device name 579 if ($in{'disk_dev'} == 0) { 580 $in{'ide_t'} =~ /^\d+$/ || 581 &error("'$in{ide_t}' is not a valid device number"); 582 $in{'ide_s'} =~ /^\d+$/ || 583 &error("'$in{ide_s}' is not a valid slice number"); 584 $in{'ide_p'} =~ /^[a-z]*$/ || 585 &error("'$in{ide_p}' is not a valid partition letter"); 586 $dv = "/dev/wd$in{ide_t}s$in{ide_s}$in{ide_p}"; 587 } 588 elsif ($in{'disk_dev'} == 1) { 589 $in{'scsi_t'} =~ /^\d+$/ || 590 &error("'$in{scsi_t}' is not a valid device number"); 591 $in{'scsi_s'} =~ /^\d+$/ || 592 &error("'$in{scsi_s}' is not a valid slice number"); 593 $in{'scsi_p'} =~ /^[a-z]*$/ || 594 &error("'$in{scsi_p}' is not a valid partition letter"); 595 $dv = "/dev/sd$in{scsi_t}s$in{scsi_s}$in{scsi_p}"; 596 } 597 else { 598 $dv = $in{'dev_path'}; 599 } 600 601 # If the device entered is a symlink, follow it 602 if ($dvlink = readlink($dv)) { 603 if ($dvlink =~ /^\//) { $dv = $dvlink; } 604 else { $dv =~ /^(.*\/)[^\/]+$/; 605 $dv = $1.$dvlink; 606 } 607 } 608 609 # Check if the device actually exists and uses the right filesystem 610 (-r $dv) || &error("The device file '$dv' does not exist"); 611 return $dv; 612 } 613} 614 615# check_options(type, device, directory) 616# Read options for some filesystem from %in, and use them to update the 617# %options array. Options handled by the user interface will be set or 618# removed, while unknown options will be left untouched. 619sub check_options 620{ 621local($k, @rv); 622 623# Parse the common options first.. 624if ($_[0] ne "swap") { 625 delete($options{"ro"}); delete($options{"rw"}); 626 delete($options{"rdonly"}); 627 if ($in{'bsd_ro'}) { $options{'ro'} = ''; } 628 else { $options{'rw'} = ""; } 629 630 delete($options{"sync"}); delete($options{"async"}); 631 if ($in{'bsd_sync'}) { $options{'sync'} = ''; } 632 633 delete($options{'nodev'}); 634 if ($in{'bsd_nodev'}) { $options{'nodev'} = ''; } 635 636 delete($options{'noexec'}); 637 if ($in{'bsd_noexec'}) { $options{'noexec'} = ''; } 638 639 delete($options{'nosuid'}); 640 if ($in{'bsd_nosuid'}) { $options{'nosuid'} = ''; } 641 642 delete($options{'noatime'}); 643 if ($in{'bsd_noatime'}) { $options{'noatime'} = ''; } 644 645 } 646else { 647 # Swap always has the sw option 648 $options{'sw'} = ""; 649 } 650 651if ($_[0] eq "ffs") { 652 # Parse FFS quota options 653 delete($options{'userquota'}) if ($in{'ffs_userquota'} == 0); 654 $options{'userquota'} = "" if ($in{'ffs_userquota'} == 1); 655 $options{'userquota'} = $in{'ffs_groupquota_file'} 656 if ($in{'ffs_userquota'} == 2); 657 658 delete($options{'groupquota'}) if ($in{'ffs_groupquota'} == 0); 659 $options{'groupquota'} = "" if ($in{'ffs_groupquota'} == 1); 660 $options{'groupquota'} = $in{'ffs_groupquota_file'} 661 if ($in{'ffs_groupquota'} == 2); 662 } 663elsif ($_[0] eq "nfs") { 664 # NFS has a few specific options.. 665 delete($options{'-b'}); 666 $options{'-b'} = "" if ($in{'nfs_b'}); 667 668 delete($options{'-s'}); 669 $options{'-s'} = "" if ($in{'nfs_s'}); 670 671 delete($options{'-t'}); 672 $options{'-t'} = $in{'nfs_t'} if (!$in{'nfs_t_def'}); 673 674 delete($options{'-x'}); 675 $options{'-x'} = $in{'nfs_x'} if (!$in{'nfs_x_def'}); 676 677 delete($options{'-2'}); delete($options{'-3'}); 678 $options{'-2'} = "" if ($in{'nfs_ver'} == 2); 679 $options{'-3'} = "" if ($in{'nfs_ver'} == 3); 680 681 delete($options{'-R'}); 682 $options{'-R'} = $in{'nfs_r'} if (!$in{'nfs_r_def'}); 683 684 delete($options{'-a'}); 685 $options{'-a'} = $in{'nfs_a'} if (!$in{'nfs_a_def'}); 686 687 delete($options{'-T'}); 688 $options{'-T'} = "" if ($in{'nfs_t2'}); 689 } 690elsif ($_[0] eq "msdos") { 691 # MSDOS options for file ownership/perms 692 delete($options{"-u"}); delete($options{"-g"}); 693 if ($in{'msdos_u'} ne "") { $options{'-u'} = getpwnam($in{'msdos_u'}); } 694 if ($in{'msdos_g'} ne "") { $options{'-g'} = getgrnam($in{'msdos_g'}); } 695 696 delete($options{"-m"}); 697 if (!$in{'msdos_m_def'}) { 698 $in{'msdos_m'} =~ /^[0-7]{3}$/ || 699 &error("'$in{'msdos_m'}' is not a valid octal mask"); 700 $options{'-m'} = $in{'msdos_m'}; 701 } 702 } 703elsif ($_[0] eq "cd9660") { 704 # Options for iso9660 cd-roms 705 delete($options{'-r'}); 706 $options{'-r'} = "" if ($in{'cd9660_r'}); 707 708 delete($options{'-g'}); 709 $options{'-g'} = "" if ($in{'cd9660_g'}); 710 711 delete($options{'-e'}); 712 $options{'-e'} = "" if ($in{'cd9660_e'}); 713 } 714 715# Return options string 716foreach $k (keys %options) { 717 if ($options{$k} eq "") { push(@rv, $k); } 718 else { push(@rv, "$k=$options{$k}"); } 719 } 720return @rv ? join(',' , @rv) : "-"; 721} 722 723# create_swap(file, size, units) 724# Calls dd and mkswap to setup a swap file 725sub create_swap 726{ 727local($out, $bl); 728$bl = $_[1] * ($_[2] eq "t" ? 1024*1024*1024 : 729 $_[2] eq "g" ? 1024*1024 : 730 $_[2] eq "m" ? 1024 : 1); 731$out = &backquote_logged("dd if=/dev/zero of=$_[0] bs=1024 count=$bl 2>&1"); 732if ($?) { return "dd failed : $out"; } 733$out = &backquote_logged("mkswap $_[0] $bl 2>&1"); 734if ($?) { return "mkswap failed : $out"; } 735&system_logged("sync >/dev/null 2>&1"); 736return 0; 737} 738 739# exports_list(host, dirarray, clientarray) 740# Fills the directory and client array references with exports from some 741# host. Returns an error string if something went wrong 742sub exports_list 743{ 744local($dref, $cref, $out, $_); 745$dref = $_[1]; $cref = $_[2]; 746$out = &backquote_command("showmount -e ".quotemeta($_[0])." 2>&1", 1); 747if ($?) { return $out; } 748foreach (split(/\n/, $out)) { 749 if (/^(\/\S*)\s+(.*)$/) { 750 push(@$dref, $1); push(@$cref, $2); 751 } 752 } 753return undef; 754} 755 756# broadcast_addr() 757# Returns a useable broadcast address for finding NFS servers 758sub broadcast_addr 759{ 760local($out); 761$out = &backquote_command("ifconfig -a 2>&1", 1); 762if ($out =~ /broadcast\s+(\S+)\s+/) { return $1; } 763return "255.255.255.255"; 764} 765 766sub device_name 767{ 768return $_[0]; 769} 770 771sub files_to_lock 772{ 773return ( $config{'fstab_file'} ); 774} 775 7761; 777 778