]> andersk Git - moira.git/blame - server/qsetup.pc
Fix the subnet problem right this time
[moira.git] / server / qsetup.pc
CommitLineData
7ac48069 1/* $Id$
73cf66ba 2 *
7ac48069 3 * Query setup routines
73cf66ba 4 *
7ac48069 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>.
73cf66ba 8 */
9
73cf66ba 10#include <mit-copyright.h>
73cf66ba 11#include "mr_server.h"
03c05291 12#include "query.h"
7ac48069 13#include "qrtn.h"
14
03c05291 15#include <arpa/inet.h>
7ac48069 16#include <netinet/in.h>
17
18#include <ctype.h>
19#include <stdlib.h>
20#include <string.h>
21
73cf66ba 22EXEC SQL INCLUDE sqlca;
73cf66ba 23
7ac48069 24RCSID("$Header$");
25
26extern char *whoami;
03c05291 27extern int dbms_errno, mr_errcode;
73cf66ba 28
29EXEC SQL BEGIN DECLARE SECTION;
30extern char stmt_buf[];
31EXEC SQL END DECLARE SECTION;
32
03c05291 33EXEC SQL WHENEVER SQLERROR DO dbmserr();
34
73cf66ba 35
03c05291 36int prefetch_value(struct query *q, char **argv, client *cl);
37int check_nfs(int mach_idx, char *name, char *access);
73cf66ba 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
5eaef520 52int setup_ausr(struct query *q, char *argv[], client *cl)
73cf66ba 53{
5eaef520 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);
73cf66ba 71 }
72
5eaef520 73 if (!strcmp(argv[0], UNIQUE_LOGIN) || atoi(argv[row]) == -1)
74 sprintf(argv[0], "#%s", argv[row]);
73cf66ba 75
5eaef520 76 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
77 return mr_errcode;
73cf66ba 78
5eaef520 79 return MR_SUCCESS;
73cf66ba 80}
81
82
83/* setup_dusr - verify that the user is no longer being referenced
84 * and may safely be deleted.
85 */
86
7ac48069 87int setup_dusr(struct query *q, char *argv[], client *cl)
73cf66ba 88{
5eaef520 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;
73cf66ba 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 */
7ac48069 131int setup_spop(struct query *q, char *argv[], client *cl)
73cf66ba 132{
5eaef520 133 EXEC SQL BEGIN DECLARE SECTION;
134 int id, mid;
e688520a 135 char type[USERS_POTYPE_SIZE];
5eaef520 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;
7ac48069 141 if (sqlca.sqlerrd[2] == 0)
5eaef520 142 return MR_MACHINE;
143 EXEC SQL SELECT mach_id INTO :mid FROM machine
144 WHERE mach_id = :mid;
7ac48069 145 if (sqlca.sqlerrd[2] == 0)
5eaef520 146 return MR_MACHINE;
147 if (strcmp(strtrim(type), "POP"))
148 set_pop_usage(mid, 1);
149 return MR_SUCCESS;
73cf66ba 150}
151
152
153/* setup_dpob: Take care of keeping track of the post office usage.
154 */
7ac48069 155int setup_dpob(struct query *q, char *argv[], client *cl)
73cf66ba 156{
5eaef520 157 EXEC SQL BEGIN DECLARE SECTION;
158 int id, user;
e688520a 159 char type[USERS_POTYPE_SIZE];
5eaef520 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;
73cf66ba 171}
172
173
174/* setup_dmac - verify that the machine is no longer being referenced
175 * and may safely be deleted.
176 */
177
7ac48069 178int setup_dmac(struct query *q, char *argv[], client *cl)
73cf66ba 179{
5eaef520 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;
73cf66ba 227}
228
229
230/* setup_dsnt - verify that the subnet is no longer being referenced
231 * and may safely be deleted.
232 */
233
7ac48069 234int setup_dsnt(struct query *q, char *argv[], client *cl)
73cf66ba 235{
5eaef520 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;
73cf66ba 246}
247
248
249/* setup_dclu - verify that the cluster is no longer being referenced
250 * and may safely be deleted.
251 */
252
7ac48069 253int setup_dclu(struct query *q, char *argv[], client *cl)
73cf66ba 254{
5eaef520 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;
73cf66ba 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
282static int badlistchars[] = {
5eaef520 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,
73cf66ba 299};
300
5eaef520 301int setup_alis(struct query *q, char *argv[], client *cl)
73cf66ba 302{
5eaef520 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 {
73cf66ba 316 if (badlistchars[*p])
5eaef520 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);
73cf66ba 331 }
5eaef520 332 else
333 strcpy(argv[6 + idx], "-1");
73cf66ba 334 }
335
5eaef520 336 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
337 return mr_errcode;
73cf66ba 338
5eaef520 339 return MR_SUCCESS;
73cf66ba 340}
341
342
343/* setup_dlis - verify that the list is no longer being referenced
344 * and may safely be deleted.
345 */
346
7ac48069 347int setup_dlis(struct query *q, char *argv[], client *cl)
73cf66ba 348{
5eaef520 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;
73cf66ba 408}
409
410
411/* setup_dsin - verify that the service is no longer being referenced
412 * and may safely be deleted.
413 */
414
7ac48069 415int setup_dsin(struct query *q, char *argv[], client *cl)
73cf66ba 416{
5eaef520 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;
73cf66ba 436}
437
438
439/* setup_dshi - verify that the service-host is no longer being referenced
440 * and may safely be deleted.
441 */
442
7ac48069 443int setup_dshi(struct query *q, char *argv[], client *cl)
73cf66ba 444{
5eaef520 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;
73cf66ba 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
03c05291 471 ** argv[5] - rwaccess
73cf66ba 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
03c05291 479 ** * verify rwaccess in {r, w, R, W}
73cf66ba 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
490EXEC SQL BEGIN DECLARE SECTION;
491int _var_phys_id;
492EXEC SQL END DECLARE SECTION;
493
5eaef520 494int setup_afil(struct query *q, char *argv[], client *cl)
73cf66ba 495{
5eaef520 496 char *type, *name;
497 int mach_id;
498 EXEC SQL BEGIN DECLARE SECTION;
499 int ok;
e688520a 500 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
5eaef520 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;
73cf66ba 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
5eaef520 532int setup_ufil(struct query *q, char *argv[], client *cl)
73cf66ba 533{
5eaef520 534 int mach_id, status;
535 char *type, *name;
536 EXEC SQL BEGIN DECLARE SECTION;
537 int fid, total, who, ok;
e688520a 538 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
5eaef520 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;
73cf66ba 590 }
73cf66ba 591 }
5eaef520 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;
73cf66ba 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
5eaef520 608int check_nfs(int mach_id, char *name, char *access)
73cf66ba 609{
5eaef520 610 EXEC SQL BEGIN DECLARE SECTION;
e688520a 611 char dir[NFSPHYS_DIR_SIZE];
5eaef520 612 int mid = mach_id;
613 EXEC SQL END DECLARE SECTION;
44d12d58 614 int status;
615 char *cp1;
616 char *cp2;
5eaef520 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)
73cf66ba 638 break;
5eaef520 639 cp2++;
640 }
641 if (!*cp2)
642 {
643 status = MR_SUCCESS;
644 break;
73cf66ba 645 }
646 }
5eaef520 647 EXEC SQL CLOSE csr101;
648 if (dbms_errno)
649 return mr_errcode;
650 return status;
73cf66ba 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
5eaef520 658int setup_dfil(struct query *q, char **argv, client *cl)
73cf66ba 659{
5eaef520 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;
73cf66ba 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
5eaef520 692int setup_dnfp(struct query *q, char **argv, client *cl)
73cf66ba 693{
5eaef520 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;
73cf66ba 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
5eaef520 718int setup_dqot(struct query *q, char **argv, client *cl)
73cf66ba 719{
5eaef520 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];
73cf66ba 735 }
736
5eaef520 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;
73cf66ba 743
5eaef520 744 if (dbms_errno)
745 return mr_errcode;
746 return MR_SUCCESS;
73cf66ba 747}
748
749
7f426981 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 *
5eaef520 755 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
7f426981 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
5eaef520 762int prefetch_value(struct query *q, char **argv, client *cl)
7f426981 763{
5eaef520 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;
7f426981 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 */
5eaef520 800int prefetch_filesys(struct query *q, char **argv, client *cl)
7f426981 801{
5eaef520 802 EXEC SQL BEGIN DECLARE SECTION;
803 int fid, phid;
804 EXEC SQL END DECLARE SECTION;
805 int argc;
7f426981 806
5eaef520 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;
7f426981 811
5eaef520 812 argc = q->argc + q->vcnt;
813 sprintf(argv[argc++], "%d", phid);
814 sprintf(argv[argc], "%d", fid);
7f426981 815
5eaef520 816 return MR_SUCCESS;
7f426981 817}
818
819
820/* setup_ahst():
821 */
822
5eaef520 823int setup_ahst(struct query *q, char **argv, client *cl)
7f426981 824{
5eaef520 825 EXEC SQL BEGIN DECLARE SECTION;
e688520a 826 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
db9491c6 827 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
ff98438b 828 int value, id, ssaddr, smask, shigh, slow, cnt;
829 unsigned int saddr, mask, high, low;
5eaef520 830 EXEC SQL END DECLARE SECTION;
831 int row;
832 struct in_addr addr;
5eaef520 833
834 if (!strcmp(q->shortname, "uhst"))
85330553 835 {
836 row = 1;
837 EXEC SQL SELECT name, vendor, model, os
838 INTO :oldname, :vendor, :model, :os
839 FROM machine WHERE mach_id = :id;
840 }
5eaef520 841 else
842 row = 0;
843
85330553 844 id = *(int *)argv[0];
845
5eaef520 846 /* sanity check name: must start with a letter, contain only
847 * letters, numerals, and hyphen, and not end with a hyphen.
848 */
ad06a10e 849 if (row == 0 || strcasecmp(argv[1], oldname))
5eaef520 850 {
851 char *p = argv[row];
852
853 if (!isalpha(*p))
854 return MR_BAD_CHAR;
855 for (; *p; p++)
856 {
857 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
858 (*p == '-' && p[1] == '.'))
859 return MR_BAD_CHAR;
7f426981 860 }
5eaef520 861 if (*(p - 1) == '-')
862 return MR_BAD_CHAR;
7f426981 863 }
864
5eaef520 865 /* sanity check host vendor: must start with a letter, contain only
866 * letters, numerals, and hyphen, and end with an alphanumeric.
867 */
ad06a10e 868 if (*argv[row + 1] && (row == 0 || strcasecmp(argv[2], vendor)))
5eaef520 869 {
870 char *p = argv[row + 1];
871
872 if (!isalpha(*p))
873 return MR_BAD_CHAR;
874 for (; *p; p++)
875 {
876 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
877 (*p == '-' && p[1] == '.'))
878 return MR_BAD_CHAR;
8ca3e341 879 }
5eaef520 880 if (!isalnum(*(p - 1)))
881 return MR_BAD_CHAR;
8ca3e341 882 }
883
5eaef520 884 /* sanity check host type: must start with a letter, contain only
885 * letters, numerals, and hyphen, and end with an alphanumeric.
886 */
ad06a10e 887 if (*argv[row + 2] && (row == 0 || strcasecmp(argv[3], model)))
5eaef520 888 {
889 char *p = argv[row + 2];
890
891 if (!isalnum(*p))
892 return MR_BAD_CHAR;
893 for (; *p; p++)
894 {
895 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
896 (*p == '-' && p[1] == '.'))
897 return MR_BAD_CHAR;
8ca3e341 898 }
5eaef520 899 if (!isalnum(*(p - 1)))
900 return MR_BAD_CHAR;
8ca3e341 901 }
902
85330553 903 /* sanity check host os: must start with a letter, contain only
5eaef520 904 * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
905 */
ad06a10e 906 if (*argv[row + 3] && (row == 0 || strcasecmp(argv[4], os)))
5eaef520 907 {
908 char *p = argv[row + 3];
909
910 if (!isalpha(*p))
911 return MR_BAD_CHAR;
912 for (; *p; p++)
913 {
914 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
915 (*p == '-' && p[1] == '.'))
916 return MR_BAD_CHAR;
8ca3e341 917 }
5eaef520 918 if (!isalnum(*(p - 1)))
919 return MR_BAD_CHAR;
8ca3e341 920 }
921
5eaef520 922 /* check for duplicate name */
923 name = argv[row];
924 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
ad06a10e 925 WHERE name = UPPER(:name);
5eaef520 926 if (dbms_errno)
927 return mr_errcode;
928 if (cnt != 0)
929 return MR_EXISTS;
930
931 /* check address */
932 if (!strcmp(argv[9 + row], "unassigned"))
933 value = -1;
934 else if (!strcmp(argv[9 + row], "unique"))
935 {
936 if (*(int *)argv[8 + row] == 0)
937 value = -1;
938 else
939 value = -2;
940 }
941 else
942 {
943 value = ntohl(inet_addr(argv[9 + row]));
944 if (value == -1)
945 return MR_ADDRESS;
5482f508 946 }
5eaef520 947 if (value == 0)
948 return MR_ADDRESS;
949 if (value != -1)
950 {
951 /*
952 * an address or unique was specified.
953 */
954 id = *(int *)argv[8 + row];
ff98438b 955 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
956 :shigh, :slow FROM subnet WHERE snet_id = :id;
5eaef520 957 if (dbms_errno)
958 return mr_errcode;
ff98438b 959 saddr = (unsigned) ssaddr;
960 mask = (unsigned) smask;
961 high = (unsigned) shigh;
962 low = (unsigned) slow;
5eaef520 963 if (value != -2)
964 {
965 /*
966 * someone specified an IP address for the host record
967 */
082466aa 968 if ((value & mask) != saddr || value < low || value > high)
5eaef520 969 return MR_ADDRESS;
970 /*
971 * run the address argument through inet_addr(). This
972 * has the effect that any out of bounds host addrs will
973 * be converted to a valid host addr. We do this now
974 * so that the uniqueness check works. We should also
975 * link in an inet_addr() that returns an error for
976 * this case.
977 */
978 addr.s_addr = inet_addr(argv[9 + row]);
979 name = inet_ntoa(addr);
980 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
981 WHERE address = :name;
982 if (dbms_errno)
983 return mr_errcode;
984 if (cnt > 0)
985 {
986 /*
987 * make IP address is unique. If this a modify request
988 * (row == 1), then we expect one record to exist.
989 */
7ac48069 990 if (row == 0 || (row == 1 && cnt > 1))
5eaef520 991 return MR_ADDRESS;
992 if (row == 1 && cnt == 1)
993 {
994 EXEC SQL SELECT mach_id INTO :id FROM machine
995 WHERE address = :name;
996 if (id != *(int *)argv[0])
997 return MR_ADDRESS;
7f426981 998 }
999 }
5eaef520 1000 }
1001 else
1002 {
1003 /*
1004 * a "unique" address was specified. Walk through the
1005 * range specified in the network record, return
1006 * error if no room left.
1007 */
1008 for (id = low; id <= high; id++)
1009 {
1010 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1011 continue;
1012 addr.s_addr = htonl(id);
7ac48069 1013 name = inet_ntoa(addr);
5eaef520 1014 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1015 WHERE address = :name;
1016 if (dbms_errno)
1017 return mr_errcode;
1018 if (cnt == 0)
1019 break;
7f426981 1020 }
5eaef520 1021 if (cnt != 0)
6715bac2 1022 return MR_NO_ID;
5eaef520 1023 else
1024 value = htonl(id);
7f426981 1025 }
5eaef520 1026 /*
1027 * we have an address in value. Convert it to a string and store it.
1028 */
1029 addr.s_addr = htonl(value);
1030 strcpy(argv[9 + row], inet_ntoa(addr));
7f426981 1031 }
5eaef520 1032 else
1033 strcpy(argv[9 + row], "unassigned");
1034
1035 /* status checking */
1036 value = atoi(argv[7 + row]);
1037 if (row == 0 && !(value == 1 || value == 0))
1038 return MR_TYPE;
1039 if (row == 1)
1040 {
1041 id = *(int *)argv[0];
1042 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1043 if (dbms_errno)
1044 return mr_errcode;
1045 if (value != cnt)
1046 {
1047 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1048 WHERE mach_id = :id;
7f426981 1049 }
1050 }
1051
5eaef520 1052 /*
1053 * If this is an update_host query, we're done.
1054 */
1055 if (row == 1)
1056 return MR_SUCCESS;
1057
1058 /*
1059 * For an add_host query, allocate and fill in a new machine id,
1060 * and then insert the creator id.
1061 */
1062 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1063 return mr_errcode;
1064
1065 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1066 return MR_SUCCESS;
7f426981 1067}
1068
1069
1070/* setup_ahal():
1071 */
1072
5eaef520 1073int setup_ahal(struct query *q, char **argv, client *cl)
7f426981 1074{
5eaef520 1075 EXEC SQL BEGIN DECLARE SECTION;
1076 char *name;
1077 int cnt;
1078 EXEC SQL END DECLARE SECTION;
1079 char *p;
1080
1081 p = name = argv[0];
1082 if (!isalpha(*p))
1083 return MR_BAD_CHAR;
1084 for (; *p; p++)
1085 {
1086 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1087 (*p == '-' && p[1] == '.'))
1088 return MR_BAD_CHAR;
7f426981 1089 }
5eaef520 1090 if (*(p - 1) == '-')
1091 return MR_BAD_CHAR;
7f426981 1092
5eaef520 1093 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
ad06a10e 1094 name = UPPER(:name);
5eaef520 1095 if (dbms_errno)
1096 return mr_errcode;
1097 if (cnt > 0)
1098 return MR_EXISTS;
7f426981 1099
5eaef520 1100 return MR_SUCCESS;
7f426981 1101}
This page took 2.098371 seconds and 5 git commands to generate.