home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / std_unix / pax / 2 / link.c < prev    next >
C/C++ Source or Header  |  1989-01-07  |  8KB  |  318 lines

  1. /* $Source: /u/mark/src/pax/RCS/link.c,v $
  2.  *
  3.  * $Revision: 1.1 $
  4.  *
  5.  * link.c - functions for handling multiple file links 
  6.  *
  7.  * DESCRIPTION
  8.  *
  9.  *    These function manage the link chains which are used to keep track
  10.  *    of outstanding links during archive reading and writing.
  11.  *
  12.  * AUTHOR
  13.  *
  14.  *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  15.  *
  16.  * Sponsored by The USENIX Association for public distribution. 
  17.  *
  18.  * Copyright (c) 1989 Mark H. Colburn.
  19.  * All rights reserved.
  20.  *
  21.  * Redistribution and use in source and binary forms are permitted
  22.  * provided that the above copyright notice is duplicated in all such 
  23.  * forms and that any documentation, advertising materials, and other 
  24.  * materials related to such distribution and use acknowledge that the 
  25.  * software was developed * by Mark H. Colburn and sponsored by The 
  26.  * USENIX Association. 
  27.  *
  28.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  29.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  30.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  31.  *
  32.  * $Log:    link.c,v $
  33.  * Revision 1.1  88/12/23  18:02:12  mark
  34.  * Initial revision
  35.  * 
  36.  */
  37.  
  38. #ifndef lint
  39. static char *ident = "$Id: link.c,v 1.1 88/12/23 18:02:12 mark Rel $";
  40. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  41. #endif /* ! lint */
  42.  
  43.  
  44. /* Headers */
  45.  
  46. #include "pax.h"
  47.  
  48.  
  49. /* Defines */
  50.  
  51. /*
  52.  * Address link information base. 
  53.  */
  54. #define    LINKHASH(ino)    (linkbase + (ino) % NEL(linkbase))
  55.  
  56. /*
  57.  * Number of array elements. 
  58.  */
  59. #define    NEL(a)        (sizeof(a) / sizeof(*(a)))
  60.  
  61.  
  62.  
  63. /* Internal Identifiers */
  64.  
  65. static Link    *linkbase[256];    /* Unresolved link information */
  66.  
  67.  
  68. /* linkfrom - find a file to link from 
  69.  *
  70.  * DESCRIPTION
  71.  *
  72.  *    Linkfrom searches the link chain to see if there is a file in the
  73.  *    link chain which has the same inode number as the file specified
  74.  *    by the stat block pointed at by asb.  If a file is found, the
  75.  *    name is returned to the caller, otherwise a NULL is returned.
  76.  *
  77.  * PARAMETERS
  78.  *
  79.  *    char    *name   - name of the file which we are attempting
  80.  *                        to find a link for
  81.  *    Stat    *asb    - stat structure of file to find a link to
  82.  *
  83.  * RETURNS
  84.  *
  85.  *     Returns a pointer to a link structure, or NULL if unsuccessful. 
  86.  *
  87.  */
  88.  
  89. #ifdef __STDC__
  90.  
  91. Link *linkfrom(char *name, Stat *asb)
  92.  
  93. #else
  94.     
  95. Link *linkfrom(name, asb)
  96. char           *name;
  97. Stat           *asb;
  98.  
  99. #endif
  100. {
  101.     Link           *linkp;
  102.     Link           *linknext;
  103.     Path           *path;
  104.     Path           *pathnext;
  105.     Link          **abase;
  106.  
  107.     for (linkp = *(abase = LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
  108.     if (linkp->l_nlink == 0) {
  109.         if (linkp->l_name) {
  110.         free((char *) linkp->l_name);
  111.         }
  112.         if (linknext = linkp->l_forw) {
  113.         linknext->l_back = linkp->l_back;
  114.         }
  115.         if (linkp->l_back) {
  116.         linkp->l_back->l_forw = linkp->l_forw;
  117.         }
  118.         free((char *) linkp);
  119.         *abase = (Link *) NULL;
  120.     } else if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  121.         /* 
  122.          * check to see if a file with the name "name" exists in the 
  123.          * chain of files which we have for this particular link
  124.          */
  125.         for (path = linkp->l_path; path; path = pathnext) {
  126.         if (strcmp(path->p_name, name) == 0) {
  127.             --linkp->l_nlink;
  128.             if (path->p_name) {
  129.             free(path->p_name);
  130.             }
  131.             if (pathnext = path->p_forw) {
  132.             pathnext->p_back = path->p_back;
  133.             }
  134.             if (path->p_back) {
  135.             path->p_back->p_forw = pathnext;
  136.             }
  137.             if (linkp->l_path == path) {
  138.             linkp->l_path = pathnext;
  139.             }
  140.             free(path);
  141.             return (linkp);
  142.         }
  143.         pathnext = path->p_forw;
  144.         }
  145.         return((Link *)NULL);
  146.     } else {
  147.         linknext = linkp->l_forw;
  148.     }
  149.     }
  150.     return ((Link *)NULL);
  151. }
  152.  
  153.  
  154.  
  155. /* islink - determine whether a given file really a link
  156.  *
  157.  * DESCRIPTION
  158.  *
  159.  *    Islink searches the link chain to see if there is a file in the
  160.  *    link chain which has the same inode number as the file specified
  161.  *    by the stat block pointed at by asb.  If a file is found, a
  162.  *    non-zero value is returned to the caller, otherwise a 0 is
  163.  *    returned.
  164.  *
  165.  * PARAMETERS
  166.  *
  167.  *    char    *name   - name of file to check to see if it is link.
  168.  *    Stat    *asb    - stat structure of file to find a link to
  169.  *
  170.  * RETURNS
  171.  *
  172.  *     Returns a pointer to a link structure, or NULL if unsuccessful. 
  173.  *
  174.  */
  175.  
  176. #ifdef __STDC__
  177.  
  178. Link *islink(char *name, Stat *asb)
  179.  
  180. #else
  181.     
  182. Link *islink(name, asb)
  183. char           *name;
  184. Stat           *asb;
  185.  
  186. #endif
  187. {
  188.     Link           *linkp;
  189.     Link           *linknext;
  190.  
  191.     for (linkp = *(LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
  192.     if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  193.         if (strcmp(name, linkp->l_name) == 0) {
  194.         return ((Link *) NULL);
  195.         } 
  196.         return (linkp);
  197.     } else {
  198.         linknext = linkp->l_forw;
  199.     }
  200.     }
  201.     return ((Link *)NULL);
  202. }
  203.  
  204.  
  205. /* linkto  - remember a file with outstanding links 
  206.  *
  207.  * DESCRIPTION
  208.  *
  209.  *    Linkto adds the specified file to the link chain.  Any subsequent
  210.  *    calls to linkfrom which have the same inode will match the file
  211.  *    just entered.  If not enough space is available to make the link
  212.  *    then the item is not added to the link chain, and a NULL is
  213.  *    returned to the calling function.
  214.  *
  215.  * PARAMETERS
  216.  *
  217.  *    char    *name    - name of file to remember
  218.  *    Stat    *asb    - pointer to stat structure of file to remember
  219.  *
  220.  * RETURNS
  221.  *
  222.  *     Returns a pointer to the associated link structure, or NULL when 
  223.  *    linking is not possible. 
  224.  *
  225.  */
  226.  
  227. #ifdef __STDC__
  228.  
  229. Link *linkto(char *name, Stat *asb)
  230.  
  231. #else
  232.     
  233. Link *linkto(name, asb)
  234. char           *name;
  235. Stat           *asb;
  236.  
  237. #endif
  238. {
  239.     Link           *linkp;
  240.     Link           *linknext;
  241.     Path           *path;
  242.     Link          **abase;
  243.  
  244.     for (linkp = *(LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
  245.     if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
  246.         if ((path = (Path *) mem_get(sizeof(Path))) == (Path *) NULL || 
  247.         (path->p_name = mem_str(name)) == (char *) NULL) {
  248.         return((Link *) NULL);
  249.         }
  250.         if (path->p_forw = linkp->l_path) {
  251.         if (linkp->l_path->p_forw) {
  252.             linkp->l_path->p_forw->p_back = path;
  253.         }
  254.         } else {
  255.         linkp->l_path = path;
  256.         }
  257.         path->p_back = (Path *) NULL;
  258.         return(linkp);
  259.     } else {
  260.         linknext = linkp->l_forw;
  261.     }
  262.     }
  263.     /*
  264.      * This is a brand new link, for which there is no other information
  265.      */
  266.  
  267.     if ((asb->sb_mode & S_IFMT) == S_IFDIR
  268.     || (linkp = (Link *) mem_get(sizeof(Link))) == NULL
  269.     || (linkp->l_name = mem_str(name)) == NULL) {
  270.     return ((Link *) NULL);
  271.     }
  272.     linkp->l_dev = asb->sb_dev;
  273.     linkp->l_ino = asb->sb_ino;
  274.     linkp->l_nlink = asb->sb_nlink - 1;
  275.     linkp->l_size = asb->sb_size;
  276.     linkp->l_path = (Path *) NULL;
  277.     if (linkp->l_forw = *(abase = LINKHASH(asb->sb_ino))) {
  278.     linkp->l_forw->l_back = linkp;
  279.     } else {
  280.     *abase = linkp;
  281.     }
  282.     linkp->l_back = NULL;
  283.     return (linkp);
  284. }
  285.  
  286.  
  287. /* linkleft - complain about files with unseen links 
  288.  *
  289.  * DESCRIPTION
  290.  *
  291.  *    Linksleft scans through the link chain to see if there were any
  292.  *    files which have outstanding links that were not processed by the
  293.  *    archive.  For each file in the link chain for which there was not
  294.  *    a file,  and error message is printed.
  295.  */
  296.  
  297. #ifdef __STDC__
  298.  
  299. void linkleft(void)
  300.  
  301. #else
  302.     
  303. void linkleft()
  304.  
  305. #endif
  306. {
  307.     Link           *lp;
  308.     Link          **base;
  309.  
  310.     for (base = linkbase; base < linkbase + NEL(linkbase); ++base) {
  311.     for (lp = *base; lp; lp = lp->l_forw) {
  312.         if (lp->l_nlink) {
  313.         warn(lp->l_path->p_name, "Unseen link(s)");
  314.         }
  315.     }
  316.     }
  317. }
  318.