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