xref: /dragonfly/sbin/jscan/dump_mirror.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3*86d7f5d3SJohn Marino  *
4*86d7f5d3SJohn Marino  * This code is derived from software contributed to The DragonFly Project
5*86d7f5d3SJohn Marino  * by Matthew Dillon <dillon@backplane.com>
6*86d7f5d3SJohn Marino  *
7*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
8*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
9*86d7f5d3SJohn Marino  * are met:
10*86d7f5d3SJohn Marino  *
11*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
12*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
13*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
14*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in
15*86d7f5d3SJohn Marino  *    the documentation and/or other materials provided with the
16*86d7f5d3SJohn Marino  *    distribution.
17*86d7f5d3SJohn Marino  * 3. Neither the name of The DragonFly Project nor the names of its
18*86d7f5d3SJohn Marino  *    contributors may be used to endorse or promote products derived
19*86d7f5d3SJohn Marino  *    from this software without specific, prior written permission.
20*86d7f5d3SJohn Marino  *
21*86d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*86d7f5d3SJohn Marino  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*86d7f5d3SJohn Marino  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*86d7f5d3SJohn Marino  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25*86d7f5d3SJohn Marino  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*86d7f5d3SJohn Marino  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*86d7f5d3SJohn Marino  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*86d7f5d3SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*86d7f5d3SJohn Marino  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*86d7f5d3SJohn Marino  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*86d7f5d3SJohn Marino  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*86d7f5d3SJohn Marino  * SUCH DAMAGE.
33*86d7f5d3SJohn Marino  *
34*86d7f5d3SJohn Marino  * $DragonFly: src/sbin/jscan/dump_mirror.c,v 1.8 2005/11/06 12:32:56 swildner Exp $
35*86d7f5d3SJohn Marino  */
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino #include "jscan.h"
38*86d7f5d3SJohn Marino #include <sys/vfscache.h>
39*86d7f5d3SJohn Marino 
40*86d7f5d3SJohn Marino static void dump_mirror_stream(struct jsession *ss, struct jstream *js);
41*86d7f5d3SJohn Marino static int dump_mirror_toprecord(struct jsession *ss, struct jstream *js,
42*86d7f5d3SJohn Marino 				 off_t *off, off_t recsize, int level);
43*86d7f5d3SJohn Marino static int dump_mirror_subrecord(enum jdirection direction, struct jstream *js,
44*86d7f5d3SJohn Marino 				 off_t *off, off_t recsize, int level,
45*86d7f5d3SJohn Marino 				 struct jattr *jattr);
46*86d7f5d3SJohn Marino static int dump_mirror_payload(int16_t rectype, struct jstream *js, off_t off,
47*86d7f5d3SJohn Marino 				 int recsize, int level, struct jattr *jattr);
48*86d7f5d3SJohn Marino static int dump_mirror_rebuild_redo(u_int16_t rectype,
49*86d7f5d3SJohn Marino 				    struct jstream *js, struct jattr *jattr);
50*86d7f5d3SJohn Marino static int dump_mirror_rebuild_undo(u_int16_t rectype,
51*86d7f5d3SJohn Marino 				    struct jstream *js, struct jattr *jattr);
52*86d7f5d3SJohn Marino static void undo_recreate(const char *filename,
53*86d7f5d3SJohn Marino 				    struct jstream *js, struct jattr *jattr);
54*86d7f5d3SJohn Marino static void dosetattr(const char *filename, int fd, struct jattr *jattr);
55*86d7f5d3SJohn Marino 
56*86d7f5d3SJohn Marino void
dump_mirror(struct jsession * ss,struct jdata * jd)57*86d7f5d3SJohn Marino dump_mirror(struct jsession *ss, struct jdata *jd)
58*86d7f5d3SJohn Marino {
59*86d7f5d3SJohn Marino     struct jstream *js;
60*86d7f5d3SJohn Marino 
61*86d7f5d3SJohn Marino     if ((js = jaddrecord(ss, jd)) != NULL) {
62*86d7f5d3SJohn Marino 	dump_mirror_stream(ss, js);
63*86d7f5d3SJohn Marino 	jscan_dispose(js);
64*86d7f5d3SJohn Marino     }
65*86d7f5d3SJohn Marino     jsession_update_transid(ss, jd->jd_transid);
66*86d7f5d3SJohn Marino }
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino static void
dump_mirror_stream(struct jsession * ss,struct jstream * js)69*86d7f5d3SJohn Marino dump_mirror_stream(struct jsession *ss, struct jstream *js)
70*86d7f5d3SJohn Marino {
71*86d7f5d3SJohn Marino 	struct journal_rawrecbeg head;
72*86d7f5d3SJohn Marino 	int16_t sid;
73*86d7f5d3SJohn Marino 	mode_t save_umask;
74*86d7f5d3SJohn Marino 
75*86d7f5d3SJohn Marino 	save_umask = umask(0);
76*86d7f5d3SJohn Marino 	jsread(js, 0, &head, sizeof(head));
77*86d7f5d3SJohn Marino 
78*86d7f5d3SJohn Marino 	sid = head.streamid & JREC_STREAMID_MASK;
79*86d7f5d3SJohn Marino 	if (sid >= JREC_STREAMID_JMIN && sid < JREC_STREAMID_JMAX) {
80*86d7f5d3SJohn Marino 	    off_t off = sizeof(head);
81*86d7f5d3SJohn Marino 	    dump_mirror_toprecord(ss, js, &off,
82*86d7f5d3SJohn Marino 				  js->js_normalized_total -
83*86d7f5d3SJohn Marino 				      sizeof(struct journal_rawrecbeg),
84*86d7f5d3SJohn Marino 				  1);
85*86d7f5d3SJohn Marino 	} else {
86*86d7f5d3SJohn Marino 	    switch(head.streamid & JREC_STREAMID_MASK) {
87*86d7f5d3SJohn Marino 	    case JREC_STREAMID_SYNCPT & JREC_STREAMID_MASK:
88*86d7f5d3SJohn Marino 		break;
89*86d7f5d3SJohn Marino 	    case JREC_STREAMID_PAD & JREC_STREAMID_MASK:
90*86d7f5d3SJohn Marino 		break;
91*86d7f5d3SJohn Marino 	    case JREC_STREAMID_DISCONT & JREC_STREAMID_MASK:
92*86d7f5d3SJohn Marino 		break;
93*86d7f5d3SJohn Marino 	    case JREC_STREAMID_ANNOTATE & JREC_STREAMID_MASK:
94*86d7f5d3SJohn Marino 		break;
95*86d7f5d3SJohn Marino 	    default:
96*86d7f5d3SJohn Marino 		break;
97*86d7f5d3SJohn Marino 	    }
98*86d7f5d3SJohn Marino 	}
99*86d7f5d3SJohn Marino 	umask(save_umask);
100*86d7f5d3SJohn Marino }
101*86d7f5d3SJohn Marino 
102*86d7f5d3SJohn Marino /*
103*86d7f5d3SJohn Marino  * Execute a meta-transaction, e.g. something like 'WRITE'.  Meta-transactions
104*86d7f5d3SJohn Marino  * are almost universally nested.
105*86d7f5d3SJohn Marino  */
106*86d7f5d3SJohn Marino static int
dump_mirror_toprecord(struct jsession * ss,struct jstream * js,off_t * off,off_t recsize,int level)107*86d7f5d3SJohn Marino dump_mirror_toprecord(struct jsession *ss, struct jstream *js,
108*86d7f5d3SJohn Marino 		      off_t *off, off_t recsize, int level)
109*86d7f5d3SJohn Marino {
110*86d7f5d3SJohn Marino     struct journal_subrecord sub;
111*86d7f5d3SJohn Marino     struct jattr jattr;
112*86d7f5d3SJohn Marino     int payload;
113*86d7f5d3SJohn Marino     int subsize;
114*86d7f5d3SJohn Marino     int error;
115*86d7f5d3SJohn Marino     off_t base = *off;
116*86d7f5d3SJohn Marino 
117*86d7f5d3SJohn Marino     error = 0;
118*86d7f5d3SJohn Marino     bzero(&jattr, sizeof(jattr));
119*86d7f5d3SJohn Marino     jattr_reset(&jattr);
120*86d7f5d3SJohn Marino 
121*86d7f5d3SJohn Marino     while (recsize > 0) {
122*86d7f5d3SJohn Marino 	if ((error = jsread(js, base, &sub, sizeof(sub))) != 0)
123*86d7f5d3SJohn Marino 	    break;
124*86d7f5d3SJohn Marino 	if (sub.recsize == -1) {
125*86d7f5d3SJohn Marino 	    if ((sub.rectype & JMASK_NESTED) == 0) {
126*86d7f5d3SJohn Marino 		printf("Record size of -1 only works for nested records\n");
127*86d7f5d3SJohn Marino 		error = -1;
128*86d7f5d3SJohn Marino 		break;
129*86d7f5d3SJohn Marino 	    }
130*86d7f5d3SJohn Marino 	    payload = 0x7FFFFFFF;
131*86d7f5d3SJohn Marino 	    subsize = 0x7FFFFFFF;
132*86d7f5d3SJohn Marino 	} else {
133*86d7f5d3SJohn Marino 	    payload = sub.recsize - sizeof(sub);
134*86d7f5d3SJohn Marino 	    subsize = (sub.recsize + 7) & ~7;
135*86d7f5d3SJohn Marino 	}
136*86d7f5d3SJohn Marino 	if (sub.rectype & JMASK_NESTED) {
137*86d7f5d3SJohn Marino 	    *off = base + sizeof(sub);
138*86d7f5d3SJohn Marino 	    error = dump_mirror_subrecord(ss->ss_direction, js, off,
139*86d7f5d3SJohn Marino 					  payload, level + 1, &jattr);
140*86d7f5d3SJohn Marino 	} else if (sub.rectype & JMASK_SUBRECORD) {
141*86d7f5d3SJohn Marino 	    *off = base + sizeof(sub) + payload;
142*86d7f5d3SJohn Marino 	} else if ((sub.rectype & JTYPE_MASK) == JLEAF_PAD) {
143*86d7f5d3SJohn Marino 	} else {
144*86d7f5d3SJohn Marino 	}
145*86d7f5d3SJohn Marino 	if (ss->ss_direction == JD_FORWARDS)
146*86d7f5d3SJohn Marino 	    dump_mirror_rebuild_redo(sub.rectype, js, &jattr);
147*86d7f5d3SJohn Marino 	else
148*86d7f5d3SJohn Marino 	    dump_mirror_rebuild_undo(sub.rectype, js, &jattr);
149*86d7f5d3SJohn Marino 	jattr_reset(&jattr);
150*86d7f5d3SJohn Marino 	if (error)
151*86d7f5d3SJohn Marino 	    break;
152*86d7f5d3SJohn Marino 	if (sub.recsize == -1) {
153*86d7f5d3SJohn Marino 	    if ((sub.rectype & JMASK_NESTED) == 0) {
154*86d7f5d3SJohn Marino 		printf("Record size of -1 only works for nested records\n");
155*86d7f5d3SJohn Marino 		error = -1;
156*86d7f5d3SJohn Marino 		break;
157*86d7f5d3SJohn Marino 	    }
158*86d7f5d3SJohn Marino 	    recsize -= ((*off + 7) & ~7) - base;
159*86d7f5d3SJohn Marino 	    base = (*off + 7) & ~7;
160*86d7f5d3SJohn Marino 	} else {
161*86d7f5d3SJohn Marino 	    if (subsize == 0)
162*86d7f5d3SJohn Marino 		subsize = sizeof(sub);
163*86d7f5d3SJohn Marino 	    recsize -= subsize;
164*86d7f5d3SJohn Marino 	    base += subsize;
165*86d7f5d3SJohn Marino 	}
166*86d7f5d3SJohn Marino 	if (sub.rectype & JMASK_LAST)
167*86d7f5d3SJohn Marino 	    break;
168*86d7f5d3SJohn Marino     }
169*86d7f5d3SJohn Marino     *off = base;
170*86d7f5d3SJohn Marino     return(error);
171*86d7f5d3SJohn Marino }
172*86d7f5d3SJohn Marino 
173*86d7f5d3SJohn Marino /*
174*86d7f5d3SJohn Marino  * Parse a meta-transaction's nested records.  The highest subrecord layer
175*86d7f5d3SJohn Marino  * starts at layer = 2 (the top layer specifying the command is layer = 1).
176*86d7f5d3SJohn Marino  *
177*86d7f5d3SJohn Marino  * The nested subrecord contains informational records containing primarily
178*86d7f5d3SJohn Marino  * namespace data, and further subrecords containing nested
179*86d7f5d3SJohn Marino  * audit, undo, and redo data.
180*86d7f5d3SJohn Marino  */
181*86d7f5d3SJohn Marino static int
dump_mirror_subrecord(enum jdirection direction,struct jstream * js,off_t * off,off_t recsize,int level,struct jattr * jattr)182*86d7f5d3SJohn Marino dump_mirror_subrecord(enum jdirection direction, struct jstream *js,
183*86d7f5d3SJohn Marino 		      off_t *off, off_t recsize, int level,
184*86d7f5d3SJohn Marino 		      struct jattr *jattr)
185*86d7f5d3SJohn Marino {
186*86d7f5d3SJohn Marino     struct journal_subrecord sub;
187*86d7f5d3SJohn Marino     int payload;
188*86d7f5d3SJohn Marino     int subsize;
189*86d7f5d3SJohn Marino     int error;
190*86d7f5d3SJohn Marino     int skip;
191*86d7f5d3SJohn Marino     u_int16_t rectype;
192*86d7f5d3SJohn Marino     off_t base = *off;
193*86d7f5d3SJohn Marino 
194*86d7f5d3SJohn Marino     error = 0;
195*86d7f5d3SJohn Marino     while (recsize > 0) {
196*86d7f5d3SJohn Marino 	if ((error = jsread(js, base, &sub, sizeof(sub))) != 0)
197*86d7f5d3SJohn Marino 	    break;
198*86d7f5d3SJohn Marino 	rectype = sub.rectype & JTYPE_MASK;	/* includes the nested bit */
199*86d7f5d3SJohn Marino 	if (sub.recsize == -1) {
200*86d7f5d3SJohn Marino 	    payload = 0x7FFFFFFF;
201*86d7f5d3SJohn Marino 	    subsize = 0x7FFFFFFF;
202*86d7f5d3SJohn Marino 	} else {
203*86d7f5d3SJohn Marino 	    payload = sub.recsize - sizeof(sub);
204*86d7f5d3SJohn Marino 	    subsize = (sub.recsize + 7) & ~7;
205*86d7f5d3SJohn Marino 	}
206*86d7f5d3SJohn Marino 
207*86d7f5d3SJohn Marino 	skip = 1;
208*86d7f5d3SJohn Marino 	*off = base + sizeof(sub);
209*86d7f5d3SJohn Marino 
210*86d7f5d3SJohn Marino 	switch(rectype) {
211*86d7f5d3SJohn Marino 	case JTYPE_REDO:	/* NESTED */
212*86d7f5d3SJohn Marino 	    /*
213*86d7f5d3SJohn Marino 	     * Process redo information when scanning forwards.
214*86d7f5d3SJohn Marino 	     */
215*86d7f5d3SJohn Marino 	    if (direction == JD_FORWARDS) {
216*86d7f5d3SJohn Marino 		error = dump_mirror_subrecord(direction, js, off, payload,
217*86d7f5d3SJohn Marino 					      level + 1, jattr);
218*86d7f5d3SJohn Marino 		skip = 0;
219*86d7f5d3SJohn Marino 	    }
220*86d7f5d3SJohn Marino 	    break;
221*86d7f5d3SJohn Marino 	case JTYPE_UNDO:	/* NESTED */
222*86d7f5d3SJohn Marino 	    /*
223*86d7f5d3SJohn Marino 	     * Process undo information when scanning backwards.
224*86d7f5d3SJohn Marino 	     */
225*86d7f5d3SJohn Marino 	    if (direction == JD_BACKWARDS) {
226*86d7f5d3SJohn Marino 		error = dump_mirror_subrecord(direction, js, off, payload,
227*86d7f5d3SJohn Marino 					      level + 1, jattr);
228*86d7f5d3SJohn Marino 		skip = 0;
229*86d7f5d3SJohn Marino 	    }
230*86d7f5d3SJohn Marino 	    break;
231*86d7f5d3SJohn Marino 	case JTYPE_CRED:	/* NESTED */
232*86d7f5d3SJohn Marino 	    /*
233*86d7f5d3SJohn Marino 	     * Ignore audit information
234*86d7f5d3SJohn Marino 	     */
235*86d7f5d3SJohn Marino 	    break;
236*86d7f5d3SJohn Marino 	default:		/* NESTED or non-NESTED */
237*86d7f5d3SJohn Marino 	    /*
238*86d7f5d3SJohn Marino 	     * Execute these.  Nested records might contain attribute
239*86d7f5d3SJohn Marino 	     * information under an UNDO or REDO parent, for example.
240*86d7f5d3SJohn Marino 	     */
241*86d7f5d3SJohn Marino 	    if (rectype & JMASK_NESTED) {
242*86d7f5d3SJohn Marino 		error = dump_mirror_subrecord(direction, js, off, payload,
243*86d7f5d3SJohn Marino 					      level + 1, jattr);
244*86d7f5d3SJohn Marino 		skip = 0;
245*86d7f5d3SJohn Marino 	    } else if (rectype & JMASK_SUBRECORD) {
246*86d7f5d3SJohn Marino 		error = dump_mirror_payload(sub.rectype, js, *off, payload,
247*86d7f5d3SJohn Marino 					    level, jattr);
248*86d7f5d3SJohn Marino 	    }
249*86d7f5d3SJohn Marino 	    break;
250*86d7f5d3SJohn Marino 	}
251*86d7f5d3SJohn Marino 	if (error)
252*86d7f5d3SJohn Marino 	    break;
253*86d7f5d3SJohn Marino 
254*86d7f5d3SJohn Marino 	/*
255*86d7f5d3SJohn Marino 	 * skip only applies to nested subrecords.  If the record size
256*86d7f5d3SJohn Marino 	 * is unknown the record MUST be a nested record, and if we have
257*86d7f5d3SJohn Marino 	 * not processed it we must recurse to figure out the actual size.
258*86d7f5d3SJohn Marino 	 */
259*86d7f5d3SJohn Marino 	if (sub.recsize == -1) {
260*86d7f5d3SJohn Marino 	    assert(sub.rectype & JMASK_NESTED);
261*86d7f5d3SJohn Marino 	    if (skip) {
262*86d7f5d3SJohn Marino 		error = dump_mirror_subrecord(direction, js, off, payload,
263*86d7f5d3SJohn Marino 					      level + 1, NULL);
264*86d7f5d3SJohn Marino 	    }
265*86d7f5d3SJohn Marino 	    recsize -= ((*off + 7) & ~7) - base;
266*86d7f5d3SJohn Marino 	    base = (*off + 7) & ~7;
267*86d7f5d3SJohn Marino 	} else {
268*86d7f5d3SJohn Marino 	    if (subsize == 0)
269*86d7f5d3SJohn Marino 		subsize = sizeof(sub);
270*86d7f5d3SJohn Marino 	    recsize -= subsize;
271*86d7f5d3SJohn Marino 	    base += subsize;
272*86d7f5d3SJohn Marino 	}
273*86d7f5d3SJohn Marino 	if (error)
274*86d7f5d3SJohn Marino 	    break;
275*86d7f5d3SJohn Marino 	if (sub.rectype & JMASK_LAST)
276*86d7f5d3SJohn Marino 	    break;
277*86d7f5d3SJohn Marino     }
278*86d7f5d3SJohn Marino     *off = base;
279*86d7f5d3SJohn Marino     return(error);
280*86d7f5d3SJohn Marino }
281*86d7f5d3SJohn Marino 
282*86d7f5d3SJohn Marino static int
dump_mirror_payload(int16_t rectype,struct jstream * js,off_t off,int recsize,int level __unused,struct jattr * jattr)283*86d7f5d3SJohn Marino dump_mirror_payload(int16_t rectype, struct jstream *js, off_t off,
284*86d7f5d3SJohn Marino 	     int recsize, int level __unused, struct jattr *jattr)
285*86d7f5d3SJohn Marino {
286*86d7f5d3SJohn Marino     const char *buf;
287*86d7f5d3SJohn Marino     struct jattr_data *data;
288*86d7f5d3SJohn Marino     int error;
289*86d7f5d3SJohn Marino 
290*86d7f5d3SJohn Marino     if (jattr == NULL)
291*86d7f5d3SJohn Marino 	return (0);
292*86d7f5d3SJohn Marino 
293*86d7f5d3SJohn Marino     if ((rectype & ~JMASK_LAST) != JLEAF_FILEDATA) {
294*86d7f5d3SJohn Marino 	error = jsreadp(js, off, (const void **)&buf, recsize);
295*86d7f5d3SJohn Marino 	if (error)
296*86d7f5d3SJohn Marino 	    return (error);
297*86d7f5d3SJohn Marino     } else {
298*86d7f5d3SJohn Marino 	buf = NULL;
299*86d7f5d3SJohn Marino 	error = 0;
300*86d7f5d3SJohn Marino     }
301*86d7f5d3SJohn Marino 
302*86d7f5d3SJohn Marino     switch(rectype & ~JMASK_LAST) {
303*86d7f5d3SJohn Marino     case JLEAF_PAD:
304*86d7f5d3SJohn Marino     case JLEAF_ABORT:
305*86d7f5d3SJohn Marino 	break;
306*86d7f5d3SJohn Marino     case JLEAF_SYMLINKDATA:
307*86d7f5d3SJohn Marino 	jattr->symlinkdata = dupdatastr(buf, recsize);
308*86d7f5d3SJohn Marino 	jattr->symlinklen = recsize;
309*86d7f5d3SJohn Marino 	break;
310*86d7f5d3SJohn Marino     case JLEAF_FILEDATA:
311*86d7f5d3SJohn Marino 	if ((data = jattr->last_data) == NULL) {
312*86d7f5d3SJohn Marino 		jattr->data.off = off;
313*86d7f5d3SJohn Marino 		jattr->data.bytes = recsize;
314*86d7f5d3SJohn Marino 		jattr->last_data = &jattr->data;
315*86d7f5d3SJohn Marino 	} else {
316*86d7f5d3SJohn Marino 		data->next = malloc(sizeof(jattr->data));
317*86d7f5d3SJohn Marino 		data = data->next;
318*86d7f5d3SJohn Marino 		data->off = off;
319*86d7f5d3SJohn Marino 		data->bytes = recsize;
320*86d7f5d3SJohn Marino 		data->next = NULL;
321*86d7f5d3SJohn Marino 		jattr->last_data = data;
322*86d7f5d3SJohn Marino 	}
323*86d7f5d3SJohn Marino 	break;
324*86d7f5d3SJohn Marino     case JLEAF_PATH1:
325*86d7f5d3SJohn Marino 	jattr->path1 = dupdatapath(buf, recsize);
326*86d7f5d3SJohn Marino 	break;
327*86d7f5d3SJohn Marino     case JLEAF_PATH2:
328*86d7f5d3SJohn Marino 	jattr->path2 = dupdatapath(buf, recsize);
329*86d7f5d3SJohn Marino 	break;
330*86d7f5d3SJohn Marino     case JLEAF_PATH3:
331*86d7f5d3SJohn Marino 	jattr->path3 = dupdatapath(buf, recsize);
332*86d7f5d3SJohn Marino 	break;
333*86d7f5d3SJohn Marino     case JLEAF_PATH4:
334*86d7f5d3SJohn Marino 	jattr->path4 = dupdatapath(buf, recsize);
335*86d7f5d3SJohn Marino 	break;
336*86d7f5d3SJohn Marino     case JLEAF_UID:
337*86d7f5d3SJohn Marino 	jattr->uid = buf_to_int64(buf, recsize);
338*86d7f5d3SJohn Marino 	break;
339*86d7f5d3SJohn Marino     case JLEAF_GID:
340*86d7f5d3SJohn Marino 	jattr->gid = buf_to_int64(buf, recsize);
341*86d7f5d3SJohn Marino 	break;
342*86d7f5d3SJohn Marino     case JLEAF_VTYPE:
343*86d7f5d3SJohn Marino 	jattr->vtype = buf_to_int64(buf, recsize);
344*86d7f5d3SJohn Marino 	break;
345*86d7f5d3SJohn Marino     case JLEAF_MODES:
346*86d7f5d3SJohn Marino 	jattr->modes = buf_to_int64(buf, recsize);
347*86d7f5d3SJohn Marino 	break;
348*86d7f5d3SJohn Marino     case JLEAF_FFLAGS:
349*86d7f5d3SJohn Marino 	jattr->fflags = buf_to_int64(buf, recsize);
350*86d7f5d3SJohn Marino 	break;
351*86d7f5d3SJohn Marino     case JLEAF_PID:
352*86d7f5d3SJohn Marino 	jattr->pid = buf_to_int64(buf, recsize);
353*86d7f5d3SJohn Marino 	break;
354*86d7f5d3SJohn Marino     case JLEAF_PPID:
355*86d7f5d3SJohn Marino 	jattr->ppid = buf_to_int64(buf, recsize);
356*86d7f5d3SJohn Marino 	break;
357*86d7f5d3SJohn Marino     case JLEAF_COMM:
358*86d7f5d3SJohn Marino 	jattr->comm = dupdatastr(buf, recsize);
359*86d7f5d3SJohn Marino 	break;
360*86d7f5d3SJohn Marino     case JLEAF_ATTRNAME:
361*86d7f5d3SJohn Marino 	jattr->attrname = dupdatastr(buf, recsize);
362*86d7f5d3SJohn Marino 	break;
363*86d7f5d3SJohn Marino     case JLEAF_PATH_REF:
364*86d7f5d3SJohn Marino 	jattr->pathref = dupdatapath(buf, recsize);
365*86d7f5d3SJohn Marino 	break;
366*86d7f5d3SJohn Marino     case JLEAF_RESERVED_0F:
367*86d7f5d3SJohn Marino 	break;
368*86d7f5d3SJohn Marino     case JLEAF_SEEKPOS:
369*86d7f5d3SJohn Marino 	jattr->seekpos = buf_to_int64(buf, recsize);
370*86d7f5d3SJohn Marino 	break;
371*86d7f5d3SJohn Marino     case JLEAF_INUM:
372*86d7f5d3SJohn Marino 	jattr->inum = buf_to_int64(buf, recsize);
373*86d7f5d3SJohn Marino 	break;
374*86d7f5d3SJohn Marino     case JLEAF_NLINK:
375*86d7f5d3SJohn Marino 	jattr->nlink = buf_to_int64(buf, recsize);
376*86d7f5d3SJohn Marino 	break;
377*86d7f5d3SJohn Marino     case JLEAF_FSID:
378*86d7f5d3SJohn Marino 	jattr->fsid = buf_to_int64(buf, recsize);
379*86d7f5d3SJohn Marino 	break;
380*86d7f5d3SJohn Marino     case JLEAF_SIZE:
381*86d7f5d3SJohn Marino 	jattr->size = buf_to_int64(buf, recsize);
382*86d7f5d3SJohn Marino 	break;
383*86d7f5d3SJohn Marino     case JLEAF_ATIME:
384*86d7f5d3SJohn Marino 	jattr->atime = *(const struct timeval *)buf;
385*86d7f5d3SJohn Marino 	break;
386*86d7f5d3SJohn Marino     case JLEAF_MTIME:
387*86d7f5d3SJohn Marino 	jattr->mtime = *(const struct timeval *)buf;
388*86d7f5d3SJohn Marino 	break;
389*86d7f5d3SJohn Marino     case JLEAF_CTIME:
390*86d7f5d3SJohn Marino 	jattr->ctime = *(const struct timeval *)buf;
391*86d7f5d3SJohn Marino 	break;
392*86d7f5d3SJohn Marino     case JLEAF_GEN:
393*86d7f5d3SJohn Marino 	jattr->gen = buf_to_int64(buf, recsize);
394*86d7f5d3SJohn Marino 	break;
395*86d7f5d3SJohn Marino     case JLEAF_FLAGS:
396*86d7f5d3SJohn Marino 	jattr->flags = buf_to_int64(buf, recsize);
397*86d7f5d3SJohn Marino 	break;
398*86d7f5d3SJohn Marino     case JLEAF_UDEV:
399*86d7f5d3SJohn Marino 	jattr->udev = buf_to_int64(buf, recsize);
400*86d7f5d3SJohn Marino 	break;
401*86d7f5d3SJohn Marino     case JLEAF_FILEREV:
402*86d7f5d3SJohn Marino 	jattr->filerev = buf_to_int64(buf, recsize);
403*86d7f5d3SJohn Marino 	break;
404*86d7f5d3SJohn Marino     default:
405*86d7f5d3SJohn Marino 	break;
406*86d7f5d3SJohn Marino     }
407*86d7f5d3SJohn Marino     return (0);
408*86d7f5d3SJohn Marino }
409*86d7f5d3SJohn Marino 
410*86d7f5d3SJohn Marino static int
dump_mirror_rebuild_redo(u_int16_t rectype,struct jstream * js,struct jattr * jattr)411*86d7f5d3SJohn Marino dump_mirror_rebuild_redo(u_int16_t rectype, struct jstream *js,
412*86d7f5d3SJohn Marino 			struct jattr *jattr)
413*86d7f5d3SJohn Marino {
414*86d7f5d3SJohn Marino     struct jattr_data *data;
415*86d7f5d3SJohn Marino     int error = 0;
416*86d7f5d3SJohn Marino     int fd;
417*86d7f5d3SJohn Marino 
418*86d7f5d3SJohn Marino     if (verbose_opt > 2) {
419*86d7f5d3SJohn Marino 	fprintf(stderr, "REDO %04x %s %s\n",
420*86d7f5d3SJohn Marino 		js->js_head->streamid, type_to_name(rectype),
421*86d7f5d3SJohn Marino 		jattr->pathref ? jattr->pathref : jattr->path1);
422*86d7f5d3SJohn Marino     }
423*86d7f5d3SJohn Marino     switch(rectype) {
424*86d7f5d3SJohn Marino     case JTYPE_SETATTR:
425*86d7f5d3SJohn Marino 	if (jattr->pathref) {
426*86d7f5d3SJohn Marino 	    if (jattr->uid != (uid_t)-1)
427*86d7f5d3SJohn Marino 		chown(jattr->pathref, jattr->uid, -1);
428*86d7f5d3SJohn Marino 	    if (jattr->gid != (gid_t)-1)
429*86d7f5d3SJohn Marino 		chown(jattr->pathref, -1, jattr->gid);
430*86d7f5d3SJohn Marino 	    if (jattr->modes != (mode_t)-1)
431*86d7f5d3SJohn Marino 		chmod(jattr->pathref, jattr->modes);
432*86d7f5d3SJohn Marino 	    if (jattr->fflags != -1)
433*86d7f5d3SJohn Marino 		chflags(jattr->pathref, jattr->fflags);
434*86d7f5d3SJohn Marino 	    if (jattr->size != -1)
435*86d7f5d3SJohn Marino 		truncate(jattr->pathref, jattr->size);
436*86d7f5d3SJohn Marino 	}
437*86d7f5d3SJohn Marino 	break;
438*86d7f5d3SJohn Marino     case JTYPE_WRITE:
439*86d7f5d3SJohn Marino     case JTYPE_PUTPAGES:
440*86d7f5d3SJohn Marino 	if (jattr->pathref && jattr->seekpos != -1) {
441*86d7f5d3SJohn Marino 	    if ((fd = open(jattr->pathref, O_RDWR)) >= 0) {
442*86d7f5d3SJohn Marino 		lseek(fd, jattr->seekpos, 0);
443*86d7f5d3SJohn Marino 		for (data = &jattr->data; data; data = data->next) {
444*86d7f5d3SJohn Marino 		    if (data->bytes)
445*86d7f5d3SJohn Marino 			jsreadcallback(js, write, fd, data->off, data->bytes);
446*86d7f5d3SJohn Marino 		}
447*86d7f5d3SJohn Marino 		close(fd);
448*86d7f5d3SJohn Marino 	    }
449*86d7f5d3SJohn Marino 	}
450*86d7f5d3SJohn Marino 	break;
451*86d7f5d3SJohn Marino     case JTYPE_SETACL:
452*86d7f5d3SJohn Marino 	break;
453*86d7f5d3SJohn Marino     case JTYPE_SETEXTATTR:
454*86d7f5d3SJohn Marino 	break;
455*86d7f5d3SJohn Marino     case JTYPE_CREATE:
456*86d7f5d3SJohn Marino 	/*
457*86d7f5d3SJohn Marino 	 * note: both path1 and pathref will exist.
458*86d7f5d3SJohn Marino 	 */
459*86d7f5d3SJohn Marino 	if (jattr->path1 && jattr->modes != (mode_t)-1) {
460*86d7f5d3SJohn Marino 	    if ((fd = open(jattr->path1, O_CREAT, jattr->modes)) >= 0) {
461*86d7f5d3SJohn Marino 		dosetattr(jattr->path1, fd, jattr);
462*86d7f5d3SJohn Marino 		close(fd);
463*86d7f5d3SJohn Marino 	    }
464*86d7f5d3SJohn Marino 	}
465*86d7f5d3SJohn Marino 	break;
466*86d7f5d3SJohn Marino     case JTYPE_MKNOD:
467*86d7f5d3SJohn Marino 	/* XXX */
468*86d7f5d3SJohn Marino 	break;
469*86d7f5d3SJohn Marino     case JTYPE_LINK:
470*86d7f5d3SJohn Marino 	if (jattr->pathref && jattr->path1) {
471*86d7f5d3SJohn Marino 	    link(jattr->pathref, jattr->path1);
472*86d7f5d3SJohn Marino 	}
473*86d7f5d3SJohn Marino 	break;
474*86d7f5d3SJohn Marino     case JTYPE_SYMLINK:
475*86d7f5d3SJohn Marino 	if (jattr->symlinkdata && jattr->path1) {
476*86d7f5d3SJohn Marino 	    symlink(jattr->symlinkdata, jattr->path1);
477*86d7f5d3SJohn Marino 	}
478*86d7f5d3SJohn Marino 	break;
479*86d7f5d3SJohn Marino     case JTYPE_WHITEOUT:
480*86d7f5d3SJohn Marino 	break;
481*86d7f5d3SJohn Marino     case JTYPE_REMOVE:
482*86d7f5d3SJohn Marino 	if (jattr->path1) {
483*86d7f5d3SJohn Marino 	    remove(jattr->path1);
484*86d7f5d3SJohn Marino 	}
485*86d7f5d3SJohn Marino 	break;
486*86d7f5d3SJohn Marino     case JTYPE_MKDIR:
487*86d7f5d3SJohn Marino 	if (jattr->path1 && jattr->modes != (mode_t)-1) {
488*86d7f5d3SJohn Marino 	    mkdir(jattr->path1, jattr->modes);
489*86d7f5d3SJohn Marino 	}
490*86d7f5d3SJohn Marino 	break;
491*86d7f5d3SJohn Marino     case JTYPE_RMDIR:
492*86d7f5d3SJohn Marino 	if (jattr->path1) {
493*86d7f5d3SJohn Marino 	    rmdir(jattr->path1);
494*86d7f5d3SJohn Marino 	}
495*86d7f5d3SJohn Marino 	break;
496*86d7f5d3SJohn Marino     case JTYPE_RENAME:
497*86d7f5d3SJohn Marino 	if (jattr->path1 && jattr->path2) {
498*86d7f5d3SJohn Marino 	    rename(jattr->path1, jattr->path2);
499*86d7f5d3SJohn Marino 	}
500*86d7f5d3SJohn Marino 	break;
501*86d7f5d3SJohn Marino     }
502*86d7f5d3SJohn Marino     return(error);
503*86d7f5d3SJohn Marino }
504*86d7f5d3SJohn Marino 
505*86d7f5d3SJohn Marino /*
506*86d7f5d3SJohn Marino  * UNDO function using parsed primary data and parsed UNDO data.  This
507*86d7f5d3SJohn Marino  * must typically
508*86d7f5d3SJohn Marino  */
509*86d7f5d3SJohn Marino static int
dump_mirror_rebuild_undo(u_int16_t rectype,struct jstream * js,struct jattr * jattr)510*86d7f5d3SJohn Marino dump_mirror_rebuild_undo(u_int16_t rectype, struct jstream *js,
511*86d7f5d3SJohn Marino 			struct jattr *jattr)
512*86d7f5d3SJohn Marino {
513*86d7f5d3SJohn Marino     struct jattr_data *data;
514*86d7f5d3SJohn Marino     int error = 0;
515*86d7f5d3SJohn Marino     int fd;
516*86d7f5d3SJohn Marino 
517*86d7f5d3SJohn Marino     if (verbose_opt > 2) {
518*86d7f5d3SJohn Marino 	fprintf(stderr, "UNDO %04x %s %s\n",
519*86d7f5d3SJohn Marino 		js->js_head->streamid, type_to_name(rectype),
520*86d7f5d3SJohn Marino 		jattr->pathref ? jattr->pathref : jattr->path1);
521*86d7f5d3SJohn Marino     }
522*86d7f5d3SJohn Marino     switch(rectype) {
523*86d7f5d3SJohn Marino     case JTYPE_SETATTR:
524*86d7f5d3SJohn Marino 	if (jattr->pathref)
525*86d7f5d3SJohn Marino 	    dosetattr(jattr->pathref, -1, jattr);
526*86d7f5d3SJohn Marino 	break;
527*86d7f5d3SJohn Marino     case JTYPE_WRITE:
528*86d7f5d3SJohn Marino     case JTYPE_PUTPAGES:
529*86d7f5d3SJohn Marino 	if (jattr->pathref && jattr->seekpos != -1) {
530*86d7f5d3SJohn Marino 	    if ((fd = open(jattr->pathref, O_RDWR)) >= 0) {
531*86d7f5d3SJohn Marino 		lseek(fd, jattr->seekpos, 0);
532*86d7f5d3SJohn Marino 		for (data = &jattr->data; data; data = data->next) {
533*86d7f5d3SJohn Marino 		    if (data->bytes)
534*86d7f5d3SJohn Marino 			jsreadcallback(js, write, fd, data->off, data->bytes);
535*86d7f5d3SJohn Marino 		}
536*86d7f5d3SJohn Marino 		close(fd);
537*86d7f5d3SJohn Marino 	    }
538*86d7f5d3SJohn Marino 	}
539*86d7f5d3SJohn Marino 	if (jattr->size != -1)
540*86d7f5d3SJohn Marino 	    truncate(jattr->pathref, jattr->size);
541*86d7f5d3SJohn Marino 	break;
542*86d7f5d3SJohn Marino     case JTYPE_SETACL:
543*86d7f5d3SJohn Marino 	break;
544*86d7f5d3SJohn Marino     case JTYPE_SETEXTATTR:
545*86d7f5d3SJohn Marino 	break;
546*86d7f5d3SJohn Marino     case JTYPE_CREATE:
547*86d7f5d3SJohn Marino 	/*
548*86d7f5d3SJohn Marino 	 * note: both path1 and pathref will exist.
549*86d7f5d3SJohn Marino 	 */
550*86d7f5d3SJohn Marino 	if (jattr->path1)
551*86d7f5d3SJohn Marino 	    remove(jattr->path1);
552*86d7f5d3SJohn Marino 	break;
553*86d7f5d3SJohn Marino     case JTYPE_MKNOD:
554*86d7f5d3SJohn Marino 	if (jattr->path1)
555*86d7f5d3SJohn Marino 	    remove(jattr->path1);
556*86d7f5d3SJohn Marino 	break;
557*86d7f5d3SJohn Marino     case JTYPE_LINK:
558*86d7f5d3SJohn Marino 	if (jattr->path1) {
559*86d7f5d3SJohn Marino 	    undo_recreate(jattr->path1, js, jattr);
560*86d7f5d3SJohn Marino 	}
561*86d7f5d3SJohn Marino 	break;
562*86d7f5d3SJohn Marino     case JTYPE_SYMLINK:
563*86d7f5d3SJohn Marino 	if (jattr->symlinkdata && jattr->path1) {
564*86d7f5d3SJohn Marino 	    undo_recreate(jattr->path1, js, jattr);
565*86d7f5d3SJohn Marino 	}
566*86d7f5d3SJohn Marino 	break;
567*86d7f5d3SJohn Marino     case JTYPE_WHITEOUT:
568*86d7f5d3SJohn Marino 	/* XXX */
569*86d7f5d3SJohn Marino 	break;
570*86d7f5d3SJohn Marino     case JTYPE_REMOVE:
571*86d7f5d3SJohn Marino 	if (jattr->path1) {
572*86d7f5d3SJohn Marino 	    undo_recreate(jattr->path1, js, jattr);
573*86d7f5d3SJohn Marino 	}
574*86d7f5d3SJohn Marino 	break;
575*86d7f5d3SJohn Marino     case JTYPE_MKDIR:
576*86d7f5d3SJohn Marino 	if (jattr->path1) {
577*86d7f5d3SJohn Marino 	    rmdir(jattr->path1);
578*86d7f5d3SJohn Marino 	}
579*86d7f5d3SJohn Marino 	break;
580*86d7f5d3SJohn Marino     case JTYPE_RMDIR:
581*86d7f5d3SJohn Marino 	if (jattr->path1 && jattr->modes != (mode_t)-1) {
582*86d7f5d3SJohn Marino 	    mkdir(jattr->path1, jattr->modes);
583*86d7f5d3SJohn Marino 	}
584*86d7f5d3SJohn Marino 	break;
585*86d7f5d3SJohn Marino     case JTYPE_RENAME:
586*86d7f5d3SJohn Marino 	if (jattr->path2) {
587*86d7f5d3SJohn Marino 	    undo_recreate(jattr->path2, js, jattr);
588*86d7f5d3SJohn Marino 	}
589*86d7f5d3SJohn Marino 	break;
590*86d7f5d3SJohn Marino     }
591*86d7f5d3SJohn Marino     return(error);
592*86d7f5d3SJohn Marino }
593*86d7f5d3SJohn Marino 
594*86d7f5d3SJohn Marino /*
595*86d7f5d3SJohn Marino  * This is a helper function for undoing operations which completely destroy
596*86d7f5d3SJohn Marino  * the file that had existed previously.  The caller will clean up the
597*86d7f5d3SJohn Marino  * attributes (including file truncations/extensions) after the fact.
598*86d7f5d3SJohn Marino  */
599*86d7f5d3SJohn Marino static void
undo_recreate(const char * filename,struct jstream * js,struct jattr * jattr)600*86d7f5d3SJohn Marino undo_recreate(const char *filename, struct jstream *js, struct jattr *jattr)
601*86d7f5d3SJohn Marino {
602*86d7f5d3SJohn Marino     struct jattr_data *data;
603*86d7f5d3SJohn Marino     int fd;
604*86d7f5d3SJohn Marino 
605*86d7f5d3SJohn Marino     if (verbose_opt > 2)
606*86d7f5d3SJohn Marino 	fprintf(stderr, "RECREATE %s (type %d)\n", filename, jattr->vtype);
607*86d7f5d3SJohn Marino 
608*86d7f5d3SJohn Marino     remove(filename);
609*86d7f5d3SJohn Marino     switch(jattr->vtype) {
610*86d7f5d3SJohn Marino     case VREG:
611*86d7f5d3SJohn Marino 	if (jattr->size != -1) {
612*86d7f5d3SJohn Marino 	    if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600)) >= 0) {
613*86d7f5d3SJohn Marino 		if (jattr->seekpos != -1) {
614*86d7f5d3SJohn Marino 		    lseek(fd, jattr->seekpos, 0);
615*86d7f5d3SJohn Marino 		    for (data = &jattr->data; data; data = data->next) {
616*86d7f5d3SJohn Marino 			if (data->bytes)
617*86d7f5d3SJohn Marino 			    jsreadcallback(js, write, fd, data->off, data->bytes);
618*86d7f5d3SJohn Marino 		    }
619*86d7f5d3SJohn Marino 		}
620*86d7f5d3SJohn Marino 		dosetattr(filename, fd, jattr);
621*86d7f5d3SJohn Marino 		close(fd);
622*86d7f5d3SJohn Marino 	    }
623*86d7f5d3SJohn Marino 	}
624*86d7f5d3SJohn Marino 	break;
625*86d7f5d3SJohn Marino     case VDIR:
626*86d7f5d3SJohn Marino 	mkdir(filename, 0600);
627*86d7f5d3SJohn Marino 	dosetattr(filename, -1, jattr);
628*86d7f5d3SJohn Marino 	break;
629*86d7f5d3SJohn Marino     case VBLK:
630*86d7f5d3SJohn Marino     case VCHR:
631*86d7f5d3SJohn Marino 	if (jattr->udev) {
632*86d7f5d3SJohn Marino 	    mknod(filename, S_IFBLK|0666, jattr->udev);
633*86d7f5d3SJohn Marino 	    dosetattr(filename, -1, jattr);
634*86d7f5d3SJohn Marino 	}
635*86d7f5d3SJohn Marino 	break;
636*86d7f5d3SJohn Marino     case VLNK:
637*86d7f5d3SJohn Marino 	if (jattr->symlinkdata) {
638*86d7f5d3SJohn Marino 	    symlink(jattr->symlinkdata, filename);
639*86d7f5d3SJohn Marino 	    dosetattr(filename, -1, jattr);
640*86d7f5d3SJohn Marino 	}
641*86d7f5d3SJohn Marino 	break;
642*86d7f5d3SJohn Marino     default:
643*86d7f5d3SJohn Marino 	break;
644*86d7f5d3SJohn Marino     }
645*86d7f5d3SJohn Marino }
646*86d7f5d3SJohn Marino 
647*86d7f5d3SJohn Marino static void
dosetattr(const char * filename,int fd,struct jattr * jattr)648*86d7f5d3SJohn Marino dosetattr(const char *filename, int fd, struct jattr *jattr)
649*86d7f5d3SJohn Marino {
650*86d7f5d3SJohn Marino     if (fd >= 0) {
651*86d7f5d3SJohn Marino 	if (jattr->uid != (uid_t)-1 && jattr->gid != (gid_t)-1)
652*86d7f5d3SJohn Marino 	    fchown(fd, jattr->uid, jattr->gid);
653*86d7f5d3SJohn Marino 	else if (jattr->uid != (uid_t)-1)
654*86d7f5d3SJohn Marino 	    fchown(fd, jattr->uid, -1);
655*86d7f5d3SJohn Marino 	else if (jattr->gid != (gid_t)-1)
656*86d7f5d3SJohn Marino 	    fchown(fd, -1, jattr->gid);
657*86d7f5d3SJohn Marino 
658*86d7f5d3SJohn Marino 	if (jattr->modes != (mode_t)-1)
659*86d7f5d3SJohn Marino 	    fchmod(fd, jattr->modes);
660*86d7f5d3SJohn Marino 	if (jattr->fflags != -1)
661*86d7f5d3SJohn Marino 	    fchflags(fd, jattr->fflags);
662*86d7f5d3SJohn Marino 	if (jattr->size != -1)
663*86d7f5d3SJohn Marino 	    ftruncate(fd, jattr->size);
664*86d7f5d3SJohn Marino     } else {
665*86d7f5d3SJohn Marino 	if (jattr->uid != (uid_t)-1 && jattr->gid != (gid_t)-1)
666*86d7f5d3SJohn Marino 	    lchown(filename, jattr->uid, jattr->gid);
667*86d7f5d3SJohn Marino 	else if (jattr->uid != (uid_t)-1)
668*86d7f5d3SJohn Marino 	    lchown(filename, jattr->uid, -1);
669*86d7f5d3SJohn Marino 	else if (jattr->gid != (gid_t)-1)
670*86d7f5d3SJohn Marino 	    lchown(filename, -1, jattr->gid);
671*86d7f5d3SJohn Marino 
672*86d7f5d3SJohn Marino 	if (jattr->modes != (mode_t)-1)
673*86d7f5d3SJohn Marino 	    lchmod(filename, jattr->modes);
674*86d7f5d3SJohn Marino 	if (jattr->fflags != -1)
675*86d7f5d3SJohn Marino 	    chflags(filename, jattr->fflags);
676*86d7f5d3SJohn Marino 	if (jattr->size != -1)
677*86d7f5d3SJohn Marino 	    truncate(filename, jattr->size);
678*86d7f5d3SJohn Marino     }
679*86d7f5d3SJohn Marino }
680*86d7f5d3SJohn Marino 
681