Handle hostnames with upper-case letters
[webmin.git] / mount / osf1-lib.pl
1 # osf1-lib.pl
2 # Filesystem functions for OSF1
3
4 # Return information about a filesystem, in the form:
5 #  directory, device, type, options, fsck_order, mount_at_boot
6 # If a field is unused or ignored, a - appears instead of the value.
7 # Swap-filesystems (devices or files mounted for VM) have a type of 'swap',
8 # and 'swap' in the directory field
9 sub list_mounts
10 {
11 local(@rv, @p, $_, $i); $i = 0;
12
13 # List normal filesystem mounts
14 open(FSTAB, $config{fstab_file});
15 while(<FSTAB>) {
16         chop; s/^#.*$//g;
17         if (!/\S/) { next; }
18         @p = split(/\s+/, $_);
19         if ($p[3] eq "swap") { $p[2] = "swap"; }
20         $rv[$i++] = [ $p[1], $p[0], $p[2], $p[3], $p[5], 1 ];
21         }
22 close(FSTAB);
23
24 return @rv;
25 }
26
27
28 # create_mount(directory, device, type, options, fsck_order, mount_at_boot)
29 # Add a new entry to the fstab file, and return the index of the new entry
30 sub create_mount
31 {
32 local($len, @mlist, $fcsk, $dir);
33 if ($_[2] eq "autofs") {
34         # An autofs mount.. add to /etc/auto_master
35         $len = grep { $_->[2] eq "autofs" } (&list_mounts());
36         &open_tempfile(AUTOTAB, ">> $config{autofs_file}");
37         &print_tempfile(AUTOTAB, "$_[0] $_[1]",($_[3] eq "-" ? "" : " -$_[3]"),"\n");
38         &close_tempfile(AUTOTAB);
39         }
40 else {
41         # Add to the fstab file
42         $len = grep { $_->[2] ne "autofs" } (&list_mounts());
43         &open_tempfile(FSTAB, ">> $config{fstab_file}");
44         if ($_[2] eq "ufs" || $_[2] eq "s5fs") {
45                 ($fsck = $_[1]) =~ s/\/dsk\//\/rdsk\//g;
46                 }
47         else { $fsck = "-"; }
48         if ($_[2] eq "swap") { $dir = "-"; }
49         else { $dir = $_[0]; }
50         &print_tempfile(FSTAB, "$_[1]  $fsck  $dir  $_[2]  $_[4]  $_[5]  $_[3]\n");
51         &close_tempfile(FSTAB);
52         }
53 return $len;
54 }
55
56
57 # delete_mount(index)
58 # Delete some mount from the table
59 sub delete_mount
60 {
61 local(@fstab, $i, $line, $_);
62 open(FSTAB, $config{fstab_file});
63 @fstab = <FSTAB>;
64 close(FSTAB);
65 $i = 0;
66
67 &open_tempfile(FSTAB, "> $config{fstab_file}");
68 foreach (@fstab) {
69         chop; ($line = $_) =~ s/#.*$//g;
70         if ($line =~ /\S/ && $i++ == $_[0]) {
71                 # found the line not to include
72                 }
73         else { &print_tempfile(FSTAB, $_,"\n"); }
74         }
75 close(FSTAB);
76
77 open(AUTOTAB, $config{autofs_file});
78 @autotab = <AUTOTAB>;
79 close(AUTOTAB);
80 &open_tempfile(AUTOTAB, "> $config{autofs_file}");
81 foreach (@autotab) {
82         chop; ($line = $_) =~ s/#.*$//g;
83         if ($line =~ /\S/ && $line !~ /^[+\-]/ && $i++ == $_[0]) {
84                 # found line not to include..
85                 }
86         else { &print_tempfile(AUTOTAB, $_,"\n"); }
87         }
88 &close_tempfile(AUTOTAB);
89 }
90
91
92 # change_mount(num, directory, device, type, options, fsck_order, mount_at_boot)
93 # Change an existing permanent mount
94 sub change_mount
95 {
96 local(@fstab, @autotab, $i, $line, $fsck, $dir, $_);
97 $i = 0;
98
99 open(FSTAB, $config{fstab_file});
100 @fstab = <FSTAB>;
101 close(FSTAB);
102 &open_tempfile(FSTAB, "> $config{fstab_file}");
103 foreach (@fstab) {
104         chop; ($line = $_) =~ s/#.*$//g;
105         if ($line =~ /\S/ && $i++ == $_[0]) {
106                 # Found the line to replace
107                 if ($_[3] eq "ufs" || $_[3] eq "s5fs") {
108                         ($fsck = $_[2]) =~ s/\/dsk\//\/rdsk\//g;
109                         }
110                 else { $fsck = "-"; }
111                 if ($_[3] eq "swap") { $dir = "-"; }
112                 else { $dir = $_[1]; }
113                 &print_tempfile(FSTAB, "$_[2]  $fsck  $dir  $_[3]  $_[5]  $_[6]  $_[4]\n");
114                 }
115         else { &print_tempfile(FSTAB, $_,"\n"); }
116         }
117 close(FSTAB);
118
119 open(AUTOTAB, $config{autofs_file});
120 @autotab = <AUTOTAB>;
121 close(AUTOTAB);
122 &open_tempfile(AUTOTAB, "> $config{autofs_file}");
123 foreach (@autotab) {
124         chop; ($line = $_) =~ s/#.*$//g;
125         if ($line =~ /\S/ && $line !~ /^[+\-]/ && $i++ == $_[0]) {
126                 # Found the line to replace
127                 &print_tempfile(AUTOTAB, "$_[1]  $_[2]  ",
128                                 ($_[4] eq "-" ? "" : "-$_[4]"),"\n");
129                 }
130         else { &print_tempfile(AUTOTAB, $_,"\n"); }
131         }
132 &close_tempfile(AUTOTAB);
133 }
134
135
136 # list_mounted()
137 # Return a list of all the currently mounted filesystems and swap files.
138 # The list is in the form:
139 #  directory device type options
140 # For swap files, the directory will be 'swap'
141 sub list_mounted
142 {
143 local(@rv, @p, $_, $i, $r);
144 &open_execute_command(MOUNT, "/usr/sbin/mount", 1, 1);
145 while(<MOUNT>) {
146         if (/^(\S+)\s+on\s+(\S+)\s+type\s+(\S+)\s+\((.*)\)/) {
147                 local $opts = $3;
148                 $opts =~ s/\s+//g;
149                 push(@rv, [ $2, $1, $3, $opts ]);
150                 }
151         }
152 close(MOUNT);
153 return @rv;
154 }
155
156
157 # mount_dir(directory, device, type, options)
158 # Mount a new directory from some device, with some options. Returns 0 if ok,
159 # or an error string if failed. If the directory is 'swap', then mount as
160 # virtual memory.
161 sub mount_dir
162 {
163 local($out, $opts);
164 if ($_[0] eq "swap") {
165         # Adding a swap device
166         $out = &backquote_logged("swap -a $_[1] 2>&1");
167         if ($?) { return $out; }
168         }
169 else {
170         # Mounting a directory
171         if ($_[2] eq "cachefs") {
172                 # Mounting a caching filesystem.. need to create cache first
173                 local(%options);
174                 &parse_options("cachefs", $_[3]);
175                 if (!(-r "$options{cachedir}/.cfs_resource")) {
176                         # The cache directory does not exist.. set it up
177                         if (-d $options{cachedir} &&
178                             !rmdir($options{"cachedir"})) {
179                                 return "The directory $options{cachedir} ".
180                                        "already exists. Delete it";
181                                 }
182                         $out = &backquote_logged("cfsadmin -c $options{cachedir} 2>&1");
183                         if ($?) { return $out; }
184                         }
185                 }
186         if ($_[2] eq "rumba") {
187                 # call 'rumba' to mount
188                 local(%options, $shortname, $shar, $opts, $rv);
189                 &parse_options("rumba", $_[3]);
190                 $shortname = hostname();
191                 if ($shortname =~ /^([^\.]+)\.(.+)$/) { $shortname = $1; }
192                 $_[1] =~ /^\\\\(.+)\\(.+)$/;
193                 $shar = "//".($options{machinename} ?$options{machinename} :$1).
194                         "/$2";
195                 $opts = ("-s $1 ").
196                  (defined($options{'clientname'}) ?
197                         "-c $options{'clientname'} " : "-c $shortname ").
198                  (defined($options{'username'}) ?
199                         "-U $options{'username'} " : "").
200                  (defined($options{'uid'}) ? "-u $options{'uid'} " : "").
201                  (defined($options{'gid'}) ? "-g $options{'gid'} " : "").
202                  (defined($options{'fmode'}) ? "-f $options{'fmode'} " : "").
203                  (defined($options{'dmode'}) ? "-d $options{'dmode'} " : "").
204                  (defined($options{'noupper'}) ? "-C " : "").
205                  (defined($options{'password'}) ?
206                         "-P $options{'password'} " : "-n ").
207                  (defined($options{'readwrite'}) ? "-S " : "").
208                  (defined($options{'readonly'}) ? "-w " : "").
209                  (defined($options{'attr'}) ? "-e " : "");
210                 local $rtemp = &transname();
211                 $rv = &system_logged("rumba \"$shar\" $_[0] $opts >$rtemp 2>&1 </dev/null");
212                 $out = `cat $rtemp`; unlink($rtemp);
213                 if ($rv) { return "<pre>$out</pre> : rumba \"$shar\" $_[0] $opts"; }
214                 }
215         else {
216                 $opts = $_[3] eq "-" ? "" : "-o \"$_[3]\"";
217                 $out = &backquote_logged("mount -F $_[2] $opts -- $_[1] $_[0] 2>&1");
218                 if ($?) { return $out; }
219                 }
220         }
221 return 0;
222 }
223
224
225 # unmount_dir(directory, device, type)
226 # Unmount a directory (or swap device) that is currently mounted. Returns 0 if
227 # ok, or an error string if failed
228 sub unmount_dir
229 {
230 if ($_[0] eq "swap") {
231         $out = &backquote_logged("swap -d $_[1] 2>&1");
232         }
233 elsif ($_[2] eq "rumba") {
234         # kill the process (if nobody is in the directory)
235         $dir = $_[0];
236         if (&backquote_command("fuser -c $_[0] 2>/dev/null", 1) =~ /\d/) {
237                 return "$_[0] is busy";
238                 }
239         if (&backquote_command("cat /etc/mnttab", 1) =~
240             /rumba-(\d+)\s+$dir\s+nfs/) {
241                 &kill_logged('TERM', $1) || return "Failed to kill rumba";
242                 }
243         else {
244                 return "Failed to find rumba pid";
245                 }
246         sleep(1);
247         }
248 else {
249         $out = &backquote_logged("umount $_[0] 2>&1");
250         }
251 if ($?) { return $out; }
252 return 0;
253 }
254
255
256 # disk_space(type, directory)
257 # Returns the amount of total and free space for some filesystem, or an
258 # empty array if not appropriate.
259 sub disk_space
260 {
261 if (&get_mounted($_[1], "*") < 0) { return (); }
262 if ($_[0] eq "fd" || $_[0] eq "proc" || $_[0] eq "swap" || $_[0] eq "autofs") {
263         return ();
264         }
265 if (&backquote_command("df -k ".quotemeta($_[1]), 1) =~
266     /Mounted on\n\S+\s+(\S+)\s+\S+\s+(\S+)/) {
267         return ($1, $2);
268         }
269 return ( );
270 }
271
272
273 # list_fstypes()
274 # Returns an array of all the supported filesystem types. If a filesystem is
275 # found that is not one of the supported types, generate_location() and
276 # generate_options() will not be called for it.
277 sub list_fstypes
278 {
279 return ("ufs", "nfs", "advfs");
280 }
281
282
283 # fstype_name(type)
284 # Given a short filesystem type, return a human-readable name for it
285 sub fstype_name
286 {
287 local(%fsmap);
288 %fsmap = ("ufs","OSF Unix Filesystem",
289           "nfs","Network Filesystem",
290           "advfs","Advanced File System",
291           "procfs","Process Image Filesystem");
292 return $config{long_fstypes} && $fsmap{$_[0]} ? $fsmap{$_[0]} : uc($_[0]);
293 }
294
295
296 # mount_modes(type)
297 # Given a filesystem type, returns 4 numbers that determine how the file
298 # system can be mounted, and whether it can be fsck'd
299 sub mount_modes
300 {
301 if ($_[0] eq "ufs" || $_[0] eq "cachefs" || $_[0] eq "s5fs") {
302         return (2, 1, 1, 0);
303         }
304 elsif ($_[0] eq "rumba") { return (0, 1, 0, 0); }
305 else { return (2, 1, 0, 0); }
306 }
307
308
309 # multiple_mount(type)
310 # Returns 1 if filesystems of this type can be mounted multiple times, 0 if not
311 sub multiple_mount
312 {
313 return ($_[0] eq "nfs" || $_[0] eq "tmpfs" || $_[0] eq "cachefs" ||
314         $_[0] eq "autofs" || $_[0] eq "lofs" || $_[0] eq "rumba");
315 }
316
317
318 # generate_location(type, location)
319 # Output HTML for editing the mount location of some filesystem.
320 sub generate_location
321 {
322 if ($_[0] eq "nfs") {
323         # NFS mount from some host and directory
324         if ($_[1] =~ /^nfs:/) { $nfsmode = 2; }
325         elsif (!$_[1] || $_[1] =~ /^([A-z0-9\-\.]+):([^,]+)$/) {
326                 $nfsmode = 0; $nfshost = $1; $nfspath = $2;
327                 }
328         else { $nfsmode = 1; }
329         if ($gconfig{'os_version'} >= 2.6) {
330                 # Solaris 2.6 can list multiple NFS servers in mount
331                 print "<tr> <td><b>NFS Source</b></td>\n";
332                 printf "<td><input type=radio name=nfs_serv value=0 %s>\n",
333                         $nfsmode == 0 ? "checked" : "";
334                 print "<b>NFS Hostname</b></td>\n";
335                 print "<td><input name=nfs_host size=20 value=\"$nfshost\">\n";
336                 &nfs_server_chooser_button("nfs_host");
337                 print "&nbsp;<b>NFS Directory</b>\n";
338                 print "<input name=nfs_dir size=20 value=\"$nfspath\">\n";
339                 &nfs_export_chooser_button("nfs_host", "nfs_dir");
340                 print "</td> </tr>\n";
341
342                 print "<tr> <td></td>\n";
343                 printf "<td><input type=radio name=nfs_serv value=1 %s>\n",
344                         $nfsmode == 1 ? "checked" : "";
345                 print "<b>Multiple NFS Servers</b></td>\n";
346                 printf "<td><input name=nfs_list size=40 value=\"%s\">\n",
347                         $nfsmode == 1 ? $_[1] : "";
348                 print "</td> </tr>\n";
349
350                 if ($gconfig{'os_version'} >= 7) {
351                         print "<tr> <td></td> <td>\n";
352                         printf "<input type=radio name=nfs_serv value=2 %s>\n",
353                                 $nfsmode == 2 ? "checked" : "";
354                         print "<b>WebNFS URL</b></td> <td>\n";
355                         printf "<input name=nfs_url size=40 value=\"%s\">\n",
356                                 $nfsmode == 2 ? $_[1] : "";
357                         print "</td> </tr>\n";
358                         }
359                 }
360         else {
361                 print "<tr> <td><b>NFS Hostname</b></td>\n";
362                 print "<td><input name=nfs_host size=20 value=\"$nfshost\">\n";
363                 &nfs_server_chooser_button("nfs_host");
364                 print "</td>\n";
365                 print "<td><b>NFS Directory</b></td>\n";
366                 print "<td><input name=nfs_dir size=20 value=\"$nfspath\">\n";
367                 &nfs_export_chooser_button("nfs_host", "nfs_dir");
368                 print "</td> </tr>\n";
369                 }
370         }
371 elsif ($_[0] eq "tmpfs") {
372         # Location is irrelevant for tmpfs filesystems
373         }
374 elsif ($_[0] eq "ufs") {
375         # Mounted from a normal disk, raid (MD) device or from
376         # somewhere else
377         print "<tr> <td valign=top><b>UFS Disk</b></td>\n";
378         print "<td colspan=3>\n";
379         if ($_[1] =~ /^\/dev\/dsk\/c([0-9]+)t([0-9]+)d([0-9]+)s([0-9]+)$/) {
380                 $ufs_dev = 0;
381                 $scsi_c = $1; $scsi_t = $2; $scsi_d = $3; $scsi_s = $4;
382                 }
383         elsif ($_[1] eq "") {
384                 $ufs_dev = 0; $scsi_c = $scsi_t = $scsi_s = $scsi_d = 0;
385                 }
386         elsif ($_[1] =~ /^\/dev\/md\/dsk\/d([0-9]+)$/) {
387                 $ufs_dev = 1; $scsi_md = $1;
388                 }
389         else {
390                 $ufs_dev = 2; $scsi_path = $_[1];
391                 }
392         printf "<input type=radio name=ufs_dev value=0 %s> SCSI Disk:\n",
393                 $ufs_dev == 0 ? "checked" : "";
394         print "Controller <input name=ufs_c size=3 value=\"$scsi_c\">\n";
395         print "Target <input name=ufs_t size=3 value=\"$scsi_t\">\n";
396         print "Unit <input name=ufs_d size=3 value=\"$scsi_d\">\n";
397         print "Partition <input name=ufs_s size=3 value=\"$scsi_s\"><br>\n";
398
399         printf "<input type=radio name=ufs_dev value=1 %s> RAID Device:\n",
400                 $ufs_dev == 1 ? "checked" : "";
401         print "Unit <input name=ufs_md size=3 value=\"$scsi_md\"><br>\n";
402
403         printf "<input type=radio name=ufs_dev value=2 %s> Other Device:\n",
404                 $ufs_dev == 2 ? "checked" : "";
405         print "<input name=ufs_path size=20 value=\"$scsi_path\"><br>\n";
406         print "</td> </tr>\n";
407         }
408 elsif ($_[0] eq "swap") {
409         # Swapping to a disk partition or a file
410         print "<tr> <td valign=top><b>Swap File</b></td>\n";
411         print "<td colspan=3>\n";
412         if ($_[1] =~ /^\/dev\/dsk\/c([0-9]+)t([0-9]+)d([0-9]+)s([0-9]+)$/) {
413                 $swap_dev = 0;
414                 $scsi_c = $1; $scsi_t = $2; $scsi_d = $3; $scsi_s = $4;
415                 }
416         elsif ($_[1] eq "") {
417                 $swap_dev = 1; $scsi_path = "";
418                 }
419         else {
420                 $swap_dev = 1; $scsi_path = $_[1];
421                 }
422         printf "<input type=radio name=swap_dev value=0 %s> SCSI Disk:\n",
423                 $swap_dev == 0 ? "checked" : "";
424         print "Controller <input name=swap_c size=3 value=\"$scsi_c\">\n";
425         print "Target <input name=swap_t size=3 value=\"$scsi_t\">\n";
426         print "Unit <input name=swap_d size=3 value=\"$scsi_d\">\n";
427         print "Partition <input name=swap_s size=3 value=\"$scsi_s\"><br>\n";
428
429         printf "<input type=radio name=swap_dev value=1 %s> File:\n",
430                 $swap_dev == 1 ? "checked" : "";
431         print "<input name=swap_path size=20 value=\"$scsi_path\"><br>\n";
432         print "</td> </tr>\n";
433         }
434 elsif ($_[0] eq "hsfs") {
435         # Mounting a SCSI cdrom
436         print "<tr> <td valign=top><b>CDROM Disk</b></td>\n";
437         print "<td colspan=3>\n";
438         if ($_[1] =~ /^\/dev\/dsk\/c([0-9]+)t([0-9]+)d([0-9]+)s([0-9]+)$/) {
439                 $hsfs_dev = 0;
440                 $scsi_c = $1; $scsi_t = $2; $scsi_d = $3; $scsi_s = $4;
441                 }
442         elsif ($_[1] eq "") {
443                 $hsfs_dev = 0;
444                 $scsi_c = 0; $scsi_t = 6; $scsi_d = 0; $scsi_s = 0;
445                 }
446         else {
447                 $hsfs_dev = 1; $scsi_path = $_[1];
448                 }
449         printf "<input type=radio name=hsfs_dev value=0 %s> SCSI Device:\n",
450                 $hsfs_dev == 0 ? "checked" : "";
451         print "Controller <input name=hsfs_c size=3 value=\"$scsi_c\">\n";
452         print "Target <input name=hsfs_t size=3 value=\"$scsi_t\">\n";
453         print "Unit <input name=hsfs_d size=3 value=\"$scsi_d\">\n";
454         print "Partition <input name=hsfs_s size=3 value=\"$scsi_s\"><br>\n";
455
456         printf "<input type=radio name=hsfs_dev value=1 %s> Other Device:\n",
457                 $hsfs_dev == 1 ? "checked" : "";
458         print "<input name=hsfs_path size=20 value=\"$scsi_path\"><br>\n";
459         print "</td> </tr>\n";
460         }
461 elsif ($_[0] eq "pcfs") {
462         # Mounting a SCSI msdos filesystem
463         print "<tr> <td valign=top><b>MS-DOS Disk</b></td>\n";
464         print "<td colspan=3>\n";
465         if ($_[1] =~ /^\/dev\/dsk\/c([0-9]+)t([0-9]+)d([0-9]+)s([0-9]+)$/) {
466                 $pcfs_dev = 0;
467                 $scsi_c = $1; $scsi_t = $2; $scsi_d = $3; $scsi_s = $4;
468                 }
469         elsif ($_[1] eq "") {
470                 $pcfs_dev = 1; $scsi_path = "";
471                 }
472         else {
473                 $pcfs_dev = 1; $scsi_path = $_[1];
474                 }
475         printf "<input type=radio name=pcfs_dev value=0 %s> SCSI Device:\n",
476                 $pcfs_dev == 0 ? "checked" : "";
477         print "Controller <input name=pcfs_c size=3 value=\"$scsi_c\">\n";
478         print "Target <input name=pcfs_t size=3 value=\"$scsi_t\">\n";
479         print "Unit <input name=pcfs_d size=3 value=\"$scsi_d\">\n";
480         print "Partition <input name=pcfs_s size=3 value=\"$scsi_s\"><br>\n";
481
482         printf "<input type=radio name=pcfs_dev value=1 %s> Other Device:\n",
483                 $pcfs_dev == 1 ? "checked" : "";
484         print "<input name=pcfs_path size=20 value=\"$scsi_path\"><br>\n";
485         print "</td> </tr>\n";
486         }
487 elsif ($_[0] eq "lofs") {
488         # Mounting some directory to another location
489         print "<tr> <td><b>Original Directory</b></td>\n";
490         print "<td><input name=lofs_src size=30 value=\"$_[1]\">\n";
491         print &file_chooser_button("lofs_src", 1);
492         print "</td> </tr>\n";
493         }
494 elsif ($_[0] eq "cachefs") {
495         # Mounting a cached filesystem of some type.. need a location for
496         # the source of the mount
497         print "<tr> <td><b>Cache Source</b></td>\n";
498         print "<td><input name=cfs_src size=20 value=\"$_[1]\"></td> </tr>\n";
499         }
500 elsif ($_[0] eq "autofs") {
501         # An automounter entry.. can be -hosts, -xfn or from some mapping
502         print "<tr> <td valign=top><b>Automounter map</b></td>\n";
503         printf "<td><input type=radio name=autofs_type value=0 %s>\n",
504                 $_[1] eq "-hosts" || $_[1] eq "-xfn" ? "" : "checked";
505         printf "Use map <input name=autofs_map size=20 value=\"%s\"><br>\n",
506                 $_[1] eq "-hosts" || $_[1] eq "-xfn" ? "" : $_[1];
507         printf "<input type=radio name=autofs_type value=1 %s>\n",
508                 $_[1] eq "-hosts" ? "checked" : "";
509         print "All NFS exports map<br>\n";
510         printf "<input type=radio name=autofs_type value=2 %s>\n",
511                 $_[1] eq "-xfn" ? "checked" : "";
512         print "Federated  Naming  Service map</td> </tr>\n";
513         }
514 elsif ($_[0] eq "rumba") {
515         # Windows filesystem
516         $_[1] =~ /^\\\\(.*)\\(.*)$/;
517         print "<tr> <td><b>Server Name</b></td>\n";
518         print "<td><input name=rumba_server value=\"$1\" size=20>\n";
519         &smb_server_chooser_button("rumba_server");
520         print "</td>\n";
521         print "<td><b>Share Name</b></td>\n";
522         print "<td><input name=rumba_share value=\"$2\" size=20>\n";
523         &smb_share_chooser_button("rumba_server", "rumba_share");
524         print "</td> </tr>\n";
525         }
526 }
527
528
529 # generate_options(type, newmount)
530 # Output HTML for editing mount options for a partilcar filesystem 
531 # under this OS
532 sub generate_options
533 {
534 if ($_[0] eq "nfs") {
535         # Solaris NFS has many options, not all of which are editable here
536         print "<tr> <td><b>Read-Only?</b></td>\n";
537         printf "<td nowrap><input type=radio name=nfs_ro value=1 %s> Yes\n",
538                 defined($options{"ro"}) ? "checked" : "";
539         printf "<input type=radio name=nfs_ro value=0 %s> No</td>\n",
540                 defined($options{"ro"}) ? "" : "checked";
541
542         print "<td><b>Disallow setuid programs?</b></td>\n";
543         printf "<td nowrap><input type=radio name=nfs_nosuid value=1 %s> Yes\n",
544                 defined($options{"nosuid"}) ? "checked" : "";
545         printf "<input type=radio name=nfs_nosuid value=0 %s> No</td> </tr>\n",
546                 defined($options{"nosuid"}) ? "" : "checked";
547
548         print "<tr> <td><b>Files inherit parent GID?</b></td>\n";
549         printf "<td nowrap><input type=radio name=nfs_grpid value=0 %s> Yes\n",
550                 defined($options{"grpid"}) ? "" : "checked";
551         printf "<input type=radio name=nfs_grpid value=1 %s> No</td>\n",
552                 defined($options{"grpid"}) ? "checked" : "";
553
554         print "<td><b>Return error on timeouts?</b></td>\n";
555         printf "<td nowrap><input type=radio name=nfs_soft value=1 %s> Yes\n",
556                 defined($options{"soft"}) ? "checked" : "";
557         printf "<input type=radio name=nfs_soft value=0 %s> No</td> </tr>\n",
558                 defined($options{"soft"}) ? "" : "checked";
559
560         print "<tr> <td><b>Retry mounts in background?</b></td>\n";
561         printf "<td nowrap><input type=radio name=nfs_bg value=1 %s> Yes\n",
562                 defined($options{"bg"}) ? "checked" : "";
563         printf "<input type=radio name=nfs_bg value=0 %s> No</td>\n",
564                 defined($options{"bg"}) ? "" : "checked";
565
566         print "<td><b>Display quotas?</b></td>\n";
567         printf "<td nowrap><input type=radio name=nfs_quota value=1 %s> Yes\n",
568                 defined($options{"quota"}) ? "checked" : "";
569         printf "<input type=radio name=nfs_quota value=0 %s> No</td> </tr>\n",
570                 defined($options{"quota"}) ? "" : "checked";
571
572         print "<tr> <td><b>Allow user interrupt?</b></td>\n";
573         printf "<td nowrap><input type=radio name=nfs_nointr value=0 %s> Yes\n",
574                 defined($options{"nointr"}) ? "" : "checked";
575         printf "<input type=radio name=nfs_nointr value=1 %s> No</td>\n",
576                 defined($options{"nointr"}) ? "checked" : "";
577
578         print "<td><b>NFS version</b></td>\n";
579         printf "<td nowrap><input type=radio name=nfs_vers_def value=1 %s> Highest\n",
580                 defined($options{"vers"}) ? "" : "checked";
581         printf "<input type=radio name=nfs_vers_def value=0 %s>\n",
582                 defined($options{"vers"}) ? "checked" : "";
583         print "<input size=1 name=nfs_vers value=$options{vers}></td> </tr>\n";
584
585         print "<tr> <td><b>Protocol</b></td>\n";
586         print "<td nowrap><select name=proto>\n";
587         printf "<option value=\"\" %s> Default\n",
588                 defined($options{"proto"}) ? "" : "selected";
589         &open_tempfile(NETCONFIG, "/etc/netconfig");
590         while(<NETCONFIG>) {
591                 if (!/^([A-z0-9\_\-]+)\s/) { next; }
592                 printf "<option value=\"$1\" %s> $1\n",
593                         $options{"proto"} eq $1 ? "selected" : "";
594                 }
595         close(NETCONFIG);
596         print "</select></td>\n";
597
598         print "<td><b>NFS Port</b></td>\n";
599         printf "<td nowrap><input type=radio name=nfs_port_def value=1 %s> Default\n",
600                 defined($options{"port"}) ? "" : "checked";
601         printf "<input type=radio name=nfs_port_def value=0 %s>\n",
602                 defined($options{"port"}) ? "checked" : "";
603         print "<input size=5 name=nfs_port value=$options{port}></td> </tr>\n";
604
605         print "<tr> <td><b>Timeout</b></td>\n";
606         printf "<td nowrap><input type=radio name=nfs_timeo_def value=1 %s> Default\n",
607                 defined($options{"timeo"}) ? "" : "checked";
608         printf "<input type=radio name=nfs_timeo_def value=0 %s>\n",
609                 defined($options{"timeo"}) ? "checked" : "";
610         printf "<input size=5 name=nfs_timeo value=$options{timeo}></td>\n";
611
612         print "<td><b>Number of Retransmissions</b></td>\n";
613         printf "<td nowrap><input type=radio name=nfs_retrans_def value=1 %s> Default\n",
614                 defined($options{"retrans"}) ? "" : "checked";
615         printf "<input type=radio name=nfs_retrans_def value=0 %s>\n",
616                 defined($options{"retrans"}) ? "checked" : "";
617         print "<input size=5 name=nfs_retrans value=$options{retrans}></td> </tr>\n";
618
619         print "<tr> <td><b>Authentication</b></td>\n";
620         $nfs_auth = $options{'sec'} ? $options{'sec'} :
621                     defined($options{"secure"}) ? "dh" :
622                     defined($options{"kerberos"}) ? "krb" : "";
623         print "<td><select name=nfs_auth>\n";
624         printf "<option value=\"\" %s> None\n",
625                 $nfs_auth eq "" ? "selected" : "";
626         printf "<option value=dh %s> DES\n",
627                 $nfs_auth eq "dh" ? "selected" : "";
628         printf "<option value=krb %s> Kerberos\n",
629                 $nfs_auth eq "krb" ? "selected" : "";
630         print "</select></td>\n";
631
632         if ($gconfig{'os_version'} >= 7) {
633                 print "<td><b>WebNFS mount?</b></td> <td>\n";
634                 printf "<input type=radio name=nfs_public value=1 %s> Yes\n",
635                         defined($options{'public'}) ? "checked" : "";
636                 printf "<input type=radio name=nfs_public value=0 %s> No\n",
637                         defined($options{'public'}) ? "" : "checked";
638                 print "</td>\n";
639                 }
640         print "</tr>\n";
641         }
642 if ($_[0] eq "ufs") {
643         # Solaris UFS also has many options, not all of which are here
644         print "<tr> <td><b>Read-Only?</b></td>\n";
645         printf "<td nowrap><input type=radio name=ufs_ro value=1 %s> Yes\n",
646                 defined($options{"ro"}) ? "checked" : "";
647         printf "<input type=radio name=ufs_ro value=0 %s> No</td>\n",
648                 defined($options{"ro"}) ? "" : "checked";
649
650         print "<td><b>Disallow setuid programs?</b></td>\n";
651         printf "<td nowrap><input type=radio name=ufs_nosuid value=1 %s> Yes\n",
652                 defined($options{"nosuid"}) ? "checked" : "";
653         printf "<input type=radio name=ufs_nosuid value=0 %s> No</td> </tr>\n",
654                 defined($options{"nosuid"}) ? "" : "checked";
655
656         print "<tr> <td><b>Allow user interrupt?</b></td>\n";
657         printf "<td nowrap><input type=radio name=ufs_nointr value=0 %s> Yes\n",
658                 defined($options{"nointr"}) ? "" : "checked";
659         printf "<input type=radio name=ufs_nointr value=1 %s> No</td>\n",
660                 defined($options{"nointr"}) ? "checked" : "";
661
662         print "<td><b>Enable quotas at boot time?</b></td>\n";
663         printf "<td nowrap><input type=radio name=ufs_quota value=1 %s> Yes\n",
664                 defined($options{"quota"}) || defined($options{"rq"}) ?
665                         "checked" : "";
666         printf "<input type=radio name=ufs_quota value=0 %s> No</td> </tr>\n",
667                 defined($options{"quota"}) || defined($options{"rq"}) ?
668                         "" : "checked";
669
670         print "<tr> <td><b>Action on error</b></td>\n";
671         print "<td><select name=ufs_onerror>\n";
672         foreach ('panic', 'lock', 'umount', 'repair') {
673                 printf "<option value=\"$_\" %s> $_\n",
674                  $options{onerror} eq $_ ||
675                  !defined($options{onerror}) && $_ eq "panic" ? "selected" : "";
676                 }
677         print "</select></td>\n";
678
679         print "<td><b>Repair Delay</b></td>\n";
680         $options{toosoon} =~ /([0-9]+)([A-z])/;
681         print "<td nowrap><input size=5 name=ufs_toosoon_time value=$1>\n";
682         print "<select name=ufs_toosoon_units>\n";
683         printf "<option value=s %s> Seconds\n", $2 eq "s" ? "selected" : "";
684         printf "<option value=m %s> Minutes\n", $2 eq "m" ? "selected" : "";
685         printf "<option value=h %s> Hours\n", $2 eq "h" ? "selected" : "";
686         printf "<option value=d %s> Days\n", $2 eq "d" ? "selected" : "";
687         printf "<option value=w %s> Months\n", $2 eq "w" ? "selected" : "";
688         printf "<option value=y %s> Years\n", $2 eq "y" ? "selected" : "";
689         print "</select></td> </tr>\n";
690
691         if ($gconfig{'os_version'} >= 7) {
692                 print "<tr> <td><b>Update access times?</b></td> <td>\n";
693                 printf "<input type=radio name=ufs_noatime value=0 %s> Yes\n",
694                         defined($options{'noatime'}) ? "" : "checked";
695                 printf "<input type=radio name=ufs_noatime value=1 %s> No\n",
696                         defined($options{'noatime'}) ? "checked" : "";
697                 print "</td>\n";
698
699                 print "<td><b>Force direct IO?</b></td> <td>\n";
700                 printf "<input type=radio name=ufs_force value=1 %s> Yes\n",
701                         defined($options{'forcedirectio'}) ? "checked" : "";
702                 printf "<input type=radio name=ufs_force value=0 %s> No\n",
703                         defined($options{'forcedirectio'}) ? "" : "checked";
704                 print "</td> </tr>\n";
705
706                 print "<tr> <td><b>Allow large files?</td> <td>\n";
707                 printf "<input type=radio name=ufs_nolarge value=0 %s> Yes\n",
708                         defined($options{'nolargefiles'}) ? "" : "checked";
709                 printf "<input type=radio name=ufs_nolarge value=1 %s> No\n",
710                         defined($options{'nolargefiles'}) ? "checked" : "";
711                 print "</td>\n";
712
713                 print "<td><b>Enabled logging?</td> <td>\n";
714                 printf "<input type=radio name=ufs_logging value=1 %s> Yes\n",
715                         defined($options{'logging'}) ? "checked" : "";
716                 printf "<input type=radio name=ufs_logging value=0 %s> No\n",
717                         defined($options{'logging'}) ? "" : "checked";
718                 print "</td> </tr>\n";
719                 }
720         }
721 if ($_[0] eq "hsfs") {
722         # Solaris hsfs is used for CDROMs
723         print "<tr> <td><b>Ignore Unix attributes?</b></td>\n";
724         printf "<td nowrap><input type=radio name=hsfs_nrr value=1 %s> Yes\n",
725                 defined($options{"nrr"}) ? "checked" : "";
726         printf "<input type=radio name=hsfs_nrr value=0 %s> No</td>\n",
727                 defined($options{"nrr"}) ? "" : "checked";
728
729         print "<td><b>Ignore trailing dot?</b></td>\n";
730         printf "<td nowrap><input type=radio name=hsfs_notraildot value=1 %s> Yes\n",
731                 defined($options{"notraildot"}) ? "checked" : "";
732         printf "<input type=radio name=hsfs_notraildot value=0 %s> No</td> </tr>\n",
733                 defined($options{"notraildot"}) ? "" : "checked";
734
735         print "<tr> <td><b>Use lower case?</b></td>\n";
736         printf "<td nowrap><input type=radio name=hsfs_nomaplcase value=0 %s> Yes\n",
737                 defined($options{"nomaplcase"}) ? "" : "checked";
738         printf "<input type=radio name=hsfs_nomaplcase value=1 %s> No</td>\n",
739                 defined($options{"nomaplcase"}) ? "checked" : "";
740
741         print "<td><b>Disallow setuid programs?</b></td>\n";
742         printf"<td nowrap><input type=radio name=hsfs_nosuid value=1 %s> Yes\n",
743                 defined($options{"nosuid"}) ? "checked" : "";
744         printf "<input type=radio name=hsfs_nosuid value=0 %s> No</td> </tr>\n",
745                 defined($options{"nosuid"}) ? "" : "checked";
746         }
747 if ($_[0] eq "pcfs") {
748         # Solaris pcfs for for FAT filesystems. It doesn't have many options
749         print "<tr> <td width=25%><b>Read Only?</b></td> <td width=25%>\n";
750         printf "<input type=radio name=pcfs_ro value=1 %s> Yes\n",
751                 defined($options{"ro"}) ? "checked" : "";
752         printf "<input type=radio name=pcfs_ro value=0 %s> No</td>\n",
753                 defined($options{"ro"}) ? "" : "checked";
754
755         if ($gconfig{'os_version'} >= 7) {
756                 print "<td><b>Force lower case?</b></td> <td>\n";
757                 printf "<input type=radio name=pcfs_foldcase value=1 %s> Yes\n",
758                         defined($options{'foldcase'}) ? "checked" : "";
759                 printf "<input type=radio name=pcfs_foldcase value=0 %s> No\n",
760                         defined($options{'foldcase'}) ? "" : "checked";
761                 print "</td>\n";
762                 }
763         else {
764                 print "<td colspan=2></td> </tr>\n";
765                 }
766         }
767 if ($_[0] eq "lofs") {
768         # No options as far as I know
769         print "<tr> <td><i>No Options Available</i></td> </tr>\n";
770         }
771 if ($_[0] eq "tmpfs") {
772         # Solaris tmpfs (virtual memory) filesystem. Only one option
773         print "<tr> <td><b>Size</b>&nbsp;&nbsp;&nbsp;</td>\n";
774         printf"<td><input type=radio name=tmpfs_size_def value=1 %s> Maximum\n",
775                 defined($options{"size"}) ? "" : "checked";
776         printf"&nbsp;&nbsp;<input type=radio name=tmpfs_size_def value=0 %s>\n",
777                 defined($options{"size"}) ? "checked" : "";
778         ($tmpsz = $options{size}) =~ s/[A-z]+$//g;
779         print "<input name=tmpfs_size size=6 value=\"$tmpsz\">\n";
780         print "<select name=tmpfs_unit>\n";
781         printf "<option value=m %s> MB\n",
782                 $options{"size"} =~ /m$/ ? "selected" : "";
783         printf "<option value=k %s> kB\n",
784                 $options{"size"} =~ /k$/ ? "selected" : "";
785         printf "<option value=b %s> bytes\n",
786                 $options{"size"} !~ /(k|m)$/ ? "selected" : "";
787         print "</select></td>\n";
788         print "<td colsan=2></td> </tr>\n";
789         }
790 if ($_[0] eq "swap") {
791         # Solaris swap has no options
792         print "<tr> <td><i>No Options Available</i></td> </tr>\n";
793         }
794 if ($_[0] eq "cachefs") {
795         # The caching filesystem has lots of options.. cachefs mounts can
796         # be of an existing 'manually' mounted back filesystem, or of a
797         # back-filesystem that has been automatically mounted by the cache.
798         # The user should never see the automatic mountings made by cachefs.
799         print "<tr> <td><b>Real filesystem type</b></td>\n";
800         print "<td nowrap><select name=cfs_backfstype>\n";
801         if (!defined($options{backfstype})) { $options{backfstype} = "nfs"; }
802         foreach (&list_fstypes()) {
803                 if ($_ eq "cachefs") { next; }
804                 printf "<option value=\"$_\" %s>$_\n",
805                         $_ eq $options{backfstype} ? "selected" : "";
806                 }
807         print "</select></td>\n";
808
809         print "<td><b>Real mount point</b></td>\n";
810         printf"<td nowrap><input type=radio name=cfs_noback value=1 %s> Automatic\n",
811                 defined($options{"backpath"}) ? "" : "checked";
812         printf "<input type=radio name=cfs_noback value=0 %s>\n",
813                 defined($options{"backpath"}) ? "checked" : "";
814         print "<input size=10 name=cfs_backpath value=\"$options{backpath}\"></td> </tr>\n";
815
816         print "<tr> <td><b>Cache directory</b></td>\n";
817         printf "<td nowrap><input size=10 name=cfs_cachedir value=\"%s\"></td>\n",
818                 defined($options{"cachedir"}) ? $options{"cachedir"} : "/cache";
819
820         print "<td><b>Write mode</b></td>\n";
821         printf"<td nowrap><input type=radio name=cfs_wmode value=0 %s> Write-around\n",
822                 defined($options{"non-shared"}) ? "" : "checked";
823         printf "<input type=radio name=cfs_wmode value=1 %s> Non-shared\n",
824                 defined($options{"non-shared"}) ? "checked" : "";
825         print "</td> </tr>\n";
826
827         print "<tr> <td><b>Consistency check</b></td>\n";
828         print "<td><select name=cfs_con>\n";
829         print "<option value=1> Periodically\n";
830         printf "<option value=0 %s> Never\n",
831                 defined($options{"noconst"}) ? "selected" : "";
832         printf "<option value=2 %s> On demand\n",
833                 defined($options{"demandconst"}) ? "selected" : "";
834         print "</select></td>\n";
835
836         print "<td><b>Check permissions in cache?</b></td>\n";
837         printf "<td nowrap><input type=radio name=cfs_local value=1 %s> Yes\n",
838                 defined($options{"local-access"}) ? "checked" : "";
839         printf "<input type=radio name=cfs_local value=0 %s> No</td> </tr>\n",
840                 defined($options{"local-access"}) ? "" : "checked";
841
842         print "<tr> <td><b>Read-Only?</b></td>\n";
843         printf "<td nowrap><input type=radio name=cfs_ro value=1 %s> Yes\n",
844                 defined($options{"ro"}) ? "checked" : "";
845         printf "<input type=radio name=cfs_ro value=0 %s> No</td>\n",
846                 defined($options{"ro"}) ? "" : "checked";
847
848         print "<td><b>Disallow setuid programs?</b></td>\n";
849         printf "<td nowrap><input type=radio name=cfs_nosuid value=1 %s> Yes\n",
850                 defined($options{"nosuid"}) ? "checked" : "";
851         printf "<input type=radio name=cfs_nosuid value=0 %s> No</td> </tr>\n",
852                 defined($options{"nosuid"}) ? "" : "checked";
853         }
854 if ($_[0] eq "autofs") {
855         # Autofs has lots of options, depending on the type of file
856         # system being automounted.. the fstype options determines this
857         local($fstype);
858         $fstype = $options{fstype} eq "" ? "nfs" : $options{fstype};
859         if ($gconfig{'os_version'} >= 2.6) {
860                 print "<tr> <td><b>Browsing enabled?</b></td> <td>\n";
861                 printf "<input type=radio name=auto_nobrowse value=0 %s> Yes\n",
862                         defined($options{'nobrowse'}) ? "" : "checked";
863                 printf "<input type=radio name=auto_nobrowse value=1 %s> No\n",
864                         defined($options{'nobrowse'}) ? "checked" : "";
865                 print "</td> <td colspan=2></td> </tr>\n";
866                 }
867         &generate_options($fstype);
868         print "<input type=hidden name=autofs_fstype value=\"$fstype\">\n";
869         }
870 if ($_[0] eq "rumba") {
871         # SMB filesystems have a few options..
872         print "<tr> <td><b>Server Hostname</b></td>\n";
873         printf "<td><input type=radio name=rumba_mname_def value=1 %s> Automatic\n",
874                 defined($options{"machinename"}) ? "" : "checked";
875         printf "<input type=radio name=rumba_mname_def value=0 %s>\n",
876                 defined($options{"machinename"}) ? "checked" : "";
877         print "<input size=10 name=rumba_mname value=\"$options{machinename}\"></td>\n";
878
879         print "<td><b>Client Name</b></td>\n";
880         printf "<td><input type=radio name=rumba_cname_def value=1 %s> Automatic\n",
881                 defined($options{"clientname"}) ? "" : "checked";
882         printf "<input type=radio name=rumba_cname_def value=0 %s>\n",
883                 defined($options{"clientname"}) ? "checked" : "";
884         print "<input size=10 name=rumba_cname value=\"$options{clientname}\"></td> </tr>\n";
885
886         print "<tr> <td><b>Login Name</b></td>\n";
887         print "<td><input name=rumba_username size=15 value=\"$options{username}\"></td>\n";
888
889         print "<td><b>Login Password</b></td>\n";
890         print "<td><input type=password name=rumba_password size=15 value=\"$options{password}\"></td> </tr>\n";
891
892         print "<tr> <td><b>User files are owned by</b></td>\n";
893         printf "<td><input name=rumba_uid size=8 value=\"%s\">\n",
894                 defined($options{'uid'}) ? getpwuid($options{'uid'}) : "";
895         print &user_chooser_button("rumba_uid", 0),"</td>\n";
896
897         print "<td><b>Group files are owned by</b></td>\n";
898         printf "<td><input name=rumba_gid size=8 value=\"%s\">\n",
899                 defined($options{'gid'}) ? getgrgid($options{'gid'}) : "";
900         print &group_chooser_button("rumba_gid", 0),"</td>\n";
901
902         print "<tr> <td><b>File permissions</b></td>\n";
903         printf "<td><input name=rumba_fmode size=5 value=\"%s\"></td>\n",
904                 defined($options{fmode}) ? $options{fmode} : "755";
905
906         print "<td><b>Directory permissions</b></td>\n";
907         printf "<td><input name=rumba_dmode size=5 value=\"%s\"></td> </tr>\n",
908                 defined($options{dmode}) ? $options{dmode} : "755";
909
910         print "<tr> <td><b>Read/write access is safe?</b></td>\n";
911         printf"<td nowrap><input type=radio name=rumba_readwrite value=1 %s> Yes\n",
912                 defined($options{"readwrite"}) ? "checked" : "";
913         printf "<input type=radio name=rumba_readwrite value=0 %s> No</td>\n",
914                 defined($options{"readwrite"}) ? "" : "checked";
915
916         print "<td><b>Files can be read-only?</b></td>\n";
917         printf"<td nowrap><input type=radio name=rumba_readonly value=1 %s> Yes\n",
918                 defined($options{"readonly"}) ? "checked" : "";
919         printf "<input type=radio name=rumba_readonly value=0 %s> No</td> </tr>\n",
920                 defined($options{"readonly"}) ? "" : "checked";
921
922         print "<tr> <td><b>Send password in upper case?</b></td>\n";
923         printf"<td nowrap><input type=radio name=rumba_noupper value=0 %s> Yes\n",
924                 defined($options{"noupper"}) ? "" : "checked";
925         printf "<input type=radio name=rumba_noupper value=1 %s> No</td>\n",
926                 defined($options{"noupper"}) ? "checked" : "";
927
928         print "<td><b>Use attrE commands?</b></td>\n";
929         printf"<td nowrap><input type=radio name=rumba_attr value=1 %s> Yes\n",
930                 defined($options{"attr"}) ? "checked" : "";
931         printf "<input type=radio name=rumba_attr value=0 %s> No</td> </tr>\n",
932                 defined($options{"attr"}) ? "" : "checked";
933         }
934 }
935
936
937 # check_location(type)
938 # Parse and check inputs from %in, calling &error() if something is wrong.
939 # Returns the location string for storing in the fstab file
940 sub check_location
941 {
942 if ($_[0] eq "nfs") {
943         local($out, $temp, $mout, $dirlist);
944
945         if ($in{'nfs_serv'} == 1) {
946                 # multiple servers listed.. assume the user has a brain
947                 return $in{'nfs_list'};
948                 }
949         elsif ($in{'nfs_serv'} == 2) {
950                 # NFS url.. check syntax
951                 if ($in{'nfs_url'} !~ /^nfs:\/\/([^\/ ]+)(\/([^\/ ]*))?$/) {
952                         &error("'$in{'nfs_url'}' is not a valid NFS URL");
953                         }
954                 return $in{'nfs_url'};
955                 }
956
957         # Use dfshares to see if the host exists and is up
958         if ($in{nfs_host} !~ /^\S+$/) {
959                 &error("'$in{nfs_host}' is not a valid hostname");
960                 }
961         $out = &backquote_command("dfshares '$in{nfs_host}' 2>&1");
962         if ($out =~ /Unknown host/) {
963                 &error("The host '$in{nfs_host}' does not exist");
964                 }
965         elsif ($out =~ /Timed out/) {
966                 &error("The host '$in{nfs_host}' is down or does not ".
967                        "support NFS");
968                 }
969         elsif ($out =~ /Program not registered/) {
970                 &error("The host '$in{nfs_host}' does not support NFS");
971                 }
972
973         # Try a test mount to see if filesystem is available
974         foreach (split(/\n/, $out)) {
975                 if (/^\s*([^ :]+):(\/\S+)\s+/) { $dirlist .= "$2\n"; }
976                 }
977         if ($in{nfs_dir} !~ /^\S+$/) {
978                 &error("'$in{nfs_dir}' is not a valid directory name. The ".
979                        "available directories on $in{nfs_host} are:".
980                        "<pre>$dirlist</pre>");
981                 }
982         $temp = &transname();
983         &make_dir($temp, 0755);
984         $mout = &backquote_command("mount $in{nfs_host}:$in{nfs_dir} $temp 2>&1");
985         if ($mout =~ /No such file or directory/) {
986                 rmdir($temp);
987                 &error("The directory '$in{nfs_dir}' does not exist on the ".
988                        "host $in{nfs_host}. The available directories are:".
989                        "<pre>$dirlist</pre>");
990                 }
991         elsif ($mout =~ /Permission denied/) {
992                 rmdir($temp);
993                 &error("This host is not allowed to mount the directory ".
994                        "$in{nfs_dir} from $in{nfs_host}");
995                 }
996         elsif ($?) {
997                 rmdir($temp);
998                 &error("NFS Error - $mout");
999                 }
1000         # It worked! unmount
1001         &execute_command("umount $temp");
1002         &unlink_file($temp);
1003         return "$in{nfs_host}:$in{nfs_dir}";
1004         }
1005 elsif ($_[0] eq "ufs") {
1006         # Get the device name
1007         if ($in{ufs_dev} == 0) {
1008                 $in{ufs_c} =~ /^[0-9]+$/ ||
1009                         &error("'$in{ufs_c}' is not a valid SCSI controller");
1010                 $in{ufs_t} =~ /^[0-9]+$/ ||
1011                         &error("'$in{ufs_t}' is not a valid SCSI target");
1012                 $in{ufs_d} =~ /^[0-9]+$/ ||
1013                         &error("'$in{ufs_d}' is not a valid SCSI unit");
1014                 $in{ufs_s} =~ /^[0-9]+$/ ||
1015                         &error("'$in{ufs_s}' is not a valid SCSI partition");
1016                 $dv = "/dev/dsk/c$in{ufs_c}t$in{ufs_t}d$in{ufs_d}s$in{ufs_s}";
1017                 }
1018         elsif ($in{ufs_dev} == 1) {
1019                 $in{ufs_md} =~ /^[0-9]+$/ ||
1020                         &error("'$in{ufs_md}' is not a valid RAID unit");
1021                 $dv = "/dev/md/dsk/d$in{ufs_md}";
1022                 }
1023         else {
1024                 $in{ufs_path} =~ /^\/\S+$/ ||
1025                         &error("'$in{ufs_path}' is not a valid pathname");
1026                 $dv = $in{ufs_path};
1027                 }
1028
1029         &fstyp_check($dv, "ufs");
1030         return $dv;
1031         }
1032 elsif ($_[0] eq "lofs") {
1033         # Get and check the original directory
1034         $dv = $in{'lofs_src'};
1035         if (!(-r $dv)) { &error("'$in{lofs_src}' does not exist"); }
1036         if (!(-d $dv)) { &error("'$in{lofs_src}' is not a directory"); }
1037         return $dv;
1038         }
1039 elsif ($_[0] eq "swap") {
1040         if ($in{swap_dev} == 0) {
1041                 $in{swap_c} =~ /^[0-9]+$/ ||
1042                         &error("'$in{swap_c}' is not a valid SCSI controller");
1043                 $in{swap_t} =~ /^[0-9]+$/ ||
1044                         &error("'$in{swap_t}' is not a valid SCSI target");
1045                 $in{swap_d} =~ /^[0-9]+$/ ||
1046                         &error("'$in{swap_d}' is not a valid SCSI unit");
1047                 $in{swap_s} =~ /^[0-9]+$/ ||
1048                         &error("'$in{swap_s}' is not a valid SCSI partition");
1049                 $dv="/dev/dsk/c$in{swap_c}t$in{swap_t}d$in{swap_d}s$in{swap_s}";
1050                 }
1051         else { $dv = $in{swap_path}; }
1052
1053         if (!open(SWAPFILE, $dv)) {
1054                 if ($! =~ /No such file/ && $in{swap_dev}) {
1055                         if ($dv !~ /^\/dev/) {
1056                                 &swap_form($dv);
1057                                 }
1058                         else {
1059                                 &error("The swap file '$dv' does not exist");
1060                                 }
1061                         }
1062                 elsif ($! =~ /No such file/) {
1063                         &error("The SCSI target '$in{swap_t}' does not exist");
1064                         }
1065                 elsif ($! =~ /No such device or address/) {
1066                         &error("The partition '$in{swap_s}' does not exist");
1067                         }
1068                 else {
1069                         &error("Failed to open '$dv' : $!");
1070                         }
1071                 }
1072         close(SWAPFILE);
1073         return $dv;
1074         }
1075 elsif ($_[0] eq "tmpfs") {
1076         # Ram-disk filesystems have no location
1077         return "swap";
1078         }
1079 elsif ($_[0] eq "cachefs") {
1080         # In order to check the location for the caching filesystem, we need
1081         # to check the back filesystem
1082         if (!$in{cfs_noback}) {
1083                 # The back filesystem is manually mounted.. hopefully
1084                 local($bidx, @mlist, @binfo);
1085                 $bidx = &get_mounted($in{cfs_backpath}, "*");
1086                 if ($bidx < 0) {
1087                         &error("The back filesystem '$in{cfs_backpath}' is ".
1088                                "not mounted");
1089                         }
1090                 @mlist = &list_mounted();
1091                 @binfo = @{$mlist[$bidx]};
1092                 if ($binfo[2] ne $in{cfs_backfstype}) {
1093                         &error("The back filesystem is '$binfo[2]', not ".
1094                                "'$in{cfs_backfstype}'");
1095                         }
1096                 }
1097         else {
1098                 # Need to automatically mount the back filesystem.. check
1099                 # it for sanity first.
1100                 # But HOW?
1101                 $in{cfs_src} =~ /^\S+$/ ||
1102                         &error("'$in{cfs_src}' is not a valid cache source");
1103                 }
1104         return $in{cfs_src};
1105         }
1106 elsif ($_[0] eq "autofs") {
1107         # An autofs filesystem can be either mounted from the special
1108         # -hosts and -xfn maps, or from a normal map. The map can be a file
1109         # name (if it starts with /), or an NIS map (if it doesn't)
1110         if ($in{autofs_type} == 0) {
1111                 # Normal map
1112                 $in{autofs_map} =~ /\S/ ||
1113                         &error("You did not enter an automount map name");
1114                 if ($in{autofs_map} =~ /^\// && !(-r $in{autofs_map})) {
1115                         &error("The map file '$in{autofs_map}' does not exist");
1116                         }
1117                 return $in{autofs_map};
1118                 }
1119         elsif ($in{autofs_type} == 1) {
1120                 # Special hosts map (automount all shares from some host)
1121                 return "-hosts";
1122                 }
1123         else {
1124                 # Special FNS map (not sure what this does)
1125                 return "-xfn";
1126                 }
1127         }
1128 elsif ($_[0] eq "rumba") {
1129         # Cannot check much here..
1130         return "\\\\$in{rumba_server}\\$in{rumba_share}";
1131         }
1132 }
1133
1134
1135 # fstyp_check(device, type)
1136 # Check if some device exists, and contains a filesystem of the given type,
1137 # using the fstyp command.
1138 sub fstyp_check
1139 {
1140 local($out, $part, $found);
1141
1142 # Check if the device/partition actually exists
1143 if ($_[0] =~ /^\/dev\/dsk\/c(.)t(.)d(.)s(.)$/) {
1144         # mounting a normal scsi device..
1145         $out = &backquote_command("prtvtoc -h $_[0] 2>&1");
1146         if ($out =~ /No such file or directory|No such device or address/) {
1147                 &error("The SCSI target for '$_[0]' does not exist");
1148                 }
1149         $part = $4;
1150         foreach (split(/\n/, $out)) {
1151                 /^\s+([0-9]+)\s+([0-9]+)/;
1152                 if ($1 == $part) {
1153                         $found = 1; last;
1154                         }
1155                 }
1156         if (!$found) {
1157                 &error("The SCSI partition for '$_[0]' does not exist");
1158                 }
1159         }
1160 elsif ($_[0] =~ /^\/dev\/md\/dsk\/d(.)$/) {
1161         # mounting a multi-disk (raid) device..
1162         $out = &backquote_command("prtvtoc -h $_[0] 2>&1");
1163         if ($out =~ /No such file or directory|No such device or address/) {
1164                 &error("The RAID device for '$_[0]' does not exist");
1165                 }
1166         if ($out !~ /\S/) {
1167                 &error("No partitions on '$_[0]' ??");
1168                 }
1169         }
1170 else {
1171         # Some other device
1172         if (!open(DEV, $_[0])) {
1173                 if ($! =~ /No such file or directory/) {
1174                         &error("The device file '$_[0]' does not exist");
1175                         }
1176                 elsif ($! =~ /No such device or address/) {
1177                         &error("The device for '$_[0]' does not exist");
1178                         }
1179                 }
1180         close(DEV);
1181         }
1182
1183 # Check the filesystem type
1184 $out = &backquote_command("fstyp $_[0] 2>&1");
1185 if ($out =~ /^([A-z0-9]+)\n$/) {
1186         if ($1 eq $_[1]) { return; }
1187         else {
1188                 # Wrong filesystem type
1189                 &error("The device '$_[0]' is formatted as a ".
1190                        &fstype_name($1));
1191                 }
1192         }
1193 else {
1194         &error("Failed to check filesystem type : $out");
1195         }
1196 }
1197
1198
1199 # check_options(type)
1200 # Read options for some filesystem from %in, and use them to update the
1201 # %options array. Options handled by the user interface will be set or
1202 # removed, while unknown options will be left untouched.
1203 sub check_options
1204 {
1205 local($k, @rv);
1206 if ($_[0] eq "nfs") {
1207         # NFS has lots of options to parse
1208         if ($in{'nfs_ro'}) {
1209                 # Read-only
1210                 $options{"ro"} = ""; delete($options{"rw"});
1211                 }
1212         else {
1213                 # Read-write
1214                 $options{"rw"} = ""; delete($options{"ro"});
1215                 }
1216
1217         delete($options{'quota'}); delete($options{'noquota'});
1218         if ($in{'nfs_quota'}) { $options{'quota'} = ""; }
1219
1220         delete($options{"nosuid"}); delete($options{"suid"});
1221         if ($in{nfs_nosuid}) { $options{"nosuid"} = ""; }
1222
1223         delete($options{"grpid"});
1224         if ($in{nfs_grpid}) { $options{"grpid"} = ""; }
1225
1226         delete($options{"soft"}); delete($options{"hard"});
1227         if ($in{nfs_soft}) { $options{"soft"} = ""; }
1228
1229         delete($options{"bg"}); delete($options{"fg"});
1230         if ($in{nfs_bg}) { $options{"bg"} = ""; }
1231
1232         delete($options{"intr"}); delete($options{"nointr"});
1233         if ($in{nfs_nointr}) { $options{"nointr"} = ""; }
1234
1235         delete($options{"vers"});
1236         if (!$in{nfs_vers_def}) { $options{"vers"} = $in{nfs_vers}; }
1237
1238         delete($options{"proto"});
1239         if ($in{nfs_proto} ne "") { $options{"proto"} = $in{nfs_proto}; }
1240
1241         delete($options{"port"});
1242         if (!$in{nfs_port_def}) { $options{"port"} = $in{nfs_port}; }
1243
1244         delete($options{"timeo"});
1245         if (!$in{nfs_timeo_def}) { $options{"timeo"} = $in{nfs_timeo}; }
1246
1247         delete($options{"secure"}); delete($options{"kerberos"});
1248         delete($options{"sec"});
1249         if ($gconfig{'os_version'} >= 2.6) {
1250                 if ($in{'nfs_auth'}) { $options{'sec'} = $in{'nfs_auth'}; }
1251                 }
1252         else {
1253                 if ($in{'nfs_auth'} eq "dh") { $options{"secure"} = ""; }
1254                 elsif ($in{'nfs_auth'} eq "krb") { $options{"kerberos"} = ""; }
1255                 }
1256
1257         if ($gconfig{'os_version'} >= 7) {
1258                 delete($options{'public'});
1259                 $options{'public'} = "" if ($in{'nfs_public'});
1260                 }
1261         }
1262 elsif ($_[0] eq "ufs") {
1263         # UFS also has lots of options..
1264         if ($in{ufs_ro}) {
1265                 # read-only (and thus no quota)
1266                 $options{"ro"} = ""; delete($options{"rw"});
1267                 delete($options{"rq"}); delete($options{"quota"});
1268                 }
1269         elsif ($in{ufs_quota}) {
1270                 # read-write, with quota
1271                 delete($options{"ro"}); $options{"rw"} = "";
1272                 $options{"quota"} = "";
1273                 }
1274         else {
1275                 # read-write, without quota
1276                 delete($options{"ro"}); $options{"rw"} = "";
1277                 delete($options{"quota"});
1278                 }
1279
1280         delete($options{"nosuid"});
1281         if ($in{ufs_nosuid}) { $options{"nosuid"} = ""; }
1282
1283         delete($options{"intr"}); delete($options{"nointr"});
1284         if ($in{ufs_nointr}) { $options{"nointr"} = ""; }
1285
1286         delete($options{"onerror"});
1287         if ($in{ufs_onerror} ne "panic") {
1288                 $options{"onerror"} = $in{ufs_onerror};
1289                 }
1290
1291         delete($options{"toosoon"});
1292         if ($in{ufs_toosoon_time}) {
1293                 $options{"toosoon"} = $in{ufs_toosoon_time}.
1294                                       $in{ufs_toosoon_units};
1295                 }
1296         if ($gconfig{'os_version'} >= 7) {
1297                 delete($options{'noatime'});
1298                 $options{'noatime'} = "" if ($in{'ufs_noatime'});
1299
1300                 delete($options{'forcedirectio'});
1301                 delete($options{'noforcedirectio'});
1302                 $options{'forcedirectio'} = "" if ($in{'ufs_force'});
1303
1304                 delete($options{'nolargefiles'});delete($options{'largefiles'});
1305                 $options{'nolargefiles'} = "" if ($in{'ufs_nolarge'});
1306
1307                 delete($options{'logging'}); delete($options{'nologging'});
1308                 $options{'logging'} = "" if ($in{'ufs_logging'});
1309                 }
1310         }
1311 elsif ($_[0] eq "lofs") {
1312         # Loopback has no options to parse
1313         }
1314 elsif ($_[0] eq "swap") {
1315         # Swap has no options to parse
1316         }
1317 elsif ($_[0] eq "pcfs") {
1318         # PCFS has only 2 options
1319         delete($options{'ro'}); delete($options{'rw'});
1320         $options{'ro'} = "" if ($in{'pcfs_rp'});
1321
1322         delete($options{'foldcase'}); delete($options{'nofoldcase'});
1323         $options{'foldcase'} = "" if ($in{'pcfs_foldcase'});
1324         }
1325 elsif ($_[0] eq "tmpfs") {
1326         # Ram-disk filesystems have only one option
1327         delete($options{"size"});
1328         if (!$in{"tmpfs_size_def"}) {
1329                 $options{"size"} = "$in{tmpfs_size}$in{tmpfs_unit}";
1330                 }
1331         }
1332 elsif ($_[0] eq "cachefs") {
1333         # The caching filesystem has lots of options
1334         $options{"backfstype"} = $in{"cfs_backfstype"};
1335
1336         delete($options{"backpath"});
1337         if (!$in{"cfs_noback"}) {
1338                 # A back filesystem was given..  (alreadys checked)
1339                 $options{"backpath"} = $in{"cfs_backpath"};
1340                 }
1341
1342         if ($in{"cfs_cachedir"} !~ /^\/\S+/) {
1343                 &error("'$in{cfs_cachedir}' is not a valid cache directory");
1344                 }
1345         $options{"cachedir"} = $in{"cfs_cachedir"};
1346
1347         delete($options{"write-around"}); delete($options{"non-shared"});
1348         if ($in{"cfs_wmode"}) {
1349                 $options{"non-shared"} = "";
1350                 }
1351
1352         delete($options{"noconst"}); delete($options{"demandconst"});
1353         if ($in{"cfs_con"} == 0) { $options{"noconst"} = ""; }
1354         elsif ($in{"cfs_con"} == 2) { $options{"demandconst"} = ""; }
1355
1356         delete($options{"ro"}); delete($options{"rw"});
1357         if ($in{"cfs_ro"}) { $options{"ro"} = ""; }
1358
1359         delete($options{"suid"}); delete($options{"nosuid"});
1360         if ($in{"cfs_nosuid"}) { $options{"nosuid"} = ""; }
1361         }
1362 elsif ($_[0] eq "autofs") {
1363         # The options for autofs depend on the type of the automounted
1364         # filesystem.. 
1365         $options{"fstype"} = $in{"autofs_fstype"};
1366         if ($gconfig{'os_version'} >= 2.6) {
1367                 delete($options{'nobrowse'}); delete($options{'browse'});
1368                 $options{'nobrowse'} = "" if ($in{'auto_nobrowse'});
1369                 }
1370         return &check_options($options{"fstype"});
1371         }
1372 elsif ($_[0] eq "rumba") {
1373         # Options for smb filesystems..
1374         delete($options{machinename});
1375         if (!$in{rumba_mname_def}) { $options{machinename} = $in{rumba_mname}; }
1376
1377         delete($options{clientname});
1378         if (!$in{rumba_cname_def}) { $options{clientname} = $in{rumba_cname}; }
1379
1380         delete($options{username});
1381         if ($in{rumba_username}) { $options{username} = $in{rumba_username}; }
1382
1383         delete($options{password});
1384         if ($in{rumba_password}) { $options{password} = $in{rumba_password}; }
1385
1386         delete($options{uid});
1387         if ($in{rumba_uid} ne "") { $options{uid} = getpwnam($in{rumba_uid}); }
1388
1389         delete($options{gid});
1390         if ($in{rumba_gid} ne "") { $options{gid} = getgrnam($in{rumba_gid}); }
1391
1392         delete($options{fmode});
1393         if ($in{rumba_fmode} !~ /^[0-7]{3}$/) {
1394                 &error("'$in{rumba_fmode}' is not a valid octal file mode");
1395                 }
1396         elsif ($in{rumba_fmode} ne "755") { $options{fmode} = $in{rumba_fmode}; }
1397
1398         delete($options{dmode});
1399         if ($in{rumba_dmode} !~ /^[0-7]{3}$/) {
1400                 &error("'$in{rumba_dmode}' is not a valid octal directory mode");
1401                 }
1402         elsif ($in{rumba_dmode} ne "755") { $options{dmode} = $in{rumba_dmode}; }
1403
1404         delete($options{'readwrite'});
1405         if ($in{'rumba_readwrite'}) { $options{'readwrite'} = ""; }
1406
1407         delete($options{'readonly'});
1408         if ($in{'rumba_readonly'}) { $options{'readonly'} = ""; }
1409
1410         delete($options{'attr'});
1411         if ($in{'rumba_attr'}) { $options{'attr'} = ""; }
1412
1413         delete($options{'noupper'});
1414         if ($in{'rumba_noupper'}) { $options{'noupper'} = ""; }
1415         }
1416
1417 # Return options string
1418 foreach $k (keys %options) {
1419         if ($options{$k} eq "") { push(@rv, $k); }
1420         else { push(@rv, "$k=$options{$k}"); }
1421         }
1422 return @rv ? join(',' , @rv) : "-";
1423 }
1424
1425
1426 # create_swap(path, size, units)
1427 # Attempt to create a swap file 
1428 sub create_swap
1429 {
1430 local($out);
1431 $out = &backquote_logged("mkfile $_[1]$_[2] $_[0] 2>&1");
1432 if ($?) {
1433         &unlink_file($_[0]);
1434         return "mkfile failed : $out";
1435         }
1436 return 0;
1437 }
1438
1439
1440 # exports_list(host, dirarray, clientarray)
1441 # Fills the directory and client array references with exports from some
1442 # host. Returns an error string if something went wrong
1443 sub exports_list
1444 {
1445 local($dref, $cref, $out, $_);
1446 $dref = $_[1]; $cref = $_[2];
1447 $out = &backquote_command("showmount -e ".quotemeta($_[0])." 2>&1", 1);
1448 if ($?) { return $out; }
1449 foreach (split(/\n/, $out)) {
1450         if (/^(\/\S*)\s+(.*)$/) {
1451                 push(@$dref, $1); push(@$cref, $2);
1452                 }
1453         }
1454 return undef;
1455 }
1456
1457 # broadcast_addr()
1458 # Returns a useable broadcast address for finding NFS servers
1459 sub broadcast_addr
1460 {
1461 local($out);
1462 $out = &backquote_command("ifconfig -a 2>&1", 1);
1463 if ($out =~ /broadcast\s+(\S+)/) { return $1; }
1464 return "255.255.255.255";
1465 }
1466
1467 sub device_name
1468 {
1469 return $_[0];
1470 }
1471
1472 sub files_to_lock
1473 {
1474 return ( $config{'fstab_file'} );
1475 }
1476
1477 1;