Diff for /freem/src/global_bltin.c between versions 1.1 and 1.8

version 1.1, 2025/01/19 02:04:04 version 1.8, 2025/04/08 14:39:21
Line 1 Line 1
 /*  /*
  *                            *   *   $Id$
  *                           * *  
  *                          *   *  
  *                     ***************  
  *                      * *       * *  
  *                       *  MUMPS  *  
  *                      * *       * *  
  *                     ***************  
  *                          *   *  
  *                           * *  
  *                            *  
  *  
  *   global.c  
  *    freem database engine   *    freem database engine
  *   *
  *     *  
  *   Author: Serena Willis <jpw@coherent-logic.com>   *   Author: Serena Willis <snw@coherent-logic.com>
  *    Copyright (C) 1998 MUG Deutschland   *    Copyright (C) 1998 MUG Deutschland
  *    Copyright (C) 2020 Coherent Logic Development LLC   *    Copyright (C) 2020, 2025 Coherent Logic Development LLC
  *   *
  *   *
  *   This file is part of FreeM.   *   This file is part of FreeM.
Line 35 Line 23
  *   You should have received a copy of the GNU Affero Public License   *   You should have received a copy of the GNU Affero Public License
  *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.   *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
  *   *
    *   $Log$
    *   Revision 1.8  2025/04/08 14:39:21  snw
    *   Initial work on global handler refactor
    *
    *   Revision 1.7  2025/03/24 04:13:11  snw
    *   Replace action macro dat with fra_dat to avoid symbol conflict on OS/2
    *
    *   Revision 1.6  2025/03/24 01:33:30  snw
    *   Guard declaration of time function in global_bltin.c for portability
    *
    *   Revision 1.5  2025/03/22 22:52:24  snw
    *   Add STRLEN_GBL macro to manage global string length
    *
    *   Revision 1.4  2025/03/09 19:14:25  snw
    *   First phase of REUSE compliance and header reformat
    *
    *
    * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
    * SPDX-License-Identifier: AGPL-3.0-or-later
  **/   **/
   
 #include <sys/types.h>  #include <sys/types.h>
Line 42 Line 49
 #include <fcntl.h>  #include <fcntl.h>
 #include <unistd.h>  #include <unistd.h>
 #include <string.h>  #include <string.h>
   #include <stdlib.h>
 #include <errno.h>  #include <errno.h>
   
   
 #include "mpsdef.h"  #include "mpsdef.h"
   #include "global_bltin.h"
   
   global_handle *global_handles_head;
   
 static void b_free (short filedes, unsigned long blknbr);  static void b_free (short filedes, unsigned long blknbr);
 static void splitp (short filedes, char *block, long *addr, long *offs, unsigned long *blknbr);  static void splitp (short filedes, char *block, long *addr, long *offs, unsigned long *blknbr);
Line 100  static void panic (void); Line 109  static void panic (void);
 #define BOTTOM   6  #define BOTTOM   6
 #define DATA     8  #define DATA     8
   
 #if !defined(__OpenBSD__) && !defined(_AIX) && !defined(__osf__) && !defined(MSDOS) && !defined(__vax__)  #if !defined(__OpenBSD__) && !defined(_AIX) && !defined(__osf__) && !defined(MSDOS) && !defined(__vax__) && !defined(__OS2__)
  long time ();   long time ();
 #endif  #endif
   
   inline long gbl_path(char *key, char *buf)
   {
       long savj;
       long savch;                 /* saved j and ch for multiple pathes */
   
       register long int i;
       register long int j;
       register long int k;
       register long int ch;
       long pathscan;                      /* flag for repeated scan of pathlist setting an undef global */
      
       /* construct full UNIX filename */
       savj = 0;
       savch = ch = EOL;
       pathscan = TRUE;
   nextpath:
       k = 0;
       j = savj;
   
       if (key[1] == '%' || key[1] == '$') {               /* %-globals and SSVN backing storage, no explicit path */
           
           if (gloplib[0] != EOL) {
               
               /* append % global access path */
               while ((ch = buf[k++] = gloplib[j++]) != ':' && ch != EOL); 
   
           } 
   
       }
       else if (key[1] != '/') {           /* no explicit path specified */
           
           if (glopath[0] != EOL) {
   
               /* append global access path */
               while ((ch = buf[k++] = glopath[j++]) != ':' && ch != EOL);
   
           }
   
       }
   
       if (savj == 0 && ch == EOL) pathscan = FALSE;               /* one path only: inhibit search */
       
       if (k > 0) {
   
           if (k == 1 || (k == 2 && buf[0] == '.')) {
               k = 0;
           }
           else {
               buf[k - 1] = '/';
           }
   
       }
   
       savch = ch;
       savj = j;
       i = 0;
       j = 0;
   
       while (key[i] != EOL) {
   
           if ((buf[k] = key[i]) == DELIM) break;
           
           if (buf[k] == '/') {
               
               j = i;
   
               if (k > i) {
                   i = 0;
                   j = 0;
                   k = 0;
   
                   continue;
               }
   
           }
   
           i++;
           k++;
       
       }
   
       buf[k] = NUL;                       /* NUL not EOL !!! */
   
       return i;
   } /* global_file */
   
   int gbl_lock(global_handle *g, int type)
   {
       if (g->locked == TRUE || lonelyflag == TRUE) {
           return TRUE;
       }
   
       locking (g->fd, type, 0L);
       g->locked = TRUE;
   }
   
   int gbl_unlock(global_handle *g)
   {
       if (g->locked == FALSE || lonelyflag == TRUE) {
           return TRUE;
       }
   
       locking (g->fd, 0, 0L);
       g->locked = FALSE;
   }
   
   void gbl_close(global_handle *g)
   {
       if (g->opened == TRUE) {
           close (g->fd);
   
           g->use_count = 0;
           g->age = 0;
           g->last_block = 0;
           g->locked = FALSE;
           g->opened = FALSE;
       }
   }
   
   void gbl_close_all(void)
   {
       global_handle *g;
   
       for (g = global_handles_head; g != NULL; g = g->next) {
           gbl_close (g);
       }
   }
   
   int gbl_create(global_handle *g)
   {
       while (1) {
           errno = 0;
   
           if ((g->fd = creat (g->global_path, 0666)) != -1) break;
   
           if (errno == EMFILE || errno == ENFILE) {
               gbl_close_all ();
               continue;
           }
   
           return PROTECT;
       }
   
       g->opened = TRUE;
       g->age = time (0L);
       g->last_block = 0;
       g->use_count = 1;
       
       return OK;
   }
   
   short gbl_open(global_handle *g, short action)
   {
       if (g->opened == FALSE) {
           while (1) {
               errno = 0;
               g->fd = open (g->global_path, 2);
               
               if (g->fd != -1) break;
               
               switch (errno) {            
                   case EINTR:
                       continue;
                       
                   case EMFILE:
                   case ENFILE:
                       close_all_globals ();
                       continue;
               }
               
               break;
           }
           
           if (g->fd == -1) {
               g->use_count = 0;
               g->age = 0;
               g->last_block = 0;
               g->locked = FALSE;
               g->opened = FALSE;
           }
           else {
               g->opened = TRUE;
           }
       }
   
       return g->opened;
       
   } /* gbl_open */
   
   global_handle *gbl_handle(char *key)
   {
       global_handle *g;
       char global_name[256];
       int i;
       long path_len;
       char block[BLOCKLEN];
       struct stat dinf;            
       
       i = 0;
       while (key[i] != EOL) {
           if ((global_name[i] = key[i]) == DELIM) break;
   
           i++;
       }
       global_name[i] = NUL;
   
       
       for (g = global_handles_head; g != NULL; g = g->next) {
           if (strncmp (g->global_name, global_name, 256) == 0) {
               g->use_count++;
               if (!lonelyflag) {
                   g->fast_path = 0;
               }
   
               fstat (g->fd, &dinf);
               if (g->age > dinf.st_mtime) {
                   g->fast_path = 2;
                   return g;
               }
   
               g->age = time (0L);
               g->fast_path = 0;
               
               return g;
           }
       }
       g = (global_handle *) malloc (sizeof (global_handle));
       NULLPTRCHK(g,"gbl_open");
   
       g->use_count = 1;
       g->locked = FALSE;
       g->age = time (0L);
       g->last_block = 0;
       g->opened = FALSE;
       g->fd = 0;
       g->fast_path = -1;
       
       strcpy (g->global_name, global_name);    
       gbl_path (key, g->global_path);
       
       g->next = global_handles_head;
       global_handles_head = g;
   
       return g;    
   }
   
   
 /* globals management */  /* globals management */
           
 /* 0 = set_sym      1 = get_sym */  /* 0 = set_sym      1 = get_sym */
