Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

niml_uuid.c

Go to the documentation of this file.
00001 #include "niml_private.h"
00002 
00003 /*************************************************************************/
00004 /***************** Unique Identifier String functions ********************/
00005 /*************************************************************************/
00006 
00007 #include <sys/utsname.h>  /* Need by UNIQ_ functions for uname() */
00008 #include <time.h>
00009 
00010 static char *get_MAC_addr(void) ;  /* prototype */
00011 
00012 /*-----------------------------------------------------------------------*/
00013 /*! Return a globally unique string (I hope).  This can be hashed to
00014     produce a unique idcode (cf. UNIQ_idcode and UUID_idcode).
00015 
00016   Method: Generate a string from the system identfier information and
00017           the current time of day.  The output string is malloc()-ed,
00018           and should be free()-ed when no longer needed.
00019 
00020   20 Aug 2002 -- RWCox: break string and hashing into separate functions.
00021 -------------------------------------------------------------------------*/
00022 
00023 static char * get_UNIQ_string(void)
00024 {
00025    static struct utsname ubuf ;
00026    static int ncall=0 ;                /* number of times I've been called */
00027    struct timeval tv ;
00028    int    nn , ii ;
00029    int  nbuf ;
00030    char *buf ;
00031 #define NURR 32                        /* # bytes from /dev/urandom at a time */
00032 #ifdef NURR
00033    static int nurr=0 ;
00034    static byte urr[NURR] ;     /* will use 1 byte from urr[nurr] */
00035 #endif
00036 
00037    /* get info about this system */
00038 
00039    if( ncall == 0 ){                   /* 21 Aug 2002: only 1st time in */
00040      nn = uname( &ubuf ) ;             /* get info about this system */
00041      if( nn == -1 ){                   /* should never happen */
00042        strcpy( ubuf.nodename , "E" ) ;
00043        strcpy( ubuf.sysname  , "L" ) ;
00044        strcpy( ubuf.release  , "V" ) ;
00045        strcpy( ubuf.version  , "I" ) ;
00046        strcpy( ubuf.machine  , "S" ) ;
00047      }
00048    }
00049 
00050    /* store system info into a string buffer */
00051 
00052    nbuf = strlen(ubuf.nodename)+strlen(ubuf.sysname)
00053          +strlen(ubuf.release )+strlen(ubuf.version)+strlen(ubuf.machine) ;
00054 
00055    buf = (char *)malloc(nbuf+222) ;      /* include some extra space */
00056    strcpy(buf,ubuf.nodename) ;
00057    strcat(buf,ubuf.sysname ) ;
00058    strcat(buf,ubuf.release ) ;
00059    strcat(buf,ubuf.version ) ;
00060    strcat(buf,ubuf.machine ) ;
00061 
00062    /* get time and store into buf (along with process+user id and ncall) */
00063 
00064    nn = gettimeofday( &tv , NULL ) ;
00065    if( nn == -1 ){              /* should never happen */
00066      tv.tv_sec  = (long) time(NULL) ;  /* get seconds another way */
00067      tv.tv_usec = (long) buf ;         /* address as an integer */
00068    }
00069 
00070    /* even if called twice in very rapid succession,
00071       at least ncall will differ, so we'll get different ID codes  */
00072 
00073    sprintf( buf+nbuf,"%d%d%d%d%d%d",
00074             (int)tv.tv_sec,(int)tv.tv_usec,
00075             (int)getpid(),(int)getppid(),(int)getuid(),
00076             ncall ) ;
00077    ncall++ ;
00078 
00079    /* 06 Jan 2003: append MAC address, if possible */
00080 
00081    strcat(buf,get_MAC_addr()) ;
00082 
00083 #ifdef NURR
00084    /* 24 Jul 2002: get random bytes from /dev/urandom  */
00085    /* 21 Aug 2002: read NURR bytes at a time, but only use 1 per call */
00086 
00087    if( nurr >= 0 ){
00088      if( nurr == 0 ){                              /* need to read more bytes */
00089        FILE *ufp=fopen("/dev/urandom","rb") ;
00090        if( ufp == NULL ){                          /* fails on open */
00091          nurr = -1; goto URR_DONE;                 /* so never try again */
00092        } else {                                    /* read some bytes */
00093          fread( &urr , 1,NURR, ufp ); fclose(ufp);
00094        }
00095      }
00096      nbuf = strlen(buf); sprintf(buf+nbuf,"%02x",(int)urr[nurr]);
00097      nurr = (nurr+1) % NURR ;
00098 URR_DONE: ;
00099    }
00100 #endif /* NURR */
00101 
00102    return buf ;
00103 }
00104 
00105 /*-----------------------------------------------------------------------*/
00106 /*! Return a globally unique identifier (I hope).  This is a malloc()-ed
00107   string of length <= 31 (plus the NUL byte; the whole thing will fit
00108   into a char[32] array).  The output does not contain any '/'s, so
00109   it could be used as a temporary filename.  Repeated calls to this
00110   function should never return the same string.
00111 
00112   Method: Generate a string from the system identfier information and
00113           the current time of day. MD5 hash this to a 128 byte code.
00114           Base64 encode this to a 22 byte string. Replace '/' with '-'
00115           and '+' with '_'. Add 4 character prefix (1st 3 characters
00116           of environment variable IDCODE_PREFIX plus '_').
00117 
00118   Sample output: "XYZ_VdfGpfzy_NlY-2d7tA8Q1w"
00119 -------------------------------------------------------------------------*/
00120 
00121 char * UNIQ_idcode(void)
00122 {
00123    char *buf , *idc ;
00124 
00125    /* get uniq string from system */
00126 
00127    buf = get_UNIQ_string() ;
00128 
00129    /* make the output by hashing the string in buf */
00130 
00131    idc = UNIQ_hashcode( buf ) ;
00132 
00133    /* free workspace and get outta here */
00134 
00135    free(buf) ; return idc ;
00136 }
00137 
00138 /*----------------------------------------------------------------------*/
00139 /*! Make an idcode-formatted malloc-ed string from an input string.
00140     Unlike UNIQ_idcode(), this will always return the same value,
00141     given the same input.
00142 ------------------------------------------------------------------------*/
00143 
00144 char * UNIQ_hashcode( char *str )
00145 {
00146    char *idc , *eee ;
00147    int ii , nn ;
00148 
00149    idc = (char *)calloc(1,32) ;
00150 
00151    eee = getenv("IDCODE_PREFIX") ;
00152    if( eee != NULL && isalpha(eee[0]) ){
00153      for( ii=0 ; ii < 3 && isalnum(eee[ii]) ; ii++ )
00154        idc[ii] = eee[ii] ;
00155    } else {
00156      strcpy(idc,"XYZ") ;  /* innocent default prefix */
00157    }
00158    strcat(idc,"_") ;  /* recall idc was calloc()-ed */
00159 
00160    if( str == NULL || str[0] == '\0' ) str = "Onen i Estel Edain" ;
00161    eee = MD5_B64_string(str) ;
00162    nn = strlen(eee) ;
00163    for( ii=0 ; ii < nn ; ii++ ){
00164           if( eee[ii] == '/' ) eee[ii] = '-' ;  /* / -> - */
00165      else if( eee[ii] == '+' ) eee[ii] = '_' ;  /* + -> _ */
00166    }
00167    strcat(idc,eee) ; free(eee) ; return idc ;
00168 }
00169 
00170 /*----------------------------------------------------------------------*/
00171 /*! Fill a user-supplied buffer (length at least 32) with an idcode.
00172     That is, idc should point to a char array of length 32 (or more).
00173 ------------------------------------------------------------------------*/
00174 
00175 void UNIQ_idcode_fill( char *idc )
00176 {
00177    char *bbb ;
00178    if( idc == NULL ) return ;
00179    bbb = UNIQ_idcode() ;
00180    strcpy(idc,bbb) ; free(bbb) ; return ;
00181 }
00182 
00183 /*----------------------------------------------------------------------*/
00184 /*! Hash a string and return a malloc()-ed string (36+1 bytes) in
00185     the "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" format.
00186 ------------------------------------------------------------------------*/
00187 
00188 char *UUID_hashcode( char *str )
00189 {
00190    MD5_CTX context;
00191    unsigned char digest[16];
00192    char *idc ;
00193    int ii , nn ;
00194 
00195    if( str == NULL || str[0] == '\0' ) str = "Onen i Estel Edain" ;
00196 
00197    MD5Init( &context ) ;
00198    MD5Update( &context, (unsigned char *)str, strlen(str) ) ;
00199    MD5Final( digest, &context ) ;
00200 
00201    idc = (char *)calloc(1,48) ;
00202    sprintf(idc,
00203      "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" ,
00204      digest[0] , digest[1] , digest[2] , digest[3] , digest[4] ,
00205      digest[5] , digest[6] , digest[7] , digest[8] , digest[9] ,
00206      digest[10], digest[11], digest[12], digest[13], digest[14],
00207      digest[15]
00208     ) ;
00209 
00210    return idc ;
00211 }
00212 
00213 /*----------------------------------------------------------------------*/
00214 /*! Hash a unique string and return a malloc()-ed string (36+1 bytes) in
00215     the "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" format.
00216     The result should be unique worldwide, for all time.
00217 ------------------------------------------------------------------------*/
00218 
00219 char * UUID_idcode(void)
00220 {
00221    char *buf , *idc ;
00222 
00223    /* get uniq string from system */
00224 
00225    buf = get_UNIQ_string() ;
00226 
00227    /* make the output by hashing the string in buf */
00228 
00229    idc = UUID_hashcode( buf ) ;
00230 
00231    /* free workspace and get outta here */
00232 
00233    free(buf) ; return idc ;
00234 }
00235 
00236 /************************************************************************/
00237 #include <sys/ioctl.h>
00238 #include <net/if.h>
00239 static char *get_MAC_addr(void)  /* 06 Jan 2003 */
00240 {
00241   static char str[64] = "?" ;
00242 #if defined(LINUX) && defined(SIOCGIFHWADDR)
00243   static int ncall=0 ;
00244 
00245   if( ncall == 0 ){
00246     int sd ;
00247     sd = socket(AF_INET, SOCK_DGRAM, 0);
00248     if( sd >= 0 ){
00249       struct ifreq ifr ;
00250       strcpy(ifr.ifr_name, "eth0") ;
00251       if( ioctl(sd,SIOCGIFHWADDR,&ifr) >= 0 ){
00252         sprintf(str ,
00253                 "%02x:%02x:%02x:%02x:%02x:%02x",
00254          (byte)ifr.ifr_hwaddr.sa_data[0], (byte)ifr.ifr_hwaddr.sa_data[1],
00255          (byte)ifr.ifr_hwaddr.sa_data[2], (byte)ifr.ifr_hwaddr.sa_data[3],
00256          (byte)ifr.ifr_hwaddr.sa_data[4], (byte)ifr.ifr_hwaddr.sa_data[5] ) ;
00257       }
00258       close(sd) ;
00259     }
00260     ncall = 1 ;
00261   }
00262 #endif
00263   return str ;
00264 }
 

Powered by Plone

This site conforms to the following standards: