/* * Alexandre Chartre - Sun Microsystems, Inc. * http://blogs.sun.com/achartre */ #pragma ident "@(#)vdlinux.c 1.1 07/08/20 SMI" #include #include #include #include #include #include #include static ushort_t lbl2cksum(struct dk_label *label) { int count; ushort_t sum, *sp; count = (sizeof (struct dk_label)) / (sizeof (short)) - 1; sp = (ushort_t *)label; sum = 0; while (count--) { sum ^= *sp++; } return (sum); } void usage() { fprintf(stderr, "Usage: vdlinux file\n"); fprintf(stderr, "Version: 1.1\n"); fprintf(stderr, "\n"); } int main(int argc, char *argv[]) { int fd, change = 0, rc = 0; char *filename; struct dk_label label; if (argc != 2) { usage(); return (1); } filename = argv[1]; fd = open64(filename, O_RDWR | O_LARGEFILE); if (fd == -1) { perror("open"); return (1); } /* read existing label */ if (pread64(fd, &label, sizeof (struct dk_label), 0) == -1) { perror("error reading label"); rc = 1; goto done; } /* check if label is correct */ if (label.dkl_vtoc.v_nparts != V_NUMPAR) { printf("Incorrect number of partition (%d).\n", label.dkl_vtoc.v_nparts); printf("Updating number of partition to %d.\n", V_NUMPAR); /* update number of partitions */ label.dkl_vtoc.v_nparts = V_NUMPAR; change++; } if (label.dkl_vtoc.v_sanity != VTOC_SANE) { printf("Incorrect vtoc sanity (%x).\n", label.dkl_vtoc.v_sanity); printf("Correcting vtoc sanity (%x).\n", VTOC_SANE); /* update vtoc sane */ label.dkl_vtoc.v_sanity = VTOC_SANE; change++; } if (change) { /* update checksum */ label.dkl_cksum = lbl2cksum(&label); } else { printf("Label looks correct.\n"); } /* check bug 6544963 */ if (label.dkl_cksum & 0x8000) { printf("Applying workaround for bug 6544963.\n"); label.dkl_cksum &= 0x7fff; label.dkl_obs3 ^= 0x8000; change++; } if (change) { /* write new label */ printf("Updating label and checksum.\n"); if (pwrite64(fd, &label, sizeof (struct dk_label), 0) == -1) { perror("error writing label"); rc = 1; } } done: (void) close(fd); return (rc); }