Annotation of freem/src/ssvn_global.c, revision 1.7

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>