home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 May / W2KPRK.iso / apps / posix / source / PAX / LINK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-17  |  9.2 KB  |  359 lines

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