Line 178  static void panic (void); Line 434  static void panic (void);
  * the file is *not* closed on return. since access is regulated by the   * the file is *not* closed on return. since access is regulated by the
  * locking mechanism, that will not spell trouble.   * locking mechanism, that will not spell trouble.
  */   */
    
 void global_bltin (short action, char *key, char *data)  void global_bltin (short action, char *key, char *data)
 {  {
   
       global_handle *g;
       
     /* these must be static variables */      /* these must be static variables */
   
     static short filedes;               /* filedescr for global access */      static short filedes;               /* filedescr for global access */
Line 191  void global_bltin (short action, char *k Line 449  void global_bltin (short action, char *k
     /* static or dynamic */      /* static or dynamic */
   
     static unsigned long blknbr;        /* block number */      static unsigned long blknbr;        /* block number */
     static unsigned long oldblk;  //    static unsigned long oldblk;
     static unsigned long newblk;      static unsigned long newblk;
     static unsigned long other;      static unsigned long other;
     static long j1;      static long j1;
Line 213  void global_bltin (short action, char *k Line 471  void global_bltin (short action, char *k
     static int tryfast;                 /* try fast access if get_sym on    */      static int tryfast;                 /* try fast access if get_sym on    */
                                 /* previous global */                                  /* previous global */
   
       int iresult;
       
     struct stat dinf;                   /* get modification date */      struct stat dinf;                   /* get modification date */
   
     long    savj,      long    savj,
Line 223  void global_bltin (short action, char *k Line 483  void global_bltin (short action, char *k
     ch;      ch;
     long    pathscan;                   /* flag for repeated scan of pathlist setting an undef global */      long    pathscan;                   /* flag for repeated scan of pathlist setting an undef global */
   
   
     /* process optional limitations */      /* process optional limitations */
     if (glvnflag.all && key[0] >= '%' && key[0] <= 'z') {      if (glvnflag.all && key[0] >= '%' && key[0] <= 'z') {
   
Line 300  void global_bltin (short action, char *k Line 559  void global_bltin (short action, char *k
         }          }
     }      }
   
   
     if (action == getnext) {      if (action == getnext) {
   
         getnflag = TRUE;          getnflag = TRUE;
Line 375  void global_bltin (short action, char *k Line 635  void global_bltin (short action, char *k
         }          }
     }      }
   
     /* construct full UNIX filename */      g = gbl_handle (key);    
     savj = 0;      i = gbl_path (key, filnam);
     savch = ch = EOL;  
     pathscan = TRUE;  
     nextpath:  
     k = 0;  
     j = savj;  
   
     if (key[1] == '%' || key[1] == '$') {               /* %-globals and SSVN backing storage, no explicit path */  
                   
         if (gloplib[0] != EOL) {  
               
             /* append % global access path */  
             while ((ch = filnam[k++] = gloplib[j++]) != ':' && ch != EOL);   
   
         }   
   
     }  
     else if (key[1] != '/') {           /* no explicit path specified */  
           
         if (glopath[0] != EOL) {  
   
             /* append global access path */  
             while ((ch = filnam[k++] = glopath[j++]) != ':' && ch != EOL);  
   
         }  
   
     }  
   
     if (savj == 0 && ch == EOL) pathscan = FALSE;               /* one path only: inhibit search */  
       
     if (k > 0) {  
   
         if (k == 1 || (k == 2 && filnam[0] == '.')) {  
             k = 0;  
         }  
         else {  
             filnam[k - 1] = '/';  
         }  
   
     }  
   
     savch = ch;  
     savj = j;  
     i = 0;  
     j = 0;  
   
     while (key[i] != EOL) {  
   
         if ((filnam[k] = key[i]) == DELIM) break;  
           
         if (filnam[k] == '/') {  
               
             j = i;  
   
             if (k > i) {  
                 i = 0;  
                 j = 0;  
                 k = 0;  
   
                 continue;  
             }  
   
         }  
   
         i++;  
         k++;  
       
     }  
   
     filnam[k] = NUL;                    /* NUL not EOL !!! */  
   
     /* if a unix directory is specified, reposition '^' */  
     /* '^/usr/test' becomes '/usr/^test'                */  
     if (j > 0) {  
   
         for (k = 0; k < j; k++) {  
             filnam[k] = filnam[k + 1];  
         }  
       
         filnam[j] = '^';  
   
     }  
   
     /* compact key to internal format: characters are shifted left */      /* compact key to internal format: characters are shifted left */
     /* delimiters become LSB of previous character                 */      /* delimiters become LSB of previous character                 */
     /* test subscripts for being numeric or not                    */      /* test subscripts for being numeric or not                    */
Line 594  void global_bltin (short action, char *k Line 773  void global_bltin (short action, char *k
   
     compactkey[k] = g_EOL;      compactkey[k] = g_EOL;
   
     /* look whether file is already open */  
     tryfast = FALSE;  
     ch = usage[i = j = inuse];  
       
     while (i < NO_GLOBLS) {  
           
         k = 0;  
           
         while (filnam[k] == oldfil[i][k]) {  
   
             if (filnam[k++] == NUL) {  
   
                 filedes = olddes[i];  
   
                 if (inuse == i && action == get_sym) {  
                       
                     tryfast = TRUE;  
                       
                     if (usage[i] != (-1)) usage[i]++;  
                     if (lonelyflag) goto tfast2;  
                       
                     fstat (filedes, &dinf);  
                       
                     if (g_ages[i] > dinf.st_mtime) goto tfast2;  
                       
                     g_ages[i] = time (0L);  
                       
                     goto tfast0;  
   
                 }  
   
                 inuse = i;  
   
                 if (usage[i] != (-1)) usage[i]++;  
                   
                 goto lock;  
             }  
   
         }  
   
         if (ch < 0 || (usage[i] >= 0 && usage[i] < ch)) ch = usage[j = i];  
           
         if (i++ == inuse) {  
             inuse = (-1);  
             i = 0;  
         }  
   
     }  
   
     inuse = j;  
     usage[j] = 1;  
   
     /* close previous file */  
     if ((filedes = olddes[j]) > 0) {  
         close (filedes);  
         olddes[j] = 0;  
     }  
   
     strcpy (oldfil[j], filnam);         /* save current filename */  
   
 reopen:  reopen:
   
     for (;;) {      gbl_open (g, action);
       if (g->fd == -1) {
         errno = 0;  
           
         if ((filedes = open (filnam, 2)) != -1) break;  
         if (errno == EINTR) continue;  
   
         if (errno == EMFILE || errno == ENFILE) {       /* too many open files now */  
             close_all_globals ();  
               
             continue;  
         }  
   
         break;  
     }  
   
     if (filedes == -1) {  
   
         usage[inuse] = 0;  
         oldfil[inuse][0] = NUL;  
         olddes[inuse] = 0;  
         g_ages[inuse] = 0;  
           
         if ((pathscan || errno != ENOENT) && (savch != EOL)) goto nextpath;             /* try next access path */  
           
         /* file not found */          /* file not found */
         if (action != set_sym) {          if (action != set_sym) {
                           
Line 689  reopen: Line 786  reopen:
                 return;                  return;
             }              }
   
             if (action == dat || action == zdata) {              if (action == fra_dat || action == zdata) {
                 data[0] = '0';                  data[0] = '0';
                 data[1] = EOL1;                  data[1] = EOL1;
                   
Line 713  reopen: Line 810  reopen:
             merr_raise (PROTECT);              merr_raise (PROTECT);
             return;              return;
         }          }
           
         if (pathscan) {  
             savj = 0;  
             savch = ch = EOL;  
             pathscan = FALSE;  
   
             goto nextpath;  
         }  
   
         if (setop) {          if (setop) {
                           
             tmp1[0] = EOL;              tmp1[0] = EOL;
Line 751  reopen: Line 840  reopen:
         block[NRBLK + 2] = ROOT + 1;    /* nr. of blocks */          block[NRBLK + 2] = ROOT + 1;    /* nr. of blocks */
   
         /* create file, write_lock it and initialize root block */          /* create file, write_lock it and initialize root block */
         for (;;) {          gbl_lock (g, 1);
   
             errno = 0;  
               
             if ((filedes = creat (filnam, 0666)) != -1) break;  
   
             if (errno == EMFILE || errno == ENFILE) {          if ((iresult = gbl_create (g)) != OK) {
                 close_all_globals ();              merr_raise (iresult);
                 continue;  
             }  
   
             merr_raise (PROTECT);  
             return;              return;
         }          }        
   
         if (lonelyflag == FALSE) locking (filedes, 1, 0L);  
                   
         for (;;) {          for (;;) {
                           
             errno = 0;              errno = 0;
                   
             lseek (filedes, ROOT * BLOCKLEN, 0);              lseek (g->fd, ROOT * BLOCKLEN, 0);
             write (filedes, block, BLOCKLEN);              write (g->fd, block, BLOCKLEN);
                   
             if (errno == 0) break;              if (errno == 0) break;
                   
Line 794  reopen: Line 873  reopen:
         for (;;) {          for (;;) {
   
             errno = 0;              errno = 0;
             write (filedes, block, BLOCKLEN);              write (g->fd, block, BLOCKLEN);
                           
             if (errno == 0) break;              if (errno == 0) break;
                           
             lseek (filedes, (ROOT + 1L) * BLOCKLEN, 0);              lseek (g->fd, (ROOT + 1L) * BLOCKLEN, 0);
             panic ();              panic ();
   
         }          }
   
         close (filedes);          gbl_close (g);
                   gbl_unlock (g);
         if (lonelyflag == FALSE) locking (filedes, 0, 0L);      /* unlock */          gbl_open (g, action);
           
         /* close new file, so other users can find it */          /* close new file, so other users can find it */
         return;          return;
     }      }
   
     olddes[inuse] = filedes;            /* save current filedescriptor */  
   
     /* request global for exclusive use                            */      /* request global for exclusive use                            */
     /* odd numbered actions get read access (get_sym,data,fra_order) 3 */      /* odd numbered actions get read access (get_sym,data,fra_order) 3 */
     /* even ones read/write access          (set_sym,kill_sym)   1 */      /* even ones read/write access          (set_sym,kill_sym)   1 */
Line 822  lock: Line 899  lock:
     if (action == get_sym) {      if (action == get_sym) {
   
 tfast0:  tfast0:
           gbl_lock (g, 3);
         if (lonelyflag == FALSE) locking (filedes, 3, 0L);          
         if (tryfast) goto tfast1;               /* try again last block */          if (tryfast) goto tfast1;               /* try again last block */
                   
         blknbr = oldblk = ROOT;         /* start with ROOT block */          blknbr = g->last_block = ROOT;          /* start with ROOT block */
                   
         for (;;) {          for (;;) {
   
   
 tfast1:  tfast1:
   
             lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);              lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
             read (filedes, block, BLOCKLEN);              read (g->fd, block, BLOCKLEN);
   
   
 tfast2:  tfast2:
Line 878  tfast2: Line 954  tfast2:
   
                 }                  }
   
                 /* key1[j]=g_EOL; */  
                 j = ch;                  j = ch;
                                   
                 do {                  do {
Line 922  tfast2: Line 997  tfast2:
             if (typ == EMPTY) {              if (typ == EMPTY) {
                                   
                 if (blknbr == ROOT) {                  if (blknbr == ROOT) {
                     close (filedes);                      //close (filedes);
                       gbl_close (g);
                     goto reopen;                      goto reopen;
                 }                  }
   
Line 937  tfast2: Line 1013  tfast2:
   
         addr += UNSIGN (block[addr]) + 2;       /* skip key */          addr += UNSIGN (block[addr]) + 2;       /* skip key */
                   
         if ((blknbr = UNSIGN (block[addr]) * 65536 + UNSIGN (block[addr + 1]) * 256 + UNSIGN (block[addr + 2])) == oldblk) {          if ((blknbr = UNSIGN (block[addr]) * 65536 + UNSIGN (block[addr + 1]) * 256 + UNSIGN (block[addr + 2])) == g->last_block) {
             merr_raise (DBDGD);              merr_raise (DBDGD);
             goto quit;              goto quit;
         }          }
   
         addr += PLEN;           /* skip data */          addr += PLEN;           /* skip data */
         oldblk = blknbr;          g->last_block = blknbr;
                   
         if (merr () == INRPT) goto quit;          if (merr () == INRPT) goto quit;
   
         }          }
     }                                   /* end of get_sym */      }                                   /* end of get_sym */
   
       gbl_lock (g, action & 01 ? 3 : 1);
     if (lonelyflag == FALSE) locking (filedes, (action & 01 ? 3 : 1), 0L);      
   
     /* a KILL on an unsubscripted global deletes the entire file */      /* a KILL on an unsubscripted global deletes the entire file */
     if (action == kill_sym && compactkey[0] == g_EOL) {      if (action == kill_sym && compactkey[0] == g_EOL) {
                   
         lseek (filedes, ROOT, 0);          lseek (g->fd, ROOT, 0);
   
         /* note : UNIX does not tell other    */          /* note : UNIX does not tell other    */
         block[BTYP] = EMPTY;            /* jobs that a file has been unlinked */          block[BTYP] = EMPTY;            /* jobs that a file has been unlinked */
                   
         /* as long as they keep it open.      */          /* as long as they keep it open.      */
         /* so we mark this global as EMPTY    */          /* so we mark this global as EMPTY    */
         write (filedes, block, BLOCKLEN);          write (g->fd, block, BLOCKLEN);
           
         if (lonelyflag == FALSE) locking (filedes, 0, 0L);      /* unlock */          gbl_unlock (g);
                   gbl_close (g);
         close (filedes);  
           
         olddes[inuse] = 0;  
         oldfil[inuse][0] = NUL;  
         usage[inuse] = 0;  
                   
         unlink (filnam);          unlink (filnam);
                   
Line 981  tfast2: Line 1051  tfast2:
 k_again:                                /* entry point for repeated kill operations */  k_again:                                /* entry point for repeated kill operations */
   
     /* scan tree for the proper position of key */      /* scan tree for the proper position of key */
     blknbr = oldblk = ROOT;             /* start with ROOT block */      blknbr = g->last_block = ROOT;              /* start with ROOT block */
     trx = (-1);      trx = (-1);
   
     for (;;) {      for (;;) {
Line 994  k_again:    /* entry point for repeated Line 1064  k_again:    /* entry point for repeated
         traceblk[trx] = blknbr;          traceblk[trx] = blknbr;
         traceadr[trx] = 0;          traceadr[trx] = 0;
                   
         lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);          lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
         read (filedes, block, BLOCKLEN);          read (g->fd, block, BLOCKLEN);
                   
         typ = block[BTYP];          typ = block[BTYP];
                   
Line 1007  k_again:    /* entry point for repeated Line 1077  k_again:    /* entry point for repeated
         if (typ == EMPTY) {          if (typ == EMPTY) {
   
             if (blknbr == ROOT) {              if (blknbr == ROOT) {
                 close (filedes);                  gbl_close (g);
                 goto reopen;                  goto reopen;
             }              }
   
Line 1021  k_again:    /* entry point for repeated Line 1091  k_again:    /* entry point for repeated
         addr += UNSIGN (block[addr]);          addr += UNSIGN (block[addr]);
         addr += 2;                      /* skip key */          addr += 2;                      /* skip key */
                   
         if ((blknbr = UNSIGN (block[addr]) * 65536 + UNSIGN (block[addr + 1]) * 256 + UNSIGN (block[addr + 2])) == oldblk) {          if ((blknbr = UNSIGN (block[addr]) * 65536 + UNSIGN (block[addr + 1]) * 256 + UNSIGN (block[addr + 2])) == g->last_block) {
             merr_raise (DBDGD);              merr_raise (DBDGD);
             goto quit;              goto quit;
         }          }
   
         addr += PLEN;                   /* skip data */          addr += PLEN;                   /* skip data */
         oldblk = blknbr;          g->last_block = blknbr;
     }      }
   
     traceadr[trx] = addr;      traceadr[trx] = addr;
Line 1162  s10:            { Line 1232  s10:            {
   
                 }                  }
   
                 lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                 write (filedes, block, BLOCKLEN);                  write (g->fd, block, BLOCKLEN);
   
                 if (traceadr[trx] == 0) update (filedes, compactkey, keyl);                  if (traceadr[trx] == 0) update (g->fd, compactkey, keyl);
   
                 break;                  break;
             }              }
Line 1207  s10:            { Line 1277  s10:            {
   
                 }                   } 
                 else {                                    else {                  
                     /* if (j1<0) */  
                     /* we need more space */                       /* we need more space */ 
   
                     if ((offset - j1) > DATALIM) {                      if ((offset - j1) > DATALIM) {
Line 1250  s20: Line 1319  s20:
             }              }
           
             stcpy0 (&block[++addr], data, (long) datal);              stcpy0 (&block[++addr], data, (long) datal);
             lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);              lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
             write (filedes, block, BLOCKLEN);              write (g->fd, block, BLOCKLEN);
             break;              break;
   
   
         case dat:          case fra_dat:
   
             data[0] = '0';              data[0] = '0';
             data[1] = EOL1;              data[1] = EOL1;
Line 1282  s20: Line 1351  s20:
   
                     if ((blknbr = UNSIGN (block[RLPTR]) * 65536 + UNSIGN (block[RLPTR + 1]) * 256 + UNSIGN (block[RLPTR + 2]))) {                      if ((blknbr = UNSIGN (block[RLPTR]) * 65536 + UNSIGN (block[RLPTR + 1]) * 256 + UNSIGN (block[RLPTR + 2]))) {
                                           
                         lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                         read (filedes, block, BLOCKLEN);                          read (g->fd, block, BLOCKLEN);
                         j1 = UNSIGN (block[0]);                          j1 = UNSIGN (block[0]);
                                           
                         i = 0;                          i = 0;
Line 1365  s20: Line 1434  s20:
                     goto quit;                      goto quit;
                 }       /* no next block */                  }       /* no next block */
                                   
                 lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                 read (filedes, block, BLOCKLEN);                  read (g->fd, block, BLOCKLEN);
                 scandblk (block, &addr, &found);                  scandblk (block, &addr, &found);
   
             }               } 
Line 1522  s20: Line 1591  s20:
                         goto quit;              /* no next block */                          goto quit;              /* no next block */
                     }                      }
   
                     lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                      lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                     read (filedes, block, BLOCKLEN);                      read (g->fd, block, BLOCKLEN);
   
                     addr = 0;                      addr = 0;
                     offset = UNSIGN (block[OFFS]) * 256 +                      offset = UNSIGN (block[OFFS]) * 256 +
Line 1546  s20: Line 1615  s20:
                     goto quit;          /* no next block */                      goto quit;          /* no next block */
                 }                  }
   
                 lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                 read (filedes, block, BLOCKLEN);                  read (g->fd, block, BLOCKLEN);
                                   
                 addr = 0;                  addr = 0;
             }               } 
Line 1611  s20: Line 1680  s20:
                         }                          }
   
                         zref[j++] = ch0;                          zref[j++] = ch0;
   
                                                   
                         if (j >= 252) {                          if (j >= 252) {
                             zref[j] = EOL;                              zref[j] = EOL;
Line 1756  killo:    /* entry from killone section Line 1826  killo:    /* entry from killone section
                         other = traceblk[--trx];                          other = traceblk[--trx];
                         addr = traceadr[trx];                          addr = traceadr[trx];
                                                   
                         lseek (filedes, (long) other * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) other * (long) (BLOCKLEN), 0);
                         read (filedes, block, BLOCKLEN);                          read (g->fd, block, BLOCKLEN);
                                                   
                         addr += UNSIGN (block[addr]);                          addr += UNSIGN (block[addr]);
                         addr += (2 + PLEN);     /* skip previous entry */                          addr += (2 + PLEN);     /* skip previous entry */
Line 1776  killo:    /* entry from killone section Line 1846  killo:    /* entry from killone section
   
                     trx = trxsav;                      trx = trxsav;
   
                     lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                      lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                     read (filedes, block, BLOCKLEN);                      read (g->fd, block, BLOCKLEN);
   
                     offset = UNSIGN (block[OFFS]) * 256 +                      offset = UNSIGN (block[OFFS]) * 256 +
                     UNSIGN (block[OFFS + 1]);                      UNSIGN (block[OFFS + 1]);
Line 1883  p_empty:  /* entry if pointer block goes Line 1953  p_empty:  /* entry if pointer block goes
   
                     if (left) {                      if (left) {
   
                         lseek (filedes, (long) left * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) left * (long) (BLOCKLEN), 0);
                         read (filedes, block0, BLOCKLEN);                          read (g->fd, block0, BLOCKLEN);
                                                   
                         block0[RLPTR] = block[RLPTR];                          block0[RLPTR] = block[RLPTR];
                         block0[RLPTR + 1] = block[RLPTR + 1];                          block0[RLPTR + 1] = block[RLPTR + 1];
                         block0[RLPTR + 2] = block[RLPTR + 2];                          block0[RLPTR + 2] = block[RLPTR + 2];
                                                   
                         lseek (filedes, (long) left * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) left * (long) (BLOCKLEN), 0);
                         write (filedes, block0, BLOCKLEN);                          write (g->fd, block0, BLOCKLEN);
   
                     }                      }
   
                     if (right) {                      if (right) {
                                                   
                         lseek (filedes, (long) right * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) right * (long) (BLOCKLEN), 0);
                         read (filedes, block0, BLOCKLEN);                          read (g->fd, block0, BLOCKLEN);
                                                   
                         block0[LLPTR] = block[LLPTR];                          block0[LLPTR] = block[LLPTR];
                         block0[LLPTR + 1] = block[LLPTR + 1];                          block0[LLPTR + 1] = block[LLPTR + 1];
                         block0[LLPTR + 2] = block[LLPTR + 2];                          block0[LLPTR + 2] = block[LLPTR + 2];
                                                   
                         lseek (filedes, (long) right * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) right * (long) (BLOCKLEN), 0);
                         write (filedes, block0, BLOCKLEN);                          write (g->fd, block0, BLOCKLEN);
   
                     }                      }
   
                     b_free (filedes, blknbr);   /* modify free list */                      b_free (g->fd, blknbr);     /* modify free list */
                                           
                     /* delete pointer */                      /* delete pointer */
                     /**************************/                      /**************************/
Line 1922  p_empty:  /* entry if pointer block goes Line 1992  p_empty:  /* entry if pointer block goes
                         blknbr = traceblk[--trx];                          blknbr = traceblk[--trx];
                         addr = traceadr[trx];                          addr = traceadr[trx];
   
                         lseek (filedes, (long) (blknbr) * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) (blknbr) * (long) (BLOCKLEN), 0);
                         read (filedes, block, BLOCKLEN);                          read (g->fd, block, BLOCKLEN);
                         offset = UNSIGN (block[OFFS]) * 256 +                          offset = UNSIGN (block[OFFS]) * 256 +
                         UNSIGN (block[OFFS + 1]);                          UNSIGN (block[OFFS + 1]);
                         freecnt = UNSIGN (block[addr]) + 2 + PLEN;                          freecnt = UNSIGN (block[addr]) + 2 + PLEN;
Line 1935  p_empty:  /* entry if pointer block goes Line 2005  p_empty:  /* entry if pointer block goes
   
                             if (blknbr == ROOT) {       /* global went empty */                              if (blknbr == ROOT) {       /* global went empty */
   
                                 lseek (filedes, 0L, 0);                                  lseek (g->fd, 0L, 0);
                                                   
                                 /* note : UNIX does not tell other    */                                  /* note : UNIX does not tell other    */
                                 block[BTYP] = EMPTY;    /* jobs that a file has been unlinked */                                  block[BTYP] = EMPTY;    /* jobs that a file has been unlinked */
                                                   
                                 /* as long as they keep it open.      */                                  /* as long as they keep it open.      */
                                 /* so we mark this global as EMPTY    */                                  /* so we mark this global as EMPTY    */
                                 write (filedes, block, BLOCKLEN);                                  write (g->fd, block, BLOCKLEN);
                                 close (filedes);                                  gbl_close (g);
                                 unlink (filnam);                                  unlink (filnam);
                           
                                 if (lonelyflag == FALSE) locking (filedes, 0, 0L);      /* unlock */                                  gbl_unlock (g);
   
                                 olddes[inuse] = 0;                                  olddes[inuse] = 0;
                                 oldfil[inuse][0] = NUL;                                  oldfil[inuse][0] = NUL;
Line 1967  p_empty:  /* entry if pointer block goes Line 2037  p_empty:  /* entry if pointer block goes
                                                   
                         for (i = offset; i < offset + freecnt; block[i++] = 0);                          for (i = offset; i < offset + freecnt; block[i++] = 0);
   
                         lseek (filedes, (long) (blknbr) * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) (blknbr) * (long) (BLOCKLEN), 0);
                         write (filedes, block, BLOCKLEN);                          write (g->fd, block, BLOCKLEN);
   
                         if (addr == 0) {        /* update of pointer */                          if (addr == 0) {        /* update of pointer */
                             traceadr[trx] = 0;                              traceadr[trx] = 0;
                                                           
                             update (filedes, &block[2], (long) UNSIGN (block[0]));                              update (g->fd, &block[2], (long) UNSIGN (block[0]));
                         }                          }
   
                         trx = trxsav;                          trx = trxsav;
Line 2015  p_empty:  /* entry if pointer block goes Line 2085  p_empty:  /* entry if pointer block goes
                 }                  }
                 block[OFFS] = offset / 256;                  block[OFFS] = offset / 256;
                 block[OFFS + 1] = offset % 256;                  block[OFFS + 1] = offset % 256;
                 lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                 write (filedes, block, BLOCKLEN);                  write (g->fd, block, BLOCKLEN);
                 if (addr < 3) {         /* update of pointer */                  if (addr < 3) {         /* update of pointer */
                 traceadr[trx] = 0;                  traceadr[trx] = 0;
                 update (filedes, &block[2], (long) UNSIGN (block[0]));                  update (g->fd, &block[2], (long) UNSIGN (block[0]));
                 }                  }
             }              }
   
Line 2042  zinv: Line 2112  zinv:
                         goto quit;                          goto quit;
                     }                   /* no previous block */                      }                   /* no previous block */
                                           
                     lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                      lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                     read (filedes, block, BLOCKLEN);                      read (g->fd, block, BLOCKLEN);
                                           
                     addr = UNSIGN (block[OFFS]) * 256 +                      addr = UNSIGN (block[OFFS]) * 256 +
                     UNSIGN (block[OFFS + 1]);                      UNSIGN (block[OFFS + 1]);
Line 2222  zinv: Line 2292  zinv:
                             break;              /* no next block */                              break;              /* no next block */
                         }                          }
   
                         lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);                          lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
                         read (filedes, block, BLOCKLEN);                          read (g->fd, block, BLOCKLEN);
                                                   
                         addr = 0;                          addr = 0;
                         offset = UNSIGN (block[OFFS]) * 256 +                          offset = UNSIGN (block[OFFS]) * 256 +
