]> andersk Git - moira.git/blob - server/qsetup.pc
add acl_access_check call to ulis as well
[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   if (idx == 1)
315     {
316       EXEC SQL BEGIN DECLARE SECTION;
317       int lid = *(int *)argv[0];
318       EXEC SQL END DECLARE SECTION;
319
320       if (acl_access_check(lid, cl))
321         return MR_PERM;
322     }
323
324   for (p = (unsigned char *) argv[idx]; *p; p++)
325     {
326       if (badlistchars[*p])
327         return MR_BAD_CHAR;
328     }
329
330   if (!strcmp(argv[6 + idx], UNIQUE_GID) || atoi(argv[6 + idx]) == -1)
331     {
332       if (atoi(argv[5 + idx]))
333         {
334           if ((err = set_next_object_id("gid", LIST_TABLE, 1)))
335             return err;
336           EXEC SQL SELECT value INTO :ngid FROM numvalues
337             WHERE name = 'gid';
338           if (dbms_errno)
339             return mr_errcode;
340           sprintf(argv[6 + idx], "%d", ngid);
341         }
342       else
343         strcpy(argv[6 + idx], "-1");
344     }
345
346   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
347     return mr_errcode;
348
349   return MR_SUCCESS;
350 }
351
352
353 /* setup_dlis - verify that the list is no longer being referenced
354  * and may safely be deleted.
355  */
356
357 int setup_dlis(struct query *q, char *argv[], client *cl)
358 {
359   int id;
360   EXEC SQL BEGIN DECLARE SECTION;
361   int cnt;
362   EXEC SQL END DECLARE SECTION;
363
364   id = *(int *)argv[0];
365
366   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
367     WHERE member_id = :id AND member_type = 'LIST';
368   if (cnt > 0)
369     return MR_IN_USE;
370
371   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
372     WHERE member_id = :id AND member_type = 'LIST';
373   if (cnt > 0)
374     return MR_IN_USE;
375
376   EXEC SQL SELECT COUNT(member_id) INTO :cnt FROM imembers
377     WHERE list_id = :id;
378   if (cnt > 0)
379     return MR_IN_USE;
380
381   EXEC SQL SELECT COUNT(label) INTO :cnt FROM filesys WHERE owners = :id;
382   if (cnt > 0)
383     return MR_IN_USE;
384
385   EXEC SQL SELECT COUNT(tag) INTO :cnt FROM capacls WHERE list_id = :id;
386   if (cnt > 0)
387     return MR_IN_USE;
388
389   EXEC SQL SELECT COUNT(name) INTO :cnt FROM list
390     WHERE acl_id = :id AND acl_type = 'LIST' AND list_id != :id;
391   if (cnt > 0)
392     return MR_IN_USE;
393
394   EXEC SQL SELECT COUNT(name) INTO :cnt FROM servers
395     WHERE acl_id = :id AND acl_type = 'LIST';
396   if (cnt > 0)
397     return MR_IN_USE;
398
399   EXEC SQL SELECT COUNT(entity_id) INTO :cnt FROM quota
400     WHERE entity_id = :id AND type = 'GROUP';
401   if (cnt > 0)
402     return MR_IN_USE;
403
404   EXEC SQL SELECT COUNT(acl_id) INTO :cnt FROM hostaccess
405     WHERE acl_id = :id AND acl_type = 'LIST';
406   if (cnt > 0)
407     return MR_IN_USE;
408
409   EXEC SQL SELECT COUNT(class) INTO :cnt FROM zephyr z
410     WHERE z.xmt_type = 'LIST' AND z.xmt_id = :id
411     OR z.sub_type = 'LIST' AND z.sub_id = :id
412     OR z.iws_type = 'LIST' AND z.iws_id = :id
413     OR z.iui_type = 'LIST' AND z.iui_id = :id;
414   if (cnt > 0)
415     return MR_IN_USE;
416
417   return MR_SUCCESS;
418 }
419
420
421 /* setup_dsin - verify that the service is no longer being referenced
422  * and may safely be deleted.
423  */
424
425 int setup_dsin(struct query *q, char *argv[], client *cl)
426 {
427   EXEC SQL BEGIN DECLARE SECTION;
428   int ec, cnt;
429   char *svrname;
430   EXEC SQL END DECLARE SECTION;
431
432   svrname = argv[0];
433   EXEC SQL SELECT COUNT(service) INTO :cnt FROM serverhosts
434     WHERE service = UPPER(:svrname);
435   if (cnt > 0)
436     return MR_IN_USE;
437
438   EXEC SQL SELECT inprogress INTO :ec FROM servers
439     WHERE name = UPPER(:svrname);
440   if (dbms_errno)
441     return mr_errcode;
442   if (ec)
443     return MR_IN_USE;
444
445   return MR_SUCCESS;
446 }
447
448
449 /* setup_dshi - verify that the service-host is no longer being referenced
450  * and may safely be deleted.
451  */
452
453 int setup_dshi(struct query *q, char *argv[], client *cl)
454 {
455   EXEC SQL BEGIN DECLARE SECTION;
456   int id, ec;
457   char *svrname;
458   EXEC SQL END DECLARE SECTION;
459
460   svrname = argv[0];
461   id = *(int *)argv[1];
462
463   EXEC SQL SELECT inprogress INTO :ec FROM serverhosts
464     WHERE service = UPPER(:svrname) AND mach_id = :id;
465   if (dbms_errno)
466     return mr_errcode;
467   if (ec)
468     return MR_IN_USE;
469
470   return MR_SUCCESS;
471 }
472
473
474 /**
475  ** setup_add_filesys - verify existance of referenced file systems
476  **
477  ** Inputs:     Add
478  **   argv[1] - type
479  **   argv[2] - mach_id
480  **   argv[3] - name
481  **   argv[5] - rwaccess
482  **
483  ** Description:
484  **   - for type = RVD:
485  **        * allow anything
486  **   - for type = NFS:
487  **        * extract directory prefix from name
488  **        * verify mach_id/dir in nfsphys
489  **        * verify rwaccess in {r, w, R, W}
490  **
491  **  Side effect: sets variable _var_phys_id to the ID of the physical
492  **     filesystem (nfsphys_id for NFS, 0 for RVD)
493  **
494  ** Errors:
495  **   MR_NFS - specified directory not exported
496  **   MR_FILESYS_ACCESS - invalid filesys access
497  **
498  **/
499
500 EXEC SQL BEGIN DECLARE SECTION;
501 int _var_phys_id;
502 EXEC SQL END DECLARE SECTION;
503
504 int setup_afil(struct query *q, char *argv[], client *cl)
505 {
506   char *type, *name;
507   int mach_id;
508   EXEC SQL BEGIN DECLARE SECTION;
509   int ok;
510   char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
511   EXEC SQL END DECLARE SECTION;
512
513   type = argv[1];
514   mach_id = *(int *)argv[2];
515   name = argv[3];
516   rwaccess = argv[5];
517   _var_phys_id = 0;
518
519   sprintf(ftype, "fs_access_%s", type);
520   EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
521     WHERE name = :ftype AND type = 'TYPE' and trans = :rwaccess;
522   if (dbms_errno)
523     return mr_errcode;
524   if (ok == 0)
525     return MR_FILESYS_ACCESS;
526
527   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
528     return mr_errcode;
529
530   if (!strcmp(type, "NFS"))
531     return check_nfs(mach_id, name, rwaccess);
532
533   return MR_SUCCESS;
534 }
535
536
537 /* Verify the arguments, depending on the FStype.  Also, if this is an
538  * NFS filesystem, then update any quotas for that filesystem to reflect
539  * the new phys_id.
540  */
541
542 int setup_ufil(struct query *q, char *argv[], client *cl)
543 {
544   int mach_id, status;
545   char *type, *name;
546   EXEC SQL BEGIN DECLARE SECTION;
547   int fid, total, who, ok;
548   char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
549   short int total_null;
550   EXEC SQL END DECLARE SECTION;
551
552   _var_phys_id = 0;
553   type = argv[2];
554   mach_id = *(int *)argv[3];
555   name = argv[4];
556   access = argv[6];
557   fid = *(int *)argv[0];
558   who = cl->client_id;
559   entity = cl->entity;
560
561   sprintf(ftype, "fs_access_%s", type);
562   EXEC SQL SELECT COUNT(trans) INTO :ok FROM alias
563     WHERE name = :ftype AND type = 'TYPE' AND trans = :access;
564   if (dbms_errno)
565     return mr_errcode;
566   if (ok == 0)
567     return MR_FILESYS_ACCESS;
568
569   EXEC SQL SELECT type INTO :ftype FROM filesys
570     WHERE filsys_id = :fid;
571   if (dbms_errno)
572     return mr_errcode;
573
574   if (!strcmp(type, "NFS"))
575     {
576       status = check_nfs(mach_id, name, access);
577       EXEC SQL UPDATE quota SET phys_id = :_var_phys_id
578         WHERE filsys_id = :fid;
579       if (dbms_errno)
580         return mr_errcode;
581       return status;
582     }
583   else if (!strcmp(type, "AFS") && strcmp(strtrim(ftype), "AFS")
584            && strcmp(strtrim(ftype), "ERR"))
585     {
586       total = 0;
587       EXEC SQL DELETE FROM quota
588         WHERE type = 'ANY' AND filsys_id = :fid;
589       EXEC SQL SELECT SUM (quota) INTO :total:total_null FROM quota
590         WHERE filsys_id = :fid AND phys_id != 0;
591       if (dbms_errno)
592         return mr_errcode;
593       if (!total_null && (total != 0))
594         {
595           EXEC SQL INSERT INTO quota (quota, filsys_id, phys_id, entity_id,
596                                       type, modtime, modby, modwith)
597             VALUES (:total, :fid, 0, 0, 'ANY', SYSDATE, :who, :entity);
598           if (dbms_errno)
599             return mr_errcode;
600         }
601     }
602   else
603     {
604       EXEC SQL UPDATE quota SET phys_id = 0 WHERE filsys_id = :fid;
605       if (dbms_errno)
606         return mr_errcode;
607     }
608   return MR_SUCCESS;
609 }
610
611
612 /* Find the NFS physical partition that the named directory is on.
613  * This is done by comparing the dir against the mount point of the
614  * partition.  To make sure we get the correct match when there is
615  * more than one, we sort the query in reverse order by dir name.
616  */
617
618 int check_nfs(int mach_id, char *name, char *access)
619 {
620   EXEC SQL BEGIN DECLARE SECTION;
621   char dir[NFSPHYS_DIR_SIZE];
622   int mid = mach_id;
623   EXEC SQL END DECLARE SECTION;
624   int status;
625   char *cp1;
626   char *cp2;
627
628   status = MR_NFS;
629   EXEC SQL DECLARE csr101 CURSOR FOR
630     SELECT nfsphys_id, dir FROM nfsphys
631     WHERE mach_id = :mid
632     ORDER BY 2 DESC;
633   if (dbms_errno)
634     return mr_errcode;
635   EXEC SQL OPEN csr101;
636   if (dbms_errno)
637     return mr_errcode;
638   while (1)
639     {
640       EXEC SQL FETCH csr101 INTO :_var_phys_id, :dir;
641       if (sqlca.sqlcode)
642         break;
643       cp1 = name;
644       cp2 = strtrim(dir);
645       while (*cp2)
646         {
647           if (*cp1++ != *cp2)
648             break;
649           cp2++;
650         }
651       if (!*cp2)
652         {
653           status = MR_SUCCESS;
654           break;
655         }
656     }
657   EXEC SQL CLOSE csr101;
658   if (dbms_errno)
659     return mr_errcode;
660   return status;
661 }
662
663
664 /* setup_dfil: free any quota records and fsgroup info associated with
665  * a filesystem when it is deleted.  Also adjust the allocation numbers.
666  */
667
668 int setup_dfil(struct query *q, char **argv, client *cl)
669 {
670   EXEC SQL BEGIN DECLARE SECTION;
671   int id, total, phys_id;
672   short int none;
673   EXEC SQL END DECLARE SECTION;
674
675   id = *(int *)argv[0];
676   EXEC SQL SELECT SUM (quota) INTO :total:none FROM quota
677     WHERE filsys_id = :id;
678
679   if (none)
680     total = 0;
681
682   /** What if there are multiple phys_id's per f/s? (bad data) **/
683   EXEC SQL SELECT phys_id INTO :phys_id FROM filesys
684     WHERE filsys_id = :id;
685   EXEC SQL UPDATE nfsphys SET allocated = allocated - :total
686     WHERE nfsphys_id = :phys_id;
687
688   if (!none)
689     EXEC SQL DELETE FROM quota WHERE filsys_id = :id;
690   EXEC SQL DELETE FROM fsgroup WHERE filsys_id = :id;
691   EXEC SQL DELETE FROM fsgroup WHERE group_id = :id;
692   if (dbms_errno)
693     return mr_errcode;
694   return MR_SUCCESS;
695 }
696
697
698 /* setup_dnfp: check to see that the nfs physical partition does not have
699  * any filesystems assigned to it before allowing it to be deleted.
700  */
701
702 int setup_dnfp(struct query *q, char **argv, client *cl)
703 {
704   EXEC SQL BEGIN DECLARE SECTION;
705   int id, cnt;
706   char *dir;
707   EXEC SQL END DECLARE SECTION;
708
709   id = *(int *)argv[0];
710   dir = argv[1];
711   EXEC SQL SELECT count(fs.rowid) INTO :cnt FROM filesys fs, nfsphys np
712     WHERE fs.mach_id = :id AND fs.phys_id = np.nfsphys_id
713     AND np.mach_id = :id AND np.dir = :dir;
714   if (cnt > 0)
715     return MR_IN_USE;
716   if (dbms_errno)
717     return mr_errcode;
718   return MR_SUCCESS;
719 }
720
721
722 /* setup_dqot: Remove allocation from nfsphys before deleting quota.
723  *   argv[0] = filsys_id
724  *   argv[1] = type if "update_quota" or "delete_quota"
725  *   argv[2 or 1] = users_id or list_id
726  */
727
728 int setup_dqot(struct query *q, char **argv, client *cl)
729 {
730   EXEC SQL BEGIN DECLARE SECTION;
731   int quota, fs, id, physid;
732   char *qtype;
733   EXEC SQL END DECLARE SECTION;
734
735   fs = *(int *)argv[0];
736   if (!strcmp(q->name, "update_quota") || !strcmp(q->name, "delete_quota"))
737     {
738       qtype = argv[1];
739       id = *(int *)argv[2];
740     }
741   else
742     {
743       qtype = "USER";
744       id = *(int *)argv[1];
745     }
746
747   EXEC SQL SELECT quota INTO :quota FROM quota
748     WHERE type = :qtype AND entity_id = :id AND filsys_id = :fs;
749   EXEC SQL SELECT phys_id INTO :physid FROM filesys
750     WHERE filsys_id = :fs;
751   EXEC SQL UPDATE nfsphys SET allocated = allocated - :quota
752     WHERE nfsphys_id = :physid;
753
754   if (dbms_errno)
755     return mr_errcode;
756   return MR_SUCCESS;
757 }
758
759
760 /* prefetch_value():
761  * This routine fetches an appropriate value from the numvalues table.
762  * It is a little hack to get around the fact that SQL doesn't let you
763  * do something like INSERT INTO table (foo) VALUES (other_table.bar).
764  *
765  * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
766  * from within a setup_...() routine with the appropriate arguments.
767  *
768  * Correct functioning of this routine may depend on the assumption
769  * that this query is an APPEND.
770  */
771
772 int prefetch_value(struct query *q, char **argv, client *cl)
773 {
774   EXEC SQL BEGIN DECLARE SECTION;
775   char *name = q->validate->object_id;
776   int value;
777   EXEC SQL END DECLARE SECTION;
778   int status, limit, argc;
779
780   /* set next object id, limiting it if necessary */
781   if (!strcmp(name, "unix_uid") || !strcmp(name, "gid"))
782     limit = 1; /* So far as I know, this isn't needed.  Just CMA. */
783   else
784     limit = 0;
785   if ((status = set_next_object_id(name, q->rtable, limit)) != MR_SUCCESS)
786     return status;
787
788   /* fetch object id */
789   EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :name;
790   if (dbms_errno)
791     return mr_errcode;
792   if (sqlca.sqlerrd[2] != 1)
793     return MR_INTERNAL;
794
795   argc = q->argc + q->vcnt;   /* end of Argv for APPENDs */
796   sprintf(argv[argc], "%d", value);
797
798   return MR_SUCCESS;
799 }
800
801 /* prefetch_filesys():
802  * Fetches the phys_id from filesys based on the filsys_id in argv[0].
803  * Appends the filsys_id and the phys_id to the argv so they can be
804  * referenced in an INSERT into a table other than filesys.  Also
805  * see comments at prefetch_value().
806  *
807  * Assumes the existence of a row where filsys_id = argv[0], since a
808  * filesys label has already been resolved to a filsys_id.
809  */
810 int prefetch_filesys(struct query *q, char **argv, client *cl)
811 {
812   EXEC SQL BEGIN DECLARE SECTION;
813   int fid, phid;
814   EXEC SQL END DECLARE SECTION;
815   int argc;
816
817   fid = *(int *)argv[0];
818   EXEC SQL SELECT phys_id INTO :phid FROM filesys WHERE filsys_id = :fid;
819   if (dbms_errno)
820     return mr_errcode;
821
822   argc = q->argc + q->vcnt;
823   sprintf(argv[argc++], "%d", phid);
824   sprintf(argv[argc], "%d", fid);
825
826   return MR_SUCCESS;
827 }
828
829
830 /* setup_ahst():
831  */
832
833 int setup_ahst(struct query *q, char **argv, client *cl)
834 {
835   EXEC SQL BEGIN DECLARE SECTION;
836   char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
837   char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
838   int value, id, ssaddr, smask, shigh, slow, cnt;
839   unsigned int saddr, mask, high, low;
840   EXEC SQL END DECLARE SECTION;
841   int row;
842   struct in_addr addr;
843
844   id = *(int *)argv[0];
845
846   if (!strcmp(q->shortname, "uhst"))
847     {
848       row = 1;
849       EXEC SQL SELECT name, vendor, model, os
850         INTO :oldname, :vendor, :model, :os
851         FROM machine WHERE mach_id = :id;
852     }
853   else
854     row = 0;
855
856   /* sanity check name: must start with a letter, contain only
857    * letters, numerals, and hyphen, and not end with a hyphen.
858    */
859   if (row == 0 || strcasecmp(argv[1], oldname))
860     {
861       char *p = argv[row];
862
863       if (!isalpha(*p))
864         return MR_BAD_CHAR;
865       for (; *p; p++)
866         {
867           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
868               (*p == '-' && p[1] == '.'))
869             return MR_BAD_CHAR;
870         }
871       if (*(p - 1) == '-')
872         return MR_BAD_CHAR;
873     }
874
875   /* sanity check host vendor: must start with a letter, contain only
876    * letters, numerals, and hyphen, and end with an alphanumeric.
877    */
878   if (*argv[row + 1] && (row == 0 || strcasecmp(argv[2], vendor)))
879     {
880       char *p = argv[row + 1];
881
882       if (!isalpha(*p))
883         return MR_BAD_CHAR;
884       for (; *p; p++)
885         {
886           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
887               (*p == '-' && p[1] == '.'))
888             return MR_BAD_CHAR;
889         }
890       if (!isalnum(*(p - 1)))
891         return MR_BAD_CHAR;
892     }
893
894   /* sanity check host type: must start with a letter, contain only
895    * letters, numerals, and hyphen, and end with an alphanumeric.
896    */
897   if (*argv[row + 2] && (row == 0 || strcasecmp(argv[3], model)))
898     {
899       char *p = argv[row + 2];
900
901       if (!isalnum(*p))
902         return MR_BAD_CHAR;
903       for (; *p; p++)
904         {
905           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
906               (*p == '-' && p[1] == '.'))
907             return MR_BAD_CHAR;
908         }
909       if (!isalnum(*(p - 1)))
910         return MR_BAD_CHAR;
911     }
912
913   /* sanity check host os: must start with a letter, contain only
914    * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
915    */
916   if (*argv[row + 3] && (row == 0 || strcasecmp(argv[4], os)))
917     {
918       char *p = argv[row + 3];
919
920       if (!isalpha(*p))
921         return MR_BAD_CHAR;
922       for (; *p; p++)
923         {
924           if ((!isalnum(*p) && *p != '-' && *p != '.') ||
925               (*p == '-' && p[1] == '.'))
926             return MR_BAD_CHAR;
927         }
928       if (!isalnum(*(p - 1)))
929         return MR_BAD_CHAR;
930     }
931
932   /* check for duplicate name */
933   name = argv[row];
934   EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
935     WHERE name = UPPER(:name);
936   if (dbms_errno)
937     return mr_errcode;
938   if (cnt != 0)
939     return MR_EXISTS;
940
941   /* check address */
942   if (!strcmp(argv[9 + row], "unassigned"))
943     value = -1;
944   else if (!strcmp(argv[9 + row], "unique"))
945     {
946       if (*(int *)argv[8 + row] == 0)
947         value = -1;
948       else
949         value = -2;
950     }
951   else
952     {
953       value = ntohl(inet_addr(argv[9 + row]));
954       if (value == -1)
955         return MR_ADDRESS;
956     }
957   if (value == 0)
958     return MR_ADDRESS;
959   if (value != -1)
960     {
961       /*
962        * an address or unique was specified.
963        */
964       id = *(int *)argv[8 + row];
965       EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
966         :shigh, :slow FROM subnet WHERE snet_id = :id;
967       if (dbms_errno)
968         return mr_errcode;
969       saddr = (unsigned) ssaddr;
970       mask = (unsigned) smask;
971       high = (unsigned) shigh;
972       low = (unsigned) slow;
973       if (value != -2)
974         {
975           /*
976            * someone specified an IP address for the host record
977            */
978           if ((value & mask) != saddr || value < low || value > high)
979             return MR_ADDRESS;
980           /*
981            * run the address argument through inet_addr(). This
982            * has the effect that any out of bounds host addrs will
983            * be converted to a valid host addr. We do this now
984            * so that the uniqueness check works. We should also
985            * link in an inet_addr() that returns an error for
986            * this case.
987            */
988           addr.s_addr = inet_addr(argv[9 + row]);
989           name = inet_ntoa(addr);
990           EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
991             WHERE address = :name;
992           if (dbms_errno)
993             return mr_errcode;
994           if (cnt > 0)
995             {
996               /*
997                * make IP address is unique. If this a modify request
998                * (row == 1), then we expect one record to exist.
999                */
1000               if (row == 0 || (row == 1 && cnt > 1))
1001                 return MR_ADDRESS;
1002               if (row == 1 && cnt == 1)
1003                 {
1004                   EXEC SQL SELECT mach_id INTO :id FROM machine
1005                     WHERE address = :name;
1006                   if (id != *(int *)argv[0])
1007                     return MR_ADDRESS;
1008                 }
1009             }
1010         }
1011       else
1012         {
1013           /*
1014            * a "unique" address was specified. Walk through the
1015            * range specified in the network record, return
1016            * error if no room left.
1017            */
1018           for (id = low; id <= high; id++)
1019             {
1020               if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1021                 continue;
1022               addr.s_addr = htonl(id);
1023               name = inet_ntoa(addr);
1024               EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1025                 WHERE address = :name;
1026               if (dbms_errno)
1027                 return mr_errcode;
1028               if (cnt == 0)
1029                 break;
1030             }
1031           if (cnt != 0)
1032             return MR_NO_ID;
1033           else
1034             value = htonl(id);
1035         }
1036       /*
1037        * we have an address in value. Convert it to a string and store it.
1038        */
1039       addr.s_addr = htonl(value);
1040       strcpy(argv[9 + row], inet_ntoa(addr));
1041     }
1042   else
1043     strcpy(argv[9 + row], "unassigned");
1044
1045   /* status checking */
1046   value = atoi(argv[7 + row]);
1047   if (row == 0 && !(value == 1 || value == 0))
1048     return MR_TYPE;
1049   if (row == 1)
1050     {
1051       id = *(int *)argv[0];
1052       EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1053       if (dbms_errno)
1054         return mr_errcode;
1055       if (value != cnt)
1056         {
1057           EXEC SQL UPDATE machine SET statuschange = SYSDATE
1058             WHERE mach_id = :id;
1059         }
1060     }
1061
1062   /*
1063    * If this is an update_host query, we're done.
1064    */
1065   if (row == 1)
1066     return MR_SUCCESS;
1067
1068   /*
1069    * For an add_host query, allocate and fill in a new machine id,
1070    * and then insert the creator id.
1071    */
1072   if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1073     return mr_errcode;
1074
1075   sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1076   return MR_SUCCESS;
1077 }
1078
1079
1080 /* setup_ahal():
1081  */
1082
1083 int setup_ahal(struct query *q, char **argv, client *cl)
1084 {
1085   EXEC SQL BEGIN DECLARE SECTION;
1086   char *name;
1087   int cnt;
1088   EXEC SQL END DECLARE SECTION;
1089   char *p;
1090
1091   p = name = argv[0];
1092   if (!isalpha(*p))
1093     return MR_BAD_CHAR;
1094   for (; *p; p++)
1095     {
1096       if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1097           (*p == '-' && p[1] == '.'))
1098         return MR_BAD_CHAR;
1099     }
1100   if (*(p - 1) == '-')
1101     return MR_BAD_CHAR;
1102
1103   EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
1104     name = UPPER(:name);
1105   if (dbms_errno)
1106     return mr_errcode;
1107   if (cnt > 0)
1108     return MR_EXISTS;
1109
1110   return MR_SUCCESS;
1111 }
This page took 0.118115 seconds and 5 git commands to generate.