/***************************************************************************** Major portions of this software are copyrighted by the Medical College of Wisconsin, 1994-2000, and are released under the Gnu General Public License, Version 2. See the file README.Copyright for details. ******************************************************************************/ #include "mrilib.h" void Syntax(void) { printf( "Assigns a new ID code to a dataset; this is useful when making\n" "a copy of a dataset, so that the internal ID codes remain unique.\n\n" "Usage: 3dnewid dataset [dataset ...]\n" " or\n" " 3dnewid -fun [n]\n" " to see what n randomly generated ID codes look like.\n" " (If the integer n is not present, 1 ID code is printed.)\n" " or\n" " 3dnewid -fun11\n" " to get an 11 character ID code (for use in scripting).\n" " or\n" " 3dnewid -int\n" " to get a random positive integer.\n" " The values are usually between 1 million and 1 billion.\n" " Such a value could be used as a random seeds in various AFNI\n" " programs, such as 3dttest++ -seed.\n" " or\n" " 3dnewid -hash STR\n" " to get a unique hashcode of STR\n" " (Unlike the other ways of using 3dnewid, if STR is the)\n" " (same in 2 different runs, the output will be the same.)\n" " (The -hash algorithm begins at step 2 in the list below.)\n" " or\n" " 3dnewid -MD5 STR\n" " to get the MD5 hash of STR, should be same as -hash output \n" " without the prefix and without the + and / char substitutions.\n" "\n" "How ID codes are created (here and in other AFNI programs):\n" "----------------------------------------------------------\n" "The AFNI ID code generator attempts to create a globally unique\n" "string identifier, using the following steps.\n" "1) A long string is created from the system identifier\n" " information ('uname -a'), the current epoch time in seconds\n" " and microseconds, the process ID, and the number of times\n" " the current process has called the ID code function.\n" "2) This string is then hashed into a 128 bit code using the\n" " MD5 algorithm. (cf. file thd_md5.c)\n" "3) This bit code is then converted to a 22 character string\n" " using Base64 encoding, replacing '/' with '-' and '+' with '_'.\n" " With these changes, the ID code can be used as a Unix filename\n" " or an XML name string. (cf. file thd_base64.c)\n" "4) A 4 character prefix is attached at the beginning to produce\n" " the final ID code. If you set the environment variable\n" " IDCODE_PREFIX to something, then its first 3 characters and an\n" " underscore will be used for the prefix of the new ID code,\n" " provided that the first character is alphabetic and the other\n" " 2 alphanumeric; otherwise, the default prefix 'NIH_' will be\n" " used.\n" "The source code is function UNIQ_idcode() in file niml_uuid.c\n" ) ; PRINT_COMPILE_DATE ; exit(0) ; } int main( int argc , char * argv[] ) { THD_3dim_dataset * dset ; int iarg ; MCW_idcode idc ; char str[256] ; if( argc < 2 || strncmp(argv[1],"-help",4) == 0 ) Syntax() ; iarg = 1 ; mainENTRY("3dnewid main"); machdep(); if( strcmp(argv[1],"-fun") == 0 ){ /* 22 May 2000: for fun */ int nid=0 , ii ; char *eee = getenv("UUID") ; if( argc > 2 ) nid = strtol(argv[2],NULL,10) ; if( nid <= 0 ) nid = 1 ; if( eee == NULL ){ for( ii=0 ; ii < nid ; ii++ ){ idc = MCW_new_idcode() ; printf("%s\n",idc.str) ; } } else { /* 20 Aug 2002: test of niml.c */ for( ii=0 ; ii < nid ; ii++ ){ eee = UUID_idcode(); printf("%s\n",eee); free(eee); } } exit(0) ; } else if ( strcmp(argv[1],"-fun11") == 0 ){ /* 10 Feb 2016 */ int nid=0 , ii ; char *eee ; if( argc > 2 ) nid = strtol(argv[2],NULL,10) ; if( nid <= 0 ) nid = 1 ; for( ii=0 ; ii < nid ; ii++ ){ eee = UNIQ_idcode_11(); printf("%s\n",eee); free(eee); } exit(0) ; } else if ( strcmp(argv[1],"-int") == 0 ){ /* 19 Jan 2021 */ int nid=0 , ii ; char *eee ; int val ; if( argc > 2 ) nid = strtol(argv[2],NULL,10) ; if( nid <= 0 ) nid = 1 ; for( ii=0 ; ii < nid ; ii++ ){ eee = UNIQ_idcode_11(); eee[5] = '\0'; val = 3*(int)strtol(eee+0,NULL,36) + 5*(int)strtol(eee+6,NULL,36) ; printf("%d\n",val) ; } exit(0) ; } else if ( strcmp(argv[1],"-hash") == 0 ){ /* Oct. 2011:for repeatable fun */ if( argc != 3 ) { ERROR_message("You need a string following -hash"); exit(1); } printf("%s\n", UNIQ_hashcode(argv[2])); exit(0) ; } else if ( strcmp(argv[1],"-MD5") == 0 ){ /* Feb. 2015:for debugging -MD5 jj.k40.gii is giving the same string as -MD5 jj.k60.gii */ char *eee = NULL; if( argc != 3 ) { ERROR_message("You need a string following -MD5"); exit(1); } MD5_set_xor_use(1) ; eee = MD5_B64_string(argv[2]) ; printf("%s [with XOR of input]\n", eee); free(eee); MD5_set_xor_use(0) ; eee = MD5_B64_string(argv[2]) ; printf("%s [without XOR of input]\n", eee); free(eee); exit(0) ; } /*-- OK, not for fun --*/ AFNI_logger("3dnewid",argc,argv) ; for( ; iarg < argc ; iarg++ ){ dset = THD_open_one_dataset( argv[iarg] ) ; if( dset == NULL ){ fprintf(stderr,"** Skipping dataset %s\n",argv[iarg]) ; continue ; } dset->idcode = MCW_new_idcode() ; sprintf(str,"3dnewid %s\n",argv[iarg]) ; tross_Append_History( dset , str) ; putenv("AFNI_DECONFLICT=OVERWRITE") ; THD_write_3dim_dataset( NULL , NULL , dset , False ) ; THD_delete_3dim_dataset( dset , False ) ; } exit(0) ; }