|
|
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.