home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume17 / zoo2 / part05 / misc.c < prev    next >
C/C++ Source or Header  |  1989-02-01  |  10KB  |  381 lines

  1. #ifndef LINT
  2. /* @(#) misc.c 2.6 88/08/15 16:17:23 */
  3. static char sccsid[]="@(#) misc.c 2.6 88/08/15 16:17:23";
  4. #endif /* LINT */
  5.  
  6. /*
  7. Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
  8. (C) Copyright 1988 Rahul Dhesi -- All rights reserved
  9. */
  10. #include "options.h"
  11. /* Miscellaneous functions needed by Zoo but not by Ooz */
  12.  
  13. #include "zoo.h"
  14. #include "zooio.h"
  15. #include "various.h"
  16.  
  17. #include "errors.i"
  18. #include "zoofns.h"
  19. #ifndef NOSIGNAL
  20. #include <signal.h>
  21. #endif
  22.  
  23. #ifdef NEEDCTYP
  24. #include <ctype.h>
  25. #else
  26. #include "portable.h"
  27. #endif
  28.  
  29. #ifdef LINT_ARGS
  30. int ver_too_high (struct zoo_header *);
  31. #else
  32. int ver_too_high ();
  33. #endif
  34.  
  35.  
  36. /*
  37. calc_ofs() is given a string that (supposedly) begins with a string
  38. of digits.  It returns a corresponding numeric value.  If no such
  39. string, it aborts the program with a fatal error message.
  40. */
  41. long calc_ofs(str)
  42. char *str;
  43. {
  44.    long retval;
  45.    char *p;
  46.    retval = 0L;
  47.    p = str; /* save for error message */
  48.    while (isdigit(*str)) {
  49.       retval = retval * 10L + (*str-'0');
  50.       str++;
  51.    }
  52.    if (*str != '\0')
  53.       prterror ('f', "Invalid number %s\n", p);
  54.    return (retval);
  55. }
  56.  
  57. /*
  58. choosefname() decides which filename to use.  If a long filename is present,
  59. and if the syntax is that of UNIX, MS-DOS or the portable form, we use it;
  60. else we use the short filename. 
  61. */
  62.  
  63. char *choosefname(direntry)
  64. struct direntry *direntry;
  65. {
  66.    char *retptr;                 /* pointer to name that we will return */
  67.    switch (direntry->system_id) {
  68.       case SYSID_NIX:
  69.       case SYSID_PORTABLE:
  70.       case SYSID_MS:
  71.          retptr = (direntry->namlen != 0) ? direntry->lfname : direntry->fname;
  72.          break;
  73.       default:
  74.          retptr = direntry->fname;
  75.          break;
  76.    }
  77.    return (retptr);
  78. } /* choosefname() */
  79.  
  80. /* 
  81. combine() combines a directory name and a filename, making sure the
  82. two are separated by a path separator 
  83. */
  84. char *combine(result, dirname, fname)
  85. char result[], *dirname, *fname;
  86. {
  87.    *result = '\0';
  88.    if (*dirname != '\0') {
  89. #ifdef DIR_LBRACK /* hack for VMS */
  90.       strcat (result, DIR_LBRACK);
  91.  
  92.       /*  "/" => "[",  "./" => "[."  others => "[." */
  93.  
  94.       if (dirname[0] == '/') {        /* absolute path => "[" */
  95.          strcat (result, dirname + 1);
  96.       } else if (dirname[0] == '.' && dirname[1] == '/') {
  97.          strcat (result, CUR_DIR);
  98.          strcat (result, dirname + 2);
  99.       } else {
  100.          strcat (result, CUR_DIR);
  101.          strcat (result, dirname);
  102.       }
  103.  
  104. /* folowing #ifdef block ought to be outside #ifdef DIR_LBRACK, and
  105.    for loop should then start with p=result.  This is currently
  106.    just a hack for VMS.
  107. */
  108. #ifdef DIR_SEP
  109.    if (DIR_SEP != '/') {   /* if char separating dirs is not "/",  */
  110.       char *p;
  111.       for (p = result+2;  *p != '\0';  p++) /* change it to underscore */
  112.         if (*p == DIR_SEP)
  113.            *p = '_';
  114.    }
  115. #endif
  116.  
  117.       {
  118.          char *p;
  119.          for (p = result; *p != '\0';  p++)
  120.          if (*p == '/')
  121.             *p = '.';
  122.       }
  123. #else
  124.       strcat (result, dirname);
  125. #endif
  126.       if (*lastptr(result) != *PATH_CH)
  127.          strcat(result, PATH_CH);
  128.    }
  129.  
  130.    strcat(result, fname);
  131.    return (result);
  132. }
  133.  
  134. /*
  135. fullpath() accepts a pointer to a directory entry and returns the
  136. combined directory name + filename.  The long filename is used
  137. if available, else the short filename is used.
  138. */
  139. char *fullpath (direntry)
  140. struct direntry *direntry;
  141. {
  142.     static char result[PATHSIZE];
  143.     combine (result,
  144.                 direntry->dirlen != 0 ? direntry->dirname : "", 
  145.                 (direntry->namlen != 0) ? direntry->lfname : direntry->fname
  146.               );
  147.     return (result);
  148. }
  149.  
  150. /* 
  151. ver_too_high returns true if version of provided archive header is
  152. too high for us to manipulate archive
  153. */
  154.  
  155. int ver_too_high (header)
  156. struct zoo_header *header;
  157. {
  158.    return (header->major_ver > MAJOR_VER ||
  159.             (header->major_ver == MAJOR_VER &&
  160.              header->minor_ver > MINOR_VER));
  161. }
  162.  
  163. /* 
  164. rwheader() reads archive header, checks consistency, makes sure its
  165. version number is not too high, updates it if too low, and seeks to
  166. beginning of first directory entr.  If `preserve' is 1, it preserves
  167. the header type;  if `preserve' is 0, it gives a fatal error message
  168. if type is 0.
  169. */
  170.  
  171. void rwheader (header, zoo_file, preserve)
  172. register struct zoo_header *header;
  173. ZOOFILE zoo_file;
  174. int preserve;
  175. {
  176.  
  177.    frd_zooh (header, zoo_file);
  178.  
  179.    if ((header->zoo_start + header->zoo_minus) != 0L)
  180.       prterror ('f', failed_consistency);
  181.    if (ver_too_high (header))
  182.       prterror ('f', wrong_version, header->major_ver, header->minor_ver);
  183.  
  184.     if (preserve == 0 && header->type == 0)
  185.         prterror ('f', packfirst);
  186.  
  187.    /* We reach here if the archive version is not too high.  Now, if it
  188.    isn't the same as ours, we bring it up to ours so the modified archive
  189.    will be safe from previous versions of Zoo */
  190.  
  191.    if (header->major_ver != MAJOR_VER || header->minor_ver != MINOR_VER) {
  192.       header->major_ver = MAJOR_VER;
  193.       header->minor_ver = MINOR_VER;
  194.       zooseek (zoo_file, 0L, 0);            /* seek to beginning */
  195.       fwr_zooh (header, zoo_file);
  196.    }
  197.    zooseek (zoo_file, header->zoo_start, 0); /* seek to where data begins */
  198. } /* rwheader */
  199.  
  200. /*
  201. writedir() write a directory entry with keyboard interrupt disabled
  202. */
  203. void writedir (direntry, zoo_file)
  204. struct direntry *direntry;
  205. ZOOFILE zoo_file;
  206. {
  207. #ifndef NOSIGNAL  
  208.    int (*oldsignal)();
  209.    oldsignal = signal (SIGINT, SIG_IGN);
  210. #endif
  211.    if (fwr_dir (direntry, zoo_file) == -1)
  212.       prterror ('f', disk_full);
  213. #ifndef NOSIGNAL
  214.    signal (SIGINT, oldsignal);
  215. #endif
  216. }
  217.  
  218. /* 
  219. readdir() reads a directory entry from an archive.  If the directory
  220. entry is invalid and if fail is 1, it causes a fatal error;
  221. else it returns.  Return value is 0 if no error else -1;
  222. */
  223.  
  224. int readdir (direntry, zoo_file, fail)    /* read directory entry */
  225. register struct direntry *direntry;
  226. ZOOFILE zoo_file;
  227. int fail;                              /* 0 -> return, 1 -> abort on error */
  228. {
  229.    if (frd_dir (direntry, zoo_file) < 0) {
  230.       if (fail) {
  231.          prterror ('f', bad_directory);
  232.       } else
  233.          return (-1);
  234.    }
  235.    if (direntry->zoo_tag != ZOO_TAG) {
  236.       if (fail)
  237.          prterror ('f', bad_directory);
  238.       else
  239.          return (-1);
  240.    }
  241.    return (0);
  242. }
  243.  
  244. /* use pointer version below */
  245. #ifdef COMMENT
  246. /* instr() searches a string for a substring */
  247. instr (s, t)      /* return index of string t in string s, -1 if none */
  248. char s[], t[];    /*  .. from K&R page 67 */
  249. {
  250.    int i;
  251.    register int j, k;
  252.    for (i = 0; s[i] != '\0'; i++) {
  253.       for (j = i, k = 0; t[k] != '\0' && s[j]==t[k]; j++, k++)
  254.          ;
  255.       if (t[k] == '\0')
  256.          return (i);
  257.    }
  258.    return (-1);
  259. }
  260. #endif COMMENT
  261.  
  262. /* instr() searches a string for a substring */
  263. /* from J. Brian Waters */
  264. int instr (s, t)           /* return the position of t in s, -1 if none */
  265. char *s, *t;                /*  a pointer version of K&R index function p.67 */
  266. {               /* renamed to instr() to avoid conflicts with C RTL - JBW */
  267.  
  268.    register char *i, *j, *k;
  269.  
  270.    for (i = s; *i; i++) {
  271.       for (j = i, k = t; (*k) && (*j++ == *k); k++)
  272.          ;
  273.        if (!*k)
  274.          return ((int) (i - s));
  275.    }
  276.    return(-1);
  277. }
  278.  
  279. /* cfactor() calculates the compression factor given a directory entry */
  280. int cfactor (org_size, size_now)
  281. long org_size, size_now;
  282. {
  283.    register int size_factor;
  284.    if ((unsigned long) org_size > 1000000) { /* avoid later overflow */
  285.       org_size = (unsigned long) org_size / 1024;
  286.       size_now = (unsigned long) size_now / 1024;
  287.    }
  288.    if (org_size == 0)         /* avoid division by zero */
  289.       size_factor = 0;
  290.    else {
  291.       size_factor = (int)
  292.          (
  293.             (1000 * 
  294.                ((unsigned long) org_size - (unsigned long) size_now)
  295.             ) / org_size + 5
  296.          ) / 10;
  297.    }
  298.    return (size_factor);
  299. }
  300.  
  301. #ifndef STRDUP
  302. /***********
  303. strdup() duplicates a string using dynamic memory.
  304. */
  305.  
  306. char *strdup (str)
  307. register char *str;
  308. {
  309.    return (strcpy (emalloc (strlen(str)+1), str));
  310. }
  311. #endif /* STRDUP */
  312.  
  313. /**************
  314. cmpnum() compares two pairs of unsigned integers and returns a negative,
  315. zero, or positive value as the comparison yields less than, equal, or
  316. greater than result.  Each pair of unsigned integers is considered to be the
  317. more significant and the less significant half of a longer unsigned number.
  318.  
  319. Note:  cmpnum is used to compare dates and times.
  320. */
  321.  
  322. int cmpnum (hi1, lo1, hi2, lo2)
  323. register unsigned int hi1, hi2;
  324. unsigned int lo1, lo2;
  325. {
  326.    if (hi1 != hi2)
  327.       return (hi1 > hi2 ? 1 : -1);
  328.    else {
  329.         if (lo1 == lo2)
  330.             return (0);
  331.         else
  332.             return (lo1 > lo2 ? 1 : -1);
  333.     }
  334. }
  335.  
  336. /*******************/
  337. /* writenull() */
  338. /* writes a null directory entry to an open archive */
  339. void writenull (file, length)
  340. ZOOFILE file;
  341. int length;
  342. {
  343. #ifndef NOSIGNAL
  344.    int (*oldsignal)();
  345. #endif
  346.    struct direntry newentry;
  347.    memset ((char *) &newentry, 0, sizeof (newentry));
  348.    newentry.zoo_tag = ZOO_TAG;
  349.    newentry.type = 2;
  350.    /* Force entry to be the required length plus possibly 2 stray bytes
  351.    by dividing up the needed padding into dirlen and namlen. */
  352.    if (length > SIZ_DIRL)
  353.       newentry.dirlen = newentry.namlen = (length-SIZ_DIRL)/2 + 2;
  354.    else
  355.       newentry.dirlen = newentry.namlen = 0;
  356. #ifndef NOSIGNAL
  357.    oldsignal = signal (SIGINT, SIG_IGN);
  358. #endif
  359.    if (fwr_dir (&newentry, file) == -1)
  360.       prterror ('f', disk_full);
  361. #ifndef NOSIGNAL
  362.    signal (SIGINT, oldsignal);
  363. #endif
  364. }
  365.  
  366. #ifdef FORCESLASH
  367. /*******************/
  368. /*
  369. fixslash() changes all "\" characters in the supplied string to "/".
  370. */
  371.  
  372. void fixslash (str)
  373. char *str;
  374. {
  375.    register char *p;
  376.    for (p = str; *p != '\0'; p++)
  377.       if (*p == '\\')
  378.          *p = '/';
  379. }
  380. #endif /* FORCESLASH */
  381.