Line 2338  quit: Line 2408  quit:
           
     /* clean things up */      /* clean things up */
   
     lseek (filedes, ROOT, 0);      lseek (g->fd, ROOT, 0);
       gbl_unlock (g);
     if (lonelyflag == FALSE) locking (filedes, 0, 0L);  /* unlock */      
   
     return;      return;
   
   
Line 2352  splitd:    /* split data block in two se Line 2421  splitd:    /* split data block in two se
     /* 'addr' there I would like to insert, if possible (which is not) */      /* 'addr' there I would like to insert, if possible (which is not) */
     /* 'offset' filled up to this limit */      /* 'offset' filled up to this limit */
   
     getnewblk (filedes, &newblk);       /* get a new block */      getnewblk (g->fd, &newblk); /* get a new block */
   
     /* if we have to insert at the begin or end of a block  */      /* if we have to insert at the begin or end of a block  */
     /* we don't split - we just start a new block           */      /* we don't split - we just start a new block           */
Line 2370  splitd:    /* split data block in two se Line 2439  splitd:    /* split data block in two se
         block[RLPTR + 1] = newblk % 65536 / 256;          block[RLPTR + 1] = newblk % 65536 / 256;
         block[RLPTR + 2] = newblk % 256;          block[RLPTR + 2] = newblk % 256;
   
         lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);          lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
         write (filedes, block, BLOCKLEN);          write (g->fd, block, BLOCKLEN);
                   
         block[RLPTR] = right;          block[RLPTR] = right;
         block[RLPTR + 1] = right1;          block[RLPTR + 1] = right1;
Line 2383  splitd:    /* split data block in two se Line 2452  splitd:    /* split data block in two se
         addr = 0;          addr = 0;
         blknbr = newblk;          blknbr = newblk;
                   
         insert (filedes, compactkey, keyl, newblk);          insert (g->fd, compactkey, keyl, newblk);
                   
         /* up-date LL-PTR of RL-block */          /* up-date LL-PTR of RL-block */
         if ((other = right * 65536 + right1 * 256 + right2)) {          if ((other = right * 65536 + right1 * 256 + right2)) {
                   
             char    block0[BLOCKLEN];              char    block0[BLOCKLEN];
   
             lseek (filedes, (long) other * (long) (BLOCKLEN), 0);              lseek (g->fd, (long) other * (long) (BLOCKLEN), 0);
             read (filedes, block0, BLOCKLEN);              read (g->fd, block0, BLOCKLEN);
                   
             block0[LLPTR] = blknbr / 65536;              block0[LLPTR] = blknbr / 65536;
             block0[LLPTR + 1] = blknbr % 65536 / 256;              block0[LLPTR + 1] = blknbr % 65536 / 256;
             block0[LLPTR + 2] = blknbr % 256;              block0[LLPTR + 2] = blknbr % 256;
                   
             lseek (filedes, (long) other * (long) (BLOCKLEN), 0);              lseek (g->fd, (long) other * (long) (BLOCKLEN), 0);
             write (filedes, block0, BLOCKLEN);              write (g->fd, block0, BLOCKLEN);
                   
         }          }
                   
