Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
    for (linkp = *(abase = LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
111
	if (linkp->l_nlink == 0) {
112
	    if (linkp->l_name) {
113
		free((char *) linkp->l_name);
114
	    }
115
	    if (linknext = linkp->l_forw) {
116
		linknext->l_back = linkp->l_back;
117
	    }
118
	    if (linkp->l_back) {
119
		linkp->l_back->l_forw = linkp->l_forw;
120
	    }
121
	    free((char *) linkp);
122
	    *abase = (Link *)NULL;
123
	} else if (linkp->l_ino == asb->sb_ino && 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
		    if (path->p_name) {
132
			free(path->p_name);
133
		    }
134
		    if (pathnext = path->p_forw) {
135
			pathnext->p_back = path->p_back;
136
		    }
137
		    if (path->p_back) {
138
			path->p_back->p_forw = pathnext;
139
		    }
140
		    if (linkp->l_path == path) {
141
			linkp->l_path = pathnext;
142
		    }
143
		    free(path);
144
		    return (linkp);
145
		}
146
		pathnext = path->p_forw;
147
	    }
148
	    return((Link *)NULL);
149
	} else {
150
	    linknext = linkp->l_forw;
151
	}
152
    }
153
    return ((Link *)NULL);
154
}
155
 
156
 
157
 
158
/* islink - determine whether a given file really a link
159
 *
160
 * DESCRIPTION
161
 *
162
 *	Islink searches the link chain to see if there is a file in the
163
 *	link chain which has the same inode number as the file specified
164
 *	by the stat block pointed at by asb.  If a file is found, a
165
 *	non-zero value is returned to the caller, otherwise a 0 is
166
 *	returned.
167
 *
168
 * PARAMETERS
169
 *
170
 *	char    *name   - name of file to check to see if it is link.
171
 *	Stat	*asb	- stat structure of file to find a link to
172
 *
173
 * RETURNS
174
 *
175
 * 	Returns a pointer to a link structure, or NULL if unsuccessful. 
176
 *
177
 */
178
 
179
#ifdef __STDC__
180
 
181
Link *islink(char *name, Stat *asb)
182
 
183
#else
184
 
185
Link *islink(name, asb)
186
char           *name;
187
Stat           *asb;
188
 
189
#endif
190
{
191
    Link           *linkp;
192
    Link           *linknext;
193
 
194
    for (linkp = *(LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
195
	if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
196
	    if (strcmp(name, linkp->l_name) == 0) {
197
		return ((Link *)NULL);
198
	    } 
199
	    return (linkp);
200
	} else {
201
	    linknext = linkp->l_forw;
202
	}
203
    }
204
    return ((Link *)NULL);
205
}
206
 
207
 
208
/* linkto  - remember a file with outstanding links 
209
 *
210
 * DESCRIPTION
211
 *
212
 *	Linkto adds the specified file to the link chain.  Any subsequent
213
 *	calls to linkfrom which have the same inode will match the file
214
 *	just entered.  If not enough space is available to make the link
215
 *	then the item is not added to the link chain, and a NULL is
216
 *	returned to the calling function.
217
 *
218
 * PARAMETERS
219
 *
220
 *	char	*name	- name of file to remember
221
 *	Stat	*asb	- pointer to stat structure of file to remember
222
 *
223
 * RETURNS
224
 *
225
 * 	Returns a pointer to the associated link structure, or NULL when 
226
 *	linking is not possible. 
227
 *
228
 */
229
 
230
#ifdef __STDC__
231
 
232
Link *linkto(char *name, Stat *asb)
233
 
234
#else
235
 
236
Link *linkto(name, asb)
237
char           *name;
238
Stat           *asb;
239
 
240
#endif
241
{
242
    Link           *linkp;
243
    Link           *linknext;
244
    Path           *path;
245
    Link          **abase;
246
 
247
    for (linkp = *(LINKHASH(asb->sb_ino)); linkp; linkp = linknext) {
248
	if (linkp->l_ino == asb->sb_ino && linkp->l_dev == asb->sb_dev) {
249
	    if ((path = (Path *) mem_get(sizeof(Path))) == (Path *)NULL || 
250
		(path->p_name = mem_str(name)) == (char *)NULL) {
251
		return((Link *)NULL);
252
	    }
253
	    if (path->p_forw = linkp->l_path) {
254
		if (linkp->l_path->p_forw) {
255
		    linkp->l_path->p_forw->p_back = path;
256
		}
257
	    } else {
258
		linkp->l_path = path;
259
	    }
260
	    path->p_back = (Path *)NULL;
261
	    return(linkp);
262
	} else {
263
	    linknext = linkp->l_forw;
264
	}
265
    }
266
    /*
267
     * This is a brand new link, for which there is no other information
268
     */
269
 
270
    if ((asb->sb_mode & S_IFMT) == S_IFDIR
271
	|| (linkp = (Link *) mem_get(sizeof(Link))) == (Link *)NULL
272
	|| (linkp->l_name = mem_str(name)) == (char *)NULL) {
273
	return ((Link *)NULL);
274
    }
275
    linkp->l_dev = asb->sb_dev;
276
    linkp->l_ino = asb->sb_ino;
277
    linkp->l_nlink = asb->sb_nlink - 1;
278
    linkp->l_size = asb->sb_size;
279
    linkp->l_path = (Path *)NULL;
280
    if (linkp->l_forw = *(abase = LINKHASH(asb->sb_ino))) {
281
	linkp->l_forw->l_back = linkp;
282
    } else {
283
	*abase = linkp;
284
    }
285
    linkp->l_back = (Link *)NULL;
286
    return (linkp);
287
}
288
 
289
 
290
/* linkleft - complain about files with unseen links 
291
 *
292
 * DESCRIPTION
293
 *
294
 *	Linksleft scans through the link chain to see if there were any
295
 *	files which have outstanding links that were not processed by the
296
 *	archive.  For each file in the link chain for which there was not
297
 *	a file,  and error message is printed.
298
 */
299
 
300
#ifdef __STDC__
301
 
302
void linkleft(void)
303
 
304
#else
305
 
306
void linkleft()
307
 
308
#endif
309
{
310
    Link           *lp;
311
    Link          **base;
312
 
313
    for (base = linkbase; base < linkbase + NEL(linkbase); ++base) {
314
	for (lp = *base; lp; lp = lp->l_forw) {
315
	    if (lp->l_nlink) {
316
		warn(lp->l_path->p_name, "Unseen link(s)");
317
	    }
318
	}
319
    }
320
}