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>