CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/GeneratorInterface/SherpaInterface/src/SherpackUtilities.cc

Go to the documentation of this file.
00001 #include "GeneratorInterface/SherpaInterface/interface/SherpackUtilities.h"
00002 
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         char newlongpathname[512];
00264         char buff[512];
00265         FILE *f = NULL;
00266         size_t bytes_read;
00267         int filesize;
00268 
00269         printf("Extracting from %s\n", path);
00270         for (;;) {
00271                 
00272                 bytes_read = fread(buff, 1, 512, a);
00273                 if (bytes_read < 512) {
00274                         fprintf(stderr,
00275                             "Short read on %s: expected 512, got %d\n",path, (int)bytes_read);
00276                         return;
00277                 }
00278                 if (is_end_of_archive(buff)) {
00279                         printf("End of %s\n", path);
00280                         return;
00281                 }
00282                 if (!verify_checksum(buff)) {
00283                         fprintf(stderr, "Checksum failure\n");
00284                         return;
00285                 }
00286                 filesize = parseoct(buff + 124, 12);
00287                 //~ printf("%c %d",buff[156],filesize);
00288                 switch (buff[156]) {
00289                 case '1':
00290                         printf(" Ignoring hardlink %s\n", buff);
00291                         break;
00292                 case '2':
00293                         printf(" Ignoring symlink %s\n", buff);
00294                         break;
00295                 case '3':
00296                         printf(" Ignoring character device %s\n", buff);
00297                                 break;
00298                 case '4':
00299                         printf(" Ignoring block device %s\n", buff);
00300                         break;
00301                 case '5':
00302                         if (!longpathname){
00303                                 int endposition=-1;
00304                                 for (int k=99; k>=0; k--){
00305                                         if (buff[k]=='\0') endposition=k;
00306                                 }       
00307                                 if (endposition==-1) {
00308                                         //~ printf("OLDNAME : %s\n",buff);
00309                                         longpathname=true;
00310                                         for (int k=0; k<100; k++){
00311                                                 newlongpathname[k]=buff[k];
00312                                         }
00313                                         newlongpathname[100]='\0';
00314                                         //~ printf("NEWNAME : %s\n",newlongpathname);
00315                                 }
00316                         }
00317                 
00318                         if (longpathname) {
00319                                 printf(" Extracting dir %s\n", newlongpathname);
00320                                 create_dir(newlongpathname, parseoct(buff + 100, 8));
00321                                 longpathname=false;
00322                         } else {
00323                         
00324                                 printf(" Extracting dir %s\n", buff);
00325                                 create_dir(buff, parseoct(buff + 100, 8));
00326                         }
00327                         //~ printf(" Extracting dir %s\n", buff);
00328                         //~ create_dir(buff, parseoct(buff + 100, 8));
00329                         filesize = 0;
00330                         break;
00331                 case '6':
00332                         printf(" Ignoring FIFO %s\n", buff);
00333                         break;
00334                 case 'L':
00335                         longpathname=true;
00336                         //~ printf(" Long Filename found 0 %s\n", buff);
00337                         //~ printf(" Long Filename found 100 %s\n", buff+100);
00338                         //~ printf(" Long Filename found 108 %s\n", buff+108);
00339                         //~ printf(" Long Filename found 116 %s\n", buff+116);
00340                         //~ printf(" Long Filename found 124 %s\n", buff+124);
00341                         //~ printf(" Long Filename found 136 %s\n", buff+136);
00342                         //~ printf(" Long Filename found 148 %s\n", buff+148);
00343                         //~ printf(" Long Filename found 156 %s\n", buff+156);
00344                         //~ printf(" Long Filename found 157 %s\n", buff+157);
00345                         //~ printf(" Long Filename found 158 %s\n", buff+158);
00346                         //~ printf(" Long Filename found 159 %s\n", buff+159);
00347                         //~ printf(" Long Filename found 257 %s\n", buff+257);
00348                         //~ printf(" Long Filename found 263 %s\n", buff+263);
00349                         //~ printf(" Long Filename found 265 %s\n", buff+265);
00350                         //~ printf(" Long Filename found 297 %s\n", buff+297);
00351                         //~ printf(" Long Filename found 329 %s\n", buff+329);
00352                         //~ printf(" Long Filename found 337 %s\n", buff+337);
00353                         //~ printf(" Long Filename found 345 %s\n", buff+345);
00354                         //~ printf(" Long Filename found 346 %s\n", buff+346);
00355                         //~ printf(" Long Filename found 347 %s\n", buff+347);
00356                         break;  
00357 
00358                 default:
00359                         if (!longpathname){
00360                                 int endposition=-1;
00361                                 for (int k=99; k>=0; k--){
00362                                         if (buff[k]=='\0') endposition=k;
00363                                 }       
00364                                 if (endposition==-1) {
00365                                         //~ printf("OLDNAME : %s\n",buff);
00366                                         longpathname=true;
00367                                         for (int k=0; k<100; k++){
00368                                                 newlongpathname[k]=buff[k];
00369                                         }
00370                                         newlongpathname[100]='\0';
00371                                         //~ printf("NEWNAME : %s\n",newlongpathname);
00372                                 }
00373                         }               
00374                         if (longpathname) {
00375                                 printf(" Extracting file %s\n", newlongpathname);
00376                                 f = create_file(newlongpathname, parseoct(buff + 100, 8));
00377                                 longpathname=false;
00378                         } else {
00379                         
00380                                 printf(" Extracting file %s\n", buff);
00381                                 f = create_file(buff, parseoct(buff + 100, 8));
00382                         }
00383                         break;
00384                 }
00385                 
00386                 
00387                 
00388                 if (longpathname) {
00389                         bytes_read = fread(buff, 1, 512, a);
00390                         for (int k=0; k<filesize; k++){
00391                                 newlongpathname[k]=buff[k];
00392                         }
00393                         newlongpathname[filesize]='\0';
00394                         for (int k=filesize+1; k<512; k++){
00395                                 newlongpathname[k]='0';
00396                         }
00397                         //~ printf("NEW FILENAME: %s\n",newlongpathname);       
00398                         
00399                 }
00400                 else{ 
00401                         while (filesize > 0) {
00402                                 bytes_read = fread(buff, 1, 512, a);
00403                                 if (bytes_read < 512) {
00404                                         fprintf(stderr,
00405                                                 "Short read on %s: Expected 512, got %d\n",   path, (int)bytes_read);
00406                                         return;
00407                                 }
00408                                 if (filesize < 512)
00409                                         bytes_read = filesize;
00410                                 if (f != NULL) {
00411                                         if (fwrite(buff, 1, bytes_read, f)
00412                                                 != bytes_read)
00413                                         {
00414                                                 fprintf(stderr, "Failed write\n");
00415                                                 fclose(f);
00416                                                 f = NULL;
00417                                         }
00418                                 }
00419                                 filesize -= bytes_read;
00420                         }
00421                         if (f != NULL) {
00422                                 fclose(f);
00423                                 f = NULL;
00424                         }
00425                 }
00426         }
00427 }
00428 
00429 
00430 
00431 // function for calculating the MD5 checksum of a file
00432 void md5_File(std::string filename, char* result ) {
00433           char buffer[4096];
00434           MD5_CTX md5;           
00435           MD5_Init(&md5);
00436 
00437           //Open File
00438           int fd = open(filename.c_str(), O_RDONLY);
00439           int nb_read;
00440           while ((nb_read = read(fd, buffer, 4096 - 1)))
00441                 {
00442                   MD5_Update(&md5, buffer, nb_read);
00443                   memset(buffer, 0, 4096);
00444                 }
00445           unsigned char tmp[MD5_DIGEST_LENGTH];
00446           MD5_Final(tmp, &md5);
00447 
00448           //Convert the result
00449           for (int k = 0; k < MD5_DIGEST_LENGTH; ++k) {
00450                 sprintf(result + k * 2, "%02x", tmp[k]);
00451           }      
00452 }
00453 
00454 
00455 } // End namespace spu
00456