]> andersk Git - moira.git/blob - server/qsetup.pc
Use moira_schema.h
[moira.git] / server / qsetup.pc
1 /* $Id$
2  *
3  * Query setup routines
4  *
5  * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include "mr_server.h"
12 #include "query.h"
13 #include "qrtn.h"
14
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
17
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 EXEC SQL INCLUDE sqlca;
23
24 RCSID("$Header$");
25
26 extern char *whoami;
27 extern int dbms_errno, mr_errcode;
28
29 EXEC SQL BEGIN DECLARE SECTION;
30 extern char stmt_buf[];
31 EXEC SQL END DECLARE SECTION;
32
33 EXEC SQL WHENEVER SQLERROR DO dbmserr();
34
35
36 int prefetch_value(struct query *q, char **argv, client *cl);
37 int check_nfs(int mach_idx, char *name, char *access);
38
39 /* Setup Routines */
40
41 /* Setup routine for add_user
42  *
43  * Inputs: argv[0] - login
44  *         argv[1] - uid
45  *
46  * Description:
47  *
48  * - if argv[1] == UNIQUE_UID then set argv[1] = next(uid)
49  * - if argv[0] == UNIQUE_LOGIN then set argv[0] = "#<uid>"
50  */
51
52 int setup_ausr(struct query *q, char *argv[], client *cl)
53 {
54   int row, err;
55   EXEC SQL BEGIN DECLARE SECTION;
56   int nuid;
57   EXEC SQL END DECLARE SECTION;
58
59   if (!strcmp(q->shortname, "uusr") || !strcmp(q->shortname, "uuac"))
60     row = 2;
61   else
62     row = 1;
63   if (!strcmp(argv[row], UNIQUE_UID) || atoi(argv[row]) == -1)
64     {
65       if ((err = set_next_object_id("unix_uid", USERS_TABLE, 1)))
66         return err;
67       EXEC SQL SELECT value INTO :nuid FROM numvalues WHERE name = 'unix_uid';
68       if (sqlca.sqlerrd[2] != 1)
69         return MR_INTERNAL;
70       sprintf(argv[row], "%d", nuid);
71     }
72
73   if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
74     sprintf(argv[0], "#%s", argv[row]);
75
76   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
77     return mr_errcode;
78
79   return MR_SUCCESS;
80 }
81
82
83 /* setup_dusr - verify that the user is no longer being referenced
84  * and may safely be deleted.
85  */
86
87 int setup_dusr(struct query *q, char *argv[], client *cl)
88 {
89   EXEC SQL BEGIN DECLARE SECTION;
90   int flag, id, cnt;
91   EXEC SQL END DECLARE SECTION;
92
93   id = *(int *)argv[0];
94
95   /* For now, only allow users to be deleted if their status is 0 */
96   EXEC SQL SELECT status INTO :flag FROM users WHERE users_id = :id;
97   if (flag != 0 && flag != 4)
98     return MR_IN_USE;
99
100   EXEC SQL DELETE FROM quota WHERE entity_id = :id AND type = 'USER';
101   EXEC SQL DELETE FROM krbmap WHERE users_id = :id;
102   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
103     WHERE member_id = :id AND member_type = 'USER';
104   if (cnt > 0)
105     return MR_IN_USE;
106   EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys
107     WHERE owner = :id;
108   if (cnt > 0)
109     return MR_IN_USE;
110   EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
111     WHERE acl_id = :id AND acl_type = 'USER';
112   if (cnt > 0)
113     return MR_IN_USE;
114   EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
115     WHERE acl_id = :id AND acl_type = 'USER';
116   if (cnt > 0)
117     return MR_IN_USE;
118   EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
119     WHERE acl_id = :id AND acl_type = 'USER';
120   if (cnt > 0)
121     return MR_IN_USE;
122   if (dbms_errno)
123     return mr_errcode;
124   return MR_SUCCESS;
125 }
126
127
128 /* setup_spop: verify that there is already a valid POP machine_id in the
129  * pop_id field.  Also take care of keeping track of the post office usage.
130  */
131 int setup_spop(struct query *q, char *argv[], client *cl)
132 {
133   EXEC SQL BEGIN DECLARE SECTION;
134   int id, mid;
135   char type[USERS_POTYPE_SIZE];
136   EXEC SQL END DECLARE SECTION;
137
138   id = *(int *)argv[0];
139   EXEC SQL SELECT potype, pop_id INTO :type, :mid FROM users
140     WHERE users_id = :id;
141   if (sqlca.sqlerrd[2] == 0)
142     return MR_MACHINE;
143   EXEC SQL SELECT mach_id INTO :mid FROM machine
144     WHERE mach_id = :mid;
145   if (sqlca.sqlerrd[2] == 0)
146     return MR_MACHINE;
147   if (strcmp(strtrim(type), "POP"))
148     set_pop_usage(mid, 1);
149   return MR_SUCCESS;
150 }
151
152
153 /* setup_dpob:  Take care of keeping track of the post office usage.
154  */
155 int setup_dpob(struct query *q, char *argv[], client *cl)
156 {
157   EXEC SQL BEGIN DECLARE SECTION;
158   int id, user;
159   char type[USERS_POTYPE_SIZE];
160   EXEC SQL END DECLARE SECTION;
161
162   user = *(int *)argv[0];
163   EXEC SQL SELECT potype, pop_id INTO :type, :id FROM users
164     WHERE users_id = :user;
165   if (dbms_errno)
166     return mr_errcode;
167
168   if (!strcmp(strtrim(type), "POP"))
169     set_pop_usage(id, -1);
170   return MR_SUCCESS;
171 }
172
173
174 /* setup_dmac - verify that the machine is no longer being referenced
175  * and may safely be deleted.
176  */
177
178 int setup_dmac(struct query *q, char *argv[], client *cl)
179 {
180   EXEC SQL BEGIN DECLARE SECTION;
181   int flag, id, cnt;
182   EXEC SQL END DECLARE SECTION;
183
184   id = *(int *)argv[0];
185
186   EXEC SQL SELECT status INTO :flag FROM machine
187     WHERE mach_id = :id;
188   if (flag != 3)
189     return MR_IN_USE;
190   EXEC SQL SELECT COUNT(login) INTO :cnt FROM users
191     WHERE potype = 'POP' AND pop_id = :id;
192   if (cnt > 0)
193     return MR_IN_USE;
194   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM serverhosts
195     WHERE mach_id = :id;
196   if (cnt > 0)
197     return MR_IN_USE;
198   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM nfsphys
199     WHERE mach_id = :id;
200   if (cnt > 0)
201     return MR_IN_USE;
202   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostaccess
203     WHERE mach_id = :id;
204   if (cnt > 0)
205     return MR_IN_USE;
206   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM printcap
207     WHERE mach_id = :id;
208   if (cnt > 0)
209     return MR_IN_USE;
210   EXEC SQL SELECT COUNT(quotaserver) INTO :cnt FROM printcap
211     WHERE quotaserver = :id;
212   if (cnt > 0)
213     return MR_IN_USE;
214   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM palladium
215     WHERE mach_id = :id;
216   if (cnt > 0)
217     return MR_IN_USE;
218   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM hostalias
219     WHERE mach_id = :id;
220   if (cnt > 0)
221     return MR_IN_USE;
222
223   EXEC SQL DELETE FROM mcmap WHERE mach_id = :id;
224   if (dbms_errno)
225     return mr_errcode;
226   return MR_SUCCESS;
227 }
228
229
230 /* setup_dsnt - verify that the subnet is no longer being referenced
231  * and may safely be deleted.
232  */
233
234 int setup_dsnt(struct query *q, char *argv[], client *cl)
235 {
236   EXEC SQL BEGIN DECLARE SECTION;
237   int id, cnt = 0;
238   EXEC SQL END DECLARE SECTION;
239
240   id = *(int *)argv[0];
241   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM machine
242     WHERE snet_id = :id;
243   if (cnt > 0)
244     return MR_IN_USE;
245   return MR_SUCCESS;
246 }
247
248
249 /* setup_dclu - verify that the cluster is no longer being referenced
250  * and may safely be deleted.
251  */
252
253 int setup_dclu(struct query *q, char *argv[], client *cl)
254 {
255   EXEC SQL BEGIN DECLARE SECTION;
256   int id, cnt;
257   EXEC SQL END DECLARE SECTION;
258
259   id = *(int *)argv[0];
260   EXEC SQL SELECT COUNT(mach_id) INTO :cnt FROM mcmap
261     WHERE clu_id = :id;
262   if (cnt > 0)
263     return MR_IN_USE;
264   EXEC SQL SELECT COUNT(clu_id) INTO :cnt FROM svc
265     WHERE clu_id = :id;
266   if (cnt > 0)
267     return MR_IN_USE;
268   if (dbms_errno)
269     return mr_errcode;
270   return MR_SUCCESS;
271 }
272
273
274 /* setup_alis - if argv[5] is non-zero and argv[6] is UNIQUE_ID, then allocate
275  * a new gid and put it in argv[6].  Otherwise if argv[6] is UNIQUE_ID but
276  * argv[5] is not, then remember that UNIQUE_ID is being stored by putting
277  * a -1 there.  Remember that this is also used for ulis, with the indexes
278  * at 6 & 7.  Also check that the list name does not contain uppercase
279  * characters, control characters, @, or :.
280  */
281
282 static int badlistchars[] = {
283   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
284   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
285   1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
286   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
287   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
288   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, /* P - _ */
289   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
290   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
291   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
292   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
293   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
294   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
295   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
296   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
297   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
298   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
299 };
300
301 int setup_alis(struct query *q, char *argv[], client *cl)
302 {
303   EXEC SQL BEGIN DECLARE SECTION;
304   int ngid;
305   EXEC SQL END DECLARE SECTION;
306   unsigned char *p;
307   int idx, err;
308
309   if (!strcmp(q->shortname, "alis"))
310     idx = 0;
311   else if (!strcmp(q->shortname, "ulis"))
312     idx = 1;
313
314   for (p = (unsigned char *) argv[idx]; *p; p++)
315     {
316       if (badlistchars[*p])
317         return MR_BAD_CHAR;
318     }
319
320   if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
321     {
322       if (atoi(argv[5 + idx]))
323         {
324           if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
325             return err;
326           EXEC SQL SELECT value INTO :ngid FROM numvalues
327             WHERE name = 'gid';
328           if (dbms_errno)
329             return mr_errcode;
330           sprintf(argv[6 + idx], "%d", ngid);
331         }
332       else
333         strcpy(argv[6 + idx], "-1");
334     }
335
336   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
337     return mr_errcode;
338
339   return MR_SUCCESS;
340 }
341
342
343 /* setup_dlis - verify that the list is no longer being referenced
344  * and may safely be deleted.
345  */
346
347 int setup_dlis(struct query *q, char *argv[], client *cl)
348 {
349   int id;
350   EXEC SQL BEGIN DECLARE SECTION;
351   int cnt;
352   EXEC SQL END DECLARE SECTION;
353
354   id = *(int *)argv[0];
355
356   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
357     WHERE member_id = :id AND member_type = 'LIST';
358   if (cnt > 0)
359     return MR_IN_USE;
360
361   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
362     WHERE member_id = :id AND member_type = 'LIST';
363   if (cnt > 0)
364     return MR_IN_USE;
365
366   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
367     WHERE list_id = :id;
368   if (cnt > 0)
369     return MR_IN_USE;
370
371   EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
372   if (cnt > 0)
373     return MR_IN_USE;
374
375   EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
376   if (cnt > 0)
377     return MR_IN_USE;
378
379   EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
380     WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
381   if (cnt > 0)
382     return MR_IN_USE;
383
384   EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
385     WHERE acl_id = :id AND acl_type = 'LIST';
386   if (cnt > 0)
387     return MR_IN_USE;
388
389   EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
390     WHERE entity_id = :id AND type = 'GROUP';
391   if (cnt > 0)
392     return MR_IN_USE;
393
394   EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
395     WHERE acl_id = :id AND acl_type = 'LIST';
396   if (cnt > 0)
397     return MR_IN_USE;
398
399   EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
400     WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
401     OR z.sub_type = 'LIST' AND z.sub_id = :id
402     OR z.iws_type = 'LIST' AND z.iws_id = :id
403     OR z.iui_type = 'LIST' AND z.iui_id = :id;
404   if (cnt > 0)
405     return MR_IN_USE;
406
407   return MR_SUCCESS;
408 }
409
410
411 /* setup_dsin - verify that the service is no longer being referenced
412  * and may safely be deleted.
413  */
414
415 int setup_dsin(struct query *q, char *argv[], client *cl)
416 {
417   EXEC SQL BEGIN DECLARE SECTION;
418   int ec, cnt;
419   char *svrname;
420   EXEC SQL END DECLARE SECTION;
421
422   svrname = argv[0];
423   EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
424     WHERE service = UPPER(:svrname);
425   if (cnt > 0)
426     return MR_IN_USE;
427
428   EXEC SQL SELECT inprogress INTO :ec FROM servers
429     WHERE name = UPPER(:svrname);
430   if (dbms_errno)
431     return mr_errcode;
432   if (ec)
433     return MR_IN_USE;
434
435   return MR_SUCCESS;
436 }
437
438
439 /* setup_dshi - verify that the service-host is no longer being referenced
440  * and may safely be deleted.
441  */
442
443 int setup_dshi(struct query *q, char *argv[], client *cl)
444 {
445   EXEC SQL BEGIN DECLARE SECTION;
446   int id, ec;
447   char *svrname;
448   EXEC SQL END DECLARE SECTION;
449
450   svrname = argv[0];
451   id = *(int *)argv[1];
452
453   EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
454     WHERE service = UPPER(:svrname) AND mach_id = :id;
455   if (dbms_errno)
456     return mr_errcode;
457   if (ec)
458     return MR_IN_USE;
459
460   return MR_SUCCESS;
461 }
462
463
464 /**
465  ** setup_add_filesys - verify existance of referenced file systems
466  **
467  ** Inputs:     Add
468  **   argv[1] - type
469  **   argv[2] - mach_id
470  **   argv[3] - name
471  **   argv[5] - rwaccess
472  **
473  ** Description:
474  **   - for type = RVD:
475  **        * allow anything
476  **   - for type = NFS:
477  **        * extract directory prefix from name
478  **        * verify mach_id/dir in nfsphys
479  **        * verify rwaccess in {r, w, R, W}
480  **
481  **  Side effect: sets variable _var_phys_id to the ID of the physical
482  **     filesystem (nfsphys_id for NFS, 0 for RVD)
483  **
484  ** Errors:
485  **   MR_NFS - specified directory not exported
486  **   MR_FILESYS_ACCESS - invalid filesys access
487  **
488  **/
489
490 EXEC SQL BEGIN DECLARE SECTION;
491 int _var_phys_id;
492 EXEC SQL END DECLARE SECTION;
493
494 int setup_afil(struct query *q, char *argv[], client *cl)
495 {
496   char *type, *name;
497   int mach_id;
498   EXEC SQL BEGIN DECLARE SECTION;
499   int ok;
500   char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
501   EXEC SQL END DECLARE SECTION;
502
503   type = argv[1];
504   mach_id = *(int *)argv[2];
505   name = argv[3];
506   rwaccess = argv[5];
507   _var_phys_id = 0;
508
509   sprintf(ftype, "fs_access_%s", type);
510   EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
511     WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
512   if (dbms_errno)
513     return mr_errcode;
514   if (ok == 0)
515     return MR_FILESYS_ACCESS;
516
517   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
518     return mr_errcode;
519
520   if (!strcmp(type, "NFS"))
521     return check_nfs(mach_id, name, rwaccess);
522
523   return MR_SUCCESS;
524 }
525
526
527 /* Verify the arguments, depending on the FStype.  Also, if this is an
528  * NFS filesystem, then update any quotas for that filesystem to reflect
529  * the new phys_id.
530  */
531
532 int setup_ufil(struct query *q, char *argv[], client *cl)
533 {
534   int mach_id, status;
535   char *type, *name;
536   EXEC SQL BEGIN DECLARE SECTION;
537   int fid, total, who, ok;
538   char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
539   short int total_null;
540   EXEC SQL END DECLARE SECTION;
541
542   _var_phys_id = 0;
543   type = argv[2];
544   mach_id = *(int *)argv[3];
545   name = argv[4];
546   access = argv[6];
547   fid = *(int *)argv[0];
548   who = cl->client_id;
549   entity = cl->entity;
550
551   sprintf(ftype, "fs_access_%s", type);
552   EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
553     WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
554   if (dbms_errno)
555     return mr_errcode;
556   if (ok == 0)
557     return MR_FILESYS_ACCESS;
558
559   EXEC SQL SELECT type INTO :ftype FROM filesys
560     WHERE filsys_id = :fid;
561   if (dbms_errno)
562     return mr_errcode;
563
564   if (!strcmp(type, "NFS"))
565     {
566       status = check_nfs(mach_id, name, access);
567       EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
568         WHERE filsys_id = :fid;
569       if (dbms_errno)
570         return mr_errcode;
571       return status;
572     }
573   else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
574            && strcmp(strtrim(ftype), "ERR"))
575     {
576       total = 0;
577       EXEC SQL DELETE FROM quota
578         WHERE type = 'ANY' AND filsys_id = :fid;
579       EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
580         WHERE filsys_id = :fid AND phys_id != 0;
581       if (dbms_errno)
582         return mr_errcode;
583       if (!total_null && (total != 0))
584         {
585           EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
586                                       type, modtime, modby, modwith)
587             VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
588           if (dbms_errno)
589             return mr_errcode;
590         }
591     }
592   else
593     {
594       EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
595       if (dbms_errno)
596         return mr_errcode;
597     }
598   return MR_SUCCESS;
599 }
600
601
602 /* Find the NFS physical partition that the named directory is on.
603  * This is done by comparing the dir against the mount point of the
604  * partition.  To make sure we get the correct match when there is
605  * more than one, we sort the query in reverse order by dir name.
606  */
607
608 int check_nfs(int mach_id, char *name, char *access)
609 {
610   EXEC SQL BEGIN DECLARE SECTION;
611   char dir[NFSPHYS_DIR_SIZE];
612   int mid = mach_id;
613   EXEC SQL END DECLARE SECTION;
614   int status;
615   char *cp1;
616   char *cp2;
617
618   status = MR_NFS;
619   EXEC SQL DECLARE csr101 CURSOR FOR
620     SELECT nfsphys_id, dir FROM nfsphys
621     WHERE mach_id = :mid
622     ORDER BY 2 DESC;
623   if (dbms_errno)
624     return mr_errcode;
625   EXEC SQL OPEN csr101;
626   if (dbms_errno)
627     return mr_errcode;
628   while (1)
629     {
630       EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
631       if (sqlca.sqlcode)
632         break;
633       cp1 = name;
634       cp2 = strtrim(dir);
635       while (*cp2)
636         {
637           if (*cp1++ != *cp2)
638             break;
639           cp2++;
640         }
641       if (!*cp2)
642         {
643           status = MR_SUCCESS;
644           break;
645         }
646     }
647   EXEC SQL CLOSE csr101;
648   if (dbms_errno)
649     return mr_errcode;
650   return status;
651 }
652
653
654 /* setup_dfil: free any quota records and fsgroup info associated with
655  * a filesystem when it is deleted.  Also adjust the allocation numbers.
656  */
657
658 int setup_dfil(struct query *q, char **argv, client *cl)
659 {
660   EXEC SQL BEGIN DECLARE SECTION;
661   int id, total, phys_id;
662   short int none;
663   EXEC SQL END DECLARE SECTION;
664
665   id = *(int *)argv[0];
666   EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
667     WHERE filsys_id = :id;
668
669   if (none)
670     total = 0;
671
672   /** What if there are multiple phys_id's per f/s? (bad data) **/
673   EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
674     WHERE filsys_id = :id;
675   EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
676     WHERE nfsphys_id = :phys_id;
677
678   if (!none)
679     EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
680   EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
681   EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
682   if (dbms_errno)
683     return mr_errcode;
684   return MR_SUCCESS;
685 }
686
687
688 /* setup_dnfp: check to see that the nfs physical partition does not have
689  * any filesystems assigned to it before allowing it to be deleted.
690  */
691
692 int setup_dnfp(struct query *q, char **argv, client *cl)
693 {
694   EXEC SQL BEGIN DECLARE SECTION;
695   int id, cnt;
696   char *dir;
697   EXEC SQL END DECLARE SECTION;
698
699   id = *(int *)argv[0];
700   dir = argv[1];
701   EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
702     WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
703     AND np.mach_id = :id AND np.dir = :dir;
704   if (cnt > 0)
705     return MR_IN_USE;
706   if (dbms_errno)
707     return mr_errcode;
708   return MR_SUCCESS;
709 }
710
711
712 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
713  *   argv[0] = filsys_id
714  *   argv[1] = type if "update_quota" or "delete_quota"
715  *   argv[2 or 1] = users_id or list_id
716  */
717
718 int setup_dqot(struct query *q, char **argv, client *cl)
719 {
720   EXEC SQL BEGIN DECLARE SECTION;
721   int quota, fs, id, physid;
722   char *qtype;
723   EXEC SQL END DECLARE SECTION;
724
725   fs = *(int *)argv[0];
726   if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
727     {
728       qtype = argv[1];
729       id = *(int *)argv[2];
730     }
731   else
732     {
733       qtype = "USER";
734       id = *(int *)argv[1];
735     }
736
737   EXEC SQL SELECT quota INTO :quota FROM quota
738     WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
739   EXEC SQL SELECT phys_id INTO :physid FROM filesys
740     WHERE filsys_id = :fs;
741   EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
742     WHERE nfsphys_id = :physid;
743
744   if (dbms_errno)
745     return mr_errcode;
746   return MR_SUCCESS;
747 }
748
749
750 /* setup add_kerberos_user_mapping: add the string to the string
751  * table if necessary.
752  */
753
754 int setup_akum(struct query *q, char **argv, client *cl)
755 {
756   EXEC SQL BEGIN DECLARE SECTION;
757   int id;
758   char *name;
759   EXEC SQL END DECLARE SECTION;
760
761   name = argv[1];
762   if (name_to_id(name, STRINGS_TABLE, &id) != MR_SUCCESS)
763     {
764       if (q->type != APPEND)
765         return MR_STRING;
766       id = add_string(name);
767       cache_entry(name, STRINGS_TABLE, id);
768     }
769   if (dbms_errno)
770     return mr_errcode;
771   *(int *)argv[1] = id;
772   return MR_SUCCESS;
773 }
774
775
776 /* prefetch_value():
777  * This routine fetches an appropriate value from the numvalues table.
778  * It is a little hack to get around the fact that SQL doesn't let you
779  * do something like INSERT INTO table (foo) VALUES (other_table.bar).
780  *
781  * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
782  * from within a setup_...() routine with the appropriate arguments.
783  *
784  * Correct functioning of this routine may depend on the assumption
785  * that this query is an APPEND.
786  */
787
788 int prefetch_value(struct query *q, char **argv, client *cl)
789 {
790   EXEC SQL BEGIN DECLARE SECTION;
791   char *name = q->validate->object_id;
792   int value;
793   EXEC SQL END DECLARE SECTION;
794   int status, limit, argc;
795
796   /* set next object id, limiting it if necessary */
797   if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
798     limit = 1; /* So far as I know, this isn't needed.  Just CMA. */
799   else
800     limit = 0;
801   if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
802     return status;
803
804   /* fetch object id */
805   EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
806   if (dbms_errno)
807     return mr_errcode;
808   if (sqlca.sqlerrd[2] != 1)
809     return MR_INTERNAL;
810
811   argc = q->argc + q->vcnt;   /* end of Argv for APPENDs */
812   sprintf(argv[argc], "%d", value);
813
814   return MR_SUCCESS;
815 }
816
817 /* prefetch_filesys():
818  * Fetches the phys_id from filesys based on the filsys_id in argv[0].
819  * Appends the filsys_id and the phys_id to the argv so they can be
820  * referenced in an INSERT into a table other than filesys.  Also
821  * see comments at prefetch_value().
822  *
823  * Assumes the existence of a row where filsys_id = argv[0], since a
824  * filesys label has already been resolved to a filsys_id.
825  */
826 int prefetch_filesys(struct query *q, char **argv, client *cl)
827 {
828   EXEC SQL BEGIN DECLARE SECTION;
829   int fid, phid;
830   EXEC SQL END DECLARE SECTION;
831   int argc;
832
833   fid = *(int *)argv[0];
834   EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
835   if (dbms_errno)
836     return mr_errcode;
837
838   argc = q->argc + q->vcnt;
839   sprintf(argv[argc++], "%d", phid);
840   sprintf(argv[argc], "%d", fid);
841
842   return MR_SUCCESS;
843 }
844
845
846 /* setup_ahst():
847  */
848
849 int setup_ahst(struct query *q, char **argv, client *cl)
850 {
851   EXEC SQL BEGIN DECLARE SECTION;
852   char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
853   char *model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
854   int value, id, saddr, mask, high, low, cnt;
855   EXEC SQL END DECLARE SECTION;
856   int row;
857   struct in_addr addr;
858
859   if (!strcmp(q->shortname, "uhst"))
860     {
861       row = 1;
862       EXEC SQL SELECT name, vendor, model, os
863         INTO :oldname, :vendor, :model, :os
864         FROM machine WHERE mach_id = :id;
865     }
866   else
867     row = 0;
868
869   id = *(int *)argv[0];
870
871   /* sanity check name: must start with a letter, contain only
872    * letters, numerals, and hyphen, and not end with a hyphen.
873    */
874   if (row == 0 || strcmp(argv[1], oldname))
875     {
876       char *p = argv[row];
877
878       if (!isalpha(*p))
879         return MR_BAD_CHAR;
880       for (; *p; p++)
881         {
882           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
883               (*p == '-' && p[1] == '.'))
884             return MR_BAD_CHAR;
885         }
886       if (*(p - 1) == '-')
887         return MR_BAD_CHAR;
888     }
889
890   /* sanity check host vendor: must start with a letter, contain only
891    * letters, numerals, and hyphen, and end with an alphanumeric.
892    */
893   if (*argv[row + 1] && (row == 0 || strcmp(argv[2], vendor)))
894     {
895       char *p = argv[row + 1];
896
897       if (!isalpha(*p))
898         return MR_BAD_CHAR;
899       for (; *p; p++)
900         {
901           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
902               (*p == '-' && p[1] == '.'))
903             return MR_BAD_CHAR;
904         }
905       if (!isalnum(*(p - 1)))
906         return MR_BAD_CHAR;
907     }
908
909   /* sanity check host type: must start with a letter, contain only
910    * letters, numerals, and hyphen, and end with an alphanumeric.
911    */
912   if (*argv[row + 2] && (row == 0 || strcmp(argv[3], model)))
913     {
914       char *p = argv[row + 2];
915
916       if (!isalnum(*p))
917         return MR_BAD_CHAR;
918       for (; *p; p++)
919         {
920           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
921               (*p == '-' && p[1] == '.'))
922             return MR_BAD_CHAR;
923         }
924       if (!isalnum(*(p - 1)))
925         return MR_BAD_CHAR;
926     }
927
928   /* sanity check host os: must start with a letter, contain only
929    * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
930    */
931   if (*argv[row + 3] && (row == 0 || strcmp(argv[4], os)))
932     {
933       char *p = argv[row + 3];
934
935       if (!isalpha(*p))
936         return MR_BAD_CHAR;
937       for (; *p; p++)
938         {
939           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
940               (*p == '-' && p[1] == '.'))
941             return MR_BAD_CHAR;
942         }
943       if (!isalnum(*(p - 1)))
944         return MR_BAD_CHAR;
945     }
946
947   /* check for duplicate name */
948   name = argv[row];
949   EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
950     WHERE name = :name;
951   if (dbms_errno)
952     return mr_errcode;
953   if (cnt != 0)
954     return MR_EXISTS;
955
956   /* check address */
957   if (!strcmp(argv[9 + row], "unassigned"))
958     value = -1;
959   else if (!strcmp(argv[9 + row], "unique"))
960     {
961       if (*(int *)argv[8 + row] == 0)
962         value = -1;
963       else
964         value = -2;
965     }
966   else
967     {
968       value = ntohl(inet_addr(argv[9 + row]));
969       if (value == -1)
970         return MR_ADDRESS;
971     }
972   if (value == 0)
973     return MR_ADDRESS;
974   if (value != -1)
975     {
976       /*
977        * an address or unique was specified.
978        */
979       id = *(int *)argv[8 + row];
980       EXEC SQL SELECT saddr, mask, high, low INTO :saddr, :mask, :high, :low
981         FROM subnet WHERE snet_id = :id;
982       if (dbms_errno)
983         return mr_errcode;
984       if (value != -2)
985         {
986           /*
987            * someone specified an IP address for the host record
988            */
989           if ((value & mask) != saddr || value < low || value > high)
990             return MR_ADDRESS;
991           /*
992            * run the address argument through inet_addr(). This
993            * has the effect that any out of bounds host addrs will
994            * be converted to a valid host addr. We do this now
995            * so that the uniqueness check works. We should also
996            * link in an inet_addr() that returns an error for
997            * this case.
998            */
999           addr.s_addr = inet_addr(argv[9 + row]);
1000           name = inet_ntoa(addr);
1001           EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1002             WHERE address = :name;
1003           if (dbms_errno)
1004             return mr_errcode;
1005           if (cnt > 0)
1006             {
1007               /*
1008                * make IP address is unique. If this a modify request
1009                * (row == 1), then we expect one record to exist.
1010                */
1011               if (row == 0 || (row == 1 && cnt > 1))
1012                 return MR_ADDRESS;
1013               if (row == 1 && cnt == 1)
1014                 {
1015                   EXEC SQL SELECT mach_id INTO :id FROM machine
1016                     WHERE address = :name;
1017                   if (id != *(int *)argv[0])
1018                     return MR_ADDRESS;
1019                 }
1020             }
1021         }
1022       else
1023         {
1024           /*
1025            * a "unique" address was specified. Walk through the
1026            * range specified in the network record, return
1027            * error if no room left.
1028            */
1029           for (id = low; id <= high; id++)
1030             {
1031               if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1032                 continue;
1033               addr.s_addr = htonl(id);
1034               name = inet_ntoa(addr);
1035               EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1036                 WHERE address = :name;
1037               if (dbms_errno)
1038                 return mr_errcode;
1039               if (cnt == 0)
1040                 break;
1041             }
1042           if (cnt != 0)
1043             return MR_ADDRESS;
1044           else
1045             value = htonl(id);
1046         }
1047       /*
1048        * we have an address in value. Convert it to a string and store it.
1049        */
1050       addr.s_addr = htonl(value);
1051       strcpy(argv[9 + row], inet_ntoa(addr));
1052     }
1053   else
1054     strcpy(argv[9 + row], "unassigned");
1055
1056   /* status checking */
1057   value = atoi(argv[7 + row]);
1058   if (row == 0 && !(value == 1 || value == 0))
1059     return MR_TYPE;
1060   if (row == 1)
1061     {
1062       id = *(int *)argv[0];
1063       EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1064       if (dbms_errno)
1065         return mr_errcode;
1066       if (value != cnt)
1067         {
1068           EXEC SQL UPDATE machine SET statuschange = SYSDATE
1069             WHERE mach_id = :id;
1070         }
1071     }
1072
1073   /*
1074    * If this is an update_host query, we're done.
1075    */
1076   if (row == 1)
1077     return MR_SUCCESS;
1078
1079   /*
1080    * For an add_host query, allocate and fill in a new machine id,
1081    * and then insert the creator id.
1082    */
1083   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1084     return mr_errcode;
1085
1086   sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1087   return MR_SUCCESS;
1088 }
1089
1090
1091 /* setup_ahal():
1092  */
1093
1094 int setup_ahal(struct query *q, char **argv, client *cl)
1095 {
1096   EXEC SQL BEGIN DECLARE SECTION;
1097   char *name;
1098   int cnt;
1099   EXEC SQL END DECLARE SECTION;
1100   char *p;
1101
1102   p = name = argv[0];
1103   if (!isalpha(*p))
1104     return MR_BAD_CHAR;
1105   for (; *p; p++)
1106     {
1107       if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1108           (*p == '-' && p[1] == '.'))
1109         return MR_BAD_CHAR;
1110     }
1111   if (*(p - 1) == '-')
1112     return MR_BAD_CHAR;
1113
1114   EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1115     name = :name;
1116   if (dbms_errno)
1117     return mr_errcode;
1118   if (cnt > 0)
1119     return MR_EXISTS;
1120
1121   return MR_SUCCESS;
1122 }
This page took 0.159509 seconds and 5 git commands to generate.