]> andersk Git - moira.git/blob - server/qsetup.pc
Revert revision 2.15: the existing code assumes that IP addrs above
[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 /* prefetch_value():
751  * This routine fetches an appropriate value from the numvalues table.
752  * It is a little hack to get around the fact that SQL doesn't let you
753  * do something like INSERT INTO table (foo) VALUES (other_table.bar).
754  *
755  * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
756  * from within a setup_...() routine with the appropriate arguments.
757  *
758  * Correct functioning of this routine may depend on the assumption
759  * that this query is an APPEND.
760  */
761
762 int prefetch_value(struct query *q, char **argv, client *cl)
763 {
764   EXEC SQL BEGIN DECLARE SECTION;
765   char *name = q->validate->object_id;
766   int value;
767   EXEC SQL END DECLARE SECTION;
768   int status, limit, argc;
769
770   /* set next object id, limiting it if necessary */
771   if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
772     limit = 1; /* So far as I know, this isn't needed.  Just CMA. */
773   else
774     limit = 0;
775   if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
776     return status;
777
778   /* fetch object id */
779   EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
780   if (dbms_errno)
781     return mr_errcode;
782   if (sqlca.sqlerrd[2] != 1)
783     return MR_INTERNAL;
784
785   argc = q->argc + q->vcnt;   /* end of Argv for APPENDs */
786   sprintf(argv[argc], "%d", value);
787
788   return MR_SUCCESS;
789 }
790
791 /* prefetch_filesys():
792  * Fetches the phys_id from filesys based on the filsys_id in argv[0].
793  * Appends the filsys_id and the phys_id to the argv so they can be
794  * referenced in an INSERT into a table other than filesys.  Also
795  * see comments at prefetch_value().
796  *
797  * Assumes the existence of a row where filsys_id = argv[0], since a
798  * filesys label has already been resolved to a filsys_id.
799  */
800 int prefetch_filesys(struct query *q, char **argv, client *cl)
801 {
802   EXEC SQL BEGIN DECLARE SECTION;
803   int fid, phid;
804   EXEC SQL END DECLARE SECTION;
805   int argc;
806
807   fid = *(int *)argv[0];
808   EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
809   if (dbms_errno)
810     return mr_errcode;
811
812   argc = q->argc + q->vcnt;
813   sprintf(argv[argc++], "%d", phid);
814   sprintf(argv[argc], "%d", fid);
815
816   return MR_SUCCESS;
817 }
818
819
820 /* setup_ahst():
821  */
822
823 int setup_ahst(struct query *q, char **argv, client *cl)
824 {
825   EXEC SQL BEGIN DECLARE SECTION;
826   char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
827   char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
828   int value, id, saddr, mask, high, low, cnt;
829   EXEC SQL END DECLARE SECTION;
830   int row;
831   struct in_addr addr;
832
833   if (!strcmp(q->shortname, "uhst"))
834     {
835       row = 1;
836       EXEC SQL SELECT name, vendor, model, os
837         INTO :oldname, :vendor, :model, :os
838         FROM machine WHERE mach_id = :id;
839     }
840   else
841     row = 0;
842
843   id = *(int *)argv[0];
844
845   /* sanity check name: must start with a letter, contain only
846    * letters, numerals, and hyphen, and not end with a hyphen.
847    */
848   if (row == 0 || strcasecmp(argv[1], oldname))
849     {
850       char *p = argv[row];
851
852       if (!isalpha(*p))
853         return MR_BAD_CHAR;
854       for (; *p; p++)
855         {
856           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
857               (*p == '-' && p[1] == '.'))
858             return MR_BAD_CHAR;
859         }
860       if (*(p - 1) == '-')
861         return MR_BAD_CHAR;
862     }
863
864   /* sanity check host vendor: must start with a letter, contain only
865    * letters, numerals, and hyphen, and end with an alphanumeric.
866    */
867   if (*argv[row + 1] && (row == 0 || strcasecmp(argv[2], vendor)))
868     {
869       char *p = argv[row + 1];
870
871       if (!isalpha(*p))
872         return MR_BAD_CHAR;
873       for (; *p; p++)
874         {
875           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
876               (*p == '-' && p[1] == '.'))
877             return MR_BAD_CHAR;
878         }
879       if (!isalnum(*(p - 1)))
880         return MR_BAD_CHAR;
881     }
882
883   /* sanity check host type: must start with a letter, contain only
884    * letters, numerals, and hyphen, and end with an alphanumeric.
885    */
886   if (*argv[row + 2] && (row == 0 || strcasecmp(argv[3], model)))
887     {
888       char *p = argv[row + 2];
889
890       if (!isalnum(*p))
891         return MR_BAD_CHAR;
892       for (; *p; p++)
893         {
894           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
895               (*p == '-' && p[1] == '.'))
896             return MR_BAD_CHAR;
897         }
898       if (!isalnum(*(p - 1)))
899         return MR_BAD_CHAR;
900     }
901
902   /* sanity check host os: must start with a letter, contain only
903    * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
904    */
905   if (*argv[row + 3] && (row == 0 || strcasecmp(argv[4], os)))
906     {
907       char *p = argv[row + 3];
908
909       if (!isalpha(*p))
910         return MR_BAD_CHAR;
911       for (; *p; p++)
912         {
913           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
914               (*p == '-' && p[1] == '.'))
915             return MR_BAD_CHAR;
916         }
917       if (!isalnum(*(p - 1)))
918         return MR_BAD_CHAR;
919     }
920
921   /* check for duplicate name */
922   name = argv[row];
923   EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
924     WHERE name = UPPER(:name);
925   if (dbms_errno)
926     return mr_errcode;
927   if (cnt != 0)
928     return MR_EXISTS;
929
930   /* check address */
931   if (!strcmp(argv[9 + row], "unassigned"))
932     value = -1;
933   else if (!strcmp(argv[9 + row], "unique"))
934     {
935       if (*(int *)argv[8 + row] == 0)
936         value = -1;
937       else
938         value = -2;
939     }
940   else
941     {
942       value = ntohl(inet_addr(argv[9 + row]));
943       if (value == -1)
944         return MR_ADDRESS;
945     }
946   if (value == 0)
947     return MR_ADDRESS;
948   if (value != -1)
949     {
950       /*
951        * an address or unique was specified.
952        */
953       id = *(int *)argv[8 + row];
954       EXEC SQL SELECT saddr, mask, high, low INTO :saddr, :mask, :high, :low
955         FROM subnet WHERE snet_id = :id;
956       if (dbms_errno)
957         return mr_errcode;
958       if (value != -2)
959         {
960           /*
961            * someone specified an IP address for the host record
962            */
963           if ((value & mask) != saddr || value < low || value > high)
964             return MR_ADDRESS;
965           /*
966            * run the address argument through inet_addr(). This
967            * has the effect that any out of bounds host addrs will
968            * be converted to a valid host addr. We do this now
969            * so that the uniqueness check works. We should also
970            * link in an inet_addr() that returns an error for
971            * this case.
972            */
973           addr.s_addr = inet_addr(argv[9 + row]);
974           name = inet_ntoa(addr);
975           EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
976             WHERE address = :name;
977           if (dbms_errno)
978             return mr_errcode;
979           if (cnt > 0)
980             {
981               /*
982                * make IP address is unique. If this a modify request
983                * (row == 1), then we expect one record to exist.
984                */
985               if (row == 0 || (row == 1 && cnt > 1))
986                 return MR_ADDRESS;
987               if (row == 1 && cnt == 1)
988                 {
989                   EXEC SQL SELECT mach_id INTO :id FROM machine
990                     WHERE address = :name;
991                   if (id != *(int *)argv[0])
992                     return MR_ADDRESS;
993                 }
994             }
995         }
996       else
997         {
998           /*
999            * a "unique" address was specified. Walk through the
1000            * range specified in the network record, return
1001            * error if no room left.
1002            */
1003           for (id = low; id <= high; id++)
1004             {
1005               if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1006                 continue;
1007               addr.s_addr = htonl(id);
1008               name = inet_ntoa(addr);
1009               EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1010                 WHERE address = :name;
1011               if (dbms_errno)
1012                 return mr_errcode;
1013               if (cnt == 0)
1014                 break;
1015             }
1016           if (cnt != 0)
1017             return MR_NO_ID;
1018           else
1019             value = htonl(id);
1020         }
1021       /*
1022        * we have an address in value. Convert it to a string and store it.
1023        */
1024       addr.s_addr = htonl(value);
1025       strcpy(argv[9 + row], inet_ntoa(addr));
1026     }
1027   else
1028     strcpy(argv[9 + row], "unassigned");
1029
1030   /* status checking */
1031   value = atoi(argv[7 + row]);
1032   if (row == 0 && !(value == 1 || value == 0))
1033     return MR_TYPE;
1034   if (row == 1)
1035     {
1036       id = *(int *)argv[0];
1037       EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1038       if (dbms_errno)
1039         return mr_errcode;
1040       if (value != cnt)
1041         {
1042           EXEC SQL UPDATE machine SET statuschange = SYSDATE
1043             WHERE mach_id = :id;
1044         }
1045     }
1046
1047   /*
1048    * If this is an update_host query, we're done.
1049    */
1050   if (row == 1)
1051     return MR_SUCCESS;
1052
1053   /*
1054    * For an add_host query, allocate and fill in a new machine id,
1055    * and then insert the creator id.
1056    */
1057   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1058     return mr_errcode;
1059
1060   sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1061   return MR_SUCCESS;
1062 }
1063
1064
1065 /* setup_ahal():
1066  */
1067
1068 int setup_ahal(struct query *q, char **argv, client *cl)
1069 {
1070   EXEC SQL BEGIN DECLARE SECTION;
1071   char *name;
1072   int cnt;
1073   EXEC SQL END DECLARE SECTION;
1074   char *p;
1075
1076   p = name = argv[0];
1077   if (!isalpha(*p))
1078     return MR_BAD_CHAR;
1079   for (; *p; p++)
1080     {
1081       if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1082           (*p == '-' && p[1] == '.'))
1083         return MR_BAD_CHAR;
1084     }
1085   if (*(p - 1) == '-')
1086     return MR_BAD_CHAR;
1087
1088   EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1089     name = UPPER(:name);
1090   if (dbms_errno)
1091     return mr_errcode;
1092   if (cnt > 0)
1093     return MR_EXISTS;
1094
1095   return MR_SUCCESS;
1096 }
This page took 0.123995 seconds and 5 git commands to generate.