home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / hdf / unix / hdf3_2r2.lha / HDF3.2r2 / util / hdfpack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-02  |  12.5 KB  |  564 lines

  1. /***************************************************************************
  2. *
  3. *
  4. *                         NCSA HDF version 3.2r2
  5. *                            October 30, 1992
  6. *
  7. * NCSA HDF Version 3.2 source code and documentation are in the public
  8. * domain.  Specifically, we give to the public domain all rights for future
  9. * licensing of the source code, all resale rights, and all publishing rights.
  10. *
  11. * We ask, but do not require, that the following message be included in all
  12. * derived works:
  13. *
  14. * Portions developed at the National Center for Supercomputing Applications at
  15. * the University of Illinois at Urbana-Champaign, in collaboration with the
  16. * Information Technology Institute of Singapore.
  17. *
  18. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  19. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  20. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  21. *
  22. ****************************************************************************
  23. */
  24.  
  25. #ifdef RCSID
  26. static char RcsId[] = "@(#)$Revision: 1.3 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/util/RCS/hdfpack.c,v 1.3 1992/07/15 21:48:48 sxu beta koziol $
  30.  
  31. $Log: hdfpack.c,v $
  32.  * Revision 1.3  1992/07/15  21:48:48  sxu
  33.  * Added changes for CONVEX
  34.  *
  35.  * Revision 1.2  1992/07/01  17:16:17  dilg
  36.  * Changed option "-#" to "-d#" and added option "-t#" to change the size of
  37.  * the linked block table entries.  Cleaned up code a bit.
  38.  *
  39.  * Revision 1.1  1992/06/22  21:23:33  dilg
  40.  * Initial revision
  41.  *
  42. */
  43. /*
  44. ** FILE
  45. **    hdfpack.c
  46. ** USAGE
  47. **    hdfpack [options] <infile> <outfile>
  48. ** DESCRIPTION
  49. **    This program will compact an HDF file by reading in all the data
  50. **    elements in the file and writing them out to a new file.
  51. **      Options are:
  52. **          -b  Don't coalesce linked-block elements
  53. **          -i  Interactive mode; prompt for each linked-block element
  54. **          -d# Force the output file to have # DDs per DD block
  55. **          -t# Force output file to have # linked blocks per table entry
  56. **      Only one of options b and i can be specified.
  57. ** COMMENTS, BUGS, ASSUMPTIONS
  58. **    Both arguments must be supplied to the program and they cannot be
  59. **    identical.
  60. **    You must have enough additional disk space for the compacted file.
  61. ** AUTHOR
  62. **    Doug Ilg
  63. */
  64.  
  65. #include <stdio.h>
  66. #include <string.h>
  67. #include "hdf.h"
  68. #include "herr.h"
  69.  
  70. typedef struct mydd_t {
  71.     uint16 tag;
  72.     uint16 ref;
  73.     int32 offset;
  74.     int32 length;
  75.     int16 special;
  76. }mydd_t;
  77.  
  78.  
  79. #ifdef PROTOTYPE
  80. int main(int, char **);
  81. int usage(char *);
  82. int hdferror(void);
  83. int error(char *);
  84. int desc_comp(const void *d1, const void *d2);
  85. #else
  86. int main();
  87. int usage();
  88. int hdferror();
  89. int error();
  90. int desc_comp();
  91. #endif /* PROTOTYPE */
  92.  
  93. unsigned char *data;
  94. char invoke[81];
  95. int32 data_size;
  96. int32 nblk = 0;
  97.  
  98. #ifdef PROTOTYPE
  99. main(int argc, char *argv[])
  100. #else
  101. main(argc, argv)
  102. int argc;
  103. char *argv[];
  104. #endif /* PROTOTYPE */
  105. {
  106.     int i, num_desc, ret, fnum, merge;
  107.     int32 infile, outfile, aid, inaid, outaid, stat;
  108.     mydd_t *dlist;
  109.     uint16 tag, ref, sptag, spref;
  110.     char spdata[128];
  111.     int32 len, oldoff, oldlen;
  112.     int blocks = 1;
  113.     int intr = 0;
  114.     int16 ndds = 0;
  115.     int optset = 0;
  116.     char *tmp, fname[2][80];
  117.     char *FUNC="main";
  118.  
  119.  
  120.  
  121. /*
  122. **   Get invocation name of program
  123. */
  124.     tmp = (char *)NULL;
  125.     strcpy(invoke, strtok(argv[0], "/]\\\0"));
  126.     for (;;) {
  127.     if (tmp != NULL)
  128.         strcpy(invoke, tmp);
  129.     if ((tmp = strtok((char *)NULL, "/]\\\0")) == NULL)
  130.         break;
  131.     }
  132.  
  133.     if (argc < 3) {
  134.         usage(invoke);
  135.         exit(1);
  136.     }
  137.  
  138. /*
  139. **   Get option flags
  140. */
  141.     fnum = 0;
  142.     i = 1;
  143.     while(i < argc){
  144.     if (argv[i][0]=='-') {
  145.             switch(argv[i][1]) {
  146.                 case 'b':
  147.             if (optset == 0) {
  148.                         blocks = 0;
  149.                 optset = 1;
  150.             } else {
  151.             error("incompatible options: -i and -b");
  152.             }
  153.                     break;
  154.                 case 'i':
  155.             if (optset == 0) {
  156.                         intr = 1;
  157.             blocks = 0;
  158.                 optset = 1;
  159.             } else {
  160.             error("incompatible options: -i and -b");
  161.             }
  162.                     break;
  163.                 case 'd':
  164.             ndds = atoi(&argv[i][2]);
  165.                     break;
  166.                 case 't':
  167.                     nblk = atoi(&argv[i][2]);
  168.                     break;
  169.                 default:
  170.                     fprintf(stderr, "Unknown option -%c ignored\n", argv[i][1]);
  171.                     break;
  172.             }
  173.     } else {
  174.         if (fnum < 2) {
  175.             strcpy(fname[fnum], argv[i]);
  176.             fnum++;
  177.         }
  178.     }
  179.         i++;
  180.     }
  181.  
  182. /*
  183. **   Enough [unique] file arguments?
  184. */
  185.     if ((fnum != 2) || (strcmp(fname[0], fname[1]) == 0)) {
  186.     error("need 2 unique file names");
  187.     }
  188.  
  189. /*
  190. **   Check to make sure input file is HDF
  191. */
  192.     ret = Hishdf(fname[0]);
  193.     if (ret == FALSE)
  194.     hdferror();
  195.  
  196. /*
  197. **   Open input and output files
  198. */
  199.     infile = Hopen(fname[0], DFACC_READ, 0);
  200.  
  201.     if (infile == FAIL)
  202.     hdferror();
  203.  
  204.     outfile = Hopen(fname[1], DFACC_CREATE | DFACC_WRITE, ndds);
  205.  
  206.     if (outfile == FAIL)
  207.     hdferror();
  208.  
  209. /*
  210. **   See how many data elements there
  211. **   are and make room for their DD's
  212. **   (Subtract one for machine type.)
  213. */
  214.     num_desc = Hnumber(infile, DFTAG_WILDCARD) - 1;
  215.     if (num_desc == FAIL)
  216.     hdferror();
  217.  
  218.     dlist = (mydd_t *)HDgetspace(num_desc * sizeof(*dlist));
  219.     if (dlist == NULL)
  220.     error("\tWow!  That file must be HUGE!\n\tThere isn't enough memory to hold the DD's.\n");
  221.  
  222. /*
  223. **   Allocate data buffer - try 1 Meg first, work down
  224. */
  225.     data_size = 1048576; /* 1 MB */
  226.     data = NULL;
  227.     while ((data = (unsigned char *)HDgetspace(data_size)) == NULL)
  228.     data_size /= 2; /* okay then, cut request by half */
  229.  
  230. /*
  231. **   Get all DD's for data elements
  232. */
  233.     aid = Hstartread(infile, DFTAG_WILDCARD, DFREF_WILDCARD);
  234.     if (aid == FAIL){
  235.     printf("MAJOR PROBLEM: Hstartread for DD's; line %d\n", __LINE__);
  236.     hdferror();
  237.     }
  238.     for (i=0; i<num_desc; i++) {
  239.     Hinquire(aid, NULL, &dlist[i].tag, &dlist[i].ref, &dlist[i].length,
  240.          &dlist[i].offset, NULL, NULL, &dlist[i].special);
  241.     stat = Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD, DF_CURRENT);
  242.     if (stat == FAIL){
  243.         printf("MAJOR PROBLEM: DDs; only got %d of %d; line %d\n",i,num_desc,__LINE__);
  244.         hdferror();
  245.         }
  246.     }
  247.     stat = Hendaccess(aid);
  248.     if (stat == FAIL)
  249.         hdferror();
  250.  
  251. /*
  252. **   Sort DD's by offset to make it easy to
  253. **   find DD's that point to the same data
  254. */
  255.     qsort((char *)dlist, num_desc, sizeof(*dlist), desc_comp);
  256.  
  257.     oldoff = -1;
  258.     oldlen = -1;
  259.     for (i=0; i<num_desc; i++) {
  260.     if (((dlist[i].tag != DFTAG_NULL) && (dlist[i].tag != DFTAG_VERSION))
  261.         && (dlist[i].tag != DFTAG_LINKED)) {
  262.         if ((dlist[i].offset != oldoff) || (dlist[i].length != oldlen)) {
  263. /*
  264. **   if this DD points to different data, read the data
  265. **   from the old file and write it to the new file
  266. */
  267.             switch (dlist[i].special){
  268.             case SPECIAL_LINKED:
  269.             if (intr == 1)
  270.                 merge = promptblocks(&dlist[i]);
  271.             else
  272.                 merge = blocks;
  273.             if (merge == 0) {
  274.                 copy_blocks(&dlist[i], infile, outfile);
  275.             } else {
  276.                 merge_blocks(&dlist[i], infile, outfile);
  277.             }
  278.             break;
  279.             default:
  280.             merge_blocks(&dlist[i], infile, outfile);
  281.             break;
  282.         } /* switch (special) */
  283.         } else {
  284. /*
  285. **   otherwise, just make a new DD for same data
  286. */
  287.         ret = Hdupdd(outfile, dlist[i].tag, dlist[i].ref,
  288.                  dlist[i-1].tag, dlist[i-1].ref);
  289.                 if (ret == FAIL) {
  290.             HERROR(DFE_GENAPP);
  291.                 hdferror();
  292.         }
  293.         }
  294.     }
  295. /*
  296. **   save offset of data to check against next DD
  297. */
  298.     oldoff = dlist[i].offset;
  299.     }
  300.  
  301. /*
  302. **   done; close files
  303. */
  304.     Hclose(infile);
  305.     Hclose(outfile);
  306.  
  307.     exit(0);
  308. }
  309.  
  310.  
  311. /*
  312. ** NAME
  313. **      promptblocks
  314. */
  315. #ifdef PROTOTYPE
  316. int promptblocks(mydd_t *dd)
  317. #else
  318. int promptblocks(dd)
  319. mydd_t *dd;
  320. #endif /* PROTOTYPE */
  321. {
  322.     char ans[80];
  323.  
  324.     printf("Would you like to coalesce the following linked-block element:\n");
  325.     printf("\ttag = %d\n\tref = %d\n(y/n): ", dd->tag, dd->ref);
  326.     gets(ans);
  327.     if ((ans[0] == 'y') || (ans[0] == 'Y'))
  328.     return(1);
  329.     else
  330.     return(0);
  331. }
  332.  
  333.  
  334. /*
  335. ** NAME
  336. **      copy_blocks -- move a linked-block element; preserve blocking
  337. */
  338. #ifdef PROTOTYPE
  339. int copy_blocks(mydd_t *dd, int32 infile, int32 outfile)
  340. #else
  341. int copy_blocks(dd, infile, outfile)
  342. mydd_t *dd;
  343. int32 infile, outfile;
  344. #endif /* PROTOTYPE */
  345. {
  346.     int32 inaid, ret, rdret, len, first_len, block_len, nblocks, outaid;
  347.     char *FUNC="copy_blocks";
  348.  
  349.  
  350.     inaid = Hstartread(infile, dd->tag, dd->ref);
  351.     ret = HDinqblockinfo(inaid, &len, &first_len, &block_len, &nblocks);
  352.     if (ret != SUCCEED) {
  353.         HERROR(DFE_GENAPP);
  354.         hdferror();
  355.     }
  356. /*
  357. **  copy first block
  358. */
  359.     outaid = Hstartwrite(outfile, HDbase_tag(dd->tag), dd->ref, first_len);
  360.     if (outaid == FAIL) {
  361.         HERROR(DFE_GENAPP);
  362.         hdferror();
  363.     }
  364.     rdret = 0;
  365.     while (rdret < first_len) {
  366.         ret = Hread(inaid, (data_size<first_len) ? data_size : first_len, data);
  367.     if (ret == FAIL) {
  368.         HERROR(DFE_GENAPP);
  369.         hdferror();
  370.     }
  371.     rdret += ret;
  372.     ret = Hwrite(outaid, ret, data);
  373.     if (ret == FAIL) {
  374.         HERROR(DFE_GENAPP);
  375.         hdferror();
  376.     }
  377.     }
  378.     ret = Hendaccess(outaid);
  379. /*
  380. **  promote to linked-block element
  381. */
  382.     if (nblk > 0)
  383.         nblocks = nblk;
  384.  
  385.     outaid = HLcreate(outfile,HDbase_tag(dd->tag), dd->ref, block_len, nblocks);
  386.     if (outaid == FAIL) {
  387.     HERROR(DFE_GENAPP);
  388.     hdferror();
  389.     }
  390. /*
  391. **  copy remaining blocks
  392. */
  393.     rdret = data_size;
  394.     while (rdret == data_size) {
  395.     rdret = Hread(inaid, data_size, data);
  396.     if (ret == FAIL) {
  397.         HERROR(DFE_GENAPP);
  398.         hdferror();
  399.     }
  400.     ret = Hwrite(outaid, rdret, data);
  401.     if (ret == FAIL) {
  402.         HERROR(DFE_GENAPP);
  403.         hdferror();
  404.     }
  405.     }
  406.     Hendaccess(outaid);
  407. }
  408.  
  409.  
  410. /*
  411. ** NAME
  412. **      merge_blocks
  413. */
  414. #ifdef PROTOTYPE
  415. int merge_blocks(mydd_t *dd, int32 infile, int32 outfile)
  416. #else
  417. int merge_blocks(dd, infile, outfile)
  418. mydd_t *dd;
  419. int32 infile, outfile;
  420. #endif /* PROTOTYPE */
  421. {
  422.     int32 inaid, outaid, ret, len;
  423.     char *FUNC="merge_blocks";
  424.  
  425.  
  426.     inaid = Hstartread(infile, dd->tag, dd->ref);
  427.     if (inaid == FAIL) {
  428.     HERROR(DFE_GENAPP);
  429.         hdferror();
  430.     }
  431.     outaid = Hstartwrite(outfile, HDbase_tag(dd->tag), dd->ref, dd->length);
  432.     if (outaid == FAIL) {
  433.     HERROR(DFE_GENAPP);
  434.     hdferror();
  435.     }
  436.  
  437.     while (dd->length>0) {
  438.     dd->length -= (len= Hread(inaid, data_size, data));
  439.         if (len == FAIL) {
  440.         HERROR(DFE_GENAPP);
  441.         hdferror();
  442.     }
  443.         ret = Hwrite(outaid, len, data);
  444.         if (len == FAIL) {
  445.         HERROR(DFE_GENAPP);
  446.             hdferror();
  447.     }
  448.     }
  449.  
  450.     ret = Hendaccess(inaid);
  451.     if (ret == FAIL) {
  452.     HERROR(DFE_GENAPP);
  453.     hdferror();
  454.     }
  455.  
  456.     ret = Hendaccess(outaid);
  457.     if (ret == FAIL) {
  458.     HERROR(DFE_GENAPP);
  459.         hdferror();
  460.     }
  461. }
  462.  
  463.  
  464. /*
  465. ** NAME
  466. **    usage -- print out usage template
  467. ** USAGE
  468. **    int usage()
  469. ** RETURNS
  470. **    none
  471. ** DESCRIPTION
  472. **    Print hdfpack's usage template to stdout.
  473. ** GLOBAL VARIABLES
  474. ** COMMENTS, BUGS, ASSUMPTIONS
  475. ** EXAMPLES
  476. */
  477. #ifdef PROTOTYPE
  478. int usage(char *name)
  479. #else
  480. int usage(name)
  481. char *name;
  482. #endif /* PROTOTYPE */
  483. {
  484.     fprintf(stderr, "Usage:  %s [-i | -b] [-d#] [-t#] <infile> <outfile>\n", name);
  485. }
  486.  
  487. /*
  488. ** NAME
  489. **    hdferror -- print out HDF error number
  490. ** USAGE
  491. **    int hdferror()
  492. ** RETURNS
  493. **    none
  494. ** DESCRIPTION
  495. **    Print an HDF error number to stderr.
  496. ** GLOBAL VARIABLES
  497. ** COMMENTS, BUGS, ASSUMPTIONS
  498. **    This routine terminates the program with code 1.
  499. ** EXAMPLES
  500. */
  501. #ifdef PROTOTYPE
  502. int hdferror(void)
  503. #else
  504. int hdferror()
  505. #endif /* PROTOTYPE */
  506. {
  507.     HEprint(stderr, 0);
  508.     exit(1);
  509. }
  510.  
  511. /*
  512. ** NAME
  513. **      error -- print error to stderr
  514. ** USAGE
  515. **      int error(string);
  516. **      char *string;           IN: pointer to error description string
  517. ** RETURNS
  518. **    none
  519. ** DESCRIPTION
  520. **    Print an HDF error number to stderr.
  521. ** GLOBAL VARIABLES
  522. ** COMMENTS, BUGS, ASSUMPTIONS
  523. **    This routine terminates the program with code 1.
  524. ** EXAMPLES
  525. */
  526. #ifdef PROTOTYPE
  527. int error(char *string)
  528. #else
  529. int error(string)
  530. char *string;
  531. #endif
  532. {
  533.     fprintf(stderr, "%s: %s\n", invoke, string);
  534.     exit(1);
  535. }
  536.  
  537. /*
  538. ** NAME
  539. **    desc_comp -- compare two DD's by offset
  540. ** USAGE
  541. **    int desc_cmp(d1, d2)
  542. **    mydd_t *d1        IN: pointer to a DD
  543. **    mydd_t *d2        IN: pointer to a DD
  544. ** RETURNS
  545. **    A number less than, greater than, or equal to 0, according to
  546. **    whether d1's offset is less than, greater than, or equal to
  547. **    d2's offset.
  548. ** DESCRIPTION
  549. **    A pointer to this routine is passed to qsort() as the comparison
  550. **    function for the sort.
  551. ** GLOBAL VARIABLES
  552. ** COMMENTS, BUGS, ASSUMPTIONS
  553. ** EXAMPLES
  554. */
  555. #ifdef PROTOTYPE
  556. int desc_comp(const void *d1, const void *d2)
  557. #else
  558. int desc_comp(d1, d2)
  559. const void *d1, *d2;
  560. #endif /* PROTOTYPE */
  561. {
  562.     return(((mydd_t *)d1)->offset - ((mydd_t *)d2)->offset);
  563. }
  564.