1 /*
2  Copyright (C) 1999-2004 IC & S  dbmail@ic-s.nl
3  Copyright (c) 2004-2012 NFG Net Facilities Group BV support@nfg.nl
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
8  version 2 of the License, or (at your option) any later
9  version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include "dbmail.h"
22 #include "dm_quota.h"
23 
24 #define THIS_MODULE "QUOTA"
25 
26 
27 #define T Quota_T
28 
29 #define QUOTA_ROOT_SIZE 128
30 
31 /* A resource type.
32  * RT_STORAGE:  "STORAGE"
33  */
34 typedef enum {
35 	RT_STORAGE
36 } resource_type_t;
37 
38 /* A resource limit.
39  * type:  the type of the resource
40  * usage: the current usage of the resource
41  * limit: the maximum allowed usage of the resource
42  */
43 typedef struct {
44 	resource_type_t type;
45 	uint64_t usage;
46 	uint64_t limit;
47 } resource_limit_t;
48 
49 /* A quota root and its resource limits.
50  * root:        the quota root, e.g. ""
51  * n_resources: the number of limted resources under this quota root
52  * resource[]:  an array with `n_resources' elements, each entry
53  *              describing a resource limit
54  */
55 struct T {
56 	char root[QUOTA_ROOT_SIZE];
57 	int n_resources;
58 	resource_limit_t resource[0];
59 };
60 
61 
62 /* Allocate a quota structure for `n_resources' resources.
63  * Returns NULL on failure.
64  */
quota_alloc(int n_resources)65 T quota_alloc(int n_resources)
66 {
67 	T quota;
68 
69 	quota = g_malloc0(sizeof(*quota) + n_resources * sizeof(resource_limit_t));
70 	quota->n_resources = n_resources;
71 
72 	return quota;
73 }
74 
75 /* Set a resource limit in a quota structure.
76  * quota:        the quota object to modify.
77  * resource_idx: the index of the resource to modify.
78  * type:         the type of the resource, e.g. RT_STORAGE.
79  * usage:        the current usage of the resource.
80  * limit:        the usage limit for the resource.
81  */
quota_set_resource_limit(T quota,int resource_idx,resource_type_t type,uint64_t usage,uint64_t limit)82 void quota_set_resource_limit(T quota, int resource_idx,
83 			      resource_type_t type,
84 			      uint64_t usage, uint64_t limit)
85 {
86 	resource_limit_t *rl = &(quota->resource[resource_idx]);
87 	rl->type = type;
88 	rl->usage = usage;
89 	rl->limit = limit;
90 }
91 
92 /* Set the name of the quota root.
93  * Returns 0 on success, 1 on failure.
94  * quota: the quota object to modify.
95  * root:  the (new) name of the quota root.
96  */
quota_get_root(T quota)97 const char * quota_get_root(T quota)
98 {
99 	return (const char *)quota->root;
100 }
101 
quota_set_root(T quota,const char * root)102 int quota_set_root(T quota, const char *root)
103 {
104 	memset(quota->root, 0, sizeof(quota->root));
105 	g_strlcpy(quota->root, root, sizeof(quota->root)-1);
106 	return 0;
107 }
108 
quota_get_limit(T quota)109 uint64_t quota_get_limit(T quota)
110 {
111 	return quota->resource[0].limit;
112 }
113 
quota_get_usage(T quota)114 uint64_t quota_get_usage(T quota)
115 {
116 	return quota->resource[0].usage;
117 }
118 
119 /* Free a quota structure. */
quota_free(T * quota)120 void quota_free(T *quota)
121 {
122 	T q = *quota;
123 	g_free(q);
124 	q = NULL;
125 }
126 
127 
128 /* Get the quota root for a given mailbox.
129  * Currently, the only supported quota root is "".
130  * Returns the name of the quota root, or NULL on failure
131  * (e.g. quota root not found). When NULL is returned, a pointer to
132  * an appropriate error message is stored in *errormsg.
133  *   useridnr: the useridnr of the mailbox owner.
134  *   mailbox:  the name of the mailbox.
135  *   errormsg: will point to an error message if NULL is returned.
136  */
quota_get_quotaroot(uint64_t useridnr,const char * mailbox,char ** errormsg)137 const char *quota_get_quotaroot(uint64_t useridnr, const char *mailbox,
138 			  char **errormsg)
139 {
140 	uint64_t mailbox_idnr;
141 
142 	if (! db_findmailbox(mailbox, useridnr, &mailbox_idnr)) {
143 		*errormsg = "mailbox not found";
144 		return NULL;
145 	}
146 
147 	return "";
148 }
149 
150 /* Get the quota for a given quota root.
151  * Currently, the only supported quota root is "".
152  * Returns a quota structure describing the given quota root,
153  * or NULL on failure. When NULL is returned, a pointer to
154  * an appropriate error message is stored in *errormsg.
155  *   useridnr:  the useridnr of the mailbox owner.
156  *   quotaroot: the quotaroot.
157  *   errormsg:  will point to an error message if NULL is returned.
158  */
quota_get_quota(uint64_t useridnr,const char * quotaroot,char ** errormsg)159 T quota_get_quota(uint64_t useridnr, const char *quotaroot, char **errormsg)
160 {
161 	T quota;
162 	uint64_t maxmail_size, usage;
163 
164 	/* Currently, there's only the quota root "". */
165 	if (strcmp(quotaroot, "") != 0) {
166 		TRACE(TRACE_ERR, "unknown quota root \"%s\"", quotaroot);
167 		*errormsg = "unknown quota root";
168 		return NULL;
169 	}
170 
171 	if (auth_getmaxmailsize(useridnr, &maxmail_size) == -1) {
172 		TRACE(TRACE_ERR, "auth_getmaxmailsize() failed\n");
173 		*errormsg = "invalid user";
174 		return NULL;
175 	}
176 
177 	if (dm_quota_user_get(useridnr, &usage) == -1) {
178 		TRACE(TRACE_ERR, "dm_quota_user_get() failed\n");
179 		*errormsg = "internal error";
180 		return NULL;
181 	}
182 
183 	/* We support exactly one resource: RT_STORAGE */
184 	quota = quota_alloc(1);
185 
186 	/* Set quota root */
187 	if (quota_set_root(quota, quotaroot)) {
188 		TRACE(TRACE_ERR, "quota_set_root() failed\n");
189 		*errormsg = "out of memory";
190 		return NULL;
191 	}
192 
193 	/* Set usage and limit for RT_STORAGE */
194 	quota_set_resource_limit(quota, 0, RT_STORAGE, usage,
195 				 maxmail_size);
196 
197 	return quota;
198 }
199