Line 2416  splitd:    /* split data block in two se Line 2485  splitd:    /* split data block in two se
         block[LLPTR + 1] = newblk % 65536 / 256;          block[LLPTR + 1] = newblk % 65536 / 256;
         block[LLPTR + 2] = newblk % 256;          block[LLPTR + 2] = newblk % 256;
   
         lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);          lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
         write (filedes, block, BLOCKLEN);          write (g->fd, block, BLOCKLEN);
                   
         block[LLPTR] = left;          block[LLPTR] = left;
         block[LLPTR + 1] = left1;          block[LLPTR + 1] = left1;
Line 2429  splitd:    /* split data block in two se Line 2498  splitd:    /* split data block in two se
         blknbr = newblk;          blknbr = newblk;
         traceadr[trx] = (-1);           /* inhibit second update of pointers */          traceadr[trx] = (-1);           /* inhibit second update of pointers */
                   
         insert (filedes, compactkey, keyl, newblk);          insert (g->fd, compactkey, keyl, newblk);
                   
         if (addr < 3) {                 /* update of pointer */          if (addr < 3) {                 /* update of pointer */
             traceadr[trx] = 0;              traceadr[trx] = 0;
                           
             update (filedes, compactkey, keyl);              update (g->fd, compactkey, keyl);
         }          }
   
         /* other is ***always*** zero !!!          /* other is ***always*** zero !!!
Line 2542  splitd:    /* split data block in two se Line 2611  splitd:    /* split data block in two se
             block0[LLPTR + 1] = blknbr % 65536 / 256;              block0[LLPTR + 1] = blknbr % 65536 / 256;
             block0[LLPTR + 2] = blknbr % 256;              block0[LLPTR + 2] = blknbr % 256;
   
             lseek (filedes, (long) (newblk) * (long) (BLOCKLEN), 0);              lseek (g->fd, (long) (newblk) * (long) (BLOCKLEN), 0);
             write (filedes, block0, BLOCKLEN);              write (g->fd, block0, BLOCKLEN);
                   
             offset = limit;              offset = limit;
             /* insert new block in pointer structure */              /* insert new block in pointer structure */
                   
             insert (filedes, &block0[2], (long) UNSIGN (block0[0]), newblk);              insert (g->fd, &block0[2], (long) UNSIGN (block0[0]), newblk);
                   
             /* up-date LL-PTR of RL-block */              /* up-date LL-PTR of RL-block */
             if (other != 0) {              if (other != 0) {
   
                 lseek (filedes, (long) other * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) other * (long) (BLOCKLEN), 0);
                 read (filedes, block0, BLOCKLEN);                  read (g->fd, block0, BLOCKLEN);
   
                 block0[LLPTR] = newblk / 65536;                  block0[LLPTR] = newblk / 65536;
                 block0[LLPTR + 1] = newblk % 65536 / 256;                  block0[LLPTR + 1] = newblk % 65536 / 256;
                 block0[LLPTR + 2] = newblk % 256;                  block0[LLPTR + 2] = newblk % 256;
                                   
                 lseek (filedes, (long) other * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) other * (long) (BLOCKLEN), 0);
                 write (filedes, block0, BLOCKLEN);                  write (g->fd, block0, BLOCKLEN);
   
             }              }
   
