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