3 * This is the file quota.c for the Moira Client, which allows users
4 * to quickly and easily maintain most parts of the Moira database.
5 * It Contains: Functions for manipulating the quota information.
8 * By: Chris D. Peterson
10 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11 * For copying and distribution information, please see the file
15 #include <mit-copyright.h>
17 #include <moira_site.h>
26 int afsfilsyshelper(int argc, char **argv, void *hint);
27 int afsfilesys(char *name);
29 static char *def_quota = NULL;
31 #define DEFAULT_FILESYS DEFAULT_NONE
32 #define DEFAULT_USER user /* this is the user who started moira. */
33 #define NOBODY "[nobody]"
34 #define DEFAULT_QTYPE "USER"
37 /* Function Name: GetDefaultUserQuota
38 * Description: gets the user quota from moira, and caches the value.
39 * Arguments: override - if true, go to moira and override the cache.
41 * NOTE: Using a queue here is pretty useless, but StoreInfo expects
42 * one, and it works, so why fuck with it.
45 static char *GetDefaultUserQuota(Bool override)
49 struct mqelem *top = NULL;
50 static char *val[] = {"def_quota", NULL};
52 if (override || (def_quota == NULL))
54 if ((status = do_mr_query("get_value", CountArgs(val), val,
57 com_err(program_name, status, " in ShowDefaultQuota");
60 Put_message("No default Quota Found, setting default to 0.");
61 def_quota = strdup("0");
64 Put_message("No default Quota Found, retaining old value.");
70 FreeAndClear(&def_quota, TRUE);
71 def_quota = strdup(info[0]);
78 /* Function Name: PrintDefaultQuota
79 * Description: Prints default quota info in a meaningful way.
80 * Arguments: value of the default quota.
84 static void PrintDefaultQuota(char *quota)
86 char temp_buf[BUFSIZ];
88 sprintf(temp_buf, "The default quota is %s Kb.", quota);
89 Put_message(temp_buf);
92 /* Function Name: PrintQuota
93 * Description: Prints a users quota information.
94 * Arguments: info - a pointer to the quota information:
98 static char *PrintQuota(char **info)
104 if (!strcmp(info[Q_TYPE], "ANY"))
105 sprintf(buf, "Filesystem: %s", info[Q_FILESYS]);
107 sprintf(buf, "Filesystem: %-45s %s %s", info[Q_FILESYS],
108 info[Q_TYPE], info[Q_NAME]);
110 sprintf(buf, "Machine: %-20s Directory: %-15s",
111 info[Q_MACHINE], info[Q_DIRECTORY]);
113 sprintf(buf, "Quota: %s", info[Q_QUOTA]);
115 sprintf(buf, MOD_FORMAT, info[Q_MODBY], info[Q_MODTIME], info[Q_MODWITH]);
117 return info[Q_FILESYS];
121 int afsfilsyshelper(int argc, char **argv, void *hint)
123 *(int *)hint = !strcmp(argv[FS_TYPE], "AFS");
128 int afsfilesys(char *name)
133 if (strchr(name, '*') || strchr(name, '?') || strchr(name, '\\'))
136 status = do_mr_query("get_filesys_by_label", 1, argv, afsfilsyshelper, &ret);
137 if (status == MR_SUCCESS)
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.
149 static char **GetQuotaArgs(Bool quota)
151 char **args = malloc(MAX_ARGS_SIZE * sizeof(char *));
157 Put_message("Could not allocate memory in GetQuotaArgs.");
161 args[Q_FILESYS] = strdup(DEFAULT_FILESYS);
162 args[Q_TYPE] = strdup(DEFAULT_QTYPE);
163 args[Q_NAME] = strdup(DEFAULT_USER);
166 args[Q_QUOTA] = strdup(GetDefaultUserQuota(FALSE));
167 args[Q_QUOTA + 1] = NULL; /* NULL terminate. */
170 args[Q_NAME + 1] = NULL; /* NULL terminate. */
172 /* Get filesystem. */
174 if (GetValueFromUser("Filesystem", &args[Q_FILESYS]) == SUB_ERROR)
176 if (quota && !ValidName(args[Q_FILESYS]))
179 af = afsfilesys(args[Q_FILESYS]);
180 if (af != 0 && af != 1)
182 if (af == MR_NO_MATCH)
183 Put_message("That filesystem does not exist.");
185 com_err(program_name, af, " in afsfilesys");
190 args[Q_TYPE] = strdup("ANY");
191 args[Q_NAME] = strdup(NOBODY);
195 if (GetTypeFromUser("Quota type", "quota_type", &args[Q_TYPE]) ==
198 if (GetValueFromUser("Name", &args[Q_NAME]) == SUB_ERROR)
200 if (!ValidName(args[Q_NAME]))
204 if (quota) /* Get and check quota. */
206 if (GetValueFromUser("Quota", &args[Q_QUOTA]) == SUB_ERROR)
208 if (!ValidName(args[Q_QUOTA]))
210 canon = ParseQuotaString(args[Q_QUOTA]);
214 args[Q_QUOTA] = canon;
219 /* Function Name: ShowDefaultQuota
220 * Description: This prints out a default quota for the system.
222 * Returns: DM_NORMAL.
225 int ShowDefaultQuota(int argc, char **argv)
227 PrintDefaultQuota(GetDefaultUserQuota(TRUE));
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.
237 int ChangeDefaultQuota(int argc, char *argv[])
240 char temp_buf[BUFSIZ];
241 static char *newval[] = {
242 "def_quota", NULL, NULL
245 if (!ValidName(argv[1]))
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))
253 if ((status = do_mr_query("update_value", CountArgs(newval),
254 newval, NULL, NULL)) == MR_SUCCESS)
256 FreeAndClear(&def_quota, TRUE);
257 def_quota = strdup(argv[1]);
260 com_err(program_name, status, " in update_value");
263 Put_message("Quota not changed.");
268 /* ------------------------ Filesystem Quotas -------------------- */
270 /* Function Name: GetQuota
271 * Description: Shows the quota of a filesystem w.r.t.
272 * a group, user, or anybody (AFS)
277 int GetQuota(int argc, char **argv)
279 struct mqelem *top = NULL;
283 if (!(args = GetQuotaArgs(FALSE)))
286 if ((status = do_mr_query("get_quota", CountArgs(args), args,
287 StoreInfo, &top)) != MR_SUCCESS)
288 com_err(program_name, status, " in get_quota");
294 Loop(top, (void (*)(char **)) PrintQuota);
300 /* Function Name: GetQuotaByFilesys
301 * Description: Shows all quotas associated with the
307 int GetQuotaByFilesys(int argc, char **argv)
309 struct mqelem *top = NULL;
311 char **args = malloc(2 * sizeof(char *));
315 Put_message("Could not allocate memory in GetQuotaByFilesys.");
319 args[0] = strdup("");
321 if (GetValueFromUser("Filesystem", &args[0]) == SUB_ERROR)
324 if ((status = do_mr_query("get_quota_by_filesys", 1, args,
325 StoreInfo, &top)) != MR_SUCCESS)
326 com_err(program_name, status, " in get_quota_by_filesys");
332 Loop(top, (void (*)(char **)) PrintQuota);
338 /* Function Name: AddQuota
339 * Description: Adds a new quota record for a filesystem
340 * w.r.t. a user, group, or anybody (AFS).
344 int AddQuota(int argc, char **argv)
349 if (!(args = GetQuotaArgs(TRUE)))
352 if ((status = do_mr_query("add_quota", CountArgs(args), args,
353 NULL, NULL)) != MR_SUCCESS)
354 com_err(program_name, status, " in add_quota");
361 /* Function Name: RealUpdateQuota
362 * Description: Performs the actual update of the quota
363 * Arguments: info - the information nesc. to update the quota.
367 static void RealUpdateQuota(char **info)
370 char temp_buf[BUFSIZ];
373 sprintf(temp_buf, "New quota for filesystem %s (in KB)", info[Q_FILESYS]);
374 if (GetValueFromUser(temp_buf, &info[Q_QUOTA]) == SUB_ERROR)
376 Put_message("Not changed.");
380 canon = ParseQuotaString(info[Q_QUOTA]);
384 info[Q_QUOTA] = canon;
386 if ((status = do_mr_query("update_quota", 4, info,
387 NULL, NULL)) != MR_SUCCESS)
389 com_err(program_name, status, " in update_quota");
390 sprintf(temp_buf, "Could not perform quota change on %s",
392 Put_message(temp_buf);
396 /* Function Name: UpdateQuota
397 * Description: Updates an existing quota for a filesytem
398 * w.r.t. a user, group, or anybody.
403 int UpdateQuota(int argc, char **argv)
407 struct mqelem *top = NULL;
409 if (!(args = GetQuotaArgs(FALSE)))
412 if ((status = do_mr_query("get_quota", CountArgs(args), args,
413 StoreInfo, &top)) != MR_SUCCESS)
414 com_err(program_name, status, " in get_quota");
416 FreeInfo(args); /* done with args, free them. */
419 Loop(top, RealUpdateQuota);
426 /* Function Name: RealDeleteQuota
427 * Description: Actually removes the quota
428 * Arguments: info - all information about this quota.
429 * one_item - true if there is only one item in the queue, and
434 static void RealDeleteQuota(char **info, Bool one_item)
437 char temp_buf[BUFSIZ];
439 if (!strcmp(info[Q_TYPE], "ANY"))
441 sprintf(temp_buf, "Do you really want to delete the quota on %s",
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],
451 if (!one_item || Confirm(temp_buf))
453 if ((status = do_mr_query("delete_quota", 3, info,
454 NULL, NULL)) != MR_SUCCESS)
455 com_err(program_name, status, " in delete_quota");
457 Put_message("Quota sucessfully removed.");
460 Put_message("Aborted.");
463 /* Function Name: DeleteQuota
464 * Description: Removes the quota record for a filesystem
465 * w.r.t. a user, group, or anybody.
470 int DeleteQuota(int argc, char **argv)
474 struct mqelem *top = NULL;
476 if (!(args = GetQuotaArgs(FALSE)))
479 if ((status = do_mr_query("get_quota", 3, args, StoreInfo, &top)))
480 com_err(program_name, status, " in get_quota");
485 QueryLoop(top, PrintQuota, RealDeleteQuota,
486 "Delete this quota on filesystem");
492 char *ParseQuotaString(char *quota)
499 while (*s && (isdigit(*s) || (*s == '.')))
502 /* If we didn't find a unit specifier, just return the old value. */
504 return strdup(quota);
509 /* value specified in megabytes. */
510 if (!sscanf(quota, "%f2", &nmegs))
511 return strdup(quota);
512 calcvalue = (int)(nmegs * 1000);
516 /* value specified in gigabytes. */
517 if (!sscanf(quota, "%f2", &ngigs))
518 return strdup(quota);
519 calcvalue = (int)(ngigs * 1000 * 1000);
522 /* Couldn't parse it. Just return the old value. */
523 return strdup(quota);
526 value = malloc(BUFSIZ);
529 sprintf(value, "%d", calcvalue);