/*
* *
* * *
* * *
* ***************
* * * * *
* * MUMPS *
* * * * *
* ***************
* * *
* * *
* *
*
* ssvn_global.c
* ^$GLOBAL ssv
*
*
* Author: Serena Willis <snw@coherent-logic.com>
* Copyright (C) 1998 MUG Deutschland
* Copyright (C) 2020 Coherent Logic Development LLC
*
*
* This file is part of FreeM.
*
* FreeM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with FreeM. If not, see <https://www.gnu.org/licenses/>.
*
**/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "mpsdef.h"
#include "mref.h"
#include "iniconf.h"
#include "namespace.h"
#define DATALIM (BLOCKLEN-11)
#define LLPTR (BLOCKLEN-10)
#define NRBLK LLPTR
#define COLLA (BLOCKLEN- 7)
#define RLPTR (BLOCKLEN- 6)
#define FREE RLPTR
#define BTYP (BLOCKLEN- 3)
#define OFFS (BLOCKLEN- 2)
/* length of blockpointers in bytes */
#define PLEN 3
#define EMPTY 0
#define FBLK 1
#define POINTER 2
#define BOTTOM 6
#define DATA 8
typedef struct db_blockinfo {
int keylen;
int keyoffs;
char key[STRLEN];
int datalen;
char data[STRLEN];
long llptr;
long rlptr;
long blockcount;
int collation;
int btype;
long free_offset;
} db_blockinfo;
short frm_global_exists(char *, char *, char *);
void frm_decode_block(db_blockinfo *, char *, long);
long frm_blockcount(char *);
long frm_bytecount(char *);
void frm_decode_block(db_blockinfo *b, char *gbpth, long blocknum)
{
int fd;
char blk[BLOCKLEN];
fd = open (gbpth, O_RDONLY);
lseek (fd, blocknum * BLOCKLEN, SEEK_SET);
read (fd, blk, BLOCKLEN);
close (fd);
b->btype = blk[BTYP];
if (blocknum == 0) {
b->collation = blk[COLLA];
b->blockcount = ((int) blk[NRBLK]) << 4;
}
else {
b->llptr = UNSIGN (blk[LLPTR]) * 65536 + UNSIGN (blk[LLPTR + 1]) * 256 + UNSIGN (blk[LLPTR + 2]);
b->rlptr = UNSIGN (blk[RLPTR]) * 65536 + UNSIGN (blk[RLPTR + 1]) * 256 + UNSIGN (blk[RLPTR + 2]);
}
if (b->btype == DATA) {
b->free_offset = UNSIGN (blk[OFFS]) * 256 + UNSIGN (blk[OFFS + 1]);
b->keylen = blk[0];
}
return;
}
void ssvn_global(short action, char *key, char *data)
{
char gb_ns[STRLEN];
char gb_path[STRLEN];
char gb_cpath[STRLEN];
char ns_key[256];
char ns_data[256];
long blkcount;
freem_ref_t *r;
db_blockinfo *bi;
r = (freem_ref_t *) malloc (sizeof (freem_ref_t));
NULLPTRCHK(r,"ssvn_global");
bi = (db_blockinfo *) malloc (sizeof (db_blockinfo));
NULLPTRCHK(bi,"ssvn_global");
mref_init (r, MREF_RT_SSV, "^$GLOBAL");
internal_to_mref (r, key);
switch (action) {
case set_sym:
if (strcmp (mref_get_subscript (r, 1), "NAMESPACE") != 0) {
merr_raise (M29);
goto done;
}
snprintf (ns_key, 255, "^$SYSTEM\202MAPPINGS\202GLOBAL\202^%s\201", mref_get_subscript (r, 0));
global (set_sym, ns_key, data);
goto done;
case kill_sym:
if (strcmp (mref_get_subscript (r, 1), "NAMESPACE") != 0) {
merr_raise (M29);
goto done;
}
snprintf (ns_key, 255, "^$SYSTEM\202MAPPINGS\202GLOBAL\202^%s\201", mref_get_subscript (r, 0));
global (kill_sym, ns_key, data);
goto done;
case get_sym:
if (frm_global_exists (gb_ns, gb_path, r->subscripts[0]) != TRUE) {
merr_raise (M7);
goto done;
}
if (strcmp (mref_get_subscript (r, 1), "BLOCK") == 0) {
long bn = atol (mref_get_subscript (r, 2));
stcpy (gb_cpath, gb_path);
stcnv_m2c (gb_cpath);
blkcount = frm_blockcount (gb_cpath);
if (bn > (blkcount - 1)) {
merr_raise (M38);
goto done;
}
frm_decode_block (bi, gb_cpath, bn);
if (strcmp (mref_get_subscript (r, 3), "TYPE") == 0) {
switch (bi->btype) {
case 2:
sprintf (data, "%s\201", "POINTER");
merr_raise (OK);
goto done;
case 6:
sprintf (data, "%s\201", "ROOT");
merr_raise (OK);
goto done;
case 8:
sprintf (data, "%s\201", "DATA");
merr_raise (OK);
goto done;
}
sprintf (data, "%d\201", bi->btype);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 3), "BLOCKCOUNT") == 0) {
if (bn != 0) {
merr_raise (M38);
goto done;
}
sprintf (data, "%ld\201", bi->blockcount);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 3), "KEYLEN") == 0) {
if (bn == 0) {
merr_raise (M38);
goto done;
}
sprintf (data, "%d\201", bi->keylen);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 3), "RLPTR") == 0) {
if (bn == 0) {
merr_raise (M38);
goto done;
}
sprintf (data, "%ld\201", bi->rlptr);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 3), "OFFS") == 0) {
if (bi->btype != DATA) {
merr_raise (M38);
goto done;
}
sprintf (data, "%ld\201", bi->free_offset);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 3), "LLPTR") == 0) {
if (bn == 0) {
merr_raise (M38);
goto done;
}
sprintf (data, "%ld\201", bi->llptr);
merr_raise (OK);
goto done;
}
}
else if (strcmp (mref_get_subscript (r, 1), "CHARACTER") == 0) {
stcpy (gb_cpath, gb_path);
stcnv_m2c (gb_cpath);
frm_decode_block (bi, gb_cpath, 0L);
if (bi->collation == 0) {
sprintf (data, "M\201");
merr_raise (OK);
goto done;
}
else {
sprintf (data, "ASCII\201");
merr_raise (OK);
goto done;
}
}
else if (strcmp (mref_get_subscript (r, 1), "COLLATE") == 0) {
stcpy (gb_cpath, gb_path);
stcnv_m2c (gb_cpath);
frm_decode_block (bi, gb_cpath, 0L);
if (bi->collation == 0) {
sprintf (data, "M\201");
merr_raise (OK);
goto done;
}
else {
sprintf (data, "ASCII\201");
merr_raise (OK);
goto done;
}
}
else if (strcmp (mref_get_subscript (r, 1), "NAMESPACE") == 0) {
sprintf (data, "%s\201", gb_ns);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 1), "FILE") == 0) {
sprintf (data, "%s\201", gb_path);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 1), "BLOCKSIZE") == 0) {
sprintf (data, "%d\201", BLOCKLEN);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 1), "BLOCKS") == 0) {
long blockcount;
stcpy (gb_cpath, gb_path);
stcnv_m2c (gb_cpath);
blockcount = frm_blockcount (gb_cpath);
sprintf (data, "%ld\201", blockcount);
merr_raise (OK);
goto done;
}
else if (strcmp (mref_get_subscript (r, 1), "BYTES") == 0) {
FILE *fp;
long bytecount;
stcpy (gb_cpath, gb_path);
stcnv_m2c (gb_cpath);
bytecount = frm_bytecount (gb_cpath);
sprintf (data, "%ld\201", bytecount);
merr_raise (OK);
goto done;
}
merr_raise (M38);
goto done;
default:
merr_raise (INVREF);
goto done;
}
done:
free (r);
return;
}
short frm_global_exists(char *gbl_namespace, char *gbl_path, char *global_name)
{
char *gpth;
char glofile[STRLEN];
char goobuf[STRLEN];
char mapk_buf[255];
char mapd_buf[255];
char old_ns[255];
int ierr_sav = OK;
if (global_name[0] != '^') {
snprintf (mapk_buf, 254, "^$SYSTEM\202MAPPINGS\202GLOBAL\202^%s\201", global_name);
}
else {
snprintf (mapk_buf, 254, "^$SYSTEM\202MAPPINGS\202GLOBAL\202%s\201", global_name);
}
global (get_sym, mapk_buf, mapd_buf);
stcnv_m2c (mapd_buf);
if (merr () == OK) {
strncpy (old_ns, nsname, 255);
set_namespace (mapd_buf, 0);
gpth = (char *) malloc (PATHLEN * sizeof (char));
NULLPTRCHK(gpth,"frm_global_exists");
strncpy (gpth, glopath, PATHLEN - 1);
strncpy (gbl_namespace, mapd_buf, 254);
set_namespace (old_ns, 0);
}
else {
merr_raise (ierr_sav);
if (global_name[0] == '%') {
gpth = gloplib;
sprintf (gbl_namespace, "SYSTEM");
}
else {
gpth = glopath;
sprintf (gbl_namespace, "%s\201", nsname);
}
}
stcpy (goobuf, gpth);
stcnv_m2c (goobuf);
if (global_name[0] != '^') {
snprintf (glofile, STRLEN - 1, "%s/^%s", goobuf, global_name);
}
else {
snprintf (glofile, STRLEN - 1, "%s/%s", goobuf, global_name);
}
strcpy (gbl_path, glofile);
stcnv_c2m (gbl_path);
if (file_exists (glofile)) {
return TRUE;
}
else {
return FALSE;
}
}
long frm_blockcount(char *gbl_path)
{
FILE *fp;
long blockcount;
fp = fopen (gbl_path, "r");
fseek (fp, 0L, SEEK_END);
blockcount = ftell (fp) / BLOCKLEN;
fclose (fp);
return blockcount;
}
long frm_bytecount(char *gbl_path)
{
FILE *fp;
long bytecount;
fp = fopen (gbl_path, "r");
fseek (fp, 0L, SEEK_END);
bytecount = ftell (fp);
fclose (fp);
return bytecount;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>