]> andersk Git - moira.git/blob - clients/moira/quota.c
Allow quotas to be specified in a form like '500mb' rather than '500000'
[moira.git] / clients / moira / quota.c
1 /* $Id$
2  *
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.
6  *
7  *      Created:        7/10/88
8  *      By:             Chris D. Peterson
9  *
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>.
13  */
14
15 #include <mit-copyright.h>
16 #include <moira.h>
17 #include <moira_site.h>
18 #include "defs.h"
19 #include "f_defs.h"
20 #include "globals.h"
21
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
29 static char *def_quota = NULL;
30
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"
35
36
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.
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
45 static char *GetDefaultUserQuota(Bool override)
46 {
47   int status;
48   char **info;
49   struct mqelem *top = NULL;
50   static char *val[] = {"def_quota", NULL};
51
52   if (override || (def_quota == NULL))
53     {
54       if ((status = do_mr_query("get_value", CountArgs(val), val,
55                                 StoreInfo, &top)))
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.");
61               def_quota = strdup("0");
62             }
63           else
64             Put_message("No default Quota Found, retaining old value.");
65         }
66       else
67         {
68           top = QueueTop(top);
69           info = top->q_data;
70           FreeAndClear(&def_quota, TRUE);
71           def_quota = strdup(info[0]);
72           FreeQueue(top);
73         }
74     }
75   return def_quota;
76 }
77
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
84 static void PrintDefaultQuota(char *quota)
85 {
86   char temp_buf[BUFSIZ];
87   Put_message("");
88   sprintf(temp_buf, "The default quota is %s Kb.", quota);
89   Put_message(temp_buf);
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
98 static char *PrintQuota(char **info)
99 {
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];
118 }
119
120
121 int afsfilsyshelper(int argc, char **argv, void *hint)
122 {
123   *(int *)hint = !strcmp(argv[FS_TYPE], "AFS");
124   return MR_CONT;
125 }
126
127
128 int afsfilesys(char *name)
129 {
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;
140 }
141
142
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
149 static char **GetQuotaArgs(Bool quota)
150 {
151   char **args = malloc(MAX_ARGS_SIZE * sizeof(char *));
152   int af;
153   char *canon;
154
155   if (!args)
156     {
157       Put_message("Could not allocate memory in GetQuotaArgs.");
158       return NULL;
159     }
160
161   args[Q_FILESYS] = strdup(DEFAULT_FILESYS);
162   args[Q_TYPE] = strdup(DEFAULT_QTYPE);
163   args[Q_NAME] = strdup(DEFAULT_USER);
164   if (quota)
165     {
166       args[Q_QUOTA] = strdup(GetDefaultUserQuota(FALSE));
167       args[Q_QUOTA + 1] = NULL; /* NULL terminate. */
168     }
169   else
170     args[Q_NAME + 1] = NULL;    /* NULL terminate. */
171
172   /* Get filesystem. */
173
174   if (GetValueFromUser("Filesystem", &args[Q_FILESYS]) == SUB_ERROR)
175     return NULL;
176   if (quota && !ValidName(args[Q_FILESYS]))
177     return NULL;
178
179   af = afsfilesys(args[Q_FILESYS]);
180   if (af != 0 && af != 1)
181     {
182       if (af == MR_NO_MATCH)
183         Put_message("That filesystem does not exist.");
184       else
185         com_err(program_name, af, " in afsfilesys");
186       return NULL;
187     }
188   if (af)
189     {
190       args[Q_TYPE] = strdup("ANY");
191       args[Q_NAME] = strdup(NOBODY);
192     }
193   else
194     {
195       if (GetTypeFromUser("Quota type", "quota_type", &args[Q_TYPE]) ==
196           SUB_ERROR)
197         return NULL;
198       if (GetValueFromUser("Name", &args[Q_NAME]) == SUB_ERROR)
199         return NULL;
200       if (!ValidName(args[Q_NAME]))
201         return NULL;
202     }
203
204   if (quota)                    /* Get and check quota. */
205     {
206       if (GetValueFromUser("Quota", &args[Q_QUOTA]) == SUB_ERROR)
207         return NULL;
208       if (!ValidName(args[Q_QUOTA]))
209         return NULL;
210       canon = ParseQuotaString(args[Q_QUOTA]);
211       if (!canon)
212         return NULL;
213       free(args[Q_QUOTA]);
214       args[Q_QUOTA] = canon;
215     }
216   return args;
217 }
218
219 /*      Function Name: ShowDefaultQuota
220  *      Description: This prints out a default quota for the system.
221  *      Arguments: none
222  *      Returns: DM_NORMAL.
223  */
224
225 int ShowDefaultQuota(int argc, char **argv)
226 {
227   PrintDefaultQuota(GetDefaultUserQuota(TRUE));
228   return DM_NORMAL;
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
237 int ChangeDefaultQuota(int argc, char *argv[])
238 {
239   int status;
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),
254                                 newval, NULL, NULL)) == MR_SUCCESS)
255         {
256           FreeAndClear(&def_quota, TRUE);
257           def_quota = strdup(argv[1]);
258         }
259       else
260         com_err(program_name, status, " in update_value");
261     }
262   else
263     Put_message("Quota not changed.");
264
265   return DM_NORMAL;
266 }
267
268 /* ------------------------ Filesystem Quotas -------------------- */
269
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
275  */
276
277 int GetQuota(int argc, char **argv)
278 {
279   struct mqelem *top = NULL;
280   int status;
281   char **args;
282
283   if (!(args = GetQuotaArgs(FALSE)))
284     return DM_NORMAL;
285
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");
289
290   FreeInfo(args);
291   free(args);
292
293   top = QueueTop(top);
294   Loop(top, (void (*)(char **)) PrintQuota);
295
296   FreeQueue(top);
297   return DM_NORMAL;
298 }
299
300 /*        Function Name: GetQuotaByFilesys
301  *        Description: Shows all quotas associated with the
302  *                     given filesystem
303  *        Arguments: none
304  *        Returns: DM_NORMAL
305  */
306
307 int GetQuotaByFilesys(int argc, char **argv)
308 {
309   struct mqelem *top = NULL;
310   int status;
311   char **args = malloc(2 * sizeof(char *));
312
313   if (!args)
314     {
315       Put_message("Could not allocate memory in GetQuotaByFilesys.");
316       return DM_NORMAL;
317     }
318
319   args[0] = strdup("");
320   args[1] = NULL;
321   if (GetValueFromUser("Filesystem", &args[0]) == SUB_ERROR)
322     return DM_NORMAL;
323
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");
327
328   FreeInfo(args);
329   free(args);
330
331   top = QueueTop(top);
332   Loop(top, (void (*)(char **)) PrintQuota);
333
334   FreeQueue(top);
335   return DM_NORMAL;
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  */
344 int AddQuota(int argc, char **argv)
345 {
346   char **args;
347   int status;
348
349   if (!(args = GetQuotaArgs(TRUE)))
350     return DM_NORMAL;
351
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");
355
356   FreeInfo(args);
357   free(args);
358   return DM_NORMAL;
359 }
360
361 /*      Function Name: RealUpdateQuota
362  *      Description: Performs the actual update of the quota
363  *      Arguments: info - the information nesc. to update the quota.
364  *      Returns: none.
365  */
366
367 static void RealUpdateQuota(char **info)
368 {
369   int status;
370   char temp_buf[BUFSIZ];
371   char *canon;
372
373   sprintf(temp_buf, "New quota for filesystem %s (in KB)", info[Q_FILESYS]);
374   if (GetValueFromUser(temp_buf, &info[Q_QUOTA]) == SUB_ERROR)
375     {
376       Put_message("Not changed.");
377       return;
378     }
379
380   canon = ParseQuotaString(info[Q_QUOTA]);
381   if (!canon)
382     return;
383   free(info[Q_QUOTA]);
384   info[Q_QUOTA] = canon;
385
386   if ((status = do_mr_query("update_quota", 4, info,
387                             NULL, NULL)) != MR_SUCCESS)
388       {
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     }
394 }
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
401  */
402
403 int UpdateQuota(int argc, char **argv)
404 {
405   int status;
406   char **args;
407   struct mqelem *top = NULL;
408
409   if (!(args = GetQuotaArgs(FALSE)))
410     return DM_NORMAL;
411
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");
415
416   FreeInfo(args);               /* done with args, free them. */
417   free(args);
418   top = QueueTop(top);
419   Loop(top, RealUpdateQuota);
420
421   FreeQueue(top);
422   return DM_NORMAL;
423 }
424
425
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
430  *                            we should confirm.
431  *      Returns: none.
432  */
433
434 static void RealDeleteQuota(char **info, Bool one_item)
435 {
436   int status;
437   char temp_buf[BUFSIZ];
438
439   if (!strcmp(info[Q_TYPE], "ANY"))
440     {
441       sprintf(temp_buf, "Do you really want to delete the quota on %s",
442               info[Q_FILESYS]);
443     }
444   else
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,
454                                 NULL, NULL)) != MR_SUCCESS)
455         com_err(program_name, status, " in delete_quota");
456       else
457         Put_message("Quota sucessfully removed.");
458     }
459   else
460     Put_message("Aborted.");
461 }
462
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
468  */
469
470 int DeleteQuota(int argc, char **argv)
471 {
472   int status;
473   char **args;
474   struct mqelem *top = NULL;
475
476   if (!(args = GetQuotaArgs(FALSE)))
477     return DM_NORMAL;
478
479   if ((status = do_mr_query("get_quota", 3, args, StoreInfo, &top)))
480     com_err(program_name, status, " in get_quota");
481
482   FreeInfo(args);
483   free(args);
484   top = QueueTop(top);
485   QueryLoop(top, PrintQuota, RealDeleteQuota,
486             "Delete this quota on filesystem");
487
488   FreeQueue(top);
489   return DM_NORMAL;
490 }
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 }
This page took 0.123158 seconds and 5 git commands to generate.