aaa22dd7 |
1 | (* |
2 | Domtool 2 (http://hcoop.sf.net/) |
3 | Copyright (C) 2007 Adam Chlipala |
4 | |
5 | This program is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU General Public License |
7 | as published by the Free Software Foundation; either version 2 |
8 | of the License, or (at your option) any later version. |
9 | |
10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU General Public License |
16 | along with this program; if not, write to the Free Software |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 | *) |
19 | |
20 | structure Quotas = struct |
21 | |
22 | fun homedir s = Posix.SysDB.Passwd.home (Posix.SysDB.getpwnam s) |
23 | fun userVols s = [homedir s] |
24 | |
25 | fun used path = |
26 | let |
27 | val proc = Unix.execute ("/bin/sh", ["-c", "/usr/bin/fs listquota -path " ^ path]) |
28 | val inf = Unix.textInstreamOf proc |
29 | in |
30 | (case TextIO.inputLine inf of |
31 | NONE => NONE |
32 | | SOME line => |
33 | if String.isPrefix "fs: " line then |
34 | NONE |
35 | else |
36 | case TextIO.inputLine inf of |
37 | NONE => NONE |
38 | | SOME line => |
39 | case String.tokens Char.isSpace line of |
40 | _ :: _ :: n :: _ => Int.fromString n |
41 | | _ => NONE) |
42 | before ignore (Unix.reap proc) |
43 | end |
44 | |
45 | fun getDiskUsage () = |
46 | let |
47 | fun explorer (level, path, acc) = |
48 | let |
49 | val dir = Posix.FileSys.opendir path |
50 | |
51 | fun loop acc = |
52 | case Posix.FileSys.readdir dir of |
53 | NONE => acc |
54 | | SOME file => |
55 | let |
56 | val acc = |
57 | if level = 2 then |
58 | file :: acc |
59 | else |
60 | explorer (level+1, OS.Path.joinDirFile {dir = path, file = file}, acc) |
61 | in |
62 | loop acc |
63 | end |
64 | in |
65 | loop acc |
66 | before Posix.FileSys.closedir dir |
67 | end |
68 | |
69 | val users = explorer (0, "/afs/hcoop.net/user", []) |
70 | |
71 | fun count uname = |
72 | foldl (fn (vol, total) => case used vol of |
73 | NONE => total |
74 | | SOME n => total + n) 0 (userVols uname) |
75 | |
76 | val users = ListMergeSort.sort (fn (s1, s2) => String.compare (s1, s2) = GREATER) users |
77 | val all = List.map (fn user => {uname = user, kbs = count user}) users |
78 | val all = ListMergeSort.sort (fn ({kbs = kb1, ...}, {kbs = kb2, ...}) => kb1 > kb2) all |
79 | in |
80 | app (fn {uname, kbs} => (print uname; |
81 | print " "; |
82 | print (Int.toString kbs); |
83 | print "\n")) all |
84 | end |
85 | |
86 | end |