home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / utilities / cli / nspark / arcfs_c < prev    next >
Encoding:
Text File  |  1995-01-06  |  6.8 KB  |  306 lines

  1. /*
  2.  * Handle ArcFS format archives
  3.  *
  4.  * Author: Andrew Brooks, arb@comp.lancs.ac.uk
  5.  *
  6.  * $Header: arcfs.c 1.4 95/01/06 $
  7.  * $Log:        arcfs.c,v $
  8.  * Revision 1.4  95/01/06  11:58:45  arb
  9.  * Fixes for Alpha.
  10.  *
  11.  * Revision 1.3  94/12/12  17:25:25  arb
  12.  * Fixes for writesize.
  13.  *
  14.  * Revision 1.2  94/10/26  15:06:35  arb
  15.  * Fixed date and time conversion.
  16.  *
  17.  * Revision 1.1  94/02/28  21:41:23  arb
  18.  * Fixed header, fixed include ordering, fixed directory check,
  19.  * added seek to start of compressed data, fixed maxbits, ...
  20.  * ie. got the thing working at last!
  21.  *
  22.  * Revision 1.0  93/08/20  12:40:15  arb
  23.  * Initial revision
  24.  */
  25.  
  26.  
  27. #include <stdio.h>
  28. #include <time.h>
  29. #include "spark.h"
  30. #ifdef UNIX
  31. #include <sys/types.h>
  32. #endif /* UNIX */
  33. #ifdef RISCOS
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #endif /* RISCOS */
  37. #include "arcfs.h"
  38. #include "io.h"
  39.  
  40. #ifndef SEEK_SET
  41. #define SEEK_SET 0
  42. #endif
  43.  
  44. #ifdef UNIX
  45. static char rcsid[] = "$Header: arcfs.c 1.4 95/01/06 $";
  46. #endif /* UNIX */
  47.  
  48.  
  49. /*
  50.  * Public flag to indicate whether the current archive is ArcFS format
  51.  */
  52. int arcfs = 0;
  53.  
  54.  
  55. /*
  56.  * Public number of compression bits, used in compress.c
  57.  */
  58. int arcfs_maxbits = 0;
  59.  
  60.  
  61. /*
  62.  * Public size of file being extracted, used in io.c, crc.c
  63.  */
  64. long writesize;
  65. long crcsize;
  66.  
  67.  
  68. /*
  69.  * ArcFS header list element
  70.  */
  71. struct arcfs_header_s
  72. {
  73.     struct arcfs_header_s *next;
  74.     Byte maxbits;
  75.     Byte is_dir;
  76.     Byte info_byte;
  77.     Word info_word;
  78.     Word seek;
  79.     Header *header;
  80. };
  81. typedef struct arcfs_header_s *arcfs_header;
  82.  
  83.  
  84. /*
  85.  * Info byte
  86.  */
  87. #define AFS_ENDDIR   0
  88. #define AFS_DELETED  1
  89. #define AFS_STORE    0x82
  90. #define AFS_PACK     0x83
  91. #define AFS_CRUNCH   0x88
  92. #define AFS_COMPRESS 0xFF
  93.  
  94.  
  95. /*
  96.  * Static data
  97.  */
  98. static int arcfs_initialised = 0;
  99. static arcfs_header header_list = NULL;
  100. static arcfs_header header_ptr = NULL;
  101.  
  102.  
  103. /*
  104.  * Convert RISC OS time to UNIX time.
  105.  * RISC OS time is five bytes of centiseconds since 1900.
  106.  * UNIX time is seconds since 1970.
  107.  * MSB of RISC OS time is LSB of `load' plus `exec'.
  108.  */
  109. struct tm *
  110. rotm(load, exec)
  111.     Word load, exec;
  112. {
  113.     Word low, high;
  114.     time_t t;
  115.  
  116.     high = (load & 0xff) - 0x33l;
  117.     low = exec - 0x6e996a00l;
  118.     t = (time_t) (high * 42949673 + low / 100);
  119.     return(localtime(&t));
  120. }
  121.  
  122.  
  123. /*
  124.  * Convert RISC OS time to SPARK time
  125.  */
  126. void
  127. arcfs_fixtime(hdr)
  128.     Header *hdr;
  129. {
  130.     time_t ti;
  131.     struct tm *tim;
  132.  
  133.     /* Convert to UNIX time first (as it is easy) */
  134.     tim = rotm(hdr->load, hdr->exec);
  135.  
  136.     /* Convert UNIX time to SPARK time */
  137.     hdr->date = (tim->tm_year-80) << 9;
  138.     hdr->date |= (tim->tm_mon+1)  << 5;
  139.     hdr->date |= (tim->tm_mday);
  140.     hdr->time = (tim->tm_hour) << 11;
  141.     hdr->time |= (tim->tm_min) << 5;
  142.     hdr->time |= (tim->tm_sec);
  143. }
  144.  
  145.  
  146. /*
  147.  * Read ArcFS header
  148.  */
  149. Header *
  150. arcfs_read_header(ifp)
  151.     FILE *ifp;
  152. {
  153.     static Header null_header;
  154.     static Word data_start;
  155.     Word header_length = 0;
  156.     Header *header;
  157.     Word version;
  158.     int i;
  159.     Byte info_byte, name[12];
  160.     Word length, load, exec, attr, complen, info_word;
  161.     arcfs_header header_prev;
  162.     int j;
  163.  
  164.     /* Return next header from list */
  165.     if (arcfs_initialised)
  166.     {
  167.     /* If end of list return an empty header structure to indicate EOF */
  168.     if (header_ptr == NULL)
  169.         return(&null_header);
  170.  
  171.     /* Return next header in list */
  172.     header = header_ptr->header;
  173.     /* Seek to start of compressed data */
  174.     if ((!header_ptr->is_dir) && (fseek(ifp, (long)header_ptr->seek, SEEK_SET)))
  175.     {
  176.         printf("Cannot seek compressed data in this file\n");
  177.         return(&null_header);
  178.     }
  179.     /* Set up number of compression bits */
  180.     arcfs_maxbits = header_ptr->maxbits;
  181.     /*if (header_ptr->is_dir) header = &null_header;*/
  182.     header_ptr = header_ptr -> next;
  183.     return(header);
  184.     }
  185.  
  186.     /* Header list not constructed yet, so read all headers from file */
  187.     arcfs_initialised = 1;
  188. #ifdef BSD
  189.     bzero((char *)&null_header, sizeof(null_header));
  190. #else /* not BSD */
  191.     memset((char *)&null_header, '\0', sizeof(null_header));
  192. #endif /* BSD */
  193.     null_header.comptype = 0;
  194.     header_length = read_word(ifp);
  195.     data_start = read_word(ifp);
  196.     if ((version = read_word(ifp)) > 40)
  197.     {
  198.     printf("Archive created by a newer version of ArcFS (%.2f)\n",((float)version)/100);
  199.     return(&null_header);
  200.     }
  201.     read_word(ifp);     /* read/write version */
  202.     if ((version = read_word(ifp)) > 0)
  203.     {
  204.     printf("Archive format %d not understood\n",version);
  205.     return(&null_header);
  206.     }
  207.     for (i=0; i<17; i++) read_word(ifp);     /* reserved */
  208.  
  209.     /* Read list of headers */
  210.     for (i=0; i < header_length/36; i++)
  211.     {
  212.     /* Create list item */
  213.     header = (Header*) malloc(sizeof(Header));
  214.     header_ptr = (arcfs_header) malloc(sizeof(struct arcfs_header_s));
  215.     if ((header==NULL) || (header_ptr==NULL))
  216.     {
  217.         printf("Out of memory\n");
  218.         return(&null_header);
  219.     }
  220.  
  221.     /* Read ArcFS file header */
  222.     info_byte = read_byte(ifp);
  223.     for (j=0; j<11; j++)
  224.     {
  225.         name[j] = read_byte(ifp);
  226.         if (name[j] == PATHSEP) name[j] = '_';
  227.         if (name[j] < ' ' || name[j] > '~') name[j] = '\0';
  228.     }
  229.     name[j] = '\0';
  230.     length = read_word(ifp);
  231.     load = read_word(ifp);
  232.     exec = read_word(ifp);
  233.     attr = read_word(ifp);
  234.     complen = read_word(ifp);
  235.     info_word = read_word(ifp);
  236.  
  237.     /* Examine, and create nspark header */
  238.     if (info_byte == AFS_DELETED)
  239.     {
  240.         free(header);
  241.         free(header_ptr);
  242.         continue;
  243.     }
  244.     header_ptr->is_dir = (info_word >> 31);
  245.     header_ptr->info_byte = info_byte;
  246.     header_ptr->info_word = info_word;
  247.     header_ptr->maxbits = (attr & 0xff00) >> 8;
  248.     header_ptr->seek = (info_word & 0x7fffffff) + data_start;
  249.     header->comptype = info_byte;
  250.     strcpy(header->name, (char*)name);
  251.     header->complen = complen;
  252.     header->date = 0;
  253.     header->time = 0;
  254.     header->crc = (Halfword)(attr >> 16);
  255.     header->origlen = length;
  256.     header->load = load;
  257.     header->exec = exec;
  258.     header->attr = attr & 0xff;
  259.  
  260.     arcfs_fixtime(header);
  261.  
  262.     if (info_byte == AFS_ENDDIR)
  263.     {
  264.         /* Just return comptype == 0 */
  265.         *header = null_header;
  266.         header_ptr->is_dir = 0;
  267.         header_ptr->seek = 0;
  268.     }
  269.  
  270.     /* If it is an ArcFS directory then convert to a Spark directory */
  271.     if (header_ptr->is_dir)
  272.     {
  273.         /* Make sure filetype is DDC */
  274.         header->comptype = CT_NOTCOMP2;
  275.         header->load = 0xfffddcff;
  276.     }
  277.  
  278.     /* Add list item to list */
  279.     /* Doing it here ensures that deleted items are not added */
  280.     header_ptr->header = header;
  281.     if (header_list == NULL)
  282.         header_list = header_ptr;
  283.     else
  284.         header_prev->next = header_ptr;
  285.     header_prev = header_ptr;
  286. #ifdef DEBUGGING
  287.     print_header(header);
  288. #endif
  289.     }
  290.  
  291.     /* Return first element */
  292.     header_ptr = header_list;
  293.     header = header_ptr->header;
  294.     /* Seek to start of data for first element */
  295.     if ((!header_ptr->is_dir) && (fseek(ifp, (long)header_ptr->seek, SEEK_SET)))
  296.     {
  297.     printf("Cannot seek compressed data in this file\n");
  298.     return(&null_header);
  299.     }
  300.     /* Set up number of compression bits */
  301.     arcfs_maxbits = header_ptr->maxbits;
  302.     /*if (header_ptr->is_dir) header = &null_header;*/
  303.     header_ptr = header_ptr->next;
  304.     return(header);
  305. }
  306.