1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License ("CDDL"), version 1.0.
6  * You may use this file only in accordance with the terms of version
7  * 1.0 of the CDDL.
8  *
9  * A full copy of the text of the CDDL should have accompanied this
10  * source.  A copy of the CDDL is also available via the Internet at
11  * http://www.opensource.org/licenses/cddl1.txt
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  *
15  * When distributing Covered Code, include this CDDL HEADER in each
16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17  * If applicable, add the following below this CDDL HEADER, with the
18  * fields enclosed by brackets "[]" replaced with your own identifying
19  * information: Portions Copyright [yyyy] [name of copyright owner]
20  *
21  * CDDL HEADER END
22  */
23 /* Copyright (c) 1988 AT&T */
24 /* All Rights Reserved */
25 /*
26  * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
27  * Use is subject to license terms.
28  */
29 /*
30  * Copyright 2006-2019 J. Schilling
31  *
32  * @(#)dodelt.c	1.27 19/11/08 J. Schilling
33  */
34 #if defined(sun)
35 #pragma ident "@(#)dodelt.c 1.27 19/11/08 J. Schilling"
36 #endif
37 /*
38  * @(#)dodelt.c 1.8 06/12/12
39  */
40 
41 #if defined(sun)
42 #pragma ident	"@(#)dodelt.c"
43 #pragma ident	"@(#)sccs:lib/comobj/dodelt.c"
44 #endif
45 #include	<defines.h>
46 #include	<had.h>
47 
48 # define ONEYEAR 31536000L
49 
50 static char	getadel	__PR((struct packet *,struct deltab *));
51 static void	doixg	__PR((char *,struct ixg **));
52 
53 dtime_t	Timenow;
54 
55 struct idel *
dodelt(pkt,statp,sidp,type)56 dodelt(pkt,statp,sidp,type)
57 register struct packet *pkt;
58 struct stats *statp;
59 struct sid *sidp;
60 char type;
61 {
62 	char *c = NULL;
63 	struct deltab dt;
64 	register struct idel *rdp = NULL;
65 	int n, founddel;
66 	int	lhash;
67 	register char *p;
68 	time_t	TN;
69 	int	Tns;
70 
71 	pkt->p_idel = 0;
72 	founddel = 0;
73 
74 	dtime(&Timenow);
75 	TN = Timenow.dt_sec;
76 	Tns = Timenow.dt_nsec;
77 #if defined(BUG_1205145) || defined(GMT_TIME)
78 	TN += Timenow.dt_zone;
79 #else
80 	if (pkt->p_flags & PF_GMT)
81 		TN += Timenow.dt_zone;
82 #endif
83 	stats_ab(pkt,statp);
84 	lhash = pkt->p_clhash;
85 	while (getadel(pkt,&dt) == BDELTAB) {
86 		if (pkt->p_idel == 0) {
87 			if ((TN < dt.d_dtime.dt_sec) ||
88 			    ((TN == dt.d_dtime.dt_sec) &&
89 			    (Tns < dt.d_dtime.dt_nsec))) {
90 				fprintf(stderr,
91 				    gettext(
92 			"Time stamp later than current clock time (co10)\n"));
93 			}
94 			pkt->p_idel = (struct idel *)
95 					fmalloc((unsigned) (n=((dt.d_serial+1)*
96 					sizeof (*pkt->p_idel))));
97 			zero((char *) pkt->p_idel,n);
98 			pkt->p_apply = (struct apply *)
99 					fmalloc((unsigned) (n=((dt.d_serial+1)*
100 					sizeof (*pkt->p_apply))));
101 			zero((char *) pkt->p_apply,n);
102 			if (pkt->p_pgmrs != NULL) {
103 				pkt->p_pgmrs = (char **)
104 					fmalloc((unsigned) (n=((dt.d_serial+1)*
105 					sizeof (char *))));
106 				zero((char *) pkt->p_pgmrs, n);
107 			}
108 			pkt->p_idel->i_pred = dt.d_serial;
109 		}
110 		if (dt.d_type == 'D' ||				/* Delta */
111 		    dt.d_type == 'U') {				/* Unlink */
112 			/*
113 			 * sidp is != NULL only for rmchg
114 			 */
115 			if (sidp && eqsid(&dt.d_sid,sidp)) {
116 				copy(dt.d_pgmr, pkt->p_pgmr);	/* for rmchg */
117 				zero((char *) sidp,sizeof (*sidp));
118 				founddel = 1;
119 				pkt->p_first_esc = 1;
120 				pkt->p_first_cmt = 1;
121 				pkt->p_cdid_mrs = 0;
122 				for (p = pkt->p_line;
123 				    *p && *p != dt.d_type; p++) {
124 					;
125 				}
126 				if (*p) {
127 					/*
128 					 * Also correct saved line hash, used
129 					 * for putline() optimization.
130 					 */
131 					pkt->p_clhash -= dt.d_type;   /* D/U */
132 					pkt->p_uclhash -= dt.d_type;  /* D/U */
133 					pkt->p_clhash += type;
134 					pkt->p_uclhash += type;
135 					*p = type;
136 				}
137 				if (type == 0) {
138 					/*
139 					 * Go back before last stats line. The
140 					 * value 21 is the lenght of any stats
141 					 * line. Never change this length.
142 					 */
143 					pkt->p_nhash -= lhash;
144 					fseek(pkt->p_xiop, (off_t)-21, SEEK_CUR);
145 					/*
146 					 * Skip this delta table entry.
147 					 */
148 					pkt->p_wrttn = 1;
149 					while ((c = getline(pkt)) != NULL) {
150 						pkt->p_wrttn = 1;
151 						if (pkt->p_line[0] != CTLCHAR)
152 							break;
153 						if (pkt->p_line[1] == EDELTAB)
154 							break;
155 					}
156 				}
157 			}
158 			else
159 				pkt->p_first_esc = pkt->p_first_cmt = founddel = 0;
160 			pkt->p_maxr = max(pkt->p_maxr,dt.d_sid.s_rel);
161 			if (pkt->p_pgmrs != NULL) {
162 				pkt->p_pgmrs[dt.d_serial] =
163 						lhash_lookup(dt.d_pgmr);
164 			}
165 			rdp = &pkt->p_idel[dt.d_serial];
166 			rdp->i_sid.s_rel = dt.d_sid.s_rel;
167 			rdp->i_sid.s_lev = dt.d_sid.s_lev;
168 			rdp->i_sid.s_br = dt.d_sid.s_br;
169 			rdp->i_sid.s_seq = dt.d_sid.s_seq;
170 			rdp->i_pred = dt.d_pred;
171 			rdp->i_dtype = dt.d_type;
172 			rdp->i_datetime.tv_sec = dt.d_dtime.dt_sec;
173 			rdp->i_datetime.tv_nsec = dt.d_dtime.dt_nsec;
174 			if (founddel && type == 0)	/* Already skipped */
175 				goto nextdelta;
176 		}
177 		while ((c = getline(pkt)) != NULL)
178 			if (pkt->p_line[0] != CTLCHAR)
179 				break;
180 			else {
181 				switch (pkt->p_line[1]) {
182 				case EDELTAB:
183 					break;
184 				case COMMENTS:
185 					if (pkt->p_line[2] == '_')
186 						sidext_v4compat_ab(pkt, &dt);
187 					/* FALLTHRU */
188 				case MRNUM:
189 					if (founddel)
190 					{
191 						(*pkt->p_escdodelt)(pkt);
192 						if (type == 'R' && HADZ && pkt->p_line[1] == MRNUM) {
193 							(*pkt->p_fredck)(pkt);
194 						}
195 					}
196 				continue;
197 
198 				case SIDEXTENS:
199 					if (pkt->p_flags & PF_V6) {
200 						sidext_ab(pkt, &dt, &pkt->p_line[2]);
201 						continue;
202 					}
203 					/* FALLTHRU */
204 				default:
205 					fmterr(pkt);
206 				/*FALLTHRU*/
207 				case INCLUDE:
208 				case EXCLUDE:
209 				case IGNORE:
210 					/*
211 					 * Is this really needed for type 'U' as well?
212 					 */
213 					if (dt.d_type == 'D' ||
214 					    dt.d_type == 'U') {
215 						doixg(pkt->p_line,&rdp->i_ixg);
216 					}
217 					continue;
218 				}
219 				break;
220 			}
221 	nextdelta:
222 		if (c == NULL || pkt->p_line[0] != CTLCHAR || getline(pkt) == NULL)
223 			fmterr(pkt);
224 		if (pkt->p_line[0] != CTLCHAR || pkt->p_line[1] != STATS)
225 			break;
226 		lhash = pkt->p_clhash;
227 	}
228 	return (pkt->p_idel);
229 }
230 
231 static char
getadel(pkt,dt)232 getadel(pkt,dt)
233 register struct packet *pkt;
234 register struct deltab *dt;
235 {
236 	if (getline(pkt) == NULL)
237 		fmterr(pkt);
238 	return (del_ab(pkt->p_line,dt, pkt));
239 }
240 
241 static void
doixg(p,ixgp)242 doixg(p,ixgp)
243 char *p;
244 struct ixg **ixgp;
245 {
246 	int *v, *ip;
247 	int type, cnt, i;
248 	struct ixg *curp, *prevp;
249 	int xtmp[MAXLINE];
250 
251 	v = ip = xtmp;
252 	++p;
253 	type = *p++;
254 	NONBLANK(p);
255 	while (numeric(*p)) {
256 		if ((ip - v) >= MAXLINE)
257 			fatal(gettext("too many include exclude or ignore entries (co30)"));
258 		p = satoi(p,ip++);
259 		NONBLANK(p);
260 	}
261 	cnt = ip - v;
262 	for (prevp = curp = (*ixgp); curp; curp = (prevp = curp)->i_next)
263 		;
264 	curp = (struct ixg *) fmalloc((unsigned)
265 		(sizeof (struct ixg) + (cnt-1)*sizeof (curp->i_ser[0])));
266 	if (*ixgp == 0)
267 		*ixgp = curp;
268 	else
269 		prevp->i_next = curp;
270 	curp->i_next = 0;
271 	curp->i_type = (char) type;
272 	curp->i_cnt = (char) cnt;
273 	for (i=0; cnt>0; --cnt)
274 		curp->i_ser[i++] = *v++;
275 }
276