source: trunk/third/moira/clients/moira/quota.c @ 23740

Revision 23740, 12.5 KB checked in by broder, 16 years ago (diff)
In moira: * New CVS snapshot (Trac: #195) * Drop patches that have been incorporated upstream. * Update to build without krb4 on systems that no longer have it. This doesn't build yet on squeeze, which lacks a krb4 library, but I'm committing now before I start hacking away at a patch to fix that.
Line 
1/* $Id: quota.c,v 1.31 2003-09-22 20:44:16 zacheiss Exp $
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
26int afsfilsyshelper(int argc, char **argv, void *hint);
27int afsfilesys(char *name);
28
29static 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
45static 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
84static 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
98static 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
121int afsfilsyshelper(int argc, char **argv, void *hint)
122{
123  *(int *)hint = !strcmp(argv[FS_TYPE], "AFS");
124  return MR_CONT;
125}
126
127
128int 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
149static 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
225int 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
237int 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
277int 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
307int 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 */
344int 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
367static 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
403int 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
434static 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
470int 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
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}
Note: See TracBrowser for help on using the repository browser.