Annotation of freem/src/ssvn_global.c, revision 1.8
1.1 snw 1: /*
1.8 ! snw 2: * $Id: ssvn_global.c,v 1.7 2025/04/10 17:21:54 snw Exp $
1.4 snw 3: * ^$GLOBAL ssvn
1.1 snw 4: *
5: *
1.3 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.4 snw 8: * Copyright (C) 2020, 2025 Coherent Logic Development LLC
1.1 snw 9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
1.5 snw 26: * $Log: ssvn_global.c,v $
1.8 ! snw 27: * Revision 1.7 2025/04/10 17:21:54 snw
! 28: * Remove traces of BDB global handler
! 29: *
1.7 snw 30: * Revision 1.6 2025/04/09 19:52:02 snw
31: * Eliminate as many warnings as possible while building with -Wall
32: *
1.6 snw 33: * Revision 1.5 2025/03/22 18:43:54 snw
34: * Make STRLEN 255 chars and add BIGSTR macro for larger buffers
35: *
1.5 snw 36: * Revision 1.4 2025/03/09 19:50:47 snw
37: * Second phase of REUSE compliance and header reformat
38: *
1.4 snw 39: *
40: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
41: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 42: **/
43:
44: #include <stdio.h>
45: #include <unistd.h>
46: #include <fcntl.h>
47: #include <string.h>
48: #include <stdlib.h>
49:
50: #include "mpsdef.h"
51: #include "mref.h"
52: #include "iniconf.h"
53: #include "namespace.h"
54:
55: #define DATALIM (BLOCKLEN-11)
56: #define LLPTR (BLOCKLEN-10)
57: #define NRBLK LLPTR
58: #define COLLA (BLOCKLEN- 7)
59: #define RLPTR (BLOCKLEN- 6)
60: #define FREE RLPTR
61: #define BTYP (BLOCKLEN- 3)
62: #define OFFS (BLOCKLEN- 2)
63:
64: /* length of blockpointers in bytes */
65: #define PLEN 3
66:
67: #define EMPTY 0
68: #define FBLK 1
69: #define POINTER 2
70: #define BOTTOM 6
71: #define DATA 8
72:
73: typedef struct db_blockinfo {
74:
75: int keylen;
76: int keyoffs;
77: char key[STRLEN];
78: int datalen;
79: char data[STRLEN];
80:
81: long llptr;
82: long rlptr;
83:
84: long blockcount;
85: int collation;
86:
87: int btype;
88: long free_offset;
89:
90: } db_blockinfo;
91:
92: short frm_global_exists(char *, char *, char *);
93: void frm_decode_block(db_blockinfo *, char *, long);
94: long frm_blockcount(char *);
95: long frm_bytecount(char *);
96:
97: void frm_decode_block(db_blockinfo *b, char *gbpth, long blocknum)
98: {
99:
100: int fd;
101: char blk[BLOCKLEN];
102:
103:
104: fd = open (gbpth, O_RDONLY);
105: lseek (fd, blocknum * BLOCKLEN, SEEK_SET);
106: read (fd, blk, BLOCKLEN);
107:
108: close (fd);
109:
110: b->btype = blk[BTYP];
111:
112: if (blocknum == 0) {
113: b->collation = blk[COLLA];
114: b->blockcount = ((int) blk[NRBLK]) << 4;
115: }
116: else {
117: b->llptr = UNSIGN (blk[LLPTR]) * 65536 + UNSIGN (blk[LLPTR + 1]) * 256 + UNSIGN (blk[LLPTR + 2]);
118: b->rlptr = UNSIGN (blk[RLPTR]) * 65536 + UNSIGN (blk[RLPTR + 1]) * 256 + UNSIGN (blk[RLPTR + 2]);
119: }
120:
121: if (b->btype == DATA) {
122: b->free_offset = UNSIGN (blk[OFFS]) * 256 + UNSIGN (blk[OFFS + 1]);
123: b->keylen = blk[0];
124: }
125:
126: return;
127:
128: }
129:
130: void ssvn_global(short action, char *key, char *data)
131: {
132: char gb_ns[STRLEN];
1.5 snw 133: char gb_path[PATHLEN];
134: char gb_cpath[PATHLEN];
1.1 snw 135:
1.5 snw 136: char ns_key[STRLEN];
1.1 snw 137:
138: long blkcount;
139:
140: freem_ref_t *r;
141: db_blockinfo *bi;
142:
143: r = (freem_ref_t *) malloc (sizeof (freem_ref_t));
144: NULLPTRCHK(r,"ssvn_global");
145:
146: bi = (db_blockinfo *) malloc (sizeof (db_blockinfo));
147: NULLPTRCHK(bi,"ssvn_global");
148:
149: mref_init (r, MREF_RT_SSV, "^$GLOBAL");
150: internal_to_mref (r, key);
151:
152: switch (action) {
153:
154: case set_sym:
155:
156: if (strcmp (mref_get_subscript (r, 1), "NAMESPACE") != 0) {
157: merr_raise (M29);
158: goto done;
159: }
160:
1.8 ! snw 161: snprintf (ns_key, STRLEN - 1, "^$SYSTEM\202MAPPINGS\202GLOBAL\202^%s\201", mref_get_subscript (r, 0));
1.7 snw 162: symtab_shm (set_sym, ns_key, data);
1.1 snw 163:
164: goto done;
165:
166: case kill_sym:
167:
168: if (strcmp (mref_get_subscript (r, 1), "NAMESPACE") != 0) {
169: merr_raise (M29);
170: goto done;
171: }
172:
1.8 ! snw 173: snprintf (ns_key, STRLEN - 1, "^$SYSTEM\202MAPPINGS\202GLOBAL\202^%s\201", mref_get_subscript (r, 0));
1.7 snw 174: symtab_shm (kill_sym, ns_key, data);
1.1 snw 175:
176: goto done;
177:
178:
179:
180: case get_sym:
181:
182: if (frm_global_exists (gb_ns, gb_path, r->subscripts[0]) != TRUE) {
183: merr_raise (M7);
184: goto done;
185: }
186:
187: if (strcmp (mref_get_subscript (r, 1), "BLOCK") == 0) {
188:
189: long bn = atol (mref_get_subscript (r, 2));
190:
191: stcpy (gb_cpath, gb_path);
192: stcnv_m2c (gb_cpath);
193:
194: blkcount = frm_blockcount (gb_cpath);
195:
196: if (bn > (blkcount - 1)) {
197: merr_raise (M38);
198: goto done;
199: }
200:
201: frm_decode_block (bi, gb_cpath, bn);
202:
203: if (strcmp (mref_get_subscript (r, 3), "TYPE") == 0) {
204:
205: switch (bi->btype) {
206:
207: case 2:
208: sprintf (data, "%s\201", "POINTER");
209: merr_raise (OK);
210: goto done;
211:
212: case 6:
213: sprintf (data, "%s\201", "ROOT");
214: merr_raise (OK);
215: goto done;
216:
217: case 8:
218: sprintf (data, "%s\201", "DATA");
219: merr_raise (OK);
220: goto done;
221: }
222:
223:
224: sprintf (data, "%d\201", bi->btype);
225: merr_raise (OK);
226: goto done;
227:
228: }
229: else if (strcmp (mref_get_subscript (r, 3), "BLOCKCOUNT") == 0) {
230:
231: if (bn != 0) {
232: merr_raise (M38);
233: goto done;
234: }
235:
1.2 snw 236: sprintf (data, "%ld\201", bi->blockcount);
1.1 snw 237: merr_raise (OK);
238: goto done;
239: }
240: else if (strcmp (mref_get_subscript (r, 3), "KEYLEN") == 0) {
241:
242: if (bn == 0) {
243: merr_raise (M38);
244: goto done;
245: }
246:
247: sprintf (data, "%d\201", bi->keylen);
248: merr_raise (OK);
249: goto done;
250: }
251: else if (strcmp (mref_get_subscript (r, 3), "RLPTR") == 0) {
252:
253: if (bn == 0) {
254: merr_raise (M38);
255: goto done;
256: }
257:
258:
1.2 snw 259: sprintf (data, "%ld\201", bi->rlptr);
1.1 snw 260: merr_raise (OK);
261: goto done;
262: }
263: else if (strcmp (mref_get_subscript (r, 3), "OFFS") == 0) {
264:
265: if (bi->btype != DATA) {
266: merr_raise (M38);
267: goto done;
268: }
269:
1.2 snw 270: sprintf (data, "%ld\201", bi->free_offset);
1.1 snw 271: merr_raise (OK);
272: goto done;
273: }
274: else if (strcmp (mref_get_subscript (r, 3), "LLPTR") == 0) {
275:
276: if (bn == 0) {
277: merr_raise (M38);
278: goto done;
279: }
280:
1.2 snw 281: sprintf (data, "%ld\201", bi->llptr);
1.1 snw 282: merr_raise (OK);
283: goto done;
284: }
285:
286: }
287: else if (strcmp (mref_get_subscript (r, 1), "CHARACTER") == 0) {
288: stcpy (gb_cpath, gb_path);
289: stcnv_m2c (gb_cpath);
290:
291: frm_decode_block (bi, gb_cpath, 0L);
292:
293: if (bi->collation == 0) {
294: sprintf (data, "M\201");
295: merr_raise (OK);
296: goto done;
297: }
298: else {
299: sprintf (data, "ASCII\201");
300: merr_raise (OK);
301: goto done;
302: }
303: }
304: else if (strcmp (mref_get_subscript (r, 1), "COLLATE") == 0) {
305: stcpy (gb_cpath, gb_path);
306: stcnv_m2c (gb_cpath);
307:
308: frm_decode_block (bi, gb_cpath, 0L);
309:
310: if (bi->collation == 0) {
311: sprintf (data, "M\201");
312: merr_raise (OK);
313: goto done;
314: }
315: else {
316: sprintf (data, "ASCII\201");
317: merr_raise (OK);
318: goto done;
319: }
320: }
321: else if (strcmp (mref_get_subscript (r, 1), "NAMESPACE") == 0) {
322: sprintf (data, "%s\201", gb_ns);
323: merr_raise (OK);
324: goto done;
325: }
326: else if (strcmp (mref_get_subscript (r, 1), "FILE") == 0) {
327: sprintf (data, "%s\201", gb_path);
328: merr_raise (OK);
329: goto done;
330: }
331: else if (strcmp (mref_get_subscript (r, 1), "BLOCKSIZE") == 0) {
332: sprintf (data, "%d\201", BLOCKLEN);
333: merr_raise (OK);
334: goto done;
335: }
336: else if (strcmp (mref_get_subscript (r, 1), "BLOCKS") == 0) {
337:
338: long blockcount;
339:
340: stcpy (gb_cpath, gb_path);
341: stcnv_m2c (gb_cpath);
342:
343: blockcount = frm_blockcount (gb_cpath);
344:
345: sprintf (data, "%ld\201", blockcount);
346:
347: merr_raise (OK);
348: goto done;
349:
350: }
351: else if (strcmp (mref_get_subscript (r, 1), "BYTES") == 0) {
352: long bytecount;
353:
354: stcpy (gb_cpath, gb_path);
355: stcnv_m2c (gb_cpath);
356:
357: bytecount = frm_bytecount (gb_cpath);
358:
359: sprintf (data, "%ld\201", bytecount);
360:
361: merr_raise (OK);
1.6 snw 362: goto done;
1.1 snw 363: }
364:
365: merr_raise (M38);
366: goto done;
367:
368:
369: default:
370: merr_raise (INVREF);
371: goto done;
372:
373: }
374:
375: done:
376:
377: free (r);
378:
379: return;
380: }
381:
382: short frm_global_exists(char *gbl_namespace, char *gbl_path, char *global_name)
383: {
384: char *gpth;
1.5 snw 385: char glofile[PATHLEN];
1.1 snw 386: char goobuf[STRLEN];
387:
1.5 snw 388: char mapk_buf[STRLEN];
389: char mapd_buf[STRLEN];
390: char old_ns[STRLEN];
1.1 snw 391:
392: int ierr_sav = OK;
393:
394: if (global_name[0] != '^') {
1.8 ! snw 395: snprintf (mapk_buf, STRLEN - 1, "^$SYSTEM\202MAPPINGS\202GLOBAL\202^%s\201", global_name);
1.1 snw 396: }
397: else {
1.8 ! snw 398: snprintf (mapk_buf, STRLEN - 1, "^$SYSTEM\202MAPPINGS\202GLOBAL\202%s\201", global_name);
1.1 snw 399: }
400:
1.7 snw 401: symtab_shm (get_sym, mapk_buf, mapd_buf);
1.1 snw 402:
403: stcnv_m2c (mapd_buf);
404:
405: if (merr () == OK) {
406:
407: strncpy (old_ns, nsname, 255);
408: set_namespace (mapd_buf, 0);
409:
410: gpth = (char *) malloc (PATHLEN * sizeof (char));
411: NULLPTRCHK(gpth,"frm_global_exists");
412:
413: strncpy (gpth, glopath, PATHLEN - 1);
414: strncpy (gbl_namespace, mapd_buf, 254);
415:
416: set_namespace (old_ns, 0);
417:
418: }
419: else {
420:
421: merr_raise (ierr_sav);
422:
423: if (global_name[0] == '%') {
424: gpth = gloplib;
425: sprintf (gbl_namespace, "SYSTEM");
426: }
427: else {
428: gpth = glopath;
429: sprintf (gbl_namespace, "%s\201", nsname);
430: }
431:
432: }
433:
434: stcpy (goobuf, gpth);
435: stcnv_m2c (goobuf);
436:
437: if (global_name[0] != '^') {
1.8 ! snw 438: snprintf (glofile, PATHLEN - 1, "%s/^%s", goobuf, global_name);
1.1 snw 439: }
440: else {
1.8 ! snw 441: snprintf (glofile, PATHLEN - 1, "%s/%s", goobuf, global_name);
1.1 snw 442: }
443:
444: strcpy (gbl_path, glofile);
445: stcnv_c2m (gbl_path);
446:
447: if (file_exists (glofile)) {
448: return TRUE;
449: }
450: else {
451: return FALSE;
452: }
453:
454:
455: }
456:
457: long frm_blockcount(char *gbl_path)
458: {
459: FILE *fp;
460: long blockcount;
461:
462:
463: fp = fopen (gbl_path, "r");
464: fseek (fp, 0L, SEEK_END);
465: blockcount = ftell (fp) / BLOCKLEN;
466: fclose (fp);
467:
468:
469: return blockcount;
470: }
471:
472: long frm_bytecount(char *gbl_path)
473: {
474: FILE *fp;
475: long bytecount;
476:
477:
478: fp = fopen (gbl_path, "r");
479: fseek (fp, 0L, SEEK_END);
480: bytecount = ftell (fp);
481: fclose (fp);
482:
483: return bytecount;
484: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>