Handle hostnames with upper-case letters
[webmin.git] / quota / freebsd-lib.pl
1 # openbsd-lib.pl
2 # Quota functions for openbsd
3
4 # quotas_init()
5 sub quotas_init
6 {
7 return undef;
8 }
9
10 # quotas_supported()
11 # Returns 1 for user quotas, 2 for group quotas or 3 for both
12 sub quotas_supported
13 {
14 return 3;
15 }
16
17 # free_space(filesystem)
18 # Returns an array containing  btotal, bfree, ftotal, ffree
19 sub free_space
20 {
21 local(@out, @rv);
22 $ENV{'BLOCKSIZE'} = 1024;
23 `df -i $_[0]` =~ /Mounted on\n\S+\s+(\d+)\s+\d+\s+(\d+)\s+\S+\s+(\d+)\s+(\d+)/;
24 return ($1, $2, $3+$4, $4);
25 }
26
27 # quota_can(&mnttab, &fstab)
28 # Can this filesystem type support quotas?
29 #  0 = No quota support (or not turned on in /etc/fstab)
30 #  1 = User quotas only
31 #  2 = Group quotas only
32 #  3 = User and group quotas
33 sub quota_can
34 {
35 return ($_[1]->[3] =~ /userquota/ ? 1 : 0) +
36        ($_[1]->[3] =~ /groupquota/ ? 2 : 0);
37 }
38
39 # quota_now(&mnttab, &fstab)
40 # Are quotas currently active?
41 #  0 = Not active
42 #  1 = User quotas active
43 #  2 = Group quotas active
44 #  3 = Both active
45 sub quota_now
46 {
47 return $_[0]->[3] =~ /quota/ ? 3 : 0;
48 }
49
50 # quotaon(filesystem, mode)
51 # Activate quotas and create quota files for some filesystem. The mode can
52 # be 1 for user only, 2 for group only or 3 for user and group
53 sub quotaon
54 {
55 return if (&is_readonly_mode());
56 local($out, $qf, @qfile, $flags);
57 if ($_[1]%2 == 1) {
58         # turn on user quotas
59         $qf = "$_[0]/quota.user";
60         if (!(-r $qf)) {
61                 &open_tempfile(QUOTAFILE, ">$qf", 0, 1);
62                 &close_tempfile(QUOTAFILE);
63                 &set_ownership_permissions(undef, undef, 0600, $qf);
64                 &system_logged("$config{'quotacheck_command'} $_[0]");
65                 }
66         $out = &backquote_logged("$config{'user_quotaon_command'} $_[0] 2>&1");
67         if ($?) { return $out; }
68         }
69 if ($_[1] > 1) {
70         # turn on group quotas
71         $qf = "$_[0]/quota.group";
72         if (!(-r $qf)) {
73                 &open_tempfile(QUOTAFILE, ">$qf", 0, 1);
74                 &close_tempfile(QUOTAFILE);
75                 &set_ownership_permissions(undef, undef, 0600, $qf);
76                 &system_logged("$config{'quotacheck_command'} $_[0]");
77                 }
78         $out = &backquote_logged("$config{'group_quotaon_command'} $_[0] 2>&1");
79         if ($?) { return $out; }
80         }
81 return undef;
82 }
83
84 # quotaoff(filesystem, mode)
85 # Turn off quotas for some filesystem
86 sub quotaoff
87 {
88 return if (&is_readonly_mode());
89 local($out);
90 if ($_[1]%2 == 1) {
91         $out = &backquote_logged("$config{'user_quotaoff_command'} $_[0] 2>&1");
92         if ($?) { return $out; }
93         }
94 if ($_[1] > 1) {
95         $out = &backquote_logged("$config{'group_quotaoff_command'} $_[0] 2>&1");
96         if ($?) { return $out; }
97         }
98 return undef;
99 }
100
101 # user_filesystems(user)
102 # Fills the array %filesys with details of all filesystem some user has
103 # quotas on
104 sub user_filesystems
105 {
106 local($n, $_, %mtab);
107 open(QUOTA, "$config{'user_quota_command'} ".quotemeta($_[0])." |");
108 $n=0; while(<QUOTA>) {
109         chop;
110         if (/^(Disk|\s+Filesystem)/) { next; }
111         if (/^(\S+)$/) {
112                 # Bogus wrapped line
113                 $filesys{$n,'filesys'} = $1;
114                 local $nl = <QUOTA>;
115                 $nl =~ /^\s+(\S+)\s+(\S+)\s+(\S+)(.{8}\s+)(\S+)\s+(\S+)\s+(\S+)(.*)/ ||
116                   $nl =~ /^.{15}(.{8}).(.{7})(.{8}).{8}(.{8}).(.{7})(.{8})/;
117                 $filesys{$n,'ublocks'} = int($1);
118                 $filesys{$n,'sblocks'} = int($2);
119                 $filesys{$n,'hblocks'} = int($3);
120                 $filesys{$n,'ufiles'} = int($4);
121                 $filesys{$n,'sfiles'} = int($5);
122                 $filesys{$n,'hfiles'} = int($6);
123                 $n++;
124                 }
125         elsif (/^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)(.{8}\s+)(\S+)\s+(\S+)\s+(\S+)(.*)/ ||
126                /^(.{15})(.{8}).(.{7})(.{8}).{8}(.{8}).(.{7})(.{8})/) {
127                 $filesys{$n,'ublocks'} = int($2);
128                 $filesys{$n,'sblocks'} = int($3);
129                 $filesys{$n,'hblocks'} = int($4);
130                 $filesys{$n,'ufiles'} = int($5);
131                 $filesys{$n,'sfiles'} = int($6);
132                 $filesys{$n,'hfiles'} = int($7);
133                 $filesys{$n,'filesys'} = $1;
134                 $filesys{$n,'filesys'} =~ s/^\s+//g;
135                 $n++;
136                 }
137         }
138 close(QUOTA);
139 return $n;
140 }
141
142 # group_filesystems(group)
143 # Fills the array %filesys with details of all filesystem some group has
144 # quotas on
145 sub group_filesystems
146 {
147 local($n, $_, %mtab);
148 open(QUOTA, "$config{'group_quota_command'} ".quotemeta($_[0])." |");
149 $n=0; while(<QUOTA>) {
150         chop;
151         if (/^(Disk|\s+Filesystem)/) { next; }
152         if (/^(\S+)$/) {
153                 # Bogus wrapped line
154                 $filesys{$n,'filesys'} = $1;
155                 <QUOTA>=~/^.{15}(.{8}).(.{7})(.{8}).{8}(.{8}).(.{7})(.{8})/;
156                 $filesys{$n,'ublocks'} = int($1);
157                 $filesys{$n,'sblocks'} = int($2);
158                 $filesys{$n,'hblocks'} = int($3);
159                 $filesys{$n,'ufiles'} = int($4);
160                 $filesys{$n,'sfiles'} = int($5);
161                 $filesys{$n,'hfiles'} = int($6);
162                 $n++;
163                 }
164         elsif (/^(.{15})(.{8}).(.{7})(.{8}).{8}(.{8}).(.{7})(.{8})/) {
165                 $filesys{$n,'ublocks'} = int($2);
166                 $filesys{$n,'sblocks'} = int($3);
167                 $filesys{$n,'hblocks'} = int($4);
168                 $filesys{$n,'ufiles'} = int($5);
169                 $filesys{$n,'sfiles'} = int($6);
170                 $filesys{$n,'hfiles'} = int($7);
171                 $filesys{$n,'filesys'} = $1;
172                 $filesys{$n,'filesys'} =~ s/^\s+//g;
173                 $n++;
174                 }
175         }
176 close(QUOTA);
177 return $n;
178 }
179
180 # filesystem_users(filesystem)
181 # Fills the array %user with information about all users with quotas
182 # on this filesystem. This may not be all users on the system..
183 sub filesystem_users
184 {
185 local($rep, @rep, $n, $what);
186 $rep = `$config{'user_repquota_command'} $_[0] 2>&1`;
187 if ($?) { return -1; }
188 @rep = split(/\n/, $rep);
189 @rep = grep { !/^root\s/ } @rep[3..$#rep];
190 for($n=0; $n<@rep; $n++) {
191         if ($rep[$n] =~ /(\S+)\s*[\-\+]{2}\s+(\d+)\s+(\d+)\s+(\d+)\s(.{0,15})\s(\d+)\s+(\d+)\s+(\d+)(.*)/ || $rep[$n] =~ /(\S+)\s+..(.{8})(.{8})(.{8})(.{7})(.{8})(.{8})(.{8})(.*)/) {
192                 $user{$n,'user'} = $1;
193                 $user{$n,'ublocks'} = int($2);
194                 $user{$n,'sblocks'} = int($3);
195                 $user{$n,'hblocks'} = int($4);
196                 $user{$n,'gblocks'} = $5;
197                 $user{$n,'ufiles'} = int($6);
198                 $user{$n,'sfiles'} = int($7);
199                 $user{$n,'hfiles'} = int($8);
200                 $user{$n,'gfiles'} = $9;
201                 $user{$n,'gblocks'} = &trunc_space($user{$n,'gblocks'});
202                 $user{$n,'gfiles'} = &trunc_space($user{$n,'gfiles'});
203                 }
204         }
205 return $n;
206 }
207
208 # filesystem_groups(filesystem)
209 # Fills the array %group with information about all groups with quotas
210 # on this filesystem. This may not be all groups on the system..
211 sub filesystem_groups
212 {
213 local($rep, @rep, $n, $what);
214 $rep = `$config{'group_repquota_command'} $_[0] 2>&1`;
215 if ($?) { return -1; }
216 @rep = split(/\n/, $rep);
217 @rep = @rep[3..$#rep];
218 for($n=0; $n<@rep; $n++) {
219         if ($rep[$n] =~ /(\S+)\s*[\-\+]{2}\s+(\d+)\s+(\d+)\s+(\d+)\s(.{0,15})\s(\d+)\s+(\d+)\s+(\d+)(.*)/ || $rep[$n] =~ /(\S+)\s+..(.{8})(.{8})(.{8})(.{7})(.{8})(.{8})(.{8})/) {
220                 $group{$n,'group'} = $1;
221                 $group{$n,'ublocks'} = int($2);
222                 $group{$n,'sblocks'} = int($3);
223                 $group{$n,'hblocks'} = int($4);
224                 $group{$n,'gblocks'} = $5;
225                 $group{$n,'ufiles'} = int($6);
226                 $group{$n,'sfiles'} = int($7);
227                 $group{$n,'hfiles'} = int($8);
228                 $group{$n,'gfiles'} = $9;
229                 $group{$n,'gblocks'} = &trunc_space($group{$n,'gblocks'});
230                 $group{$n,'gfiles'} = &trunc_space($group{$n,'gfiles'});
231                 }
232         }
233 return $n;
234 }
235
236 # edit_quota_file(data, filesys, sblocks, hblocks, sfiles, hfiles)
237 sub edit_quota_file
238 {
239 local($rv, $line, %mtab, @m);
240 @line = split(/\n/, $_[0]);
241 for($i=0; $i<@line; $i++) {
242         if ($line[$i] =~ /^(\S+): (blocks|kbytes) in use: (\d+), limits \(soft = (\d+), hard = (\d+)\)$/ && $1 eq $_[1]) {
243                 # found lines to change
244                 $rv .= "$1: $2 in use: $3, limits (soft = $_[2], hard = $_[3])\n";
245                 $line[++$i] =~ /^\s*inodes in use: (\d+), limits \(soft = (\d+), hard = (\d+)\)$/;
246                 $rv .= "\tinodes in use: $1, limits (soft = $_[4], hard = $_[5])\n";
247                 }
248         else { $rv .= "$line[$i]\n"; }
249         }
250 return $rv;
251 }
252
253 # quotacheck(filesystem, mode)
254 # Runs quotacheck on some filesystem
255 sub quotacheck
256 {
257 $out = &backquote_logged("$config{'quotacheck_command'} $_[0] 2>&1");
258 if ($?) { return $out; }
259 return undef;
260 }
261
262 # copy_user_quota(user, [user]+)
263 # Copy the quotas for some user to many others
264 sub copy_user_quota
265 {
266 for($i=1; $i<@_; $i++) {
267         $out = &backquote_logged("$config{'user_copy_command'} ".
268                                 quotemeta($_[0])." ".quotemeta($_[$i])." 2>&1");
269         if ($?) { return $out; }
270         }
271 return undef;
272 }
273
274 # copy_group_quota(group, [group]+)
275 # Copy the quotas for some group to many others
276 sub copy_group_quota
277 {
278 for($i=1; $i<@_; $i++) {
279         $out = &backquote_logged("$config{'group_copy_command'} ".
280                                 quotemeta($_[0])." ".quotemeta($_[$i])." 2>&1");
281         if ($?) { return $out; }
282         }
283 return undef;
284 }
285
286 # default_grace()
287 # Returns 0 if grace time can be 0, 1 if zero grace means default
288 sub default_grace
289 {
290 return 0;
291 }
292
293 # get_user_grace(filesystem)
294 # Returns an array containing  btime, bunits, ftime, funits
295 # The units can be 0=sec, 1=min, 2=hour, 3=day
296 sub get_user_grace
297 {
298 local(@rv, %mtab, @m);
299 $ENV{'EDITOR'} = $ENV{'VISUAL'} = "cat";
300 open(GRACE, "$config{'user_grace_command'} $_[0] |");
301 while(<GRACE>) {
302         if (/^(\S+): block grace period: (\d+) (\S+), file grace period: (\d+) (\S+)/ && $1 eq $_[0]) {
303                 @rv = ($2, $name_to_unit{$3}, $4, $name_to_unit{$5});
304                 }
305         }
306 close(GRACE);
307 return @rv;
308 }
309
310 # get_group_grace(filesystem)
311 # Returns an array containing  btime, bunits, ftime, funits
312 # The units can be 0=sec, 1=min, 2=hour, 3=day
313 sub get_group_grace
314 {
315 local(@rv, %mtab, @m);
316 $ENV{'EDITOR'} = $ENV{'VISUAL'} = "cat";
317 open(GRACE, "$config{'group_grace_command'} $_[0] |");
318 while(<GRACE>) {
319         if (/^(\S+): block grace period: (\d+) (\S+), file grace period: (\d+) (\S+)/ && $1 eq $_[0]) {
320                 @rv = ($2, $name_to_unit{$3}, $4, $name_to_unit{$5});
321                 }
322         }
323 close(GRACE);
324 return @rv;
325 }
326
327 # edit_grace_file(data, filesystem, btime, bunits, ftime, funits)
328 sub edit_grace_file
329 {
330 local($rv, $line, @m, %mtab);
331 foreach $line (split(/\n/, $_[0])) {
332         if ($line =~ /^(\S+): block grace period: (\d+) (\S+), file grace period: (\d+) (\S+)/ && $1 eq $_[1]) {
333                 # replace this line
334                 $line = "$1: block grace period: $_[2] $unit_to_name{$_[3]}, file grace period: $_[4] $unit_to_name{$_[5]}";
335                 }
336         $rv .= "$line\n";
337         }
338 return $rv;
339 }
340
341 # grace_units()
342 # Returns an array of possible units for grace periods
343 sub grace_units
344 {
345 return ($text{'grace_seconds'}, $text{'grace_minutes'}, $text{'grace_hours'},
346         $text{'grace_days'});
347 }
348
349 # fs_block_size(dir, device, filesystem)
350 # Returns the size of blocks on some filesystem, or undef if unknown.
351 # Always 1024, because the ENV setting above forces this.
352 sub fs_block_size
353 {
354 return 1024;
355 }
356
357 %name_to_unit = ( "second", 0, "seconds", 0,
358                   "minute", 1, "minutes", 1,
359                   "hour", 2, "hours", 2,
360                   "day", 3, "days", 3,
361                 );
362 foreach $k (keys %name_to_unit) {
363         $unit_to_name{$name_to_unit{$k}} = $k;
364         }
365
366 1;
367