This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / intermezzo / kml_unpack.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
5  *
6  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
7  *
8  *   InterMezzo is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   InterMezzo is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with InterMezzo; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * Unpacking of KML records
22  *
23  */
24
25 #ifdef __KERNEL__
26 #  include <linux/module.h>
27 #  include <linux/errno.h>
28 #  include <linux/kernel.h>
29 #  include <linux/major.h>
30 #  include <linux/sched.h>
31 #  include <linux/lp.h>
32 #  include <linux/slab.h>
33 #  include <linux/ioport.h>
34 #  include <linux/fcntl.h>
35 #  include <linux/delay.h>
36 #  include <linux/skbuff.h>
37 #  include <linux/proc_fs.h>
38 #  include <linux/vmalloc.h>
39 #  include <linux/fs.h>
40 #  include <linux/poll.h>
41 #  include <linux/init.h>
42 #  include <linux/list.h>
43 #  include <linux/stat.h>
44 #  include <asm/io.h>
45 #  include <asm/segment.h>
46 #  include <asm/system.h>
47 #  include <asm/poll.h>
48 #  include <asm/uaccess.h>
49 #else
50 #  include <time.h>
51 #  include <stdio.h>
52 #  include <string.h>
53 #  include <stdlib.h>
54 #  include <errno.h>
55 #  include <sys/stat.h>
56 #  include <glib.h>
57 #endif
58
59 #include "intermezzo_lib.h"
60 #include "intermezzo_idl.h"
61 #include "intermezzo_fs.h"
62
63 int kml_unpack_version(struct presto_version **ver, char **buf, char *end) 
64 {
65         char *ptr = *buf;
66         struct presto_version *pv;
67
68         UNLOGP(*ver, struct presto_version, ptr, end);
69         pv = *ver;
70         pv->pv_mtime_sec   = NTOH__u32(pv->pv_mtime_sec);
71         pv->pv_mtime_nsec   = NTOH__u32(pv->pv_mtime_nsec);
72         pv->pv_ctime_sec   = NTOH__u32(pv->pv_ctime_sec);
73         pv->pv_ctime_nsec   = NTOH__u32(pv->pv_ctime_nsec);
74         pv->pv_size    = NTOH__u64(pv->pv_size);
75
76         *buf = ptr;
77
78         return 0;
79 }
80
81
82 static int kml_unpack_noop(struct kml_rec *rec, char **buf, char *end)
83 {
84         return 0;
85 }
86
87  
88 static int kml_unpack_get_fileid(struct kml_rec *rec, char **buf, char *end)
89 {
90         char *ptr = *buf;
91
92         LUNLOGV(rec->pathlen, __u32, ptr, end);
93         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
94
95         *buf = ptr;
96         return 0;
97 }
98
99 static int kml_unpack_create(struct kml_rec *rec, char **buf, char *end)
100 {
101         char *ptr = *buf;
102
103         kml_unpack_version(&rec->old_parentv, &ptr, end);
104         kml_unpack_version(&rec->new_parentv, &ptr, end);
105         kml_unpack_version(&rec->new_objectv, &ptr, end);
106         LUNLOGV(rec->mode, __u32, ptr, end);
107         LUNLOGV(rec->uid, __u32, ptr, end);
108         LUNLOGV(rec->gid, __u32, ptr, end);
109         LUNLOGV(rec->pathlen, __u32, ptr, end);
110         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
111
112         *buf = ptr;
113
114         return 0;
115 }
116
117  
118 static int kml_unpack_mkdir(struct kml_rec *rec, char **buf, char *end)
119 {
120         char *ptr = *buf;
121
122         kml_unpack_version(&rec->old_parentv, &ptr, end);
123         kml_unpack_version(&rec->new_parentv, &ptr, end);
124         kml_unpack_version(&rec->new_objectv, &ptr, end);
125         LUNLOGV(rec->mode, __u32, ptr, end);
126         LUNLOGV(rec->uid, __u32, ptr, end);
127         LUNLOGV(rec->gid, __u32, ptr, end);
128         LUNLOGV(rec->pathlen, __u32, ptr, end);
129         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
130
131         *buf = ptr;
132
133         return 0;
134 }
135
136
137 static int kml_unpack_unlink(struct kml_rec *rec, char **buf, char *end)
138 {
139         char *ptr = *buf;
140
141         kml_unpack_version(&rec->old_parentv, &ptr, end);
142         kml_unpack_version(&rec->new_parentv, &ptr, end);
143         kml_unpack_version(&rec->old_objectv, &ptr, end);
144         LUNLOGV(rec->old_mode, __u32, ptr, end);
145         LUNLOGV(rec->old_rdev, __u32, ptr, end);
146         LUNLOGV(rec->old_uid, __u64, ptr, end);
147         LUNLOGV(rec->old_gid, __u64, ptr, end);
148         LUNLOGV(rec->pathlen, __u32, ptr, end);
149         LUNLOGV(rec->targetlen, __u32, ptr, end);
150         LUNLOGV(rec->old_targetlen, __u32, ptr, end);
151         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
152         UNLOGL(rec->target, char, rec->targetlen, ptr, end);
153         UNLOGL(rec->old_target, char, rec->old_targetlen, ptr, end);
154
155         *buf = ptr;
156
157         return 0;
158 }
159
160
161 static int kml_unpack_rmdir(struct kml_rec *rec, char **buf, char *end)
162 {
163         char *ptr = *buf;
164
165         kml_unpack_version(&rec->old_parentv, &ptr, end);
166         kml_unpack_version(&rec->new_parentv, &ptr, end);
167         kml_unpack_version(&rec->old_objectv, &ptr, end);
168         LUNLOGV(rec->old_mode, __u32, ptr, end);
169         LUNLOGV(rec->old_rdev, __u32, ptr, end);
170         LUNLOGV(rec->old_uid, __u64, ptr, end);
171         LUNLOGV(rec->old_gid, __u64, ptr, end);
172         LUNLOGV(rec->pathlen, __u32, ptr, end);
173         LUNLOGV(rec->targetlen, __u32, ptr, end);
174         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
175         UNLOGL(rec->target, char, rec->targetlen, ptr, end);
176
177         *buf = ptr;
178
179         return 0;
180 }
181
182
183 static int kml_unpack_close(struct kml_rec *rec, char **buf, char *end)
184 {
185         char *ptr = *buf;
186
187         LUNLOGV(rec->mode, __u32, ptr, end);  // used for open_mode
188         LUNLOGV(rec->uid, __u32, ptr, end);   // used for open_uid
189         LUNLOGV(rec->gid, __u32, ptr, end);   // used for open_gid
190         kml_unpack_version(&rec->old_objectv, &ptr, end);
191         kml_unpack_version(&rec->new_objectv, &ptr, end);
192         LUNLOGV(rec->ino, __u64, ptr, end);
193         LUNLOGV(rec->generation, __u32, ptr, end);
194         LUNLOGV(rec->pathlen, __u32, ptr, end);
195         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
196
197         *buf = ptr;
198
199         return 0;
200 }
201
202
203 static int kml_unpack_symlink(struct kml_rec *rec, char **buf, char *end)
204 {
205         char *ptr = *buf;
206
207         kml_unpack_version(&rec->old_parentv, &ptr, end);
208         kml_unpack_version(&rec->new_parentv, &ptr, end);
209         kml_unpack_version(&rec->new_objectv, &ptr, end);
210         LUNLOGV(rec->uid, __u32, ptr, end);
211         LUNLOGV(rec->gid, __u32, ptr, end);
212         LUNLOGV(rec->pathlen, __u32, ptr, end);
213         LUNLOGV(rec->targetlen, __u32, ptr, end);
214         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
215         UNLOGL(rec->target, char, rec->targetlen, ptr, end);
216
217         *buf = ptr;
218
219         return 0;
220 }
221
222
223 static int kml_unpack_rename(struct kml_rec *rec, char **buf, char *end)
224 {
225         char *ptr = *buf;
226
227         kml_unpack_version(&rec->old_objectv, &ptr, end);
228         kml_unpack_version(&rec->new_objectv, &ptr, end);
229         kml_unpack_version(&rec->old_parentv, &ptr, end);
230         kml_unpack_version(&rec->new_parentv, &ptr, end);
231         LUNLOGV(rec->pathlen, __u32, ptr, end);
232         LUNLOGV(rec->targetlen, __u32, ptr, end);
233         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
234         UNLOGL(rec->target, char, rec->targetlen, ptr, end);
235
236         *buf = ptr;
237
238         return 0;
239 }
240
241
242 static int kml_unpack_setattr(struct kml_rec *rec, char **buf, char *end)
243 {
244         char *ptr = *buf;
245
246         kml_unpack_version(&rec->old_objectv, &ptr, end);
247         LUNLOGV(rec->valid, __u32, ptr, end);
248         LUNLOGV(rec->mode, __u32, ptr, end);
249         LUNLOGV(rec->uid, __u32, ptr, end);
250         LUNLOGV(rec->gid, __u32, ptr, end);
251         LUNLOGV(rec->size, __u64, ptr, end);
252         LUNLOGV(rec->mtime_sec, __u32, ptr, end);
253         LUNLOGV(rec->mtime_nsec, __u32, ptr, end);
254         LUNLOGV(rec->ctime_sec, __u32, ptr, end);
255         LUNLOGV(rec->ctime_nsec, __u32, ptr, end);
256         LUNLOGV(rec->flags, __u32, ptr, end);
257         LUNLOGV(rec->old_mode, __u32, ptr, end);
258         LUNLOGV(rec->old_rdev, __u32, ptr, end);
259         LUNLOGV(rec->old_uid, __u64, ptr, end);
260         LUNLOGV(rec->old_gid, __u64, ptr, end);
261         LUNLOGV(rec->pathlen, __u32, ptr, end);
262         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
263         
264         *buf = ptr;
265
266         return 0;
267 }
268
269
270 static int kml_unpack_link(struct kml_rec *rec, char **buf, char *end)
271 {
272         char *ptr = *buf;
273
274         kml_unpack_version(&rec->old_parentv, &ptr, end);
275         kml_unpack_version(&rec->new_parentv, &ptr, end);
276         kml_unpack_version(&rec->new_objectv, &ptr, end);
277         LUNLOGV(rec->pathlen, __u32, ptr, end);
278         LUNLOGV(rec->targetlen, __u32, ptr, end);
279         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
280         UNLOGL(rec->target, char, rec->targetlen, ptr, end);
281
282         *buf = ptr;
283
284         return 0;
285 }
286
287 static int kml_unpack_mknod(struct kml_rec *rec, char **buf, char *end)
288 {
289         char *ptr = *buf;
290
291         kml_unpack_version(&rec->old_parentv, &ptr, end);
292         kml_unpack_version(&rec->new_parentv, &ptr, end);
293         kml_unpack_version(&rec->new_objectv, &ptr, end);
294         LUNLOGV(rec->mode, __u32, ptr, end);
295         LUNLOGV(rec->uid, __u32, ptr, end);
296         LUNLOGV(rec->gid, __u32, ptr, end);
297         LUNLOGV(rec->major, __u32, ptr, end);
298         LUNLOGV(rec->minor, __u32, ptr, end);
299         LUNLOGV(rec->pathlen, __u32, ptr, end);
300         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
301
302         *buf = ptr;
303
304         return 0;
305 }
306
307
308 static int kml_unpack_write(struct kml_rec *rec, char **buf, char *end)
309 {
310         printf("NOT IMPLEMENTED");
311         return 0;
312 }
313
314
315 static int kml_unpack_release(struct kml_rec *rec, char **buf, char *end)
316 {
317         printf("NOT IMPLEMENTED");
318         return 0;
319 }
320
321
322 static int kml_unpack_trunc(struct kml_rec *rec, char **buf, char *end)
323 {
324         printf("NOT IMPLEMENTED");
325         return 0;
326 }
327
328
329 static int kml_unpack_setextattr(struct kml_rec *rec, char **buf, char *end)
330 {
331         char *ptr = *buf;
332
333         kml_unpack_version(&rec->old_objectv, &ptr, end);
334         kml_unpack_version(&rec->new_objectv, &ptr, end);
335         LUNLOGV(rec->flags, __u32, ptr, end);
336         LUNLOGV(rec->mode, __u32, ptr, end);
337         LUNLOGV(rec->pathlen, __u32, ptr, end);
338         LUNLOGV(rec->namelen, __u32, ptr, end);
339         LUNLOGV(rec->targetlen, __u32, ptr, end);
340         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
341         UNLOGL(rec->name, char, rec->namelen, ptr, end);
342         UNLOGL(rec->target, char, rec->targetlen, ptr, end);
343
344         *buf = ptr;
345
346         return 0;
347 }
348
349
350 static int kml_unpack_delextattr(struct kml_rec *rec, char **buf, char *end)
351 {
352         char *ptr = *buf;
353
354         kml_unpack_version(&rec->old_objectv, &ptr, end);
355         kml_unpack_version(&rec->new_objectv, &ptr, end);
356         LUNLOGV(rec->flags, __u32, ptr, end);
357         LUNLOGV(rec->mode, __u32, ptr, end);
358         LUNLOGV(rec->pathlen, __u32, ptr, end);
359         LUNLOGV(rec->namelen, __u32, ptr, end);
360         LUNLOGV(rec->targetlen, __u32, ptr, end);
361         UNLOGL(rec->path, char, rec->pathlen, ptr, end);
362         UNLOGL(rec->name, char, rec->namelen, ptr, end);
363
364         *buf = ptr;
365
366         return 0;
367 }
368
369 static int kml_unpack_open(struct kml_rec *rec, char **buf, char *end)
370 {
371         printf("NOT IMPLEMENTED");
372         return 0;
373 }
374
375 static int kml_unpack_kml_trunc(struct kml_rec *rec, char **buf, char *end)
376 {
377
378         printf("NOT IMPLEMENTED");
379         return 0;
380 }
381
382
383 typedef int (*unpacker)(struct kml_rec *rec, char **buf, char *end);
384
385 static unpacker unpackers[KML_OPCODE_NUM] = 
386 {
387         [KML_OPCODE_NOOP] = kml_unpack_noop,
388         [KML_OPCODE_CREATE] = kml_unpack_create, 
389         [KML_OPCODE_MKDIR] = kml_unpack_mkdir,
390         [KML_OPCODE_UNLINK] = kml_unpack_unlink,
391         [KML_OPCODE_RMDIR] = kml_unpack_rmdir,
392         [KML_OPCODE_CLOSE] = kml_unpack_close,
393         [KML_OPCODE_SYMLINK] = kml_unpack_symlink,
394         [KML_OPCODE_RENAME] = kml_unpack_rename,
395         [KML_OPCODE_SETATTR] = kml_unpack_setattr,
396         [KML_OPCODE_LINK] = kml_unpack_link,
397         [KML_OPCODE_OPEN] = kml_unpack_open,
398         [KML_OPCODE_MKNOD] = kml_unpack_mknod,
399         [KML_OPCODE_WRITE] = kml_unpack_write,
400         [KML_OPCODE_RELEASE] = kml_unpack_release,
401         [KML_OPCODE_TRUNC] = kml_unpack_trunc,
402         [KML_OPCODE_SETEXTATTR] = kml_unpack_setextattr,
403         [KML_OPCODE_DELEXTATTR] = kml_unpack_delextattr,
404         [KML_OPCODE_KML_TRUNC] = kml_unpack_kml_trunc,
405         [KML_OPCODE_GET_FILEID] = kml_unpack_get_fileid
406 };
407
408 int kml_unpack_prefix(struct kml_rec *rec, char **buf, char *end) 
409 {
410         char *ptr = *buf;
411         int n;
412
413         UNLOGP(rec->prefix.hdr, struct kml_prefix_hdr, ptr, end);
414         rec->prefix.hdr->len     = NTOH__u32(rec->prefix.hdr->len);
415         rec->prefix.hdr->version = NTOH__u32(rec->prefix.hdr->version);
416         rec->prefix.hdr->pid     = NTOH__u32(rec->prefix.hdr->pid);
417         rec->prefix.hdr->auid    = NTOH__u32(rec->prefix.hdr->auid);
418         rec->prefix.hdr->fsuid   = NTOH__u32(rec->prefix.hdr->fsuid);
419         rec->prefix.hdr->fsgid   = NTOH__u32(rec->prefix.hdr->fsgid);
420         rec->prefix.hdr->opcode  = NTOH__u32(rec->prefix.hdr->opcode);
421         rec->prefix.hdr->ngroups = NTOH__u32(rec->prefix.hdr->ngroups);
422
423         UNLOGL(rec->prefix.groups, __u32, rec->prefix.hdr->ngroups, ptr, end);
424         for (n = 0; n < rec->prefix.hdr->ngroups; n++) {
425                 rec->prefix.groups[n] = NTOH__u32(rec->prefix.groups[n]);
426         }
427
428         *buf = ptr;
429
430         return 0;
431 }
432
433 int kml_unpack_suffix(struct kml_rec *rec, char **buf, char *end) 
434 {
435         char *ptr = *buf;
436
437         UNLOGP(rec->suffix, struct kml_suffix, ptr, end);
438         rec->suffix->prevrec   = NTOH__u32(rec->suffix->prevrec);
439         rec->suffix->recno    = NTOH__u32(rec->suffix->recno);
440         rec->suffix->time     = NTOH__u32(rec->suffix->time);
441         rec->suffix->len      = NTOH__u32(rec->suffix->len);
442
443         *buf = ptr;
444
445         return 0;
446 }
447
448 int kml_unpack(struct kml_rec *rec, char **buf, char *end)
449 {
450         char *ptr = *buf;
451         int err; 
452
453         if (((unsigned long)ptr % 4) != 0) {
454                 printf("InterMezzo: %s: record misaligned.\n", __FUNCTION__);
455                 return -EINVAL;
456         }
457
458         while (ptr < end) { 
459                 __u32 *i = (__u32 *)ptr;
460                 if (*i)
461                         break;
462                 ptr += sizeof(*i);
463         }
464         *buf = ptr;
465
466         memset(rec, 0, sizeof(*rec));
467
468         err = kml_unpack_prefix(rec, &ptr, end);
469         if (err) {
470                 printf("InterMezzo: %s: unpack_prefix failed: %d\n",
471                        __FUNCTION__, err);
472                 return err;
473         }
474
475         if (rec->prefix.hdr->opcode < 0  ||
476             rec->prefix.hdr->opcode >= KML_OPCODE_NUM) {
477                 printf("InterMezzo: %s: invalid opcode (%d)\n",
478                        __FUNCTION__, rec->prefix.hdr->opcode);
479                 return -EINVAL;
480         }
481         err = unpackers[rec->prefix.hdr->opcode](rec, &ptr, end);
482         if (err) {
483                 printf("InterMezzo: %s: unpacker failed: %d\n",
484                        __FUNCTION__, err);
485                 return err;
486         }
487
488         err = kml_unpack_suffix(rec, &ptr, end);
489         if (err) {
490                 printf("InterMezzo: %s: unpack_suffix failed: %d\n",
491                        __FUNCTION__, err);
492                 return err;
493         }
494
495
496         if (rec->prefix.hdr->len != rec->suffix->len) {
497                 printf("InterMezzo: %s: lengths don't match\n",
498                        __FUNCTION__);
499                 return -EINVAL;
500         }
501         if ((rec->prefix.hdr->len % 4) != 0) {
502                 printf("InterMezzo: %s: record length not a "
503                        "multiple of 4.\n", __FUNCTION__);
504                 return -EINVAL;
505         }
506         if (ptr - *buf != rec->prefix.hdr->len) {
507                 printf("InterMezzo: %s: unpacking error\n",
508                        __FUNCTION__);
509                 return -EINVAL;
510         }
511         while (ptr < end) { 
512                 __u32 *i = (__u32 *)ptr;
513                 if (*i)
514                         break;
515                 ptr += sizeof(*i);
516         }
517         *buf = ptr;
518         return 0;
519 }
520
521
522 #ifndef __KERNEL__
523 #define STR(ptr) ((ptr))? (ptr) : ""
524
525 #define OPNAME(n) [KML_OPCODE_##n] = #n
526 static char *opnames[KML_OPCODE_NUM] = {
527         OPNAME(NOOP),
528         OPNAME(CREATE),
529         OPNAME(MKDIR), 
530         OPNAME(UNLINK),
531         OPNAME(RMDIR),
532         OPNAME(CLOSE),
533         OPNAME(SYMLINK),
534         OPNAME(RENAME),
535         OPNAME(SETATTR),
536         OPNAME(LINK),
537         OPNAME(OPEN),
538         OPNAME(MKNOD),
539         OPNAME(WRITE),
540         OPNAME(RELEASE),
541         OPNAME(TRUNC),
542         OPNAME(SETEXTATTR),
543         OPNAME(DELEXTATTR),
544         OPNAME(KML_TRUNC),
545         OPNAME(GET_FILEID)
546 };
547 #undef OPNAME
548
549 static char *print_opname(int op)
550 {
551         if (op < 0 || op >= sizeof (opnames) / sizeof (*opnames))
552                 return NULL;
553         return opnames[op];
554 }
555
556
557 static char *print_time(__u64 i)
558 {
559         char buf[128];
560         
561         memset(buf, 0, 128);
562
563 #ifndef __KERNEL__
564         strftime(buf, 128, "%Y/%m/%d %H:%M:%S", gmtime((time_t *)&i));
565 #else
566         sprintf(buf, "%Ld\n", i);
567 #endif
568
569         return strdup(buf);
570 }
571
572 static char *print_version(struct presto_version *ver)
573 {
574         char ver_buf[128];
575         char *mtime;
576         char *ctime;
577
578         if (!ver || ver->pv_ctime == 0) {
579                 return strdup("");
580         } 
581         mtime = print_time(ver->pv_mtime);
582         ctime = print_time(ver->pv_ctime);
583         sprintf(ver_buf, "mtime %s, ctime %s, len %lld", 
584                 mtime, ctime, ver->pv_size);
585         free(mtime);
586         free(ctime);
587         return strdup(ver_buf);
588 }
589
590
591 char *kml_print_rec(struct kml_rec *rec, int brief)
592 {
593         char *str;
594         char *nov, *oov, *ntv, *otv, *npv, *opv;
595         char *rectime, *mtime, *ctime;
596
597         if (brief) {
598                 str = g_strdup_printf(" %08d %7s %*s %*s", 
599                                       rec->suffix->recno,
600                                       print_opname (rec->prefix.hdr->opcode),
601                                       rec->pathlen, STR(rec->path),
602                                       rec->targetlen, STR(rec->target));
603                 
604                 return str;
605         }
606
607         rectime = print_time(rec->suffix->time);
608         mtime = print_time(rec->mtime);
609         ctime = print_time(rec->ctime);
610
611         nov = print_version(rec->new_objectv);
612         oov = print_version(rec->old_objectv);
613         ntv = print_version(rec->new_targetv);
614         otv = print_version(rec->old_targetv);
615         npv = print_version(rec->new_parentv);
616         opv = print_version(rec->old_parentv);
617
618         str = g_strdup_printf("\n -- Record:\n"
619                 "    Recno     %d\n"
620                 "    KML off   %lld\n" 
621                 "    Version   %d\n" 
622                 "    Len       %d\n"
623                 "    Suf len   %d\n"
624                 "    Time      %s\n"
625                 "    Opcode    %d\n"
626                 "    Op        %s\n"
627                 "    Pid       %d\n"
628                 "    AUid      %d\n"
629                 "    Fsuid     %d\n" 
630                 "    Fsgid     %d\n"
631                 "    Prevrec   %d\n" 
632                 "    Ngroups   %d\n"
633                 //"    Groups    @{$self->{groups}}\n" 
634                 " -- Path:\n"
635                 "    Inode     %d\n"
636                 "    Gen num   %u\n"
637                 "    Old mode  %o\n"
638                 "    Old rdev  %x\n"
639                 "    Old uid   %llu\n"
640                 "    Old gid   %llu\n"
641                 "    Path      %*s\n"
642                 //"    Open_mode %o\n",
643                 "    Pathlen   %d\n"
644                 "    Tgt       %*s\n"
645                 "    Tgtlen    %d\n" 
646                 "    Old Tgt   %*s\n"
647                 "    Old Tgtln %d\n" 
648                 " -- Attr:\n"
649                 "    Valid     %x\n"
650                 "    mode %o, uid %d, gid %d, size %lld, mtime %s, ctime %s rdev %x (%d:%d)\n"
651                 " -- Versions:\n"
652                 "    New object %s\n"
653                 "    Old object %s\n"
654                 "    New target %s\n"
655                 "    Old target %s\n"
656                 "    New parent %s\n"
657                 "    Old parent %s\n", 
658                 
659                 rec->suffix->recno, 
660                 rec->offset, 
661                 rec->prefix.hdr->version, 
662                 rec->prefix.hdr->len, 
663                 rec->suffix->len, 
664                 rectime,
665                 rec->prefix.hdr->opcode, 
666                 print_opname (rec->prefix.hdr->opcode),
667                 rec->prefix.hdr->pid,
668                 rec->prefix.hdr->auid,
669                 rec->prefix.hdr->fsuid,
670                 rec->prefix.hdr->fsgid,
671                 rec->suffix->prevrec,
672                 rec->prefix.hdr->ngroups,
673                 rec->ino,
674                 rec->generation,
675                 rec->old_mode,
676                 rec->old_rdev,
677                 rec->old_uid,
678                 rec->old_gid,
679                 rec->pathlen,
680                 STR(rec->path),
681                 rec->pathlen,
682                 rec->targetlen,
683                 STR(rec->target),
684                 rec->targetlen,
685                 rec->old_targetlen,
686                 STR(rec->old_target),
687                 rec->old_targetlen,
688                 
689                 rec->valid, 
690                 rec->mode,
691                 rec->uid,
692                 rec->gid,
693                 rec->size,
694                 mtime,
695                 ctime,
696                 rec->rdev, rec->major, rec->minor,
697                 nov, oov, ntv, otv, npv, opv);
698                 
699         free(nov);
700         free(oov);
701         free(ntv);
702         free(otv);
703         free(npv);
704         free(opv);
705
706         free(rectime); 
707         free(ctime);
708         free(mtime);
709
710         return str;
711 }
712 #endif