]> andersk Git - moira.git/blame - server/qsetup.pc
use "login = :argv[0]" instead of "login LIKE :argv[0]" in access_login:
[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
5a22fdf5 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
5eaef520 324 for (p = (unsigned char *) argv[idx]; *p; p++)
325 {
73cf66ba 326 if (badlistchars[*p])
5eaef520 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);
73cf66ba 341 }
5eaef520 342 else
343 strcpy(argv[6 + idx], "-1");
73cf66ba 344 }
345
5eaef520 346 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
347 return mr_errcode;
73cf66ba 348
5eaef520 349 return MR_SUCCESS;
73cf66ba 350}
351
352
353/* setup_dlis - verify that the list is no longer being referenced
354 * and may safely be deleted.
355 */
356
7ac48069 357int setup_dlis(struct query *q, char *argv[], client *cl)
73cf66ba 358{
5eaef520 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;
73cf66ba 418}
419
420
421/* setup_dsin - verify that the service is no longer being referenced
422 * and may safely be deleted.
423 */
424
7ac48069 425int setup_dsin(struct query *q, char *argv[], client *cl)
73cf66ba 426{
5eaef520 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;
73cf66ba 446}
447
448
449/* setup_dshi - verify that the service-host is no longer being referenced
450 * and may safely be deleted.
451 */
452
7ac48069 453int setup_dshi(struct query *q, char *argv[], client *cl)
73cf66ba 454{
5eaef520 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;
73cf66ba 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
03c05291 481 ** argv[5] - rwaccess
73cf66ba 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
03c05291 489 ** * verify rwaccess in {r, w, R, W}
73cf66ba 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
500EXEC SQL BEGIN DECLARE SECTION;
501int _var_phys_id;
502EXEC SQL END DECLARE SECTION;
503
5eaef520 504int setup_afil(struct query *q, char *argv[], client *cl)
73cf66ba 505{
5eaef520 506 char *type, *name;
507 int mach_id;
508 EXEC SQL BEGIN DECLARE SECTION;
509 int ok;
e688520a 510 char ftype[FILESYS_TYPE_SIZE + 10], *rwaccess;
5eaef520 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;
73cf66ba 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
5eaef520 542int setup_ufil(struct query *q, char *argv[], client *cl)
73cf66ba 543{
5eaef520 544 int mach_id, status;
545 char *type, *name;
546 EXEC SQL BEGIN DECLARE SECTION;
547 int fid, total, who, ok;
e688520a 548 char *entity, ftype[FILESYS_TYPE_SIZE + 10], *access;
5eaef520 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;
73cf66ba 600 }
73cf66ba 601 }
5eaef520 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;
73cf66ba 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
5eaef520 618int check_nfs(int mach_id, char *name, char *access)
73cf66ba 619{
5eaef520 620 EXEC SQL BEGIN DECLARE SECTION;
e688520a 621 char dir[NFSPHYS_DIR_SIZE];
5eaef520 622 int mid = mach_id;
623 EXEC SQL END DECLARE SECTION;
44d12d58 624 int status;
625 char *cp1;
626 char *cp2;
5eaef520 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)
73cf66ba 648 break;
5eaef520 649 cp2++;
650 }
651 if (!*cp2)
652 {
653 status = MR_SUCCESS;
654 break;
73cf66ba 655 }
656 }
5eaef520 657 EXEC SQL CLOSE csr101;
658 if (dbms_errno)
659 return mr_errcode;
660 return status;
73cf66ba 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
5eaef520 668int setup_dfil(struct query *q, char **argv, client *cl)
73cf66ba 669{
5eaef520 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;
73cf66ba 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
5eaef520 702int setup_dnfp(struct query *q, char **argv, client *cl)
73cf66ba 703{
5eaef520 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;
73cf66ba 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
5eaef520 728int setup_dqot(struct query *q, char **argv, client *cl)
73cf66ba 729{
5eaef520 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];
73cf66ba 745 }
746
5eaef520 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;
73cf66ba 753
5eaef520 754 if (dbms_errno)
755 return mr_errcode;
756 return MR_SUCCESS;
73cf66ba 757}
758
759
7f426981 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 *
5eaef520 765 * It is called from the query table as (*v->pre_rtn)(q, Argv, cl) or
7f426981 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
5eaef520 772int prefetch_value(struct query *q, char **argv, client *cl)
7f426981 773{
5eaef520 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;
7f426981 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 */
5eaef520 810int prefetch_filesys(struct query *q, char **argv, client *cl)
7f426981 811{
5eaef520 812 EXEC SQL BEGIN DECLARE SECTION;
813 int fid, phid;
814 EXEC SQL END DECLARE SECTION;
815 int argc;
7f426981 816
5eaef520 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;
7f426981 821
5eaef520 822 argc = q->argc + q->vcnt;
823 sprintf(argv[argc++], "%d", phid);
824 sprintf(argv[argc], "%d", fid);
7f426981 825
5eaef520 826 return MR_SUCCESS;
7f426981 827}
828
829
830/* setup_ahst():
831 */
832
5eaef520 833int setup_ahst(struct query *q, char **argv, client *cl)
7f426981 834{
5eaef520 835 EXEC SQL BEGIN DECLARE SECTION;
e688520a 836 char *name, oldname[MACHINE_NAME_SIZE], vendor[MACHINE_VENDOR_SIZE];
db9491c6 837 char model[MACHINE_MODEL_SIZE], os[MACHINE_OS_SIZE];
ff98438b 838 int value, id, ssaddr, smask, shigh, slow, cnt;
839 unsigned int saddr, mask, high, low;
5eaef520 840 EXEC SQL END DECLARE SECTION;
841 int row;
842 struct in_addr addr;
5eaef520 843
fde09f2c 844 id = *(int *)argv[0];
845
5eaef520 846 if (!strcmp(q->shortname, "uhst"))
85330553 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 }
5eaef520 853 else
854 row = 0;
855
ad06a10e 856 if (row == 0 || strcasecmp(argv[1], oldname))
5eaef520 857 {
84f3d463 858 if (!hostname_check(argv[row]))
5eaef520 859 return MR_BAD_CHAR;
7f426981 860 }
861
5eaef520 862 /* sanity check host vendor: must start with a letter, contain only
863 * letters, numerals, and hyphen, and end with an alphanumeric.
864 */
ad06a10e 865 if (*argv[row + 1] && (row == 0 || strcasecmp(argv[2], vendor)))
5eaef520 866 {
867 char *p = argv[row + 1];
868
869 if (!isalpha(*p))
870 return MR_BAD_CHAR;
871 for (; *p; p++)
872 {
873 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
874 (*p == '-' && p[1] == '.'))
875 return MR_BAD_CHAR;
8ca3e341 876 }
5eaef520 877 if (!isalnum(*(p - 1)))
878 return MR_BAD_CHAR;
8ca3e341 879 }
880
5eaef520 881 /* sanity check host type: must start with a letter, contain only
882 * letters, numerals, and hyphen, and end with an alphanumeric.
883 */
ad06a10e 884 if (*argv[row + 2] && (row == 0 || strcasecmp(argv[3], model)))
5eaef520 885 {
886 char *p = argv[row + 2];
887
888 if (!isalnum(*p))
889 return MR_BAD_CHAR;
890 for (; *p; p++)
891 {
892 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
893 (*p == '-' && p[1] == '.'))
894 return MR_BAD_CHAR;
8ca3e341 895 }
5eaef520 896 if (!isalnum(*(p - 1)))
897 return MR_BAD_CHAR;
8ca3e341 898 }
899
85330553 900 /* sanity check host os: must start with a letter, contain only
5eaef520 901 * letters, numerals, and hyphen, and end with an hyphen alphanumeric.
902 */
ad06a10e 903 if (*argv[row + 3] && (row == 0 || strcasecmp(argv[4], os)))
5eaef520 904 {
905 char *p = argv[row + 3];
906
907 if (!isalpha(*p))
908 return MR_BAD_CHAR;
909 for (; *p; p++)
910 {
911 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
912 (*p == '-' && p[1] == '.'))
913 return MR_BAD_CHAR;
8ca3e341 914 }
5eaef520 915 if (!isalnum(*(p - 1)))
916 return MR_BAD_CHAR;
8ca3e341 917 }
918
5eaef520 919 /* check for duplicate name */
920 name = argv[row];
921 EXEC SQL SELECT count(mach_id) INTO :cnt FROM hostalias
ad06a10e 922 WHERE name = UPPER(:name);
5eaef520 923 if (dbms_errno)
924 return mr_errcode;
925 if (cnt != 0)
926 return MR_EXISTS;
927
928 /* check address */
929 if (!strcmp(argv[9 + row], "unassigned"))
930 value = -1;
931 else if (!strcmp(argv[9 + row], "unique"))
932 {
933 if (*(int *)argv[8 + row] == 0)
934 value = -1;
935 else
936 value = -2;
937 }
938 else
939 {
940 value = ntohl(inet_addr(argv[9 + row]));
941 if (value == -1)
942 return MR_ADDRESS;
5482f508 943 }
5eaef520 944 if (value == 0)
945 return MR_ADDRESS;
946 if (value != -1)
947 {
948 /*
949 * an address or unique was specified.
950 */
951 id = *(int *)argv[8 + row];
ff98438b 952 EXEC SQL SELECT saddr, mask, high, low INTO :ssaddr, :smask,
953 :shigh, :slow FROM subnet WHERE snet_id = :id;
5eaef520 954 if (dbms_errno)
955 return mr_errcode;
ff98438b 956 saddr = (unsigned) ssaddr;
957 mask = (unsigned) smask;
958 high = (unsigned) shigh;
959 low = (unsigned) slow;
5eaef520 960 if (value != -2)
961 {
962 /*
963 * someone specified an IP address for the host record
964 */
082466aa 965 if ((value & mask) != saddr || value < low || value > high)
5eaef520 966 return MR_ADDRESS;
967 /*
968 * run the address argument through inet_addr(). This
969 * has the effect that any out of bounds host addrs will
970 * be converted to a valid host addr. We do this now
971 * so that the uniqueness check works. We should also
972 * link in an inet_addr() that returns an error for
973 * this case.
974 */
975 addr.s_addr = inet_addr(argv[9 + row]);
976 name = inet_ntoa(addr);
977 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
978 WHERE address = :name;
979 if (dbms_errno)
980 return mr_errcode;
981 if (cnt > 0)
982 {
983 /*
984 * make IP address is unique. If this a modify request
985 * (row == 1), then we expect one record to exist.
986 */
7ac48069 987 if (row == 0 || (row == 1 && cnt > 1))
5eaef520 988 return MR_ADDRESS;
989 if (row == 1 && cnt == 1)
990 {
991 EXEC SQL SELECT mach_id INTO :id FROM machine
992 WHERE address = :name;
993 if (id != *(int *)argv[0])
994 return MR_ADDRESS;
7f426981 995 }
996 }
5eaef520 997 }
998 else
999 {
1000 /*
1001 * a "unique" address was specified. Walk through the
1002 * range specified in the network record, return
1003 * error if no room left.
1004 */
1005 for (id = low; id <= high; id++)
1006 {
1007 if (((id & 0xff) == 0) || ((id & 0xff) == 255))
1008 continue;
1009 addr.s_addr = htonl(id);
7ac48069 1010 name = inet_ntoa(addr);
5eaef520 1011 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine
1012 WHERE address = :name;
1013 if (dbms_errno)
1014 return mr_errcode;
1015 if (cnt == 0)
1016 break;
7f426981 1017 }
5eaef520 1018 if (cnt != 0)
6715bac2 1019 return MR_NO_ID;
5eaef520 1020 else
1021 value = htonl(id);
7f426981 1022 }
5eaef520 1023 /*
1024 * we have an address in value. Convert it to a string and store it.
1025 */
1026 addr.s_addr = htonl(value);
1027 strcpy(argv[9 + row], inet_ntoa(addr));
7f426981 1028 }
5eaef520 1029 else
1030 strcpy(argv[9 + row], "unassigned");
1031
1032 /* status checking */
1033 value = atoi(argv[7 + row]);
1034 if (row == 0 && !(value == 1 || value == 0))
1035 return MR_TYPE;
1036 if (row == 1)
1037 {
1038 id = *(int *)argv[0];
1039 EXEC SQL SELECT status INTO :cnt FROM machine WHERE mach_id = :id;
1040 if (dbms_errno)
1041 return mr_errcode;
1042 if (value != cnt)
1043 {
1044 EXEC SQL UPDATE machine SET statuschange = SYSDATE
1045 WHERE mach_id = :id;
7f426981 1046 }
1047 }
1048
5eaef520 1049 /*
1050 * If this is an update_host query, we're done.
1051 */
1052 if (row == 1)
1053 return MR_SUCCESS;
1054
1055 /*
1056 * For an add_host query, allocate and fill in a new machine id,
1057 * and then insert the creator id.
1058 */
1059 if ((mr_errcode = prefetch_value(q, argv, cl)) != MR_SUCCESS)
1060 return mr_errcode;
1061
1062 sprintf(argv[q->argc + q->vcnt + 1], "%d", cl->client_id);
1063 return MR_SUCCESS;
7f426981 1064}
1065
1066
1067/* setup_ahal():
1068 */
1069
5eaef520 1070int setup_ahal(struct query *q, char **argv, client *cl)
7f426981 1071{
5eaef520 1072 EXEC SQL BEGIN DECLARE SECTION;
1073 char *name;
1074 int cnt;
1075 EXEC SQL END DECLARE SECTION;
1076 char *p;
1077
84f3d463 1078 name = argv[0];
1079 if (!hostname_check(argv[0]))
5eaef520 1080 return MR_BAD_CHAR;
7f426981 1081
5eaef520 1082 EXEC SQL SELECT count(mach_id) INTO :cnt FROM machine WHERE
ad06a10e 1083 name = UPPER(:name);
5eaef520 1084 if (dbms_errno)
1085 return mr_errcode;
1086 if (cnt > 0)
1087 return MR_EXISTS;
7f426981 1088
5eaef520 1089 return MR_SUCCESS;
7f426981 1090}
84f3d463 1091
1092/* hostname_check()
1093 * validate the rfc1035-ness of a hostname
1094 */
1095
1096int hostname_check(char *name)
1097{
1098 char *p;
1099 int count;
1100
1101 /* sanity check name: must start with a letter, contain only
1102 * letters, numerals, and hyphen, and not end with a hyphen.
1103 * also make sure no label (the thing the .s seperate) is longer
1104 * than 63 characters.
1105 */
1106
1107 p = name;
1108 if (!isalpha(*p))
1109 return 0;
1110 count = 0;
1111 for (; *p; p++)
1112 {
1113 count++;
1114 if ((!isalnum(*p) && *p != '-' && *p != '.') ||
1115 (*p == '-' && p[1] == '.'))
1116 return 0;
1117 if (*p == '.')
1118 count = 0;
1119 if (count == 64)
1120 return 0;
1121 }
1122 if (*(p - 1) == '-')
1123 return 0;
1124 return 1;
1125}
This page took 7.415795 seconds and 5 git commands to generate.