2 # Mount table functions for freebsd
4 $uname_release = `uname -r`;
5 if (&has_command("mount_smbfs")) {
7 $nsmb_conf = "/etc/nsmb.conf";
10 # Return information about a filesystem, in the form:
11 # directory, device, type, options, fsck_order, mount_at_boot
12 # If a field is unused or ignored, a - appears instead of the value.
13 # Swap-filesystems (devices or files mounted for VM) have a type of 'swap',
14 # and 'swap' in the directory field
17 local(@rv, @p, @o, $_, $i, $j); $i = 0;
19 # Get /etc/fstab mounts
20 open(FSTAB, $config{'fstab_file'});
25 @p = split(/\s+/, $_);
26 if ($p[2] eq "proc" || $p[2] eq "procfs") { $p[2] = $p[0] = "proc"; }
27 elsif ($p[2] eq "swap") { $p[1] = "swap"; }
28 elsif ($p[2] eq "smbfs") {
29 # Need to get nsmb.conf options, covert share and extract user
31 local $noptions = &read_nsmb($p[0]);
33 &parse_options($p[3]);
34 if ($p[0] =~ /^\/\/(\S+)\@(\S+)\/(.*)$/) {
36 $options{'user'} = $1;
38 elsif ($p[0] =~ /\/\/(\S+)\/(.*)$/) {
41 %options = ( %options, %$noptions );
42 $p[3] = &join_options();
44 $rv[$i] = [ $p[1], $p[0], $p[2] ];
46 @o = split(/,/ , $p[3] eq "defaults" ? "" : $p[3]);
47 if (($j = &indexof("noauto", @o)) >= 0) {
48 # filesytem is not mounted at boot
52 $rv[$i]->[3] = (@o ? join(',' , @o) : "-");
53 $rv[$i]->[4] = (@p >= 5 ? $p[5] : 0);
61 # create_mount(directory, device, type, options, fsck_order, mount_at_boot)
62 # Add a new entry to the fstab file, old or new automounter file
65 local(@mlist, @amd, $_, $opts);
67 &open_tempfile(FSTAB, ">> $config{'fstab_file'}");
68 &print_mount_line(@_);
69 &close_tempfile(FSTAB);
72 # print_mount_line(directory, device, type, options, fsck_order, mount_at_boot)
75 if ($_[2] eq "smbfs") {
76 # Adding an SMB mount, which needs special handling
78 &parse_options("smbfs", $_[3]);
80 if ($options{'user'} && $_[1] =~ /^\\\\(.*)\\(.*)$/) {
81 $share = "//$options{'user'}\@$1/$2";
84 ($share = $_[1]) =~ s/\\/\//g;
86 &print_tempfile(FSTAB, "$share $_[0] $_[2]");
87 local $roptions = &update_nsmb($share, \%options);
88 delete($roptions->{'user'});
89 $opts = &join_options($_[2], $roptions);
92 # Adding a normal mount to the fstab file
93 &print_tempfile(FSTAB, "$_[1] $_[0] $_[2]");
94 $opts = $_[3] eq "-" ? "" : $_[3];
97 $opts = join(',' , (split(/,/ , $opts) , "noauto"));
100 &print_tempfile(FSTAB, " defaults");
103 &print_tempfile(FSTAB, " $opts");
105 &print_tempfile(FSTAB, " 0 ");
106 &print_tempfile(FSTAB, $_[4] eq "-" ? "0\n" : "$_[4]\n");
110 # change_mount(num, directory, device, type, options, fsck_order, mount_at_boot)
111 # Change an existing permanent mount
114 local($i, @fstab, $line, $opts, $j, @amd);
118 open(FSTAB, $config{fstab_file});
121 &open_tempfile(FSTAB, "> $config{fstab_file}");
123 chop; ($line = $_) =~ s/#.*$//g;
124 if ($line =~ /\S/ && $i++ == $_[0]) {
125 # Found the line to replace
126 &print_mount_line(@_[1..$#_]);
129 &print_tempfile(FSTAB, $_,"\n");
132 &close_tempfile(FSTAB);
136 # delete_mount(index)
137 # Delete an existing permanent mount
140 local($i, @fstab, $line, $opts, $j, @amd);
144 open(FSTAB, $config{fstab_file});
147 &open_tempfile(FSTAB, "> $config{fstab_file}");
149 chop; ($line = $_) =~ s/#.*$//g;
150 if ($line !~ /\S/ || $i++ != $_[0]) {
151 # Don't delete this line
152 &print_tempfile(FSTAB, $_,"\n");
155 &close_tempfile(FSTAB);
160 # Return a list of all the currently mounted filesystems and swap files.
161 # The list is in the form:
162 # directory device type options
163 # Under FreeBSD, there seems to be no way to get additional mount options
164 # used by filesystems like NFS etc. Even getting the full details of mounted
165 # filesystems requires C code! So we have to call a specially-written external
166 # program to get the mount list
169 # get the list of mounted filesystems
171 local $cmd = $uname_release =~ /^[789]\.[0-9]/ ? "freebsd-mounts-7" :
172 $uname_release =~ /^[56]\.[0-9]/ ? "freebsd-mounts-5" :
173 $uname_release =~ /^4\.[0-9]/ ? "freebsd-mounts-4" :
174 $uname_release =~ /^3\.[1-9]/ ? "freebsd-mounts-3" :
176 &compile_program($cmd, '.*86');
177 open(CMD, "$module_config_directory/$cmd |");
179 local @p = split(/\t/, $_);
180 if ($p[2] eq "procfs" || $p[1] eq "procfs") { $p[1] = $p[2] = "proc"; }
181 elsif ($p[2] eq "mfs") { $p[1] =~ s/:.*$//; }
182 elsif ($p[2] eq "smbfs") {
183 # Need to get nsmb.conf options, covert share and extract user
185 local $noptions = &read_nsmb($p[1]);
187 &parse_options($p[3]);
188 if ($p[1] =~ /^\/\/(\S+)\@(\S+)\/(.*)$/) {
189 $p[1] = "\\\\$2\\$3";
190 $options{'user'} = $1;
192 elsif ($p[1] =~ /\/\/(\S+)\/(.*)$/) {
193 $p[1] = "\\\\$1\\$2";
195 %options = ( %options, %$noptions );
196 $p[3] = &join_options();
202 # add output from swapinfo
204 &execute_command("swapinfo", undef, \$out, undef, 0, 1);
205 foreach (split(/\n/, $out)) {
206 if (/^(\/\S+)\s+\d+\s+\d+/) {
207 push(@rv, [ "swap", $1, "swap", "-" ]);
214 # mount_dir(directory, device, type, options)
215 # Mount a new directory from some device, with some options. Returns 0 if ok,
216 # or an error string if failed
219 local($out, $opts, $shar, %options, %smbopts);
220 if ($_[2] eq "swap") {
221 # Use swapon to add the swap space..
222 $out = &backquote_logged("swapon $_[1] 2>&1");
223 if ($?) { return "<pre>$out</pre>"; }
225 elsif ($_[2] eq "smbfs") {
226 # Need special handling for SMB mounts
228 &parse_options($_[2], $_[3]);
230 if ($options{'user'} && $_[1] =~ /^\\\\(.*)\\(.*)$/) {
231 $share = "//$options{'user'}\@$1/$2";
234 ($share = $_[1]) =~ s/\\/\//g;
236 local $roptions = &update_nsmb($share, \%options);
237 delete($roptions->{'user'});
238 local $opts = &join_options($_[2], $roptions);
239 $opts = $opts ne "-" ? " -o $opts" : "";
240 &foreign_require("proc");
241 local ($fh, $fpid) = &proc::pty_process_exec_logged(
242 "mount -t $_[2] $opts $share $_[0]");
244 local $rv = &wait_for($fh, "Password:");
245 $got .= $wait_for_input;
247 print $fh $options{'nsmb_password'},"\n";
249 $rv = &wait_for($fh);
250 $got .= $wait_for_input;
252 if ($? || $got =~ /failed|error|syserr|usage:/i) { return "<pre>$out</pre>"; }
255 # Can use mount command for this filesystem
256 $opts = $_[3] eq "-" ? "" :
257 "-o ".join(',', grep { !/quota/ } split(/,/, $_[3]));
258 $out = &backquote_logged("mount -t $_[2] $opts $_[1] $_[0] 2>&1");
259 if ($?) { return "<pre>$out</pre>"; }
265 # unmount_dir(directory, device, type)
266 # Unmount a directory that is currently mounted. Returns 0 if ok,
267 # or an error string if failed
270 local($out, %smbopts, $dir);
271 if ($_[2] eq "swap") {
273 &error("Swap space cannot be removed");
276 $out = &backquote_logged("umount $_[0] 2>&1");
277 if ($?) { return "<pre>$out</pre>"; }
284 # Given a filesystem type, returns 4 numbers that determine how the file
285 # system can be mounted, and whether it can be fsck'd
287 # 0 - cannot be permanently recorded
288 # (smbfs under linux)
289 # 1 - can be permanently recorded, and is always mounted at boot
291 # 2 - can be permanently recorded, and may or may not be mounted at boot
292 # (most normal filesystems)
294 # 0 - mount is always permanent => mounted when saved
296 # 1 - doesn't have to be permanent
299 # 0 - cannot be fsck'd at boot time
300 # 1 - can be be fsck'd at boot
302 # 0 - can be unmounted
303 # 1 - cannot be unmounted
307 { return (2, 1, 0, 1); }
308 elsif ($_[0] eq "ufs")
309 { return (2, 1, 1, 0); }
311 { return (2, 1, 0, 0); }
315 # disk_space(type, directory)
316 # Returns the amount of total and free space for some filesystem, or an
317 # empty array if not appropriate.
320 if (&get_mounted($_[1], "*") < 0) { return (); }
321 if ($_[0] eq "proc" || $_[0] eq "swap") { return (); }
323 &execute_command("df -k ".quotemeta($_[1]), undef, \$out, undef, 0, 1);
324 if ($out =~ /Mounted on\n\S+\s+(\S+)\s+\S+\s+(\S+)/) {
334 # Returns an array of all the supported filesystem types. If a filesystem is
335 # found that is not one of the supported types, generate_location() and
336 # generate_options() will not be called for it.
339 local @rv = ("ufs", "nfs", "cd9660", "msdos", "swap");
340 push(@rv, "ext2fs") if (&has_command("mount_ext2fs"));
341 push(@rv, "ntfs") if (&has_command("mount_ntfs"));
342 push(@rv, "smbfs") if ($smbfs_support);
348 # Given a short filesystem type, return a human-readable name for it
352 %fsmap = ("ufs", "FreeBSD Unix Filesystem",
353 "nfs", "Network Filesystem",
354 "cd9660", "ISO9660 CD-ROM",
355 "msdos", "MS-DOS Filesystem",
356 "ext2fs", "Linux Filesystem",
357 "ntfs", "Windows NT Filesystem",
358 "swap", "Virtual Memory",
359 "proc", "Process Image Filesystem",
360 "smbfs", "Windows Networking Filesystem");
361 return $config{long_fstypes} && $fsmap{$_[0]} ? $fsmap{$_[0]} : uc($_[0]);
365 # multiple_mount(type)
366 # Returns 1 if filesystems of this type can be mounted multiple times, 0 if not
369 return $_[0] eq "nfs" || $_[0] eq "smbfs";
373 # generate_location(type, location)
374 # Output HTML for editing the mount location of some filesystem.
375 sub generate_location
377 if ($_[0] eq "nfs") {
378 # NFS mount from some host and directory
379 $_[1] =~ /^([^:]+):(.*)$/;
380 print "<tr> <td><b>NFS Hostname</b></td>\n";
381 print "<td><input name=nfs_host size=20 value=\"$1\">\n";
382 &nfs_server_chooser_button("nfs_host");
384 print "<td><b>NFS Directory</b></td>\n";
385 print "<td><input name=nfs_dir size=20 value=\"$2\">\n";
386 &nfs_export_chooser_button("nfs_host", "nfs_dir");
387 print "</td> </tr>\n";
389 elsif ($_[0] eq "smbfs") {
390 # SMB mount from some server and share
391 $_[1] =~ /^\\\\(.*)\\(.*)$/;
392 print "<tr> <td><b>$text{'linux_smbserver'}</b></td>\n";
393 print "<td><input name=smbfs_server value=\"$1\" size=20>\n";
394 &smb_server_chooser_button("smbfs_server");
396 print "<td><b>$text{'linux_smbshare'}</b></td>\n";
397 print "<td><input name=smbfs_share value=\"$2\" size=20>\n";
398 &smb_share_chooser_button("smbfs_server", "smbfs_share");
399 print "</td> </tr>\n";
402 if ($_[0] eq "swap") {
403 # Swap file or device
404 printf "<tr> <td valign=top><b>Swap File</b></td>\n";
407 # Disk-based filesystem
408 printf "<tr> <td valign=top><b>%s Disk</b></td>\n",
411 print "<td colspan=3>\n";
412 if ($_[1] =~ /^\/dev\/ad(\d)s(\d)([a-z]*)$/) {
413 $disk_dev = 0; $ide_t = $1; $ide_s = $2; $ide_p = $3;
415 elsif ($_[1] =~ /^\/dev\/da(\d)s(\d)([a-z]*)$/) {
416 $disk_dev = 1; $scsi_t = $1; $scsi_s = $2; $scsi_p = $3;
418 else { $disk_dev = 2; }
420 printf "<input type=radio name=disk_dev value=0 %s> IDE Hard Disk:\n",
421 $disk_dev == 0 ? "checked" : "";
422 print "Device <input name=ide_t size=3 value=\"$ide_t\">\n";
423 print "Slice <input name=ide_s size=3 value=\"$ide_s\">\n";
424 print "Partition <input name=ide_p size=3 value=\"$ide_p\"><br>\n";
426 printf "<input type=radio name=disk_dev value=1 %s> SCSI Disk:\n",
427 $disk_dev == 1 ? "checked" : "";
428 print "Device <input name=scsi_t size=3 value=\"$scsi_t\">\n";
429 print "Slice <input name=scsi_s size=3 value=\"$scsi_s\">\n";
430 print "Partition <input name=scsi_p size=3 value=\"$scsi_p\"><br>\n";
432 printf "<input type=radio name=disk_dev value=2 %s> Other Device:\n",
433 $disk_dev == 2 ? "checked" : "";
434 printf "<input size=20 name=dev_path value=\"%s\"><br>\n",
435 $disk_dev == 2 ? $_[1] : "";
436 print "</td> </tr>\n";
441 # generate_options(type, newmount)
442 # Output HTML for editing mount options for a particular filesystem
446 if ($_[0] ne "swap") {
447 # These options are common to all filesystems
448 print "<tr> <td><b>Read-only?</b></td>\n";
449 printf "<td nowrap><input type=radio name=bsd_ro value=1 %s> Yes\n",
450 defined($options{"rdonly"}) || defined($options{"ro"})
452 printf "<input type=radio name=bsd_ro value=0 %s> No</td>\n",
453 defined($options{"rdonly"}) || defined($options{"ro"})
456 print "<td><b>Buffer writes to filesystem?</b></td>\n";
457 printf"<td nowrap><input type=radio name=bsd_sync value=0 %s> Yes\n",
458 defined($options{"sync"}) ? "" : "checked";
459 printf "<input type=radio name=bsd_sync value=1 %s> No</td> </tr>\n",
460 defined($options{"sync"}) ? "checked" : "";
462 print "<tr> <td><b>Allow device files?</b></td>\n";
463 printf "<td nowrap><input type=radio name=bsd_nodev value=0 %s> Yes\n",
464 defined($options{"nodev"}) ? "" : "checked";
465 printf "<input type=radio name=bsd_nodev value=1 %s> No</td>\n",
466 defined($options{"nodev"}) ? "checked" : "";
468 print "<td><b>Allow execution of binaries?</b></td>\n";
469 printf"<td nowrap><input type=radio name=bsd_noexec value=0 %s> Yes\n",
470 defined($options{"noexec"}) ? "" : "checked";
471 printf "<input type=radio name=bsd_noexec value=1 %s> No</td> </tr>\n",
472 defined($options{"noexec"}) ? "checked" : "";
474 print "<tr> <td><b>Disallow setuid programs?</b></td>\n";
475 printf "<td nowrap><input type=radio name=bsd_nosuid value=1 %s> Yes\n",
476 defined($options{"nosuid"}) ? "checked" : "";
477 printf "<input type=radio name=bsd_nosuid value=0 %s> No</td>\n",
478 defined($options{"nosuid"}) ? "" : "checked";
480 print "<td><b>Update access times?</b></td>\n";
481 printf"<td nowrap><input type=radio name=bsd_noatime value=0 %s> Yes\n",
482 defined($options{"noatime"}) ? "" : "checked";
483 printf "<input type=radio name=bsd_noatime value=1 %s> No</td> </tr>\n",
484 defined($options{"noatime"}) ? "checked" : "";
486 if ($uname_release =~ /^[34]\./) {
487 # FreeBSD 3.x has some more options
488 print "<tr> <td><b>Follow symbolic links?</b></td>\n";
489 printf "<td nowrap><input type=radio name=bsd_nosymfollow value=0 %s> Yes\n",
490 defined($options{"nosymfollow"}) ? "" : "checked";
491 printf "<input type=radio name=bsd_nosymfollow value=1 %s> No</td>\n",
492 defined($options{"nosymfollow"}) ? "checked" : "";
494 print "<td><b>Files inherit group from SUID directories?</b></td>\n";
495 printf"<td nowrap><input type=radio name=bsd_suiddir value=1 %s> Yes\n",
496 defined($options{"suiddir"}) ? "checked" : "";
497 printf "<input type=radio name=bsd_suiddir value=0 %s> No</td> </tr>\n",
498 defined($options{"suiddir"}) ? "" : "checked";
502 if ($_[0] eq "ufs") {
503 # UFS filesystems support quotas
504 print "<tr> <td><b>User quotas at boot</b></td> <td colspan=3>\n";
505 printf "<input type=radio name=ufs_userquota value=0 %s> Disabled\n",
506 defined($options{'userquota'}) ? "" : "checked";
507 printf "<input type=radio name=ufs_userquota value=1 %s> Enabled\n",
508 defined($options{'userquota'}) && $options{'userquota'} eq ""
510 printf "<input type=radio name=ufs_userquota value=2 %s>\n",
511 $options{'userquota'} ? "checked" : "";
512 print "Enabled, use file\n";
513 printf "<input name=ufs_userquota_file size=30 value=\"%s\">\n",
514 $options{'userquota'};
515 print "</td> </tr>\n";
517 print "<tr> <td><b>Group quotas at boot</b></td> <td colspan=3>\n";
518 printf "<input type=radio name=ufs_groupquota value=0 %s> Disabled\n",
519 defined($options{'groupquota'}) ? "" : "checked";
520 printf "<input type=radio name=ufs_groupquota value=1 %s> Enabled\n",
521 defined($options{'groupquota'}) && $options{'groupquota'} eq ""
523 printf "<input type=radio name=ufs_groupquota value=2 %s>\n",
524 $options{'groupquota'} ? "checked" : "";
525 print "Enabled, use file\n";
526 printf "<input name=ufs_groupquota_file size=30 value=\"%s\">\n",
527 $options{'groupquota'};
528 print "</td> </tr>\n";
530 elsif ($_[0] eq "nfs") {
531 # NFS filesystems have lots more options
532 print "<tr> <td><b>Retry mounts in background?</b></td>\n";
533 printf "<td nowrap><input type=radio name=nfs_b value=1 %s> Yes\n",
534 defined($options{"-b"}) ? "checked" : "";
535 printf "<input type=radio name=nfs_b value=0 %s> No</td>\n",
536 defined($options{"-b"}) ? "" : "checked";
538 print "<td><b>Return error on timeouts?</b></td>\n";
539 printf "<td nowrap><input type=radio name=nfs_s value=1 %s> Yes\n",
540 defined($options{"-s"}) ? "checked" : "";
541 printf "<input type=radio name=nfs_s value=0 %s> No</td> </tr>\n",
542 defined($options{"-s"}) ? "" : "checked";
544 print "<tr> <td><b>Timeout</b></td>\n";
545 printf "<td nowrap><input type=radio name=nfs_t_def value=1 %s> Default\n",
546 defined($options{"-t"}) ? "" : "checked";
547 printf "<input type=radio name=nfs_t_def value=0 %s>\n",
548 defined($options{"-t"}) ? "checked" : "";
549 printf "<input size=5 name=nfs_t value=\"$options{'-t'}\"></td>\n";
551 print "<td><b>Number of Retransmissions</b></td>\n";
552 printf "<td nowrap><input type=radio name=nfs_x_def value=1 %s> Default\n",
553 defined($options{"-x"}) ? "" : "checked";
554 printf "<input type=radio name=nfs_x_def value=0 %s>\n",
555 defined($options{"-x"}) ? "checked" : "";
556 print "<input size=5 name=nfs_x value=\"$options{'-x'}\"></td> </tr>\n";
558 print "<tr> <td><b>NFS version</b></td> <td nowrap>\n";
559 local $v = defined($options{"-2"}) ? 2 :
560 defined($options{"-3"}) ? 3 : 0;
561 printf "<input type=radio name=nfs_ver value=0 %s> Auto\n",
563 printf "<input type=radio name=nfs_ver value=2 %s> V2\n",
564 $v == 2 ? "checked" : "";
565 printf "<input type=radio name=nfs_ver value=3 %s> V3</td>\n",
566 $v == 3 ? "checked" : "";
568 print "<td><b>Mount retries</b></td>\n";
569 printf "<td nowrap><input type=radio name=nfs_r_def value=1 %s> Default\n",
570 defined($options{"-R"}) ? "" : "checked";
571 printf "<input type=radio name=nfs_r_def value=0 %s>\n",
572 defined($options{"-R"}) ? "checked" : "";
573 print "<input size=5 name=nfs_r value=\"$options{'-R'}\"></td> </tr>\n";
575 print "<tr> <td><b>Read-ahead blocks</b></td>\n";
576 printf "<td nowrap><input type=radio name=nfs_a_def value=1 %s> Default\n",
577 defined($options{"-a"}) ? "" : "checked";
578 printf "<input type=radio name=nfs_a_def value=0 %s>\n",
579 defined($options{"-a"}) ? "checked" : "";
580 print "<input size=5 name=nfs_a value=\"$options{'-a'}\"></td>\n";
582 print "<td><b>RPC Protocol</b></td>\n";
583 printf "<td nowrap><input type=radio name=nfs_t2 value=1 %s> TCP\n",
584 defined($options{"-T"}) ? "checked" : "";
585 printf "<input type=radio name=nfs_t2 value=0 %s> UDP</td> </tr>\n",
586 defined($options{"-T"}) ? "" : "checked";
588 elsif ($_[0] eq "msdos"){
589 # MS-DOS filesystems options deal with filling in
590 # missing unix functionality
591 print "<tr> <td><b>User files are owned by</b></td>\n";
592 printf "<td><input name=msdos_u size=8 value=\"%s\">\n",
593 defined($options{"-u"}) ? getpwuid($options{"-u"}) : "";
594 print &user_chooser_button("msdos_u", 0),"</td>\n";
596 print "<td><b>Group files are owned by</b></td>\n";
597 printf "<td><input name=msdos_g size=8 value=\"%s\">\n",
598 defined($options{"-g"}) ? getgrgid($options{"-g"}) : "";
599 print &group_chooser_button("msdos_g", 0),"</td>\n";
601 print "<tr> <td><b>File permissions mask</b></td>\n";
602 printf "<td><input type=radio name=msdos_m_def value=1 %s> Default\n",
603 defined($options{"-m"}) ? "" : "checked";
604 printf "<input type=radio name=msdos_m_def value=0 %s>\n",
605 defined($options{"-m"}) ? "checked" : "";
606 print "<input size=5 name=msdos_m value=\"$options{'-m'}\"></td>\n";
608 elsif ($_[0] eq "cd9660") {
610 print "<tr> <td><b>Ignore Unix Attributes?</b></td>\n";
611 printf "<td><input type=radio name=cd9660_r value=1 %s> Yes\n",
612 defined($options{"-r"}) ? "checked" : "";
613 printf "<input type=radio name=cd9660_r value=0 %s> No</td>\n",
614 defined($options{"-r"}) ? "" : "checked";
616 print "<td><b>Show version numbers?</b></td>\n";
617 printf "<td><input type=radio name=cd9660_g value=1 %s> Yes\n",
618 defined($options{"-g"}) ? "checked" : "";
619 printf "<input type=radio name=cd9660_g value=0 %s> No</td> </tr>\n",
620 defined($options{"-g"}) ? "" : "checked";
622 print "<tr> <td><b>Use extended attributes?</b></td>\n";
623 printf "<td><input type=radio name=cd9660_e value=1 %s> Yes\n",
624 defined($options{"-e"}) ? "checked" : "";
625 printf "<input type=radio name=cd9660_e value=0 %s> No</td> </tr>\n",
626 defined($options{"-e"}) ? "" : "checked";
628 elsif ($_[0] eq "ntfs") {
629 # Windows NT filesystem
630 print "<tr> <td><b>Display MSDOS 8.3 filenames?</b></td>\n";
631 printf "<td><input type=radio name=ntfs_a value=1 %s> Yes\n",
632 defined($options{"-a"}) ? "checked" : "";
633 printf "<input type=radio name=ntfs_a value=0 %s> No</td>\n",
634 defined($options{"-a"}) ? "" : "checked";
636 print "<td><b>Case sensitive filenames?</b></td>\n";
637 printf "<td><input type=radio name=ntfs_i value=0 %s> Yes\n",
638 defined($options{"-i"}) ? "" : "checked";
639 printf "<input type=radio name=ntfs_i value=1 %s> No</td> </tr>\n",
640 defined($options{"-i"}) ? "checked" : "";
642 print "<tr> <td><b>User files are owned by</b></td>\n";
643 printf "<td><input type=radio name=ntfs_u_def value=1 %s> Default\n",
644 defined($options{"-u"}) ? "" : "checked";
645 printf "<input type=radio name=ntfs_u_def value=0 %s>\n",
646 defined($options{"-u"}) ? "checked" : "";
647 printf "<input name=ntfs_u size=8 value='%s'> %s</td>\n",
648 defined($options{"-u"}) ? scalar(getpwuid($options{"-u"})) : "",
649 &user_chooser_button("ntfs_u");
651 print "<td><b>Group files are owned by</b></td>\n";
652 printf "<td><input type=radio name=ntfs_g_def value=1 %s> Default\n",
653 defined($options{"-u"}) ? "" : "checked";
654 printf "<input type=radio name=ntfs_g_def value=0 %s>\n",
655 defined($options{"-u"}) ? "checked" : "";
656 printf "<input name=ntfs_g size=8 value='%s'> %s</td> </tr>\n",
657 defined($options{"-g"}) ? scalar(getgrgid($options{"-g"})) : "",
658 &group_chooser_button("ntfs_g");
660 elsif ($_[0] eq "swap") {
661 # Swap has no options..
662 print "<tr> <td><i>No Options Available</i></td> </tr>\n";
664 elsif ($_[0] eq "smbfs") {
665 # SMBFS has some special options
666 print "<tr> <td><b>$text{'linux_username'}</b></td>\n";
667 printf "<td><input name=smbfs_user size=15 value=\"%s\"></td>\n",
670 print "<td><b>$text{'linux_password'}</b></td>\n";
671 printf "<td><input type=password name=smbfs_password size=15 value=\"%s\"></td> </tr>\n",
672 $options{"nsmb_password"};
674 print "<tr> <td><b>$text{'linux_wg'}</b></td>\n";
675 printf "<td colspan=3><input type=radio name=smbfs_workgroup_def value=1 %s> $text{'linux_auto'}\n",
676 defined($options{"nsmb_workgroup"}) ? "" : "checked";
677 printf "<input type=radio name=smbfs_workgroup_def value=0 %s>\n",
678 defined($options{"nsmb_workgroup"}) ? "checked" : "";
679 print "<input size=10 name=smbfs_workgroup value=\"$options{'nsmb_workgroup'}\"></td> </tr>\n";
681 print "<tr> <td><b>$text{'linux_mname'}</b></td>\n";
682 printf "<td colspan=3><input type=radio name=smbfs_addr_def value=1 %s> %s\n",
683 defined($options{"nsmb_addr"}) ? "" : "checked", $text{'linux_auto'};
684 printf "<input type=radio name=smbfs_addr_def value=0 %s>\n",
685 defined($options{"nsmb_addr"}) ? "checked" : "";
686 print "<input size=30 name=smbfs_addr value=\"$options{'nsmb_addr'}\"></td> </tr>\n";
691 # check_location(type)
692 # Parse and check inputs from %in, calling &error() if something is wrong.
693 # Returns the location string for storing in the fstab file
696 if ($_[0] eq "nfs") {
697 local($out, $temp, $mout, $dirlist);
699 # Use ping and showmount to see if the host exists and is up
700 if ($in{nfs_host} !~ /^\S+$/) {
701 &error("'$in{nfs_host}' is not a valid hostname");
703 &execute_command("ping -c 1 '$in{nfs_host}'", undef, \$out, \$out);
704 if ($out =~ /unknown host/i) {
705 &error("The host '$in{nfs_host}' does not exist");
707 elsif ($out =~ /100\% packet loss/) {
708 &error("The host '$in{nfs_host}' is down");
710 &execute_command("showmount -e '$in{nfs_host}'", undef, \$out, \$out);
711 if ($out =~ /Unable to receive/) {
712 &error("The host '$in{nfs_host}' does not support NFS");
715 &error("Failed to get mount list : $out");
718 # Validate directory name
719 foreach (split(/\n/, $out)) {
720 if (/^(\/\S+)/) { $dirlist .= "$1\n"; }
722 if ($in{nfs_dir} !~ /^\/\S+$/) {
723 &error("'$in{nfs_dir}' is not a valid directory name. The ".
724 "available directories on $in{nfs_host} are:".
725 "<pre>$dirlist</pre>");
728 # Try a test mount to see if filesystem is available
729 $temp = &transname();
730 &make_dir($temp, 0755);
731 &execute_command("mount $in{nfs_host}:$in{nfs_dir} $temp",
732 undef, \$mout, \$mout);
733 if ($mout =~ /No such file or directory/) {
734 &error("The directory '$in{nfs_dir}' does not exist on the ".
735 "host $in{nfs_host}. The available directories are:".
736 "<pre>$dirlist</pre>");
738 elsif ($mout =~ /Permission denied/) {
739 &error("This host is not allowed to mount the directory ".
740 "$in{nfs_dir} from $in{nfs_host}");
743 &error("NFS Error - $mout");
746 &execute_command("umount $temp");
748 return "$in{nfs_host}:$in{nfs_dir}";
750 elsif ($_[0] eq "smbfs") {
751 # A windows server filesystem .. check the server and share
752 $in{'smbfs_server'} =~ /\S/ || &error($text{'linux_eserver'});
753 $in{'smbfs_share'} =~ /\S/ || &error($text{'linux_eshare'});
754 return "\\\\".lc($in{'smbfs_server'})."\\".lc($in{'smbfs_share'});
757 # This is some kind of disk-based filesystem.. get the device name
758 if ($in{'disk_dev'} == 0) {
759 $in{'ide_t'} =~ /^\d+$/ ||
760 &error("'$in{ide_t}' is not a valid device number");
761 $in{'ide_s'} =~ /^\d+$/ ||
762 &error("'$in{ide_s}' is not a valid slice number");
763 $in{'ide_p'} =~ /^[a-z]*$/ ||
764 &error("'$in{ide_p}' is not a valid partition letter");
765 $dv = "/dev/ad$in{ide_t}s$in{ide_s}$in{ide_p}";
767 elsif ($in{'disk_dev'} == 1) {
768 $in{'scsi_t'} =~ /^\d+$/ ||
769 &error("'$in{scsi_t}' is not a valid device number");
770 $in{'scsi_s'} =~ /^\d+$/ ||
771 &error("'$in{scsi_s}' is not a valid slice number");
772 $in{'scsi_p'} =~ /^[a-z]*$/ ||
773 &error("'$in{scsi_p}' is not a valid partition letter");
774 $dv = "/dev/da$in{scsi_t}s$in{scsi_s}$in{scsi_p}";
777 $dv = $in{'dev_path'};
780 # If the device entered is a symlink, follow it
781 if ($dvlink = readlink($dv)) {
782 if ($dvlink =~ /^\//) { $dv = $dvlink; }
783 else { $dv =~ /^(.*\/)[^\/]+$/;
788 # Check if the device actually exists and uses the right filesystem
789 (-r $dv) || &error("The device file '$dv' does not exist");
794 # check_options(type, device, directory)
795 # Read options for some filesystem from %in, and use them to update the
796 # %options array. Options handled by the user interface will be set or
797 # removed, while unknown options will be left untouched.
802 # Parse the common options first..
803 if ($_[0] ne "swap") {
804 delete($options{"ro"}); delete($options{"rw"});
805 delete($options{"rdonly"});
806 if ($in{'bsd_ro'}) { $options{'ro'} = ''; }
807 else { $options{'rw'} = ""; }
809 delete($options{"sync"}); delete($options{"async"});
810 if ($in{'bsd_sync'}) { $options{'sync'} = ''; }
812 delete($options{'nodev'});
813 if ($in{'bsd_nodev'}) { $options{'nodev'} = ''; }
815 delete($options{'noexec'});
816 if ($in{'bsd_noexec'}) { $options{'noexec'} = ''; }
818 delete($options{'nosuid'});
819 if ($in{'bsd_nosuid'}) { $options{'nosuid'} = ''; }
821 delete($options{'noatime'});
822 if ($in{'bsd_noatime'}) { $options{'noatime'} = ''; }
824 if ($uname_release =~ /^[34]\./) {
825 delete($options{'nosymfollow'});
826 $options{'nosymfollow'} = '' if ($in{'bsd_nosymfollow'});
828 delete($options{'suiddir'});
829 $options{'suiddir'} = '' if ($in{'bsd_suiddir'});
833 # Swap always has the sw option
837 if ($_[0] eq "ufs") {
838 # Parse UFS quota options
839 delete($options{'userquota'}) if ($in{'ufs_userquota'} == 0);
840 $options{'userquota'} = "" if ($in{'ufs_userquota'} == 1);
841 $options{'userquota'} = $in{'ufs_groupquota_file'}
842 if ($in{'ufs_userquota'} == 2);
844 delete($options{'groupquota'}) if ($in{'ufs_groupquota'} == 0);
845 $options{'groupquota'} = "" if ($in{'ufs_groupquota'} == 1);
846 $options{'groupquota'} = $in{'ufs_groupquota_file'}
847 if ($in{'ufs_groupquota'} == 2);
849 elsif ($_[0] eq "nfs") {
850 # NFS has a few specific options..
851 delete($options{'-b'});
852 $options{'-b'} = "" if ($in{'nfs_b'});
854 delete($options{'-s'});
855 $options{'-s'} = "" if ($in{'nfs_s'});
857 delete($options{'-t'});
858 $options{'-t'} = $in{'nfs_t'} if (!$in{'nfs_t_def'});
860 delete($options{'-x'});
861 $options{'-x'} = $in{'nfs_x'} if (!$in{'nfs_x_def'});
863 delete($options{'-2'}); delete($options{'-3'});
864 $options{'-2'} = "" if ($in{'nfs_ver'} == 2);
865 $options{'-3'} = "" if ($in{'nfs_ver'} == 3);
867 delete($options{'-R'});
868 $options{'-R'} = $in{'nfs_r'} if (!$in{'nfs_r_def'});
870 delete($options{'-a'});
871 $options{'-a'} = $in{'nfs_a'} if (!$in{'nfs_a_def'});
873 delete($options{'-T'});
874 $options{'-T'} = "" if ($in{'nfs_t2'});
876 elsif ($_[0] eq "msdos") {
877 # MSDOS options for file ownership/perms
878 delete($options{"-u"}); delete($options{"-g"});
879 if ($in{'msdos_u'} ne "") { $options{'-u'} = getpwnam($in{'msdos_u'}); }
880 if ($in{'msdos_g'} ne "") { $options{'-g'} = getgrnam($in{'msdos_g'}); }
882 delete($options{"-m"});
883 if (!$in{'msdos_m_def'}) {
884 $in{'msdos_m'} =~ /^[0-7]{3}$/ ||
885 &error("'$in{'msdos_m'}' is not a valid octal mask");
886 $options{'-m'} = $in{'msdos_m'};
889 elsif ($_[0] eq "cd9660") {
890 # Options for iso9660 cd-roms
891 delete($options{'-r'});
892 $options{'-r'} = "" if ($in{'cd9660_r'});
894 delete($options{'-g'});
895 $options{'-g'} = "" if ($in{'cd9660_g'});
897 delete($options{'-e'});
898 $options{'-e'} = "" if ($in{'cd9660_e'});
900 elsif ($_[0] eq "ntfs") {
901 delete($options{"-u"}); delete($options{"-g"});
902 if ($in{'ntfs_u'} ne "") { $options{'-u'} = getpwnam($in{'ntfs_u'}); }
903 if ($in{'ntfs_g'} ne "") { $options{'-g'} = getgrnam($in{'ntfs_g'}); }
905 delete($options{"-a"});
906 $options{"-a"} = '' if ($in{'ntfs_a'});
908 delete($options{"-i"});
909 $options{"-i"} = '' if ($in{'ntfs_i'});
911 elsif ($_[0] eq "smbfs") {
912 # Parse SMBFS options
913 delete($options{'user'});
914 $options{'user'} = $in{'smbfs_user'} if ($in{'smbfs_user'});
916 delete($options{'nsmb_password'});
917 $options{'nsmb_password'} = $in{'smbfs_password'}
918 if ($in{'smbfs_password'});
920 delete($options{'nsmb_addr'});
921 if (!$in{"smbfs_addr_def"}) {
922 &check_ipaddress($in{"smbfs_addr"}) ||
923 &error($text{'freebsd_eaddr'});
924 $options{'nsmb_addr'} = $in{"smbfs_addr"};
927 delete($options{'nsmb_workgroup'});
928 if (!$in{"smbfs_workgroup_def"}) {
929 $in{"smbfs_workgroup"} =~ /^\S+$/ ||
930 &error($text{'freebsd_eworkgroup'});
931 $options{'nsmb_workgroup'} = $in{"smbfs_workgroup"};
935 # Return options string
936 return &join_options();
939 # create_swap(file, size, units)
940 # Calls dd and mkswap to setup a swap file
944 $bl = $_[1] * ($_[2] eq "g" ? 1024*1024 :
945 $_[2] eq "m" ? 1024 : 1);
946 $out = &backquote_logged("dd if=/dev/zero of=$_[0] bs=1024 count=$bl 2>&1");
947 if ($?) { return "dd failed : $out"; }
948 $out = &backquote_logged("mkswap $_[0] $bl 2>&1");
949 if ($?) { return "mkswap failed : $out"; }
950 &system_logged("sync >/dev/null 2>&1");
954 # exports_list(host, dirarray, clientarray)
955 # Fills the directory and client array references with exports from some
956 # host. Returns an error string if something went wrong
959 local($dref, $cref, $out, $_);
960 $dref = $_[1]; $cref = $_[2];
961 &execute_command("showmount -e ".quotemeta($_[0]), undef, \$out, \$out, 0, 1);
962 if ($?) { return $out; }
963 foreach (split(/\n/, $out)) {
964 if (/^(\/\S*)\s+(.*)$/) {
965 push(@$dref, $1); push(@$cref, $2);
972 # Returns a useable broadcast address for finding NFS servers
976 &execute_command("ifconfig -a", undef, \$out, \$out, 0, 1);
977 if ($out =~ /broadcast\s+(\S+)\s+/) { return $1; }
978 return "255.255.255.255";
988 return ( $config{'fstab_file'}, $nsmb_conf );
991 # get_nsmb_conf(server, share, user)
992 # Finds a single nsmb.conf section
996 local $insection = 0;
998 open(CONF, $nsmb_conf);
1002 if (/^\s*\[([^:]+):([^:]+):([^:]+)\]/ &&
1003 lc($1) eq lc($_[0]) && lc($2) eq lc($_[2]) && lc($3) eq lc($_[1])) {
1006 $conf = { 'line' => $lnum,
1008 'server' => lc($_[0]),
1009 'user' => lc($_[2]),
1010 'share' => lc($_[1]) };
1012 elsif (/^\s*\[.*\]/) {
1013 # Start of another section
1016 elsif (/^\s*(\S+)\s*=\s*(\S+)/ && $insection) {
1017 $conf->{'values'}->{lc($1)} = $2;
1018 $conf->{'eline'} = $lnum;
1026 # save_nsmb_conf(&conf)
1027 # Updates or creates a single nsmb.conf section
1030 local $lref = &read_file_lines($nsmb_conf);
1031 local @lines = ( "[$_[0]->{'server'}:$_[0]->{'user'}:$_[0]->{'share'}]" );
1032 foreach $k (keys %{$_[0]->{'values'}}) {
1033 push(@lines, $k."=".$_[0]->{'values'}->{$k});
1035 if (defined($_[0]->{'line'})) {
1037 splice(@$lref, $_[0]->{'line'}, $_[0]->{'eline'} - $_[0]->{'line'} + 1,
1042 push(@$lref, @lines);
1044 &flush_file_lines();
1047 # update_nsmb(share, &options)
1050 local ($server, $share, $user);
1051 if ($_[0] =~ /^[\\\/]{2}(\S+)\@(\S+)[\\\/](\S+)$/) {
1052 ($user, $server, $share) = ($1, $2, $3);
1054 elsif ($_[0] =~ /^[\\\/]{2}(\S+)[\\\/](\S+)$/) {
1055 ($user, $server, $share) = ("root", $1, $2);
1058 &error("Invalid share $_[0]");
1060 local $conf = &get_nsmb_conf($server, $share, $user);
1061 $conf ||= { "server" => $server,
1064 $conf->{'values'} = { };
1066 foreach $k (keys %{$_[1]}) {
1067 if ($k =~ /^nsmb_(.*)$/) {
1068 $conf->{'values'}->{$1} = $_[1]->{$k};
1071 $others{$k} = $_[1]->{$k};
1074 &save_nsmb_conf($conf);
1079 # Returns a hash reference containing options for some share
1082 local ($server, $share, $user);
1083 if ($_[0] =~ /^[\\\/]{2}(\S+)\@(\S+)[\\\/](\S+)$/) {
1084 ($user, $server, $share) = ($1, $2, $3);
1086 elsif ($_[0] =~ /^[\\\/]{2}(\S+)[\\\/](\S+)$/) {
1087 ($user, $server, $share) = ("root", $1, $2);
1090 &error("Invalid share $_[0]");
1092 local $conf = &get_nsmb_conf($server, $share, $user);
1095 foreach $k (keys %{$conf->{'values'}}) {
1096 $rv{"nsmb_".$k} = $conf->{'values'}->{$k};