]>
Commit | Line | Data |
---|---|---|
c441a31a | 1 | /* $Id$ |
7ac48069 | 2 | * |
3 | * This is the file quota.c for the Moira Client, which allows users | |
59ec8dae | 4 | * to quickly and easily maintain most parts of the Moira database. |
0a2c64cb | 5 | * It Contains: Functions for manipulating the quota information. |
5eaef520 | 6 | * |
0a2c64cb | 7 | * Created: 7/10/88 |
8 | * By: Chris D. Peterson | |
73c83e3d | 9 | * |
7ac48069 | 10 | * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. |
11 | * For copying and distribution information, please see the file | |
12 | * <mit-copyright.h>. | |
73c83e3d | 13 | */ |
14 | ||
7ac48069 | 15 | #include <mit-copyright.h> |
8defc06b | 16 | #include <moira.h> |
17 | #include <moira_site.h> | |
0a2c64cb | 18 | #include "defs.h" |
19 | #include "f_defs.h" | |
73c83e3d | 20 | #include "globals.h" |
73c83e3d | 21 | |
7ac48069 | 22 | #include <stdio.h> |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | ||
26 | int afsfilsyshelper(int argc, char **argv, void *hint); | |
27 | int afsfilesys(char *name); | |
28 | ||
5eaef520 | 29 | static char *def_quota = NULL; |
30 | ||
73c83e3d | 31 | #define DEFAULT_FILESYS DEFAULT_NONE |
8defc06b | 32 | #define DEFAULT_USER user /* this is the user who started moira. */ |
6966e6fe | 33 | #define NOBODY "[nobody]" |
b124ed18 | 34 | #define DEFAULT_QTYPE "USER" |
bf96ab95 | 35 | |
73c83e3d | 36 | |
37 | /* Function Name: GetDefaultUserQuota | |
8defc06b | 38 | * Description: gets the user quota from moira, and caches the value. |
39 | * Arguments: override - if true, go to moira and override the cache. | |
73c83e3d | 40 | * Returns: none. |
41 | * NOTE: Using a queue here is pretty useless, but StoreInfo expects | |
42 | * one, and it works, so why fuck with it. | |
43 | */ | |
44 | ||
5eaef520 | 45 | static char *GetDefaultUserQuota(Bool override) |
73c83e3d | 46 | { |
44d12d58 | 47 | int status; |
5eaef520 | 48 | char **info; |
600b459e | 49 | struct mqelem *top = NULL; |
73c83e3d | 50 | static char *val[] = {"def_quota", NULL}; |
51 | ||
5eaef520 | 52 | if (override || (def_quota == NULL)) |
53 | { | |
54 | if ((status = do_mr_query("get_value", CountArgs(val), val, | |
7ac48069 | 55 | StoreInfo, &top))) |
5eaef520 | 56 | { |
57 | com_err(program_name, status, " in ShowDefaultQuota"); | |
58 | if (!def_quota) | |
59 | { | |
60 | Put_message("No default Quota Found, setting default to 0."); | |
7ac48069 | 61 | def_quota = strdup("0"); |
5eaef520 | 62 | } |
63 | else | |
64 | Put_message("No default Quota Found, retaining old value."); | |
65 | } | |
66 | else | |
67 | { | |
68 | top = QueueTop(top); | |
7ac48069 | 69 | info = top->q_data; |
5eaef520 | 70 | FreeAndClear(&def_quota, TRUE); |
7ac48069 | 71 | def_quota = strdup(info[0]); |
5eaef520 | 72 | FreeQueue(top); |
73c83e3d | 73 | } |
73c83e3d | 74 | } |
5eaef520 | 75 | return def_quota; |
73c83e3d | 76 | } |
5eaef520 | 77 | |
73c83e3d | 78 | /* Function Name: PrintDefaultQuota |
79 | * Description: Prints default quota info in a meaningful way. | |
80 | * Arguments: value of the default quota. | |
81 | * Returns: none. | |
82 | */ | |
83 | ||
5eaef520 | 84 | static void PrintDefaultQuota(char *quota) |
73c83e3d | 85 | { |
5eaef520 | 86 | char temp_buf[BUFSIZ]; |
87 | Put_message(""); | |
88 | sprintf(temp_buf, "The default quota is %s Kb.", quota); | |
89 | Put_message(temp_buf); | |
73c83e3d | 90 | } |
91 | ||
92 | /* Function Name: PrintQuota | |
93 | * Description: Prints a users quota information. | |
94 | * Arguments: info - a pointer to the quota information: | |
95 | * Returns: none. | |
96 | */ | |
97 | ||
5eaef520 | 98 | static char *PrintQuota(char **info) |
73c83e3d | 99 | { |
5eaef520 | 100 | char buf[BUFSIZ]; |
101 | ||
102 | Put_message(""); | |
103 | ||
104 | if (!strcmp(info[Q_TYPE], "ANY")) | |
105 | sprintf(buf, "Filesystem: %s", info[Q_FILESYS]); | |
106 | else | |
107 | sprintf(buf, "Filesystem: %-45s %s %s", info[Q_FILESYS], | |
108 | info[Q_TYPE], info[Q_NAME]); | |
109 | Put_message(buf); | |
110 | sprintf(buf, "Machine: %-20s Directory: %-15s", | |
111 | info[Q_MACHINE], info[Q_DIRECTORY]); | |
112 | Put_message(buf); | |
113 | sprintf(buf, "Quota: %s", info[Q_QUOTA]); | |
114 | Put_message(buf); | |
115 | sprintf(buf, MOD_FORMAT, info[Q_MODBY], info[Q_MODTIME], info[Q_MODWITH]); | |
116 | Put_message(buf); | |
117 | return info[Q_FILESYS]; | |
73c83e3d | 118 | } |
119 | ||
bf96ab95 | 120 | |
7ac48069 | 121 | int afsfilsyshelper(int argc, char **argv, void *hint) |
bf96ab95 | 122 | { |
7ac48069 | 123 | *(int *)hint = !strcmp(argv[FS_TYPE], "AFS"); |
124 | return MR_CONT; | |
bf96ab95 | 125 | } |
126 | ||
127 | ||
5eaef520 | 128 | int afsfilesys(char *name) |
bf96ab95 | 129 | { |
5eaef520 | 130 | int status, ret = 0; |
131 | char *argv[1]; | |
132 | ||
133 | if (strchr(name, '*') || strchr(name, '?') || strchr(name, '\\')) | |
134 | return 0; | |
135 | argv[0] = name; | |
136 | status = do_mr_query("get_filesys_by_label", 1, argv, afsfilsyshelper, &ret); | |
137 | if (status == MR_SUCCESS) | |
138 | return ret; | |
139 | return status; | |
bf96ab95 | 140 | } |
141 | ||
142 | ||
73c83e3d | 143 | /* Function Name: GetQuotaArgs |
144 | * Description: gets quota args from the user | |
145 | * Arguments: quota - if TRUE the get quota too. | |
146 | * Returns: the arguments. | |
147 | */ | |
148 | ||
5eaef520 | 149 | static char **GetQuotaArgs(Bool quota) |
73c83e3d | 150 | { |
5eaef520 | 151 | char **args = malloc(MAX_ARGS_SIZE * sizeof(char *)); |
6d8848f6 | 152 | int af; |
9db8c552 | 153 | char *canon; |
5eaef520 | 154 | |
155 | if (!args) | |
156 | { | |
157 | Put_message("Could not allocate memory in GetQuotaArgs."); | |
158 | return NULL; | |
159 | } | |
73c83e3d | 160 | |
7ac48069 | 161 | args[Q_FILESYS] = strdup(DEFAULT_FILESYS); |
162 | args[Q_TYPE] = strdup(DEFAULT_QTYPE); | |
163 | args[Q_NAME] = strdup(DEFAULT_USER); | |
5eaef520 | 164 | if (quota) |
165 | { | |
7ac48069 | 166 | args[Q_QUOTA] = strdup(GetDefaultUserQuota(FALSE)); |
5eaef520 | 167 | args[Q_QUOTA + 1] = NULL; /* NULL terminate. */ |
168 | } | |
169 | else | |
170 | args[Q_NAME + 1] = NULL; /* NULL terminate. */ | |
73c83e3d | 171 | |
172 | /* Get filesystem. */ | |
173 | ||
245b2337 | 174 | if (GetValueFromUser("Filesystem", &args[Q_FILESYS]) == SUB_ERROR) |
5eaef520 | 175 | return NULL; |
bf96ab95 | 176 | if (quota && !ValidName(args[Q_FILESYS])) |
5eaef520 | 177 | return NULL; |
178 | ||
6d8848f6 | 179 | af = afsfilesys(args[Q_FILESYS]); |
5eaef520 | 180 | if (af != 0 && af != 1) |
181 | { | |
6d8848f6 | 182 | if (af == MR_NO_MATCH) |
183 | Put_message("That filesystem does not exist."); | |
184 | else | |
185 | com_err(program_name, af, " in afsfilesys"); | |
5eaef520 | 186 | return NULL; |
187 | } | |
188 | if (af) | |
189 | { | |
7ac48069 | 190 | args[Q_TYPE] = strdup("ANY"); |
191 | args[Q_NAME] = strdup(NOBODY); | |
5eaef520 | 192 | } |
193 | else | |
194 | { | |
245b2337 | 195 | if (GetTypeFromUser("Quota type", "quota_type", &args[Q_TYPE]) == |
196 | SUB_ERROR) | |
5eaef520 | 197 | return NULL; |
245b2337 | 198 | if (GetValueFromUser("Name", &args[Q_NAME]) == SUB_ERROR) |
5eaef520 | 199 | return NULL; |
200 | if (!ValidName(args[Q_NAME])) | |
201 | return NULL; | |
202 | } | |
73c83e3d | 203 | |
5eaef520 | 204 | if (quota) /* Get and check quota. */ |
205 | { | |
245b2337 | 206 | if (GetValueFromUser("Quota", &args[Q_QUOTA]) == SUB_ERROR) |
5eaef520 | 207 | return NULL; |
208 | if (!ValidName(args[Q_QUOTA])) | |
209 | return NULL; | |
9db8c552 | 210 | canon = ParseQuotaString(args[Q_QUOTA]); |
211 | if (!canon) | |
212 | return NULL; | |
213 | free(args[Q_QUOTA]); | |
214 | args[Q_QUOTA] = canon; | |
5eaef520 | 215 | } |
216 | return args; | |
217 | } | |
73c83e3d | 218 | |
73c83e3d | 219 | /* Function Name: ShowDefaultQuota |
220 | * Description: This prints out a default quota for the system. | |
221 | * Arguments: none | |
222 | * Returns: DM_NORMAL. | |
223 | */ | |
224 | ||
7ac48069 | 225 | int ShowDefaultQuota(int argc, char **argv) |
73c83e3d | 226 | { |
227 | PrintDefaultQuota(GetDefaultUserQuota(TRUE)); | |
5eaef520 | 228 | return DM_NORMAL; |
73c83e3d | 229 | } |
230 | ||
231 | /* Function Name: ChangeDefaultQuota | |
232 | * Description: Changes the System Wide default quota. | |
233 | * Arguments: argc, argv - New quota in argv[1]. | |
234 | * Returns: DM_NORMAL. | |
235 | */ | |
236 | ||
5eaef520 | 237 | int ChangeDefaultQuota(int argc, char *argv[]) |
73c83e3d | 238 | { |
44d12d58 | 239 | int status; |
5eaef520 | 240 | char temp_buf[BUFSIZ]; |
241 | static char *newval[] = { | |
242 | "def_quota", NULL, NULL | |
243 | }; | |
244 | ||
245 | if (!ValidName(argv[1])) | |
246 | return DM_NORMAL; | |
247 | ||
248 | sprintf(temp_buf, "%s %s", "Are you sure that you want to", | |
249 | "change the default quota for all new users"); | |
250 | if (Confirm(temp_buf)) | |
251 | { | |
252 | newval[1] = argv[1]; | |
253 | if ((status = do_mr_query("update_value", CountArgs(newval), | |
7ac48069 | 254 | newval, NULL, NULL)) == MR_SUCCESS) |
5eaef520 | 255 | { |
73c83e3d | 256 | FreeAndClear(&def_quota, TRUE); |
7ac48069 | 257 | def_quota = strdup(argv[1]); |
73c83e3d | 258 | } |
5eaef520 | 259 | else |
260 | com_err(program_name, status, " in update_value"); | |
73c83e3d | 261 | } |
5eaef520 | 262 | else |
263 | Put_message("Quota not changed."); | |
73c83e3d | 264 | |
5eaef520 | 265 | return DM_NORMAL; |
73c83e3d | 266 | } |
267 | ||
b124ed18 | 268 | /* ------------------------ Filesystem Quotas -------------------- */ |
73c83e3d | 269 | |
b124ed18 | 270 | /* Function Name: GetQuota |
271 | * Description: Shows the quota of a filesystem w.r.t. | |
272 | * a group, user, or anybody (AFS) | |
273 | * Arguments: none | |
274 | * Returns: DM_NORMAL | |
73c83e3d | 275 | */ |
276 | ||
7ac48069 | 277 | int GetQuota(int argc, char **argv) |
73c83e3d | 278 | { |
600b459e | 279 | struct mqelem *top = NULL; |
44d12d58 | 280 | int status; |
5eaef520 | 281 | char **args; |
73c83e3d | 282 | |
5eaef520 | 283 | if (!(args = GetQuotaArgs(FALSE))) |
284 | return DM_NORMAL; | |
73c83e3d | 285 | |
5eaef520 | 286 | if ((status = do_mr_query("get_quota", CountArgs(args), args, |
7ac48069 | 287 | StoreInfo, &top)) != MR_SUCCESS) |
b124ed18 | 288 | com_err(program_name, status, " in get_quota"); |
289 | ||
290 | FreeInfo(args); | |
73c83e3d | 291 | free(args); |
292 | ||
293 | top = QueueTop(top); | |
a6da9354 | 294 | Loop(top, (void (*)(char **)) PrintQuota); |
b124ed18 | 295 | |
73c83e3d | 296 | FreeQueue(top); |
5eaef520 | 297 | return DM_NORMAL; |
73c83e3d | 298 | } |
299 | ||
b124ed18 | 300 | /* Function Name: GetQuotaByFilesys |
301 | * Description: Shows all quotas associated with the | |
302 | * given filesystem | |
303 | * Arguments: none | |
304 | * Returns: DM_NORMAL | |
73c83e3d | 305 | */ |
306 | ||
7ac48069 | 307 | int GetQuotaByFilesys(int argc, char **argv) |
b124ed18 | 308 | { |
600b459e | 309 | struct mqelem *top = NULL; |
44d12d58 | 310 | int status; |
5eaef520 | 311 | char **args = malloc(2 * sizeof(char *)); |
b124ed18 | 312 | |
5eaef520 | 313 | if (!args) |
314 | { | |
315 | Put_message("Could not allocate memory in GetQuotaByFilesys."); | |
316 | return DM_NORMAL; | |
317 | } | |
b124ed18 | 318 | |
7ac48069 | 319 | args[0] = strdup(""); |
0b48ba68 | 320 | args[1] = NULL; |
245b2337 | 321 | if (GetValueFromUser("Filesystem", &args[0]) == SUB_ERROR) |
5eaef520 | 322 | return DM_NORMAL; |
b124ed18 | 323 | |
5eaef520 | 324 | if ((status = do_mr_query("get_quota_by_filesys", 1, args, |
7ac48069 | 325 | StoreInfo, &top)) != MR_SUCCESS) |
b124ed18 | 326 | com_err(program_name, status, " in get_quota_by_filesys"); |
327 | ||
328 | FreeInfo(args); | |
329 | free(args); | |
330 | ||
331 | top = QueueTop(top); | |
a6da9354 | 332 | Loop(top, (void (*)(char **)) PrintQuota); |
b124ed18 | 333 | |
334 | FreeQueue(top); | |
5eaef520 | 335 | return DM_NORMAL; |
b124ed18 | 336 | } |
337 | ||
338 | /* Function Name: AddQuota | |
339 | * Description: Adds a new quota record for a filesystem | |
340 | * w.r.t. a user, group, or anybody (AFS). | |
341 | * Arguments: None | |
342 | * Returns: DM_NORMAL | |
343 | */ | |
7ac48069 | 344 | int AddQuota(int argc, char **argv) |
73c83e3d | 345 | { |
5eaef520 | 346 | char **args; |
44d12d58 | 347 | int status; |
73c83e3d | 348 | |
5eaef520 | 349 | if (!(args = GetQuotaArgs(TRUE))) |
350 | return DM_NORMAL; | |
351 | ||
352 | if ((status = do_mr_query("add_quota", CountArgs(args), args, | |
7ac48069 | 353 | NULL, NULL)) != MR_SUCCESS) |
b124ed18 | 354 | com_err(program_name, status, " in add_quota"); |
5eaef520 | 355 | |
73c83e3d | 356 | FreeInfo(args); |
357 | free(args); | |
5eaef520 | 358 | return DM_NORMAL; |
73c83e3d | 359 | } |
360 | ||
b124ed18 | 361 | /* Function Name: RealUpdateQuota |
362 | * Description: Performs the actual update of the quota | |
363 | * Arguments: info - the information nesc. to update the quota. | |
73c83e3d | 364 | * Returns: none. |
365 | */ | |
366 | ||
5eaef520 | 367 | static void RealUpdateQuota(char **info) |
73c83e3d | 368 | { |
44d12d58 | 369 | int status; |
73c83e3d | 370 | char temp_buf[BUFSIZ]; |
9db8c552 | 371 | char *canon; |
73c83e3d | 372 | |
373 | sprintf(temp_buf, "New quota for filesystem %s (in KB)", info[Q_FILESYS]); | |
5eaef520 | 374 | if (GetValueFromUser(temp_buf, &info[Q_QUOTA]) == SUB_ERROR) |
375 | { | |
245b2337 | 376 | Put_message("Not changed."); |
377 | return; | |
5eaef520 | 378 | } |
b124ed18 | 379 | |
9db8c552 | 380 | canon = ParseQuotaString(info[Q_QUOTA]); |
381 | if (!canon) | |
382 | return; | |
383 | free(info[Q_QUOTA]); | |
384 | info[Q_QUOTA] = canon; | |
385 | ||
7ac48069 | 386 | if ((status = do_mr_query("update_quota", 4, info, |
387 | NULL, NULL)) != MR_SUCCESS) | |
388 | { | |
5eaef520 | 389 | com_err(program_name, status, " in update_quota"); |
390 | sprintf(temp_buf, "Could not perform quota change on %s", | |
391 | info[Q_FILESYS]); | |
392 | Put_message(temp_buf); | |
393 | } | |
73c83e3d | 394 | } |
b124ed18 | 395 | |
396 | /* Function Name: UpdateQuota | |
397 | * Description: Updates an existing quota for a filesytem | |
398 | * w.r.t. a user, group, or anybody. | |
399 | * Arguments: None | |
400 | * Returns: DM_NORMAL | |
73c83e3d | 401 | */ |
402 | ||
7ac48069 | 403 | int UpdateQuota(int argc, char **argv) |
73c83e3d | 404 | { |
405 | int status; | |
406 | char **args; | |
600b459e | 407 | struct mqelem *top = NULL; |
73c83e3d | 408 | |
5eaef520 | 409 | if (!(args = GetQuotaArgs(FALSE))) |
410 | return DM_NORMAL; | |
411 | ||
412 | if ((status = do_mr_query("get_quota", CountArgs(args), args, | |
7ac48069 | 413 | StoreInfo, &top)) != MR_SUCCESS) |
b124ed18 | 414 | com_err(program_name, status, " in get_quota"); |
5eaef520 | 415 | |
73c83e3d | 416 | FreeInfo(args); /* done with args, free them. */ |
417 | free(args); | |
418 | top = QueueTop(top); | |
b124ed18 | 419 | Loop(top, RealUpdateQuota); |
73c83e3d | 420 | |
421 | FreeQueue(top); | |
5eaef520 | 422 | return DM_NORMAL; |
73c83e3d | 423 | } |
b124ed18 | 424 | |
425 | ||
426 | /* Function Name: RealDeleteQuota | |
427 | * Description: Actually removes the quota | |
428 | * Arguments: info - all information about this quota. | |
73c83e3d | 429 | * one_item - true if there is only one item in the queue, and |
430 | * we should confirm. | |
431 | * Returns: none. | |
432 | */ | |
433 | ||
5eaef520 | 434 | static void RealDeleteQuota(char **info, Bool one_item) |
73c83e3d | 435 | { |
44d12d58 | 436 | int status; |
73c83e3d | 437 | char temp_buf[BUFSIZ]; |
438 | ||
b124ed18 | 439 | if (!strcmp(info[Q_TYPE], "ANY")) |
5eaef520 | 440 | { |
441 | sprintf(temp_buf, "Do you really want to delete the quota on %s", | |
442 | info[Q_FILESYS]); | |
443 | } | |
b124ed18 | 444 | else |
5eaef520 | 445 | { |
446 | sprintf(temp_buf, "Do you really want to delete the %s %s's quota on %s", | |
447 | (strcmp(info[Q_TYPE], "USER") ? "group" : "user"), info[Q_NAME], | |
448 | info[Q_FILESYS]); | |
449 | } | |
450 | ||
451 | if (!one_item || Confirm(temp_buf)) | |
452 | { | |
453 | if ((status = do_mr_query("delete_quota", 3, info, | |
7ac48069 | 454 | NULL, NULL)) != MR_SUCCESS) |
5eaef520 | 455 | com_err(program_name, status, " in delete_quota"); |
456 | else | |
457 | Put_message("Quota sucessfully removed."); | |
458 | } | |
73c83e3d | 459 | else |
460 | Put_message("Aborted."); | |
461 | } | |
462 | ||
b124ed18 | 463 | /* Function Name: DeleteQuota |
464 | * Description: Removes the quota record for a filesystem | |
465 | * w.r.t. a user, group, or anybody. | |
466 | * Arguments: None | |
467 | * Returns: DM_NORMAL | |
73c83e3d | 468 | */ |
469 | ||
7ac48069 | 470 | int DeleteQuota(int argc, char **argv) |
73c83e3d | 471 | { |
44d12d58 | 472 | int status; |
73c83e3d | 473 | char **args; |
600b459e | 474 | struct mqelem *top = NULL; |
73c83e3d | 475 | |
5eaef520 | 476 | if (!(args = GetQuotaArgs(FALSE))) |
477 | return DM_NORMAL; | |
73c83e3d | 478 | |
7ac48069 | 479 | if ((status = do_mr_query("get_quota", 3, args, StoreInfo, &top))) |
b124ed18 | 480 | com_err(program_name, status, " in get_quota"); |
73c83e3d | 481 | |
482 | FreeInfo(args); | |
483 | free(args); | |
484 | top = QueueTop(top); | |
b124ed18 | 485 | QueryLoop(top, PrintQuota, RealDeleteQuota, |
486 | "Delete this quota on filesystem"); | |
73c83e3d | 487 | |
488 | FreeQueue(top); | |
5eaef520 | 489 | return DM_NORMAL; |
73c83e3d | 490 | } |
9db8c552 | 491 | |
492 | char *ParseQuotaString(char *quota) | |
493 | { | |
494 | char *s, *value; | |
495 | float ngigs, nmegs; | |
496 | int calcvalue; | |
497 | ||
498 | s = quota; | |
499 | while (*s && (isdigit(*s) || (*s == '.'))) | |
500 | s++; | |
501 | ||
502 | /* If we didn't find a unit specifier, just return the old value. */ | |
503 | if (!*s) | |
504 | return strdup(quota); | |
505 | ||
506 | switch (*s) { | |
507 | case 'm': | |
508 | case 'M': | |
509 | /* value specified in megabytes. */ | |
510 | if (!sscanf(quota, "%f2", &nmegs)) | |
511 | return strdup(quota); | |
512 | calcvalue = (int)(nmegs * 1000); | |
513 | break; | |
514 | case 'g': | |
515 | case 'G': | |
516 | /* value specified in gigabytes. */ | |
517 | if (!sscanf(quota, "%f2", &ngigs)) | |
518 | return strdup(quota); | |
519 | calcvalue = (int)(ngigs * 1000 * 1000); | |
520 | break; | |
521 | default: | |
522 | /* Couldn't parse it. Just return the old value. */ | |
523 | return strdup(quota); | |
524 | } | |
525 | ||
526 | value = malloc(BUFSIZ); | |
527 | if (!value) | |
528 | return NULL; | |
529 | sprintf(value, "%d", calcvalue); | |
530 | return value; | |
531 | } |