Handle hostnames with upper-case letters
[webmin.git] / bsdexports / save_export.cgi
1 #!/usr/local/bin/perl
2 # save_export.cgi
3 # Save or create an export
4
5 require './bsdexports-lib.pl';
6 &ReadParse();
7 &error_setup($text{'save_err'});
8
9 if ($in{'delete'}) {
10         # Redirect to delete CGI
11         &redirect("delete_export.cgi?idx=$in{'idx'}");
12         exit(0);
13         }
14
15 # Validate and save inputs
16 @dl = split(/\s+/, $in{'dirs'});
17 foreach $d (@dl) {
18         -d $d || &error(&text('save_edir', $d));
19         }
20 @dl || &error($text{'save_enone'});
21 if ($in{'alldirs'}) {
22         @dl == 1 || &error($text{'save_esub'});
23         if (&root_dir($dl[0]) ne $dl[0]) {
24                 &error($text{'save_eroot'});
25                 }
26         }
27 $exp{'dirs'} = \@dl;
28 @devno = map { (stat($_))[0] } @dl;
29 $exp{'alldirs'} = $in{'alldirs'};
30 $exp{'ro'} = $in{'ro'};
31 $exp{'kerb'} = $in{'kerb'};
32
33 if (!$in{'maproot_def'}) {
34         $in{'maproot'} =~ /^-?\d+$/ || defined(getpwnam($in{'maproot'})) ||
35                 &error(&text('save_euser', $in{'maproot'}));
36         if ($in{'maprootg_def'}) {
37                 @rgl = split(/\s+/, $in{'maprootg'});
38                 foreach $g (@rgl) {
39                         $g =~ /^-?\d+$/ || defined(getgrnam($g)) ||
40                                 &error(&text('save_egroup', $g));
41                         }
42                 $exp{'maproot'} = "$in{'maproot'}:".join(':', @rgl);
43                 }
44         else { $exp{'maproot'} = $in{'maproot'}; }
45         }
46
47 if (!$in{'mapall_def'}) {
48         $in{'mapall'} =~ /^-?\d+$/ || defined(getpwnam($in{'mapall'})) ||
49                 &error(&text('save_euser', $in{'mapall'}));
50         if ($in{'mapallg_def'}) {
51                 @rgl = split(/\s+/, $in{'mapallg'});
52                 foreach $g (@agl) {
53                         $g =~ /^-?\d+$/ || defined(getgrnam($g)) ||
54                                 &error(&text('save_egroup', $g));
55                         }
56                 $exp{'mapall'} = "$in{'mapall'}:".join(':', @agl);
57                 }
58         else { $exp{'mapall'} = $in{'mapall'}; }
59         }
60
61 if (!$in{'maproot_def'} + !$in{'mapall_def'} + $in{'kerb'} > 1) {
62         &error($text{'save_ekerb'});
63         }
64
65 if ($in{'cmode'} == 0) {
66         # Exporting to a list of hosts
67         @hl = split(/\s+/, $in{'hosts'});
68         @hl || &error($text{'save_ehosts'});
69         $exp{'hosts'} = \@hl;
70         foreach $h (@hl) {
71                 $ip = &to_ipaddress($h) || &to_ip6address($h);
72                 if ($ip) { push(@iplist, $ip); }
73                 }
74         }
75 else {
76         # Exporting to a subnet
77         &check_ipaddress($in{'network'}) ||
78                 &error(&text('save_enetwork', $in{'network'}));
79         &check_ipaddress($in{'mask'}) ||
80                 &error(&text('save_enetmask', $in{'netmask'}));
81         $exp{'network'} = $in{'network'};
82         $exp{'mask'} = $in{'mask'};
83         }
84
85 # Check for an export to the same host on the same local filesystem
86 &lock_file($config{'exports_file'});
87 @exps = &list_exports();
88 for($i=0; $i<@exps; $i++) {
89         next if (defined($in{'index'}) && $in{'index'} == $i);
90         $samefs = 0;
91         foreach $d (@{$exps[$i]->{'dirs'}}) {
92                 if (&indexof((stat($d))[0], @devno) >= 0) {
93                         # Same filesystem as this export..
94                         $samefs = $d;
95                         }
96                 }
97         next if (!$samefs);
98         foreach $h (@{$exps[$i]->{'hosts'}}) {
99                 $ip = &to_ipaddress($h) || &to_ip6address($h);
100                 if ($ip && &indexof($ip, @iplist) >= 0) {
101                         # Another export on this filesystem is to the same host
102                         &error(&text('save_esame1', $samefs, $h));
103                         }
104                 }
105         if ($exp{'mask'} && $exp{'mask'} eq $exps[$i]->{'mask'} &&
106                             $exp{'network'} eq $exps[$i]->{'network'}) {
107                 # Another export on this filesystem to the same net
108                 &error(&text('save_esame1', $samefs, $exp{'network'}));
109                 }
110         }
111
112 if (defined($in{'index'})) {
113         $old = $exps[$in{'index'}];
114         $exp{'public'} = $old->{'public'};
115         $exp{'webnfs'} = $old->{'webnfs'};
116         $exp{'index'} = $old->{'index'};
117         &modify_export($old, \%exp);
118         }
119 else {
120         &create_export(\%exp);
121         }
122 &unlock_file($config{'exports_file'});
123 &redirect("");
124
125 # root_dir(path)
126 # Returns the root directory of the filesystem some path is in
127 sub root_dir
128 {
129 my $dir = $_[0];
130 my @pst = stat($dir);
131 while(1) {
132         if ($dir eq "/") { return "/"; }
133         my $lastdir = $dir;
134         $dir =~ s/\/[^\/]+$//g;
135         if ($dir eq "") { $dir = "/"; }
136         my @ust = stat($dir);
137         if ($ust[0] != $pst[0]) { return $lastdir; }
138         }
139 }
140