Line 2582  splitd:    /* split data block in two se Line 2651  splitd:    /* split data block in two se
             block0[LLPTR + 1] = blknbr % 65536 / 256;              block0[LLPTR + 1] = blknbr % 65536 / 256;
             block0[LLPTR + 2] = blknbr % 256;              block0[LLPTR + 2] = blknbr % 256;
   
             lseek (filedes, (long) blknbr * (long) (BLOCKLEN), 0);              lseek (g->fd, (long) blknbr * (long) (BLOCKLEN), 0);
             write (filedes, block, BLOCKLEN);              write (g->fd, block, BLOCKLEN);
             stcpy0 (block, block0, (long) BLOCKLEN);              stcpy0 (block, block0, (long) BLOCKLEN);
   
             traceadr[trx] = (addr -= limit);              traceadr[trx] = (addr -= limit);
             traceblk[trx] = (blknbr = newblk);              traceblk[trx] = (blknbr = newblk);
                           
             /* insert new block in pointer structure */              /* insert new block in pointer structure */
             insert (filedes, &block0[2], (long) UNSIGN (block0[0]), newblk);              insert (g->fd, &block0[2], (long) UNSIGN (block0[0]), newblk);
                           
             /* up-date LL-PTR of RL-block */              /* up-date LL-PTR of RL-block */
             if (other != 0) {              if (other != 0) {
   
                 lseek (filedes, (long) other * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) other * (long) (BLOCKLEN), 0);
                 read (filedes, block0, BLOCKLEN);                  read (g->fd, block0, BLOCKLEN);
                                   
                 block0[LLPTR] = newblk / 65536;                  block0[LLPTR] = newblk / 65536;
                 block0[LLPTR + 1] = newblk % 65536 / 256;                  block0[LLPTR + 1] = newblk % 65536 / 256;
                 block0[LLPTR + 2] = newblk % 256;                  block0[LLPTR + 2] = newblk % 256;
                                   
                 lseek (filedes, (long) other * (long) (BLOCKLEN), 0);                  lseek (g->fd, (long) other * (long) (BLOCKLEN), 0);
                 write (filedes, block0, BLOCKLEN);                  write (g->fd, block0, BLOCKLEN);
   
             }              }
   
