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