]> jfr.im git - irc/quakenet/newserv.git/blobdiff - lib/sstring-new.c
Implement --help parameter.
[irc/quakenet/newserv.git] / lib / sstring-new.c
index ebb35c79053cf0cdd6c86f9f367a6be197ecf636..90581f93af0b93ae2c0cea65d9e5637b26424f8b 100644 (file)
@@ -1,6 +1,7 @@
 /* sstring.h - Declaration of "static strings" functions */
 
 #define COMPILING_SSTRING
+#define SSTRING_NEW
 #include "sstring.h"
 
 #include "../core/hooks.h"
@@ -12,7 +13,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
-#define __USE_GNU
+#define _GNU_SOURCE
 #include <string.h>
 
 /* List of free stuff */
@@ -28,8 +29,38 @@ static int getcalls;
 static int freecalls;
 static int allocs;
 
-/* Internal function */
+/* Internal functions */
 static void sstringstats(int hooknum, void *arg);
+static void salloc(void);
+
+#ifndef SSTRING_MMAP
+
+#define sunprotect(x)
+#define sunprotectb(x)
+#define sprotect(x)
+
+#else
+
+#define __USE_MISC
+
+#include <sys/mman.h>
+static void *mblock;
+struct mblock_list {
+  void *block;
+  struct mblock_list *next;
+};
+
+static void *mblock_head;
+
+#define sunprotectb(x) mprotect(x, SSTRING_ALLOC, PROT_READ|PROT_WRITE);
+#define sunprotect(x) sunprotectb((x)->block);
+#define sprotect(x) mprotect((x)->block, SSTRING_ALLOC, PROT_READ);
+
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+
+#endif /* SSTRING_MMAP */
 
 void initsstring() {
   int i;
@@ -51,45 +82,70 @@ void initsstring() {
 }
 
 void finisstring() {
+  deregisterhook(HOOK_CORE_STATSREQUEST,&sstringstats);
+
+  #ifndef SSTRING_MMAP
   nsfreeall(POOL_SSTRING);
+  #endif /* SSTRING_MMAP */ 
+}
+
+#ifndef SSTRING_MMAP
+static void salloc(void) {
+  ssmem=(char *)nsmalloc(POOL_SSTRING, SSTRING_ALLOC);
+  ssmemfree=SSTRING_ALLOC;
 }
+#endif /* SSTRING_MMAP */
 
 sstring *findsstring(const char *str) {
   unsigned int hash=crc32(str)%SSTRING_HASHSIZE;
   sstring *ss;
   
   for (ss=sshash[hash];ss;ss=ss->next)
-    if (!strcmp(str, ss->content))
+    if (!strcmp(str, sstring_content(ss)))
       return ss;
   
   return NULL;
 }
 
 void sstring_enhash(sstring *ss) {
-  unsigned int hash=crc32(ss->content)%SSTRING_HASHSIZE;
+  unsigned int hash=crc32(sstring_content(ss))%SSTRING_HASHSIZE;
   
   ss->next=sshash[hash];
   sshash[hash]=ss;
 }
 
 void sstring_dehash(sstring *ss) {
-  unsigned int hash=crc32(ss->content)%SSTRING_HASHSIZE;
-  sstring **ssh;
+  unsigned int hash=crc32(sstring_content(ss))%SSTRING_HASHSIZE;
+  sstring *ssh, *ssp;
   
-  for (ssh=&(sshash[hash]); *ssh; ssh=&((*ssh)->next)) {
-    if (*ssh==ss) {
-      *ssh=ss->next;
+  for (ssh=sshash[hash],ssp=NULL; ssh; ssp=ssh,ssh=ssh->next) {
+    if (ssh==ss) {
+      if (!ssp) {
+        sshash[hash]=ss->next;
+      } else {
+#ifndef SSTRING_MMAP
+        ssp->next=ss->next;
+#else
+        if (ssp->block!=ss->block) {
+          sunprotect(ssp) {
+            ssp->next=ss->next;
+          } sprotect(ssp);
+        } else {
+          ssp->next=ss->next;
+        }
+#endif
+      }
       return;
     }
   }
   
-  Error("sstring",ERR_WARNING,"sstring_dehash(): Unable to find string (ref=%d, length=%d) in hash: %s",ss->refcount,ss->length,ss->content);
+  Error("sstring",ERR_WARNING,"sstring_dehash(): Unable to find string (ref=%lu, length=%d) in hash: %s",ss->refcount,ss->length,sstring_content(ss));
 }
 
 sstring *getsstring(const char *inputstr, int maxlen) {
   int i;
   sstring *retval=NULL;
-  int length;
+  int length, foreignblock;
   char strbuf[SSTRING_MAXLEN];
 
   /* getsstring() on a NULL pointer returns a NULL sstring.. */
@@ -121,10 +177,14 @@ sstring *getsstring(const char *inputstr, int maxlen) {
 
   /* If it's hashed this is easy */
   if ((retval=findsstring(strbuf))) {
-    retval->refcount++;
+    sunprotect(retval) {
+      retval->refcount++;
+    } sprotect(retval);
+
     return retval;
   }
-  
+
+  foreignblock=0;  
   /* Check to see if an approximately correct 
    * sized string is available */
   for(i=0;i<SSTRING_SLACK;i++) {
@@ -134,6 +194,9 @@ sstring *getsstring(const char *inputstr, int maxlen) {
     if (freelist[length+i]!=NULL) {
       retval=freelist[length+i];
       freelist[length+i]=retval->next;
+      sunprotect(retval);
+      foreignblock=1;
+
       retval->alloc=(length+i);
       break;
     }  
@@ -146,14 +209,19 @@ sstring *getsstring(const char *inputstr, int maxlen) {
       /* Not enough for us - turn the remaining memory into a free string for later */
       if (ssmemfree>sizeof(sstring)) {
         retval=(sstring *)ssmem;
+        sunprotectb(mblock);
+#ifdef SSTRING_MMAP
+        retval->block=mblock;
+#endif
         retval->alloc=(ssmemfree-sizeof(sstring));
         retval->refcount=0;
         freesstring(retval);
       }
   
-      allocs++;      
-      ssmem=(char *)nsmalloc(POOL_SSTRING, SSTRING_ALLOC);
-      ssmemfree=SSTRING_ALLOC;
+      allocs++;     
+      salloc();
+    } else {
+      sunprotectb(mblock);
     }
     
     retval=(sstring *)ssmem;
@@ -176,11 +244,22 @@ sstring *getsstring(const char *inputstr, int maxlen) {
    */
   
   retval->length=(length-1);
-  strcpy(retval->content,strbuf);
+  strcpy(sstring_content(retval),strbuf);
   retval->refcount=1;
-  
+
+#ifdef SSTRING_MMAP 
+  if(!foreignblock)
+    retval->block = mblock;
+#endif
+
   sstring_enhash(retval);
-  
+
+#ifdef SSTRING_COMPAT
+  retval->content = retval->__content;
+#endif
+
+  sprotect(retval);
+
   return retval;    
 }
 
@@ -194,19 +273,24 @@ void freesstring(sstring *inval) {
   /* Only count calls that actually did something */
   freecalls++;
   
+  if (inval->refcount)
+    sunprotect(inval);
+
   if (inval->refcount > 1) {
     inval->refcount--;
+    sprotect(inval);
     return;
   }
 
-  /* If refcount==0 it wasn't hashed */
+  /* If refcount==0 it wasn't hashed, or protected */
   if (inval->refcount)
     sstring_dehash(inval);
-  
+
   alloc=inval->alloc;
   assert(alloc<=SSTRING_MAXLEN);
   inval->next=freelist[alloc];
   freelist[alloc]=inval;
+  sprotect(inval);
 }
 
 void sstringstats(int hooknum, void *arg) {
@@ -226,10 +310,25 @@ void sstringstats(int hooknum, void *arg) {
   }
 }
 
-int sstringcompare(sstring *ss1, sstring *ss2) {
-  if (ss1->length != ss2->length)
-    return -1;
-  
-  return strncmp(ss1->content, ss2->content, ss1->length);
+#ifdef SSTRING_MMAP
+void finisstring() {
+  struct mblock_list *c, *n;
+  for (c=mblock_head;c;c=n) {
+    n=c->next;
+    munmap(c->block, SSTRING_ALLOC);
+  }
 }
 
+static void salloc(void) {
+  struct mblock_list *n;
+  mblock=mmap((void *)0, SSTRING_ALLOC, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANON, -1, 0);
+
+  n=(struct mblock_list *)mblock;
+  n->block = mblock;
+  n->next = mblock_head;
+  mblock_head = n;
+
+  ssmem=(char *)mblock + sizeof(struct mblock_list);
+  ssmemfree=SSTRING_ALLOC-sizeof(struct mblock_list);
+}
+#endif /* SSTRING_MMAP */