Line 3483  void close_all_globals (void) Line 3552  void close_all_globals (void)
 }                                       /* end close_all_globals() */  }                                       /* end close_all_globals() */
   
 static void panic (void)  static void panic (void)
 {                                         {
       printf ("write failed\r\n");
       
     printf ("\033[s\033[25H\033[5;7mwrite needs more disk space immediately\007");      printf ("\033[s\033[25H\033[5;7mwrite needs more disk space immediately\007");
     sleep (1);      sleep (1);
     printf ("\033[m\007\033[2K\033[u");      printf ("\033[m\007\033[2K\033[u");
Line 3503  static void panic (void) Line 3574  static void panic (void)
   
 void gbl_dump_stat(void)  void gbl_dump_stat(void)
 {  {
     register int i;      global_handle *g;
           
     printf ("FreeM Global Statistics [PID %d]\r\n", pid);      printf ("FreeM Global Statistics [PID %d]\r\n", pid);
   
     printf ("%-10s%-20s%s\r\n", "USECT", "AGE", "FILE");      printf ("%-20s%-10s%-20s%-10s%s\r\n", "GLOBAL", "USECT", "AGE", "LAST BLK", "FILE");
     printf ("%-10s%-20s%s\r\n", "=====", "===", "====");      printf ("%-20s%-10s%-20s%-10s%s\r\n", "======", "=====", "===", "========", "====");
           
     for (i = 0; i < NO_GLOBLS; i++) {      for (g = global_handles_head; g != NULL; g = g->next) {
         printf ("%-10d%-20d%s\r\n", usage[i], g_ages[i], oldfil[i]);              printf ("%-20s%-10d%-20d%-10d%s\r\n", g->global_name, g->use_count, g->age, g->last_block, g->global_path);
     }      }
           
 }  }

Removed from v.1.1  
changed lines
  Added in v.1.8


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