home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / PAX20.ZIP / LINK.C < prev    next >
C/C++ Source or Header  |  1990-11-12  |  9KB  |  342 lines

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