CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/GeneratorInterface/SherpaInterface/src/SherpackUtilities.cc

Go to the documentation of this file.
00001 #include "GeneratorInterface/SherpaInterface/interface/SherpackUtilities.h"
00002 #include <unistd.h>
00003 namespace spu {
00004         
00005 // functions for inflating (and deflating)
00006 
00007 //~ /* Compress from file source to file dest until EOF on source.
00008    //~ def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
00009    //~ allocated for processing, Z_STREAM_ERROR if an invalid compression
00010    //~ level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
00011    //~ version of the library linked do not match, or Z_ERRNO if there is
00012    //~ an error reading or writing the files. */
00013 int def(FILE *source, FILE *dest, int level)
00014 {
00015     int ret, flush;
00016     unsigned have;
00017     z_stream strm;
00018     unsigned char in[CHUNK];
00019     unsigned char out[CHUNK];
00020 
00021     /* allocate deflate state */
00022     strm.zalloc = Z_NULL;
00023     strm.zfree = Z_NULL;
00024     strm.opaque = Z_NULL;
00025     ret = deflateInit(&strm, level);
00026     if (ret != Z_OK)
00027         return ret;
00028 
00029     /* compress until end of file */
00030     do {
00031         strm.avail_in = fread(in, 1, CHUNK, source);
00032         if (ferror(source)) {
00033             (void)deflateEnd(&strm);
00034             return Z_ERRNO;
00035         }
00036         flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
00037         strm.next_in = in;
00038 
00039         /* run deflate() on input until output buffer not full, finish
00040            compression if all of source has been read in */
00041         do {
00042             strm.avail_out = CHUNK;
00043             strm.next_out = out;
00044             ret = deflate(&strm, flush);    /* no bad return value */
00045             assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
00046             have = CHUNK - strm.avail_out;
00047             if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
00048                 (void)deflateEnd(&strm);
00049                 return Z_ERRNO;
00050             }
00051         } while (strm.avail_out == 0);
00052         assert(strm.avail_in == 0);     /* all input will be used */
00053 
00054         /* done when last data in file processed */
00055     } while (flush != Z_FINISH);
00056     assert(ret == Z_STREAM_END);        /* stream will be complete */
00057 
00058     /* clean up and return */
00059     (void)deflateEnd(&strm);
00060     return Z_OK;
00061 }
00062 
00063 /* Decompress from file source to file dest until stream ends or EOF.
00064    inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
00065    allocated for processing, Z_DATA_ERROR if the deflate data is
00066    invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
00067    the version of the library linked do not match, or Z_ERRNO if there
00068    is an error reading or writing the files. */
00069 int inf(FILE *source, FILE *dest)
00070 {
00071     int ret;
00072     unsigned have;
00073     z_stream strm;
00074     unsigned char in[CHUNK];
00075     unsigned char out[CHUNK];
00076 
00077     /* allocate inflate state */
00078     strm.zalloc = Z_NULL;
00079     strm.zfree = Z_NULL;
00080     strm.opaque = Z_NULL;
00081     strm.avail_in = 0;
00082     strm.next_in = Z_NULL;
00083     //~ ret = inflateInit(&strm,15);
00084     ret = inflateInit2(&strm, (16+MAX_WBITS));
00085     if (ret != Z_OK)
00086         return ret;
00087 
00088     /* decompress until deflate stream ends or end of file */
00089     do {
00090         strm.avail_in = fread(in, 1, CHUNK, source);
00091         if (ferror(source)) {
00092             (void)inflateEnd(&strm);
00093             return Z_ERRNO;
00094         }
00095         if (strm.avail_in == 0)
00096             break;
00097         strm.next_in = in;
00098 
00099         /* run inflate() on input until output buffer not full */
00100         do {
00101             strm.avail_out = CHUNK;
00102             strm.next_out = out;
00103             ret = inflate(&strm, Z_NO_FLUSH);
00104             assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
00105             switch (ret) {
00106             case Z_NEED_DICT:
00107                 ret = Z_DATA_ERROR;     /* and fall through */
00108             case Z_DATA_ERROR:
00109             case Z_MEM_ERROR:
00110                 (void)inflateEnd(&strm);
00111                 return ret;
00112             }
00113             have = CHUNK - strm.avail_out;
00114             if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
00115                 (void)inflateEnd(&strm);
00116                 return Z_ERRNO;
00117             }
00118         } while (strm.avail_out == 0);
00119 
00120         /* done when inflate() says it's done */
00121     } while (ret != Z_STREAM_END);
00122 
00123     /* clean up and return */
00124     (void)inflateEnd(&strm);
00125     return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
00126 }
00127 
00128 /* report a zlib or i/o error */
00129 void zerr(int ret)
00130 {
00131     fputs("zpipe: ", stderr);
00132     switch (ret) {
00133     case Z_ERRNO:
00134         if (ferror(stdin))
00135             fputs("error reading stdin\n", stderr);
00136         if (ferror(stdout))
00137             fputs("error writing stdout\n", stderr);
00138         break;
00139     case Z_STREAM_ERROR:
00140         fputs("invalid compression level\n", stderr);
00141         break;
00142     case Z_DATA_ERROR:
00143         fputs("invalid or incomplete deflate data\n", stderr);
00144         break;
00145     case Z_MEM_ERROR:
00146         fputs("out of memory\n", stderr);
00147         break;
00148     case Z_VERSION_ERROR:
00149         fputs("zlib version mismatch!\n", stderr);
00150     }
00151 }
00152 
00153 /* compress or decompress from stdin to stdout */
00154 int Unzip(std::string infile, std::string outfile)
00155 {
00156     int ret;
00157         FILE *in = fopen(infile.c_str(),"r");
00158         if (!in) return -1;
00159         FILE *out = fopen(outfile.c_str(),"w");
00160         if (!out) return -2;
00161     /* avoid end-of-line conversions */
00162     SET_BINARY_MODE(in);
00163     SET_BINARY_MODE(out);
00164 
00165         ret = inf(in, out);
00166         if (ret != Z_OK)
00167                 zerr(ret);
00168         
00169         fclose(in);
00170         fclose(out);
00171         return ret;
00172 }
00173 
00174 
00175 
00176 // functions for untaring Sherpacks
00177 /* Parse an octal number, ignoring leading and trailing nonsense. */
00178 int parseoct(const char *p, size_t n) {
00179         int i = 0;
00180 
00181         while (*p < '0' || *p > '7') {
00182                 ++p;
00183                 --n;
00184         }
00185         while (*p >= '0' && *p <= '7' && n > 0) {
00186                 i *= 8;
00187                 i += *p - '0';
00188                 ++p;
00189                 --n;
00190         }
00191         return (i);
00192 }
00193 
00194 /* Returns true if this is 512 zero bytes. */
00195 int is_end_of_archive(const char *p) {
00196         int n;
00197         for (n = 511; n >= 0; --n)
00198                 if (p[n] != '\0')
00199                         return (0);
00200         return (1);
00201 }
00202 
00203 /* Create a directory, including parent directories as necessary. */
00204 void create_dir(char *pathname, int mode) {
00205         char *p;
00206         int r;
00207 
00208         /* Strip trailing '/' */
00209         if (pathname[strlen(pathname) - 1] == '/')
00210                 pathname[strlen(pathname) - 1] = '\0';
00211 
00212         /* Try creating the directory. */
00213         r = mkdir(pathname, mode);
00214 
00215         if (r != 0) {
00216                 /* On failure, try creating parent directory. */
00217                 p = strrchr(pathname, '/');
00218                 if (p != NULL) {
00219                         *p = '\0';
00220                         create_dir(pathname, 0755);
00221                         *p = '/';
00222                         r = mkdir(pathname, mode);
00223                 }
00224         }
00225         if (r != 0)
00226                 fprintf(stderr, "Could not create directory %s\n", pathname);
00227 }
00228 
00229 /* Create a file, including parent directory as necessary. */
00230 FILE* create_file(char *pathname, int mode) {
00231         FILE *f;
00232         f = fopen(pathname, "w+");
00233         if (f == NULL) {
00234                 /* Try creating parent dir and then creating file. */
00235                 char *p = strrchr(pathname, '/');
00236                 if (p != NULL) {
00237                         *p = '\0';
00238                         create_dir(pathname, 0755);
00239                         *p = '/';
00240                         f = fopen(pathname, "w+");
00241                 }
00242         }
00243         return (f);
00244 }
00245 
00246 /* Verify the tar checksum. */
00247 int verify_checksum(const char *p) {
00248         int n, u = 0;
00249         for (n = 0; n < 512; ++n) {
00250                 if (n < 148 || n > 155)
00251                         /* Standard tar checksum adds unsigned bytes. */
00252                         u += ((unsigned char *)p)[n];
00253                 else
00254                         u += 0x20;
00255 
00256         }
00257         return (u == parseoct(p + 148, 8));
00258 }
00259 
00260 /* Extract a tar archive. */
00261 void Untar(FILE *a, const char *path) {
00262         bool longpathname=false;
00263         bool longlinkname=false;
00264         char newlongpathname[512];
00265         char newlonglinkname[512];
00266         char buff[512];
00267         FILE *f = NULL;
00268         size_t bytes_read;
00269         int filesize;
00270 
00271         printf("Extracting from %s\n", path);
00272         for (;;) {
00273                 
00274                 bytes_read = fread(buff, 1, 512, a);
00275                 if (bytes_read < 512) {
00276                         fprintf(stderr,
00277                             "Short read on %s: expected 512, got %d\n",path, (int)bytes_read);
00278                         return;
00279                 }
00280                 if (is_end_of_archive(buff)) {
00281                         printf("End of %s\n", path);
00282                         return;
00283                 }
00284                 if (!verify_checksum(buff)) {
00285                         fprintf(stderr, "Checksum failure\n");
00286                         return;
00287                 }
00288                 filesize = parseoct(buff + 124, 12);
00289 //              printf("%c %d\n",buff[156],filesize);
00290                 switch (buff[156]) {
00291                 case '1':
00292                         printf(" Ignoring hardlink %s\n", buff);
00293                         break;
00294                 case '2':
00295                         if (longpathname && longlinkname){
00296                                         longlinkname=false;
00297                                         longpathname=false;
00298                                         printf(" Extracting symlink %s\n", newlongpathname);
00299                                         symlink(newlonglinkname,newlongpathname);                                               
00300                         } else if (longpathname) {
00301                                         longpathname=false;
00302                                         printf(" Extracting symlink %s\n", newlongpathname);
00303                                         symlink(buff+157,newlongpathname);
00304                         } else if (longlinkname) {
00305                                         longlinkname=false;
00306                                         printf(" Extracting symlink %s\n", buff);
00307                                         symlink(newlonglinkname,buff);
00308                         } else {
00309                                         printf(" Extracting symlink %s\n", buff);
00310                                         symlink(buff+157,buff);
00311                         }
00312                         break;
00313                 case '3':
00314                         printf(" Ignoring character device %s\n", buff);
00315                                 break;
00316                 case '4':
00317                         printf(" Ignoring block device %s\n", buff);
00318                         break;
00319                 case '5':
00320                         if (!longpathname){
00321                                 int endposition=-1;
00322                                 for (int k=99; k>=0; k--){
00323                                         if (buff[k]=='\0') endposition=k;
00324                                 }       
00325                                 if (endposition==-1) {
00326                                         //~ printf("OLDNAME : %s\n",buff);
00327                                         longpathname=true;
00328                                         for (int k=0; k<100; k++){
00329                                                 newlongpathname[k]=buff[k];
00330                                         }
00331                                         newlongpathname[100]='\0';
00332                                         //~ printf("NEWNAME : %s\n",newlongpathname);
00333                                 }
00334                         }
00335                 
00336                         if (longpathname) {
00337                                 printf(" Extracting dir %s\n", newlongpathname);
00338                                 create_dir(newlongpathname, parseoct(buff + 100, 8));
00339                                 longpathname=false;
00340                         } else {
00341                         
00342                                 printf(" Extracting dir %s\n", buff);
00343                                 create_dir(buff, parseoct(buff + 100, 8));
00344                         }
00345                         //~ printf(" Extracting dir %s\n", buff);
00346                         //~ create_dir(buff, parseoct(buff + 100, 8));
00347                         filesize = 0;
00348                         break;
00349                 case '6':
00350                         printf(" Ignoring FIFO %s\n", buff);
00351                         break;
00352                 case 'L':
00353                         longpathname=true;
00354                         //~ printf(" Long Filename found 0 %s\n", buff);
00355                         //~ printf(" Long Filename found 100 %s\n", buff+100);
00356                         //~ printf(" Long Filename found 108 %s\n", buff+108);
00357                         //~ printf(" Long Filename found 116 %s\n", buff+116);
00358                         //~ printf(" Long Filename found 124 %s\n", buff+124);
00359                         //~ printf(" Long Filename found 136 %s\n", buff+136);
00360                         //~ printf(" Long Filename found 148 %s\n", buff+148);
00361                         //~ printf(" Long Filename found 156 %s\n", buff+156);
00362                         //~ printf(" Long Filename found 157 %s\n", buff+157);
00363                         //~ printf(" Long Filename found 158 %s\n", buff+158);
00364                         //~ printf(" Long Filename found 159 %s\n", buff+159);
00365                         //~ printf(" Long Filename found 257 %s\n", buff+257);
00366                         //~ printf(" Long Filename found 263 %s\n", buff+263);
00367                         //~ printf(" Long Filename found 265 %s\n", buff+265);
00368                         //~ printf(" Long Filename found 297 %s\n", buff+297);
00369                         //~ printf(" Long Filename found 329 %s\n", buff+329);
00370                         //~ printf(" Long Filename found 337 %s\n", buff+337);
00371                         //~ printf(" Long Filename found 345 %s\n", buff+345);
00372                         //~ printf(" Long Filename found 346 %s\n", buff+346);
00373                         //~ printf(" Long Filename found 347 %s\n", buff+347);
00374                         break;  
00375                 
00376                 case 'K':
00377                         longlinkname=true;
00378                         break;
00379 
00380                 default:
00381                         if (!longpathname){
00382                                 int endposition=-1;
00383                                 for (int k=99; k>=0; k--){
00384                                         if (buff[k]=='\0') endposition=k;
00385                                 }       
00386                                 if (endposition==-1) {
00387                                         //~ printf("OLDNAME : %s\n",buff);
00388                                         longpathname=true;
00389                                         for (int k=0; k<100; k++){
00390                                                 newlongpathname[k]=buff[k];
00391                                         }
00392                                         newlongpathname[100]='\0';
00393                                         //~ printf("NEWNAME : %s\n",newlongpathname);
00394                                 }
00395                         }               
00396                         if (longpathname) {
00397                                 printf(" Extracting file %s\n", newlongpathname);
00398                                 f = create_file(newlongpathname, parseoct(buff + 100, 8));
00399                                 longpathname=false;
00400                         } else {
00401                         
00402                                 printf(" Extracting file %s\n", buff);
00403                                 f = create_file(buff, parseoct(buff + 100, 8));
00404                         }
00405                         break;
00406                 }
00407                 
00408                 if (longlinkname || longpathname) {
00409                         if (buff[156]=='K'){
00410                                 
00411                                 for (int ll=0; ll<512; ll++){ printf("%c",buff[ll]);} printf("\n");
00412                                 bytes_read = fread(buff, 1, 512, a);
00413                                 for (int ll=0; ll<512; ll++){ printf("%c",buff[ll]);} printf("\n");
00414                                 for (int k=0; k<filesize; k++){
00415                                         newlonglinkname[k]=buff[k];
00416                                 }
00417                                 newlonglinkname[filesize]='\0';
00418                                 for (int k=filesize+1; k<512; k++){
00419                                         newlonglinkname[k]='0';
00420                                 }
00421                                 //~ printf("NEW LinkNAME: %s\n",newlonglinkname);       
00422                         } else if (buff[156]=='L'){
00423                                 bytes_read = fread(buff, 1, 512, a);
00424                                 for (int k=0; k<filesize; k++){
00425                                         newlongpathname[k]=buff[k];
00426                                 }
00427                                 newlongpathname[filesize]='\0';
00428                                 for (int k=filesize+1; k<512; k++){
00429                                         newlongpathname[k]='0';
00430                                 }
00431                         //~ printf("NEW FILENAME: %s\n",newlongpathname);       
00432                         }
00433                 }       
00434                 
00435                 //~ 
00436                 //~ if (longpathname) {
00437                         //~ bytes_read = fread(buff, 1, 512, a);
00438                         //~ for (int k=0; k<filesize; k++){
00439                                 //~ newlongpathname[k]=buff[k];
00440                         //~ }
00441                         //~ newlongpathname[filesize]='\0';
00442                         //~ for (int k=filesize+1; k<512; k++){
00443                                 //~ newlongpathname[k]='0';
00444                         //~ }
00445                         //~ printf("NEW FILENAME: %s\n",newlongpathname);       
00446                         //~ 
00447                 //~ }
00448                 //~ else if (!longpathname && !longlinkname) { 
00449                 if (!longpathname && !longlinkname) { 
00450                         while (filesize > 0) {
00451                                 bytes_read = fread(buff, 1, 512, a);
00452                                 if (bytes_read < 512) {
00453                                         fprintf(stderr,
00454                                                 "Short read on %s: Expected 512, got %d\n",   path, (int)bytes_read);
00455                                         return;
00456                                 }
00457                                 if (filesize < 512)
00458                                         bytes_read = filesize;
00459                                 if (f != NULL) {
00460                                         if (fwrite(buff, 1, bytes_read, f)
00461                                                 != bytes_read)
00462                                         {
00463                                                 fprintf(stderr, "Failed write\n");
00464                                                 fclose(f);
00465                                                 f = NULL;
00466                                         }
00467                                 }
00468                                 filesize -= bytes_read;
00469                         }
00470                         if (f != NULL) {
00471                                 fclose(f);
00472                                 f = NULL;
00473                         }
00474                 }
00475         }
00476 }
00477 
00478 
00479 
00480 // function for calculating the MD5 checksum of a file
00481 void md5_File(std::string filename, char* result ) {
00482           char buffer[4096];
00483           MD5_CTX md5;           
00484           MD5_Init(&md5);
00485 
00486           //Open File
00487           int fd = open(filename.c_str(), O_RDONLY);
00488           int nb_read;
00489           while ((nb_read = read(fd, buffer, 4096 - 1)))
00490                 {
00491                   MD5_Update(&md5, buffer, nb_read);
00492                   memset(buffer, 0, 4096);
00493                 }
00494           unsigned char tmp[MD5_DIGEST_LENGTH];
00495           MD5_Final(tmp, &md5);
00496 
00497           //Convert the result
00498           for (int k = 0; k < MD5_DIGEST_LENGTH; ++k) {
00499                 sprintf(result + k * 2, "%02x", tmp[k]);
00500           }      
00501 }
00502 
00503 
00504 } // End namespace spu
00505