2 * Copyright (c) 2005 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sbin/jscan/dump_mirror.c,v 1.1 2005/07/05 00:26:03 dillon Exp $
39 static void dump_mirror_stream(struct jstream *js);
40 static int dump_mirror_toprecord(struct jstream *js, off_t *off,
41 off_t recsize, int level);
42 static int dump_mirror_subrecord(struct jstream *js, off_t *off,
43 off_t recsize, int level, struct jattr *jattr);
44 static int dump_mirror_payload(int16_t rectype, struct jstream *js, off_t off,
45 int recsize, int level, struct jattr *jattr);
46 static int dump_mirror_rebuild(u_int16_t rectype, struct jattr *jattr);
49 dump_mirror(struct jfile *jf)
53 while ((js = jscan_stream(jf)) != NULL) {
54 dump_mirror_stream(js);
60 dump_mirror_stream(struct jstream *js)
62 struct journal_rawrecbeg head;
66 save_umask = umask(0);
67 jsread(js, 0, &head, sizeof(head));
69 sid = head.streamid & JREC_STREAMID_MASK;
71 printf("STREAM %04x {\n", (int)(u_int16_t)head.streamid);
72 if (sid >= JREC_STREAMID_JMIN && sid < JREC_STREAMID_JMAX) {
73 off_t off = sizeof(head);
74 dump_mirror_toprecord(js, &off, js->js_normalized_total -
75 sizeof(struct journal_rawrecbeg),
78 switch(head.streamid & JREC_STREAMID_MASK) {
79 case JREC_STREAMID_SYNCPT & JREC_STREAMID_MASK:
83 case JREC_STREAMID_PAD & JREC_STREAMID_MASK:
87 case JREC_STREAMID_DISCONT & JREC_STREAMID_MASK:
91 case JREC_STREAMID_ANNOTATE & JREC_STREAMID_MASK:
93 printf(" ANNOTATION\n");
107 dump_mirror_toprecord(struct jstream *js, off_t *off, off_t recsize, int level)
109 struct journal_subrecord sub;
117 bzero(&jattr, sizeof(jattr));
120 while (recsize > 0) {
121 if ((error = jsread(js, base, &sub, sizeof(sub))) != 0)
124 printf("%*.*s", level * 4, level * 4, "");
125 printf("@%lld ", base);
126 printf("RECORD %s [%04x/%d]", type_to_name(sub.rectype),
127 (int)(u_int16_t)sub.rectype, sub.recsize);
129 if (sub.recsize == -1) {
130 if ((sub.rectype & JMASK_NESTED) == 0) {
131 printf("Record size of -1 only works for nested records\n");
135 payload = 0x7FFFFFFF;
136 subsize = 0x7FFFFFFF;
138 payload = sub.recsize - sizeof(sub);
139 subsize = (sub.recsize + 7) & ~7;
141 if (sub.rectype & JMASK_NESTED) {
144 *off = base + sizeof(sub);
145 error = dump_mirror_subrecord(js, off,
146 payload, level + 1, &jattr);
148 printf("%*.*s}\n", level * 4, level * 4, "");
149 } else if (sub.rectype & JMASK_SUBRECORD) {
151 printf(" DATA (%d)", payload);
152 error = dump_debug_payload(sub.rectype, js, base + sizeof(sub), payload, level);
154 *off = base + sizeof(sub) + payload;
159 printf("[%d bytes of unknown content]\n", sub.recsize);
161 dump_mirror_rebuild(sub.rectype, &jattr);
165 if (sub.recsize == -1) {
166 if ((sub.rectype & JMASK_NESTED) == 0) {
167 printf("Record size of -1 only works for nested records\n");
171 recsize -= ((*off + 7) & ~7) - base;
172 base = (*off + 7) & ~7;
175 subsize = sizeof(sub);
179 if (sub.rectype & JMASK_LAST)
187 dump_mirror_subrecord(struct jstream *js, off_t *off, off_t recsize, int level,
190 struct journal_subrecord sub;
198 while (recsize > 0) {
199 if ((error = jsread(js, base, &sub, sizeof(sub))) != 0)
201 rectype = sub.rectype & JTYPE_MASK;
203 printf("%*.*s", level * 4, level * 4, "");
204 printf("@%lld ", base);
205 printf("RECORD %s [%04x/%d]", type_to_name(sub.rectype),
206 (int)(u_int16_t)sub.rectype, sub.recsize);
208 if (sub.recsize == -1) {
209 payload = 0x7FFFFFFF;
210 subsize = 0x7FFFFFFF;
212 payload = sub.recsize - sizeof(sub);
213 subsize = (sub.recsize + 7) & ~7;
215 if (sub.rectype & JMASK_NESTED) {
220 * Only recurse through vattr records. XXX currently assuming
221 * only on VATTR subrecord.
223 *off = base + sizeof(sub);
224 if (payload && rectype == JTYPE_VATTR) {
225 error = dump_mirror_subrecord(js, off,
226 payload, level + 1, jattr);
228 error = dump_mirror_subrecord(js, off,
229 payload, level + 1, NULL);
232 printf("%*.*s}\n", level * 4, level * 4, "");
233 } else if (sub.rectype & JMASK_SUBRECORD) {
235 printf(" DATA (%d)", payload);
236 dump_debug_payload(sub.rectype, js, base + sizeof(sub),
239 error = dump_mirror_payload(sub.rectype, js, base + sizeof(sub),
240 payload, level, jattr);
241 *off = base + sizeof(sub) + payload;
246 printf("[%d bytes of unknown content]\n", sub.recsize);
250 if (sub.recsize == -1) {
251 recsize -= ((*off + 7) & ~7) - base;
252 base = (*off + 7) & ~7;
255 subsize = sizeof(sub);
259 if (sub.rectype & JMASK_LAST)
267 dump_mirror_payload(int16_t rectype, struct jstream *js, off_t off,
268 int recsize, int level __unused, struct jattr *jattr)
276 error = jsreadp(js, off, (const void **)&buf, recsize);
280 switch(rectype & ~JMASK_LAST) {
285 jattr->data = dupdata(buf, recsize);
286 jattr->datalen = recsize;
289 jattr->path1 = dupdatapath(buf, recsize);
292 jattr->path2 = dupdatapath(buf, recsize);
295 jattr->path3 = dupdatapath(buf, recsize);
298 jattr->path4 = dupdatapath(buf, recsize);
301 jattr->uid = buf_to_int64(buf, recsize);
304 jattr->gid = buf_to_int64(buf, recsize);
307 jattr->vtype = buf_to_int64(buf, recsize);
310 jattr->modes = buf_to_int64(buf, recsize);
313 jattr->fflags = buf_to_int64(buf, recsize);
316 jattr->pid = buf_to_int64(buf, recsize);
319 jattr->ppid = buf_to_int64(buf, recsize);
322 jattr->comm = dupdatastr(buf, recsize);
325 jattr->attrname = dupdatastr(buf, recsize);
328 jattr->pathref = dupdatapath(buf, recsize);
330 case JLEAF_RESERVED_0F:
332 case JLEAF_SYMLINKDATA:
333 jattr->data = dupdata(buf, recsize);
334 jattr->datalen = recsize;
337 jattr->seekpos = buf_to_int64(buf, recsize);
340 jattr->inum = buf_to_int64(buf, recsize);
343 jattr->nlink = buf_to_int64(buf, recsize);
346 jattr->fsid = buf_to_int64(buf, recsize);
349 jattr->size = buf_to_int64(buf, recsize);
352 jattr->atime = *(const struct timeval *)buf;
355 jattr->mtime = *(const struct timeval *)buf;
358 jattr->ctime = *(const struct timeval *)buf;
361 jattr->gen = buf_to_int64(buf, recsize);
364 jattr->flags = buf_to_int64(buf, recsize);
367 jattr->udev = buf_to_int64(buf, recsize);
370 jattr->filerev = buf_to_int64(buf, recsize);
379 dump_mirror_rebuild(u_int16_t rectype, struct jattr *jattr)
387 if (jattr->pathref) {
388 if (jattr->uid != (uid_t)-1)
389 chown(jattr->pathref, jattr->uid, -1);
390 if (jattr->gid != (gid_t)-1)
391 chown(jattr->pathref, -1, jattr->gid);
392 if (jattr->modes != (mode_t)-1)
393 chmod(jattr->pathref, jattr->modes);
394 if (jattr->fflags != -1)
395 chflags(jattr->pathref, jattr->fflags);
396 if (jattr->size != -1)
397 truncate(jattr->pathref, jattr->size);
402 if (jattr->pathref && jattr->seekpos != -1 && jattr->data) {
403 if ((fd = open(jattr->pathref, O_RDWR)) >= 0) {
404 lseek(fd, jattr->seekpos, 0);
405 write(fd, jattr->data, jattr->datalen);
412 case JTYPE_SETEXTATTR:
416 * note: both path1 and pathref will exist.
418 if (jattr->path1 && jattr->modes != (mode_t)-1) {
419 if ((fd = open(jattr->path1, O_CREAT, jattr->modes)) >= 0) {
421 rectype = JTYPE_SETATTR;
436 remove(jattr->path1);
440 if (jattr->path1 && jattr->modes != (mode_t)-1) {
441 mkdir(jattr->path1, jattr->modes);
450 if (jattr->path1 && jattr->path2) {
451 rename(jattr->path1, jattr->path2);