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