]> andersk Git - moira.git/blame - clients/moira/quota.c
Allow quotas to be specified in a form like '500mb' rather than '500000'
[moira.git] / clients / moira / quota.c
CommitLineData
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
26int afsfilsyshelper(int argc, char **argv, void *hint);
27int afsfilesys(char *name);
28
5eaef520 29static 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 45static 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 84static 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 98static 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 121int 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 128int 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 149static 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 225int 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 237int 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 277int 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 307int 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 344int 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 367static 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 403int 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 434static 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 470int 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
492char *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}
This page took 0.180732 seconds and 5 git commands to generate.