/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Copyright (C) 2001 Cluster File Systems, Inc. * * This file is part of InterMezzo, http://www.inter-mezzo.org. * * InterMezzo is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * InterMezzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with InterMezzo; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Unpacking of KML records * */ #ifdef __KERNEL__ # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #else # include # include # include # include # include # include # include #endif #include "intermezzo_lib.h" #include "intermezzo_idl.h" #include "intermezzo_fs.h" int kml_unpack_version(struct presto_version **ver, char **buf, char *end) { char *ptr = *buf; struct presto_version *pv; UNLOGP(*ver, struct presto_version, ptr, end); pv = *ver; pv->pv_mtime_sec = NTOH__u32(pv->pv_mtime_sec); pv->pv_mtime_nsec = NTOH__u32(pv->pv_mtime_nsec); pv->pv_ctime_sec = NTOH__u32(pv->pv_ctime_sec); pv->pv_ctime_nsec = NTOH__u32(pv->pv_ctime_nsec); pv->pv_size = NTOH__u64(pv->pv_size); *buf = ptr; return 0; } static int kml_unpack_noop(struct kml_rec *rec, char **buf, char *end) { return 0; } static int kml_unpack_get_fileid(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; LUNLOGV(rec->pathlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_create(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->mode, __u32, ptr, end); LUNLOGV(rec->uid, __u32, ptr, end); LUNLOGV(rec->gid, __u32, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_mkdir(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->mode, __u32, ptr, end); LUNLOGV(rec->uid, __u32, ptr, end); LUNLOGV(rec->gid, __u32, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_unlink(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); kml_unpack_version(&rec->old_objectv, &ptr, end); LUNLOGV(rec->old_mode, __u32, ptr, end); LUNLOGV(rec->old_rdev, __u32, ptr, end); LUNLOGV(rec->old_uid, __u64, ptr, end); LUNLOGV(rec->old_gid, __u64, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); LUNLOGV(rec->targetlen, __u32, ptr, end); LUNLOGV(rec->old_targetlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); UNLOGL(rec->target, char, rec->targetlen, ptr, end); UNLOGL(rec->old_target, char, rec->old_targetlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_rmdir(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); kml_unpack_version(&rec->old_objectv, &ptr, end); LUNLOGV(rec->old_mode, __u32, ptr, end); LUNLOGV(rec->old_rdev, __u32, ptr, end); LUNLOGV(rec->old_uid, __u64, ptr, end); LUNLOGV(rec->old_gid, __u64, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); LUNLOGV(rec->targetlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); UNLOGL(rec->target, char, rec->targetlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_close(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; LUNLOGV(rec->mode, __u32, ptr, end); // used for open_mode LUNLOGV(rec->uid, __u32, ptr, end); // used for open_uid LUNLOGV(rec->gid, __u32, ptr, end); // used for open_gid kml_unpack_version(&rec->old_objectv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->ino, __u64, ptr, end); LUNLOGV(rec->generation, __u32, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_symlink(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->uid, __u32, ptr, end); LUNLOGV(rec->gid, __u32, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); LUNLOGV(rec->targetlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); UNLOGL(rec->target, char, rec->targetlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_rename(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_objectv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); LUNLOGV(rec->targetlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); UNLOGL(rec->target, char, rec->targetlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_setattr(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_objectv, &ptr, end); LUNLOGV(rec->valid, __u32, ptr, end); LUNLOGV(rec->mode, __u32, ptr, end); LUNLOGV(rec->uid, __u32, ptr, end); LUNLOGV(rec->gid, __u32, ptr, end); LUNLOGV(rec->size, __u64, ptr, end); LUNLOGV(rec->mtime_sec, __u32, ptr, end); LUNLOGV(rec->mtime_nsec, __u32, ptr, end); LUNLOGV(rec->ctime_sec, __u32, ptr, end); LUNLOGV(rec->ctime_nsec, __u32, ptr, end); LUNLOGV(rec->flags, __u32, ptr, end); LUNLOGV(rec->old_mode, __u32, ptr, end); LUNLOGV(rec->old_rdev, __u32, ptr, end); LUNLOGV(rec->old_uid, __u64, ptr, end); LUNLOGV(rec->old_gid, __u64, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_link(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); LUNLOGV(rec->targetlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); UNLOGL(rec->target, char, rec->targetlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_mknod(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_parentv, &ptr, end); kml_unpack_version(&rec->new_parentv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->mode, __u32, ptr, end); LUNLOGV(rec->uid, __u32, ptr, end); LUNLOGV(rec->gid, __u32, ptr, end); LUNLOGV(rec->major, __u32, ptr, end); LUNLOGV(rec->minor, __u32, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_write(struct kml_rec *rec, char **buf, char *end) { printf("NOT IMPLEMENTED"); return 0; } static int kml_unpack_release(struct kml_rec *rec, char **buf, char *end) { printf("NOT IMPLEMENTED"); return 0; } static int kml_unpack_trunc(struct kml_rec *rec, char **buf, char *end) { printf("NOT IMPLEMENTED"); return 0; } static int kml_unpack_setextattr(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_objectv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->flags, __u32, ptr, end); LUNLOGV(rec->mode, __u32, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); LUNLOGV(rec->namelen, __u32, ptr, end); LUNLOGV(rec->targetlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); UNLOGL(rec->name, char, rec->namelen, ptr, end); UNLOGL(rec->target, char, rec->targetlen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_delextattr(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; kml_unpack_version(&rec->old_objectv, &ptr, end); kml_unpack_version(&rec->new_objectv, &ptr, end); LUNLOGV(rec->flags, __u32, ptr, end); LUNLOGV(rec->mode, __u32, ptr, end); LUNLOGV(rec->pathlen, __u32, ptr, end); LUNLOGV(rec->namelen, __u32, ptr, end); LUNLOGV(rec->targetlen, __u32, ptr, end); UNLOGL(rec->path, char, rec->pathlen, ptr, end); UNLOGL(rec->name, char, rec->namelen, ptr, end); *buf = ptr; return 0; } static int kml_unpack_open(struct kml_rec *rec, char **buf, char *end) { printf("NOT IMPLEMENTED"); return 0; } static int kml_unpack_kml_trunc(struct kml_rec *rec, char **buf, char *end) { printf("NOT IMPLEMENTED"); return 0; } typedef int (*unpacker)(struct kml_rec *rec, char **buf, char *end); static unpacker unpackers[KML_OPCODE_NUM] = { [KML_OPCODE_NOOP] = kml_unpack_noop, [KML_OPCODE_CREATE] = kml_unpack_create, [KML_OPCODE_MKDIR] = kml_unpack_mkdir, [KML_OPCODE_UNLINK] = kml_unpack_unlink, [KML_OPCODE_RMDIR] = kml_unpack_rmdir, [KML_OPCODE_CLOSE] = kml_unpack_close, [KML_OPCODE_SYMLINK] = kml_unpack_symlink, [KML_OPCODE_RENAME] = kml_unpack_rename, [KML_OPCODE_SETATTR] = kml_unpack_setattr, [KML_OPCODE_LINK] = kml_unpack_link, [KML_OPCODE_OPEN] = kml_unpack_open, [KML_OPCODE_MKNOD] = kml_unpack_mknod, [KML_OPCODE_WRITE] = kml_unpack_write, [KML_OPCODE_RELEASE] = kml_unpack_release, [KML_OPCODE_TRUNC] = kml_unpack_trunc, [KML_OPCODE_SETEXTATTR] = kml_unpack_setextattr, [KML_OPCODE_DELEXTATTR] = kml_unpack_delextattr, [KML_OPCODE_KML_TRUNC] = kml_unpack_kml_trunc, [KML_OPCODE_GET_FILEID] = kml_unpack_get_fileid }; int kml_unpack_prefix(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; int n; UNLOGP(rec->prefix.hdr, struct kml_prefix_hdr, ptr, end); rec->prefix.hdr->len = NTOH__u32(rec->prefix.hdr->len); rec->prefix.hdr->version = NTOH__u32(rec->prefix.hdr->version); rec->prefix.hdr->pid = NTOH__u32(rec->prefix.hdr->pid); rec->prefix.hdr->auid = NTOH__u32(rec->prefix.hdr->auid); rec->prefix.hdr->fsuid = NTOH__u32(rec->prefix.hdr->fsuid); rec->prefix.hdr->fsgid = NTOH__u32(rec->prefix.hdr->fsgid); rec->prefix.hdr->opcode = NTOH__u32(rec->prefix.hdr->opcode); rec->prefix.hdr->ngroups = NTOH__u32(rec->prefix.hdr->ngroups); UNLOGL(rec->prefix.groups, __u32, rec->prefix.hdr->ngroups, ptr, end); for (n = 0; n < rec->prefix.hdr->ngroups; n++) { rec->prefix.groups[n] = NTOH__u32(rec->prefix.groups[n]); } *buf = ptr; return 0; } int kml_unpack_suffix(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; UNLOGP(rec->suffix, struct kml_suffix, ptr, end); rec->suffix->prevrec = NTOH__u32(rec->suffix->prevrec); rec->suffix->recno = NTOH__u32(rec->suffix->recno); rec->suffix->time = NTOH__u32(rec->suffix->time); rec->suffix->len = NTOH__u32(rec->suffix->len); *buf = ptr; return 0; } int kml_unpack(struct kml_rec *rec, char **buf, char *end) { char *ptr = *buf; int err; if (((unsigned long)ptr % 4) != 0) { printf("InterMezzo: %s: record misaligned.\n", __FUNCTION__); return -EINVAL; } while (ptr < end) { __u32 *i = (__u32 *)ptr; if (*i) break; ptr += sizeof(*i); } *buf = ptr; memset(rec, 0, sizeof(*rec)); err = kml_unpack_prefix(rec, &ptr, end); if (err) { printf("InterMezzo: %s: unpack_prefix failed: %d\n", __FUNCTION__, err); return err; } if (rec->prefix.hdr->opcode < 0 || rec->prefix.hdr->opcode >= KML_OPCODE_NUM) { printf("InterMezzo: %s: invalid opcode (%d)\n", __FUNCTION__, rec->prefix.hdr->opcode); return -EINVAL; } err = unpackers[rec->prefix.hdr->opcode](rec, &ptr, end); if (err) { printf("InterMezzo: %s: unpacker failed: %d\n", __FUNCTION__, err); return err; } err = kml_unpack_suffix(rec, &ptr, end); if (err) { printf("InterMezzo: %s: unpack_suffix failed: %d\n", __FUNCTION__, err); return err; } if (rec->prefix.hdr->len != rec->suffix->len) { printf("InterMezzo: %s: lengths don't match\n", __FUNCTION__); return -EINVAL; } if ((rec->prefix.hdr->len % 4) != 0) { printf("InterMezzo: %s: record length not a " "multiple of 4.\n", __FUNCTION__); return -EINVAL; } if (ptr - *buf != rec->prefix.hdr->len) { printf("InterMezzo: %s: unpacking error\n", __FUNCTION__); return -EINVAL; } while (ptr < end) { __u32 *i = (__u32 *)ptr; if (*i) break; ptr += sizeof(*i); } *buf = ptr; return 0; } #ifndef __KERNEL__ #define STR(ptr) ((ptr))? (ptr) : "" #define OPNAME(n) [KML_OPCODE_##n] = #n static char *opnames[KML_OPCODE_NUM] = { OPNAME(NOOP), OPNAME(CREATE), OPNAME(MKDIR), OPNAME(UNLINK), OPNAME(RMDIR), OPNAME(CLOSE), OPNAME(SYMLINK), OPNAME(RENAME), OPNAME(SETATTR), OPNAME(LINK), OPNAME(OPEN), OPNAME(MKNOD), OPNAME(WRITE), OPNAME(RELEASE), OPNAME(TRUNC), OPNAME(SETEXTATTR), OPNAME(DELEXTATTR), OPNAME(KML_TRUNC), OPNAME(GET_FILEID) }; #undef OPNAME static char *print_opname(int op) { if (op < 0 || op >= sizeof (opnames) / sizeof (*opnames)) return NULL; return opnames[op]; } static char *print_time(__u64 i) { char buf[128]; memset(buf, 0, 128); #ifndef __KERNEL__ strftime(buf, 128, "%Y/%m/%d %H:%M:%S", gmtime((time_t *)&i)); #else sprintf(buf, "%Ld\n", i); #endif return strdup(buf); } static char *print_version(struct presto_version *ver) { char ver_buf[128]; char *mtime; char *ctime; if (!ver || ver->pv_ctime == 0) { return strdup(""); } mtime = print_time(ver->pv_mtime); ctime = print_time(ver->pv_ctime); sprintf(ver_buf, "mtime %s, ctime %s, len %lld", mtime, ctime, ver->pv_size); free(mtime); free(ctime); return strdup(ver_buf); } char *kml_print_rec(struct kml_rec *rec, int brief) { char *str; char *nov, *oov, *ntv, *otv, *npv, *opv; char *rectime, *mtime, *ctime; if (brief) { str = g_strdup_printf(" %08d %7s %*s %*s", rec->suffix->recno, print_opname (rec->prefix.hdr->opcode), rec->pathlen, STR(rec->path), rec->targetlen, STR(rec->target)); return str; } rectime = print_time(rec->suffix->time); mtime = print_time(rec->mtime); ctime = print_time(rec->ctime); nov = print_version(rec->new_objectv); oov = print_version(rec->old_objectv); ntv = print_version(rec->new_targetv); otv = print_version(rec->old_targetv); npv = print_version(rec->new_parentv); opv = print_version(rec->old_parentv); str = g_strdup_printf("\n -- Record:\n" " Recno %d\n" " KML off %lld\n" " Version %d\n" " Len %d\n" " Suf len %d\n" " Time %s\n" " Opcode %d\n" " Op %s\n" " Pid %d\n" " AUid %d\n" " Fsuid %d\n" " Fsgid %d\n" " Prevrec %d\n" " Ngroups %d\n" //" Groups @{$self->{groups}}\n" " -- Path:\n" " Inode %d\n" " Gen num %u\n" " Old mode %o\n" " Old rdev %x\n" " Old uid %llu\n" " Old gid %llu\n" " Path %*s\n" //" Open_mode %o\n", " Pathlen %d\n" " Tgt %*s\n" " Tgtlen %d\n" " Old Tgt %*s\n" " Old Tgtln %d\n" " -- Attr:\n" " Valid %x\n" " mode %o, uid %d, gid %d, size %lld, mtime %s, ctime %s rdev %x (%d:%d)\n" " -- Versions:\n" " New object %s\n" " Old object %s\n" " New target %s\n" " Old target %s\n" " New parent %s\n" " Old parent %s\n", rec->suffix->recno, rec->offset, rec->prefix.hdr->version, rec->prefix.hdr->len, rec->suffix->len, rectime, rec->prefix.hdr->opcode, print_opname (rec->prefix.hdr->opcode), rec->prefix.hdr->pid, rec->prefix.hdr->auid, rec->prefix.hdr->fsuid, rec->prefix.hdr->fsgid, rec->suffix->prevrec, rec->prefix.hdr->ngroups, rec->ino, rec->generation, rec->old_mode, rec->old_rdev, rec->old_uid, rec->old_gid, rec->pathlen, STR(rec->path), rec->pathlen, rec->targetlen, STR(rec->target), rec->targetlen, rec->old_targetlen, STR(rec->old_target), rec->old_targetlen, rec->valid, rec->mode, rec->uid, rec->gid, rec->size, mtime, ctime, rec->rdev, rec->major, rec->minor, nov, oov, ntv, otv, npv, opv); free(nov); free(oov); free(ntv); free(otv); free(npv); free(opv); free(rectime); free(ctime); free(mtime); return str; } #endif