modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/random.c (about)

     1  /*
     2  ** 2001 September 15
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  *************************************************************************
    12  ** This file contains code to implement a pseudo-random number
    13  ** generator (PRNG) for SQLite.
    14  **
    15  ** Random numbers are used by some of the database backends in order
    16  ** to generate random integer keys for tables or random filenames.
    17  */
    18  #include "sqliteInt.h"
    19  
    20  
    21  /* All threads share a single random number generator.
    22  ** This structure is the current state of the generator.
    23  */
    24  static SQLITE_WSD struct sqlite3PrngType {
    25    unsigned char isInit;          /* True if initialized */
    26    unsigned char i, j;            /* State variables */
    27    unsigned char s[256];          /* State variables */
    28  } sqlite3Prng;
    29  
    30  /*
    31  ** Return N random bytes.
    32  */
    33  void sqlite3_randomness(int N, void *pBuf){
    34    unsigned char t;
    35    unsigned char *zBuf = pBuf;
    36  
    37    /* The "wsdPrng" macro will resolve to the pseudo-random number generator
    38    ** state vector.  If writable static data is unsupported on the target,
    39    ** we have to locate the state vector at run-time.  In the more common
    40    ** case where writable static data is supported, wsdPrng can refer directly
    41    ** to the "sqlite3Prng" state vector declared above.
    42    */
    43  #ifdef SQLITE_OMIT_WSD
    44    struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
    45  # define wsdPrng p[0]
    46  #else
    47  # define wsdPrng sqlite3Prng
    48  #endif
    49  
    50  #if SQLITE_THREADSAFE
    51    sqlite3_mutex *mutex;
    52  #endif
    53  
    54  #ifndef SQLITE_OMIT_AUTOINIT
    55    if( sqlite3_initialize() ) return;
    56  #endif
    57  
    58  #if SQLITE_THREADSAFE
    59    mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
    60  #endif
    61  
    62    sqlite3_mutex_enter(mutex);
    63    if( N<=0 || pBuf==0 ){
    64      wsdPrng.isInit = 0;
    65      sqlite3_mutex_leave(mutex);
    66      return;
    67    }
    68  
    69    /* Initialize the state of the random number generator once,
    70    ** the first time this routine is called.  The seed value does
    71    ** not need to contain a lot of randomness since we are not
    72    ** trying to do secure encryption or anything like that...
    73    **
    74    ** Nothing in this file or anywhere else in SQLite does any kind of
    75    ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
    76    ** number generator) not as an encryption device.
    77    */
    78    if( !wsdPrng.isInit ){
    79      int i;
    80      char k[256];
    81      wsdPrng.j = 0;
    82      wsdPrng.i = 0;
    83      sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
    84      for(i=0; i<256; i++){
    85        wsdPrng.s[i] = (u8)i;
    86      }
    87      for(i=0; i<256; i++){
    88        wsdPrng.j += wsdPrng.s[i] + k[i];
    89        t = wsdPrng.s[wsdPrng.j];
    90        wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
    91        wsdPrng.s[i] = t;
    92      }
    93      wsdPrng.isInit = 1;
    94    }
    95  
    96    assert( N>0 );
    97    do{
    98      wsdPrng.i++;
    99      t = wsdPrng.s[wsdPrng.i];
   100      wsdPrng.j += t;
   101      wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
   102      wsdPrng.s[wsdPrng.j] = t;
   103      t += wsdPrng.s[wsdPrng.i];
   104      *(zBuf++) = wsdPrng.s[t];
   105    }while( --N );
   106    sqlite3_mutex_leave(mutex);
   107  }
   108  
   109  #ifndef SQLITE_UNTESTABLE
   110  /*
   111  ** For testing purposes, we sometimes want to preserve the state of
   112  ** PRNG and restore the PRNG to its saved state at a later time, or
   113  ** to reset the PRNG to its initial state.  These routines accomplish
   114  ** those tasks.
   115  **
   116  ** The sqlite3_test_control() interface calls these routines to
   117  ** control the PRNG.
   118  */
   119  static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
   120  void sqlite3PrngSaveState(void){
   121    memcpy(
   122      &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
   123      &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
   124      sizeof(sqlite3Prng)
   125    );
   126  }
   127  void sqlite3PrngRestoreState(void){
   128    memcpy(
   129      &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
   130      &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
   131      sizeof(sqlite3Prng)
   132    );
   133  }
   134  #endif /* SQLITE_UNTESTABLE */